C
Giriş
David Carraher tarafından yorumlandığı gibi, altıgen döşemeyi analiz etmenin en basit yolu, z yüksekliğinin aynı kalması veya artması gereken tamsayı yükseklik çubuklarıyla dolu bir x, y karesinin 3 boyutlu Genç Diyagramı ile izomorfizminden faydalanmak gibi görünüyordu. z ekseni yaklaştığında.
Simetri sayımı için uyarlanmaya daha elverişli toplamları bulmak için algoritmayı, üç kartezyen ekseninden birine olan önyargılı olan yayınlanmış algoritmadan daha fazla kullanmaya başladım.
Algoritma
Alanın geri kalanı sıfır içerdiğinde, x, y ve z düzlemlerinin hücrelerini 1'lerle doldurmaya başladım. Bu yapıldıktan sonra, desen katmanını katman katman yapıyorum, her katman menşe ile ortak bir 3D manhattan mesafesine sahip hücreleri içeren hücreleri oluşturuyorum. Bir hücre ancak altındaki üç hücrede 1 varsa 1 de içerebilir, bunlardan herhangi biri 0 içeriyorsa, hücre 0 olmalıdır.
Deseni bu şekilde oluşturmanın avantajı, her katmanın x = y = z çizgisi etrafında simetrik olmasıdır. Bu, her bir katmanın simetri için bağımsız olarak kontrol edilebileceği anlamına gelir.
Simetri kontrolü
Katı simetrileri aşağıdaki gibidir: x = y = z çizgisi etrafında 3 kat rotasyonu - altıgen merkez etrafında 3 kat rotasyonu; ve x = y = z çizgisini ve x, y, z -> eksenlerinin her birini altıgen köşelerden geçen çizgiler hakkında yansıtan 3 düzlem hakkında 3 x yansıma.
Bu sadece 6 kat simetriye kadar ekler. Altıgenin tam simetrisini elde etmek için başka tür bir simetri düşünülmelidir. Her katı (1'lerden inşa edilmiş) tamamlayıcı bir katıya sahiptir (0'dan yapılan). N'nin tuhaf olduğu yerlerde, tamamlayıcı katı, orijinal katıdan farklı olmalıdır (çünkü aynı sayıda küpü olması mümkün değildir). Yine tamamlayıcı katı yuvarlak hale getirildiğinde, bir elmas karo olarak 2D gösteriminin orijinal katı ile aynı olduğu (2 kat simetri işlemi hariç) olduğu görülecektir. N'nin olduğu yerde, katının kendi kendine ters olması mümkündür.
Bu, sorudaki N = 2 örneklerinde görülebilir. Soldan bakıldığında, ilk altıgen 8 küçük küp ile dolu bir küp gibi görünürken, son altıgen 0 küçük küp içeren boş bir kabuk gibi görünür. Sağdan bakıldığında, tersi geçerlidir. 3, 4 ve 5'inci altıgenler ve 16, 17 ve 18'inci altıgenler 2 veya 6 küp içeriyor gibi görünür ve böylece birbirlerini 3 boyutta tamamlarlar. 2-boyutlu bir simetri operasyonu (2-kat rotasyon veya altıgen kenarlarından bir eksen etrafındaki yansıma) ile 2 boyutta birbirleriyle ilgilidirler. bunlar kendi tamamlayıcılarıdır ve bu nedenle daha yüksek bir simetriye sahiptirler (bunlar bu nedenle tek çeşitlilikteki tek kalıplardır).
(N ^ 3) / 2 küpün olmasının kendi tamamlayıcısı olmak için gerekli bir şart olduğunu, ancak genel olarak N> 2 olması durumunda yeterli bir koşul olmadığını unutmayın. Tüm bunların sonucu, garip N için, her zaman çiftler halinde meydana gelen eğimlerin (N ^ 3) / 2 küplerin dikkatlice incelenmesi gerektiğidir.
Geçerli kod (N = 1,2,3,5 için doğru toplamı oluşturur. N = 4 için tartışıldığı gibi hata.)
int n; //side length
char t[11][11][11]; //grid sized for N up to 10
int q[29][192], r[29]; //tables of coordinates for up to 10*3-2=28 layers
int c[9]; //counts arrangements found by symmetry class. c[8] contains total.
//recursive layer counting function. m= manhattan distance, e= number of cells in previous layers, s=symmetry class.
void f(int m,int e,int s){
int u[64], v[64], w[64]; //shortlists for x,y,z coordinates of cells in this layer
int j=0;
int x,y,z;
for (int i=r[m]*3; i; i-=3){
// get a set of coordinates for a cell in the current layer.
x=q[m][i-3]; y= q[m][i-2]; z= q[m][i-1];
// if the three cells in the previous layer are filled, add it to the shortlist u[],v[],w[]. j indicates the length of the shortlist.
if (t[x][y][z-1] && t[x][y-1][z] && t[x-1][y][z]) u[j]=x, v[j]=y, w[j++]=z ;
}
// there are 1<<j possible arrangements for this layer.
for (int i = 1 << j; i--;) {
int d = 0;
// for each value of i, set the 1's bits of t[] to the 1's bits of i. Count the number of 1's into d as we go.
for (int k = j; k--;) d+=(t[u[k]][v[k]][w[k]]=(i>>k)&1);
// we have no interest in i=0 as it is the empty layer and therefore the same as the previous recursion step.
// Still we loop through it to ensure t[] is properly cleared.
if(i>0){
int s1=s; //local copy of symmetry class. 1's bit for 3 fold rotation, 2's bit for reflection in y axis.
int sc=0; //symmetry of self-complement.
//if previous layers were symmetrical, test if the symmetry has been reduced by the current layer
if (s1) for (int k = j; k--;) s1 &= (t[u[k]][v[k]][w[k]]==t[w[k]][u[k]][v[k]]) | (t[u[k]][v[k]][w[k]]==t[w[k]][v[k]][u[k]])<<1;
//if exactly half the cells are filled, test for self complement
if ((e+d)*2==n*n*n){
sc=1;
for(int A=1; A<=(n>>1); A++)for(int B=1; B<=n; B++)for(int C=1; C<=n; C++) sc&=t[A][B][C]^t[n+1-A][n+1-B][n+1-C];
}
//increment counters for total and for symmetry class.
c[8]++; c[s1+(sc<<2)]++;
//uncomment for graphic display of each block stacking with metadata. not recommended for n>3.
//printf("m=%d j=%d i=%d c1=%d-2*%d=%d c3=%d cy=%d(cs=%d) c3v=%d ctot=%d\n",m,j,i,c[0],c[2],c[0]-2*c[2],c[1],c[2],c[2]*3,c[3],c[8]);
//printf("m=%d j=%d i=%d C1=%d-2*%d=%d C3=%d CY=%d(CS=%d) C3V=%d ctot=%d\n",m,j,i,c[4],c[6],c[4]-2*c[6],c[5],c[6],c[6]*3,c[7],c[8]);
//for (int A = 0; A<4; A++, puts(""))for (int B = 0; B<4; B++, printf(" "))for (int C = 0; C<4; C++) printf("%c",34+t[A][B][C]);
//recurse to next level.
if(m<n*3-2)f(m + 1,e+d,s1);
}
}
}
main()
{
scanf("%d",&n);
int x,y,z;
// Fill x,y and z planes of t[] with 1's
for (int a=0; a<9; a++) for (int b=0; b<9; b++) t[a][b][0]= t[0][a][b]= t[b][0][a]= 1;
// Build table of coordinates for each manhattan layer
for (int m=1; m < n*3-1; m++){
printf("m=%d : ",m);
int j=0;
for (x = 1; x <= n; x++) for (y = 1; y <= n; y++) {
z=m+2-x-y;
if (z>0 && z <= n) q[m][j++] = x, q[m][j++] = y, q[m][j++]=z, printf(" %d%d%d ",x,y,z);
r[m]=j/3;
}
printf(" : r=%d\n",r[m]);
}
// Set count to 1 representing the empty box (symmetry c3v)
c[8]=1; c[3]=1;
// Start searching at f=1, with 0 cells occupied and symmetry 3=c3v
f(1,0,3);
// c[2 and 6] only contain reflections in y axis, therefore must be multiplied by 3.
// Similarly the reflections in x and z axis must be subtracted from c[0] and c[4].
c[0]-=c[2]*2; c[2]*=3;
c[4]-=c[6]*2; c[6]*=3;
int cr[9];cr[8]=0;
printf("non self-complement self-complement\n");
printf("c1 %9d/12=%9d C1 %9d/6=%9d\n", c[0], cr[0]=c[0]/12, c[4], cr[4]=c[4]/6);
if(cr[0]*12!=c[0])puts("c1 division error");if(cr[4]*6!=c[4])puts("C1 division error");
printf("c3 %9d/4 =%9d C3 %9d/2=%9d\n", c[1], cr[1]=c[1]/4, c[5], cr[5]=c[5]/2);
if(cr[1]*4!=c[1])puts("c3 division error");if(cr[5]*2!=c[5])puts("C3 division error");
printf("cs %9d/6 =%9d CS %9d/3=%9d\n", c[2], cr[2]=c[2]/6, c[6], cr[6]=c[6]/3);
if(cr[2]*6!=c[2])puts("cs division error");if(cr[6]*3!=c[6])puts("CS division error");
printf("c3v %9d/2 =%9d C3V %9d/1=%9d\n", c[3], cr[3]=c[3]/2, c[7], cr[7]=c[7]);
if(cr[3]*2!=c[3])puts("c3v division error");
for(int i=8;i--;)cr[8]+=cr[i];
printf("total =%d unique =%d",c[8],cr[8]);
}
Çıktı
Program, katının 8 simetrisi uyarınca 8 girişli bir çıktı tablosu oluşturur. Katı, aşağıdaki gibi 4 simetriden birine sahip olabilir (Schoenflies notasyonu)
c1: no symmetry
c3: 3-fold axis of rotation (produces 3-fold axis of rotation in hexagon tiling)
cs: plane of reflection (produces line of reflection in hexagon tiling)
c3v both of the above (produces 3-fold axis of rotation and three lines of reflection through the hexagon corners)
Ek olarak, katı, hücrelerin 1 'i ve yarısı 0'lı hücrelerin tam yarısına sahip olduğunda, tüm 1'leri ve 0'ları çevirip, koordinatları küp boşluğun ortasından tersine çevirme olasılığı vardır. Ben buna kendi tamamlayıcı derim, ama daha matematiksel bir terim "bir inversiyon merkezine göre antisimetrik" olacaktır.
Bu simetri işlemi, altıgen döşemede 2 kat dönme ekseni sağlar.
Bu simetriye sahip desenler ayrı bir sütunda listelenir. Sadece N'nin olduğu yerde meydana gelirler.
Sayılarım N = 4 için biraz kapalı görünüyor. Peter Taylor ile tartışırken, altıgen kenarlardan sadece bir çizgi simetrisine sahip eğimleri tespit edemediğim anlaşılıyor. Bu muhtemelen (ters) x (kimlik) dışındaki işlemler için kendinden tamamlayıcı (antisimetri) testi yapmadığım için (inversiyon) x (kimlik). ) eksik simetrileri ortaya çıkarabilir. Daha sonra N = 4 için verilerin ilk satırının şöyle görünmesini beklerdim (c1'de 16, C1'de 32 daha):
c1 224064/12=18672 C1 534/6=89
Bu toplamları Peter'ın cevabına uygun hale getirir ve https://oeis.org/A066931/a066931.txt
akım çıkışı aşağıdaki gibidir.
N=1
non self-complement self-complement
c1 0/12= 0 C1 0/6= 0
c3 0/4 = 0 C3 0/2= 0
cs 0/6 = 0 CS 0/3= 0
c3v 2/2 = 1 C3V 0/1= 0
total =2 unique =1
non self-complement self-complement
N=2
c1 0/12= 0 C1 0/6= 0
c3 0/4 = 0 C3 0/2= 0
cs 12/6 = 2 CS 3/3= 1
c3v 4/2 = 2 C3V 1/1= 1
total =20 unique =6
N=3
non self-complement self-complement
c1 672/12=56 C1 0/6= 0
c3 4/4 = 1 C3 0/2= 0
cs 288/6 =48 CS 0/3= 0
c3v 16/2 = 8 C3V 0/1= 0
total =980 unique =113
N=4 (errors as discussed)
non self-complement self-complement
c1 224256/12=18688 C1 342/6=57
c3 64/4 =16 C3 2/2= 1
cs 8064/6 =1344 CS 54/3=18
c3v 64/2 =32 C3V 2/1= 2
total =232848 unique =20158
N=5
non self-complement self-complement
c1 266774112/12=22231176 C1 0/6= 0
c3 1100/4 =275 C3 0/2= 0
cs 451968/6 =75328 CS 0/3= 0
c3v 352/2 =176 C3V 0/1= 0
total =267227532 unique =22306955
Yapılacaklar listesi (güncellendi)
Mevcut kodu düzenleyin.
Yapıldı, az ya da çok
Mevcut katman için simetri kontrolü uygular ve önceki katmanın simetrisi için bir parametre iletir (son katmanın asimetrik olup olmadığını kontrol etmenin bir anlamı yoktur).
Bitti, garip N sonuçları yayınlanmış verilerle aynı fikirde
Asimetrik sayıları saymak için bir seçenek ekleyin (çok daha hızlı çalışması gerekir)
Bu özyineleme çağrısına başka bir koşul ekleyerek yapılabilir: if(s1 && m<n*3-2)f(m + 1,e+d,s1)
N = 5 için çalışma süresini 5 dakikadan bir saniyeye düşürür. Sonuç olarak, çıktının ilk satırı toplam çöp haline gelir (toplam toplamlar gibi), ancak toplam OEIS'ten zaten biliniyorsa, asimetrik eğim sayısı, en azından garip N için sulandırılabilir.
Ancak N için bile, kendi kendine tamamlayıcı olan asimetrik (c3v simetrilerine göre) katıların sayısı kaybedilir. Bu durumda, katı maddelere adanmış tam bir (N ** 3) / 2 hücreli 1 ayrı bir program faydalı olabilir. Bu kullanılabilir durumdayken (ve doğru sayımla) N = 6 denemek mümkün olabilir, ancak çalışması uzun zaman alabilir.
Aramayı (N ^ 3) / 2 küp kadar azaltmak için hücre sayımı uygulayın.
Yapılmadı, tasarrufların marjinal olması bekleniyor
Tam (N ^ 3) / 2 küp içeren kalıpları kontrol etmek için simetri (tamamlayıcı katı) kontrolü uygulayın.
Tamam, ama ihmaller var gibi görünüyor, bakınız N = 4.
Asimetrik olandan en düşük en düşük rakamı seçmenin bir yolunu bul.
Tasarrufların bu kadar büyük olması beklenmiyor. Asimetrik şekilleri bastırmak, bunların çoğunu ortadan kaldırır. Kontrol edilen tek yansıma y ekseni boyunca düzlemdir (x ve z, daha sonra 3 ile çarpılarak hesaplanır). Sadece dönme simetrisine sahip şekiller, her iki enantiyomerik formunda sayılır. Belki sadece bir kişi sayılırsa neredeyse iki kat daha hızlı koşardı.
Bunu kolaylaştırmak için, muhtemelen her katmandaki koordinatların listelenme şeklini geliştirmek (katmanın tam merkezinde muhtemelen 1 olan bir grupla birlikte 6 veya 3 dejenere gruplar oluştururlar.)
İlginç ama muhtemelen sitede keşfedilecek başka sorular var.
N = 6
fazla 10 ^ 12 bir çıkış verir, yapıcı olmayan bir çözüm neredeyse kesin gerekli uzakta olduğunu elde etmektir.