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();}}}}
이 다이어그램은 대부분의 상황을 설명합니다.
너비가 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
}
}
}
}