C #, 530 byte
Selesaikan program C #, ambil input sebagai satu baris dari STDIN, dan output satu baris ke STDOUT, dengan trailing "".
Ini agak lama ... dan memiliki terlalu banyak pengulangan x / y / z, tapi saya belum bisa menguranginya menjadi sesuatu yang masuk akal sejauh ini, dan memiliki ujian dalam 2 jam, mungkin akan kembali ke besok.
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();}}}}
Diagram ini menjelaskan sebagian besar dari apa yang terjadi.
Ketahuilah bahwa karena kita tidak dapat memiliki bagian 0-lebar, "segi enam" selalu akan menjadi bentuk termurah (dan memiliki manfaat memberi angsa ruang maksimum untuk bergerak).
Program ini bekerja dengan terlebih dahulu menerjemahkan semua indeks sel input ke dalam x / y / z coords, dan menemukan min / max masing-masing 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
Selanjutnya, ia melewati setiap indeks sel, dan memeriksa apakah itu cocok dengan 'segi enam' yang telah kami jelaskan. Jika ya maka ia memeriksa apakah ada di salah satu tepi ekstrim batas (yaitu x = xmin, atau y = ymax) dan menambahkan tepi yang sesuai jika itu. Itu harus bekerja di luar indeks tepi sebelahnya. Untuk x dan z, kami hanya menambah / mengurangi mereka seperti yang kami inginkan, dan kemudian menggunakan rumus berikut:
i = z^2 + 2*x + (1-p)
Perhatikan bahwa "paritas" selalu berubah, dan bahwa Anda tidak terlibat. Untuk y, kita tidak perlu mengubah apa pun, tetapi kodenya agak berantakan karena harus melakukan pemeriksaan "segitiga" untuk mendeteksi apakah sel di sebelahnya harus "X" atau tidak.
Contoh solusi (Sel dengan angsa hanya dari tiga sudut):
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
Kode lebih rapi dengan komentar:
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
}
}
}
}