멸종에서 거위를 구하십시오


13

Alex A 로 알려진 기러기의 종은 64 개의 세포로 구성된 삼각형 격자에 상주하는 것으로 알려져 있습니다.

세포
(이 관련없는 프로젝트 오일러 문제 에서 찍은 사진 입니다.)

각 셀 에는 맨 윗줄부터 시작하여 그 아래의 각 행에 대해 왼쪽에서 오른쪽으로 숫자 0가 레이블로 지정됩니다 63. 따라서 상단 셀은 0오른쪽 하단 셀입니다 63.

각 셀에는 세 개의 테두리가 있습니다. 우리는 형태로 각각의 국경에 레이블을 지정할 수 있습니다 a,bab세포의 수 주 그 경계가 있습니다. 예를 들어, 셀 사이의 경계 0와는 2호출 할 것이다 0,2또는 2,0(당신이에 넣어 주문할 중요하지 않습니다).

그리드의 가장 자리에있는 테두리의 레이블 시스템은 서로 다릅니다. 그리드의 가장자리에있는 셀은 다른 셀과 공유하지 않는 테두리가 있기 때문입니다. 테두리가 한 셀의 일부일 경우 글자를 사용합니다 X. 예를 들어, 셀의 세 가지 테두리 0입니다 0,2, 0,X하고 0,X.

일부 세포에는 거위가 들어 있습니다 . 그러나이 거위들은 당신이 그들을 보호하지 않으면 사악한 여우 (그리드의 경계 바깥에서 온)에 의해 죽습니다. 그리고 모든 거위가 죽으면 BrainSteel은 슬플 것입니다. 따라서 우리는 기러기 주변에 울타리를 만들어 여우로부터 그들을 보호하는 프로그램을 작성할 것입니다. 기러기는 완전히 밀폐 된 하나 의 울타리 다각형으로 존재해야합니다 . 우리의 울타리 예산은 매우 낮으므로 가능한 한 적은 수의 울타리를 사용하십시오.

입력 설명

번호 목록은 쉼표로 분리 0하는 63거위가 포함 된 셀을 나타내는. 예:

6,12

출력 설명

거위를 성공적으로 보호하기 위해 울타리가 있어야하는 국경 목록. 이것은 가능한 가장 적은 울타리 수 여야합니다. 예:

5,6 6,7 11,12 12,13 

"거위는 완전히 밀폐 된 다각형 울타리에 있어야합니다." 모든 거위가 동일한 다각형에 있어야합니까, 아니면 여러 (또는 0) 다각형이있을 수 있습니까?
feersum

@feersum 모든 거위는 같은 다각형으로 살아야합니다. 명확하게하기 위해 질문을 편집했습니다.
압생트

@Katya 다각형에 자체 교차 섹션 또는 너비가 0 인 섹션이있을 수 있습니까? 모래 시계 모양처럼 생각하십시오.
orlp

@orlp 너비가 0 인 섹션은 무엇입니까?
압생트

2
@orlp 다각형에는 폭이 0 인 섹션이 없어야합니다.
압생트

답변:


10

C #, 530 바이트

완전한 C # 프로그램은 STDIN에서 단일 행으로 입력을 받고 후행 ""을 사용하여 단일 행을 STDOUT으로 출력합니다.

이것은 다소 길고 ... x / y / z 반복이 너무 많지만 지금까지 합리적인 것으로 줄이 지 못했고 2 시간 안에 시험을 치르면 내일 다시 올 수 있습니다.

using Q=System.Console;class P{static void Main(){int q=9,w=0,e=9,r=0,t=9,u=0,i=0,x=0,y=0,z=0,p=0;System.Action V=()=>{z=(int)System.Math.Sqrt(i);p=(x=i-z*z)%2;x/=2;y=(++z*z--+~i)/2;},W=()=>{Q.Write(i+","+(x<0|y++<0|z>7?"X":""+(z*z+2*x+1-p))+" ");};foreach(var g in Q.ReadLine().Split(',')){i=int.Parse(g);V();q=q>x?x:q;w=w<x?x:w;e=e>y?y:e;r=r<y?y:r;t=t>z?z:t;u=u<z?z:u;}for(i=64;i-->0;){V();if(!(x<q|x>w|y<e|y>r|z<t|z>u))if(p>0){if(y==r)W();if(x++==w)W();x--;if(z--==t)W();}else{if(y--==e)W();if(x--==q)W();x++;if(z++==u)W();}}}}

이 다이어그램은 대부분의 상황을 설명합니다.

x / y / z / (p)로 설명 된 그리드, 예제 솔루션 표시

너비가 0 인 섹션을 사용할 수 없기 때문에 "육각형"은 항상 가장 저렴한 모양이됩니다 (거위로 이동할 수있는 최대 공간 제공).

이 프로그램은 먼저 모든 입력 셀 인덱스를 x / y / z 좌표로 변환하고 각 x / y / z의 최소 / 최대 값을 찾아 작동합니다.

z = floor(root(i))
x = floor((i - z^2) / 2)
y = floor((z+1)^2 - i - 1) / 2)
p = (i - z^2) % 2

다음으로 각 셀 인덱스를 살펴보고 설명 된 '육각형'경계에 맞는지 확인합니다. 그렇다면 경계의 가장 가장자리 (예 : x = xmin 또는 y = ymax)에 있는지 확인하고 해당 가장자리를 추가합니다. 옆에있는 가장자리의 색인을 해결해야합니다. x와 z의 경우 원하는대로 증가 / 감소한 후 다음 공식을 사용하십시오.

i = z^2 + 2*x + (1-p)

"패리티"는 항상 변경되며 y는 포함되지 않습니다. y의 경우 아무것도 변경할 필요가 없지만 옆에있는 셀이 "X"인지 여부를 감지하기 위해 "삼각형"경계를 수행해야하기 때문에 코드가 약간 혼란 스러울 수 있습니다.

솔루션 예 (세 모서리에서 거위가있는 셀) :

Input
2,50,62

Output
62,63 61,X 59,X 57,X 55,X 53,X 51,X 50,49 48,X 36,X 35,X 25,X 24,X 16,X 15,X 9,X 8,X 4,X 3,X 2,0 1,X 

주석이 포함 된 간단한 코드 :

using Q=System.Console;

class P
{
    static void Main()
    {
        int q=9,w=0,e=9,r=0,t=9,u=0, // min/max x/y/z/ (init min high, and max low)
        i=0, // index of cell we are looking at
        x=0,y=0,z=0,p=0; // x,y,z dimension

        System.Action V=()=>
            { // translates the index into x/y/z/p
                z=(int)System.Math.Sqrt(i);
                p=(x=i-z*z)%2; // 'parity'
                x/=2; // see p assignment
                y=(++z*z--+~i)/2; // ~i == -i - 1
            },
            W=()=>
            { // writes out the edge of i, and the cell described by x/z/inverse of p   (the inversion of p handles y +/-)
                Q.Write(i+","+ // write out the edge
                        (x<0|y++<0|z>7?"X":""+(z*z+2*x+1-p)) // either X (if we go out of 'trianlge' bounds), or we translate x/z/inverse of p into an index
                        +" "); // leaves a trailing space (as shown in example output)
            };

        foreach(var g in Q.ReadLine().Split(',')) // for each cell with geese
        {
            i=int.Parse(g); // grab index of cell
            V(); // compute x/y/z/p
            q=q>x?x:q; // sort out mins/maxes
            w=w<x?x:w;
            e=e>y?y:e;
            r=r<y?y:r;
            t=t>z?z:t;
            u=u<z?z:u;

            // code like the above suggests a solution with a couple of arrays would be better...
            // I've not had success with that yet, but maybe in a couple of days I will try again
        }

        for(i=64;i-->0;) // for each cell
        {
            V(); // compute x/y/z/p
            if(!(x<q|x>w|y<e|y>r|z<t|z>u)) // if we are inside the 'hex' bounds
                if(p>0)
                { // x max, y max, z min
                    // these checks check that we are on the extremes of the 'hex' bounds,
                    // and set up the appropriate vars for W calls to put the edges in
                    // must do y first, because W modifies it for us (saves 2 bytes in the next block)
                    if(y==r) // don't need the ++ (can't go out of 'trianlge' bounds)
                        W();
                    if(x++==w)
                        W();
                    x--;
                    if(z--==t)
                        W();
                    //z++; not used again
                }
                else
                { // x min, y min, z max
                    if(y--==e) // do need the -- (used for 'trianlge' bounds checking)
                        W();
                    // y is reset in W, as such
                    if(x--==q)
                        W();
                    x++;
                    if(z++==u)
                        W();
                    //z--; not used again
                }
        }
    }
}

로 바이트를 저장할 수 있습니다 using System;.
LegionMammal978

@ LegionMammal978은 실제로 두 가지를 얻습니다. 그는 Q.Write와 Q.ReadLine에만 사용합니다. 이것들과 그가 지금 사용하는 진술은 using Q=System.Console;Q.Write();Q.ReadLine()(45 바이트) 대 당신의 제안 using System;Console.Write();Console.ReadLine()(47 바이트)입니다.
Kade

또한, 당신은하지 불필요하게 초기화하여 10 바이트를 삭제할 수 있습니다 i, x, y, z, 및 p0으로
LegionMammal978

@ LegionMammal978 확실합니까? 나는 그것을 시도했고 할당되지 않은 vairable을 사용하는 데 오류가 발생했습니다.
Kade

@ Vioz- 어떤 변수? 주석이 달린 버전의 어떤 줄?
LegionMammal978
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.