C #, 530 bayt
C # programını tamamlayın, girişi STDIN'den tek bir satır olarak alır ve arkadaki "" ile STDOUT'a tek bir satır çıkarır.
Bu oldukça uzun ... ve çok fazla x / y / z tekrarı var, ama şimdiye kadar mantıklı bir şeye indiremedim ve 2 saat içinde bir sınavım var, bu yarına geri gelebilir.
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();}}}}
Bu şema neler olup bittiğini açıklamaktadır.
0 genişlikli bölümlere sahip olamadığımızdan, bir "altıgen" in her zaman en ucuz şekil olacağını (ve kazlara hareket etmek için maksimum alan sağlama avantajına sahip olacağını) unutmayın.
Program ilk olarak tüm giriş hücresi indekslerini x / y / z koordinatlarına çevirerek ve x / y / z'nin her birinin min / max'ını bularak çalışır.
z = floor(root(i))
x = floor((i - z^2) / 2)
y = floor((z+1)^2 - i - 1) / 2)
p = (i - z^2) % 2
Daha sonra, her bir hücre indeksinden geçer ve tarif ettiğimiz 'altıgen' sınırına uyup uymadığını kontrol eder. Öyleyse, sınırların uç kenarlarından herhangi birinde olup olmadığını kontrol eder (yani x = xmin veya y = ymax) ve varsa karşılık gelen kenarları ekler. Yanındaki kenarın dizinini bulmalıdır. X ve z için, onları istediğimiz gibi artırırız / azaltırız ve sonra aşağıdaki formülü kullanırız:
i = z^2 + 2*x + (1-p)
"Eşlik" in her zaman değiştiğine ve y'nin dahil olmadığına dikkat edin. Y için, hiçbir şeyi değiştirmek zorunda değiliz, ancak kod biraz karışıklıktır, çünkü sonraki kapının hücresinin "X" olup olmadığını tespit etmek için "üçgen" sınırları kontrol etmesi gerekir.
Örnek çözüm (Üç köşeden kazlı hücreler):
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
Yorumlar içeren düzen kodu:
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
}
}
}
}