C #, 530 byte
Hoàn thành chương trình C #, nhận đầu vào dưới dạng một dòng từ STDIN và xuất một dòng đơn sang STDOUT, với dấu "".
Việc này khá dài ... và có quá nhiều lần lặp lại x / y / z, nhưng tôi đã không thể giảm nó thành bất cứ điều gì hợp lý cho đến nay, và có một bài kiểm tra trong 2 giờ, có thể quay lại vào ngày mai.
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();}}}}
Sơ đồ này giải thích hầu hết những gì đang xảy ra.
Hãy nhận ra rằng vì chúng ta không thể có các phần có chiều rộng 0, "hình lục giác" sẽ luôn có hình dạng rẻ nhất (và có lợi ích là cho ngỗng tối đa không gian để di chuyển vào).
Chương trình hoạt động bằng cách trước tiên dịch tất cả các chỉ mục ô đầu vào thành các chuỗi x / y / z và tìm min / max của mỗi 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
Tiếp theo, nó đi qua từng chỉ số ô và kiểm tra xem nó có khớp với 'hình lục giác' mà chúng tôi đã mô tả hay không. Nếu đúng thì nó sẽ kiểm tra xem nó có nằm ở bất kỳ cạnh cực nào của giới hạn không (ví dụ x = xmin hoặc y = ymax) và thêm các cạnh tương ứng nếu có. Nó phải tìm ra chỉ số của cạnh bên cạnh. Đối với x và z, chúng ta chỉ cần tăng / giảm chúng theo cách chúng ta muốn và sau đó sử dụng công thức sau:
i = z^2 + 2*x + (1-p)
Lưu ý rằng "chẵn lẻ" luôn thay đổi và y không liên quan. Đối với y, chúng ta không phải thay đổi bất cứ điều gì, nhưng mã hơi lộn xộn vì nó phải thực hiện kiểm tra giới hạn "tam giác" để phát hiện xem ô bên cạnh có phải là "X" hay không.
Giải pháp ví dụ (Các ô có ngỗng chỉ từ ba góc):
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
Mã Tidier với ý kiến:
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
}
}
}
}