C
introduzione
Come commentato da David Carraher, il modo più semplice di analizzare la piastrellatura esagonale sembrava essere quello di sfruttare il suo isomorfismo con il diagramma giovane tridimensionale, essenzialmente un quadrato x, y riempito con barre di altezza intere le cui altezze z devono rimanere le stesse o aumentare quando si avvicina l'asse z.
Ho iniziato con un algoritmo per trovare i totali che è più suscettibile all'adattamento per il conteggio di simmetria rispetto all'algoritmo pubblicato, che si basa su una propensione per uno dei tre assi cartesiani.
Algoritmo
Comincio riempiendo le celle dei piani x, ye z con 1, mentre il resto dell'area contiene zeri. Una volta fatto ciò, costruisco il modello strato per strato, con ogni strato contenente le celle che hanno una distanza 3D comune di Manhattan dall'origine. Una cella può contenere un 1 solo se le tre celle sottostanti contengono anche un 1. se una di esse contiene uno 0, la cella deve essere uno 0.
Il vantaggio di costruire il modello in questo modo è che ogni livello è simmetrico rispetto alla linea x = y = z. Ciò significa che ogni strato può essere controllato indipendentemente per simmetria.
Verifica della simmetria
Le simmetrie del solido sono le seguenti: rotazione di 3 volte attorno alla linea x = y = z -> rotazione di 3 volte intorno al centro esagonale; e 3 x riflessioni sui 3 piani contenenti la linea x = y = z e ciascuno degli assi x, y, z -> riflessione sulle linee attraverso gli angoli esagonali.
Ciò aggiunge solo una simmetria di 6 volte. Per ottenere la simmetria completa dell'esagono, è necessario considerare un altro tipo di simmetria. Ogni solido (costruito da 1) ha un solido complementare (costruito da 0). Dove N è dispari, il solido complementare deve essere diverso dal solido originale (perché non è possibile che abbiano lo stesso numero di cubi). Tuttavia, quando il solido complementare viene girato, si scoprirà che la sua rappresentazione 2D come piastrellatura a diamante è identica (tranne per un'operazione di simmetria doppia) al solido originale. Dove N è pari, è possibile che il solido sia auto-inverso.
Questo può essere visto negli esempi per N = 2 nella domanda. Se visto da sinistra, il primo esagono sembra un cubo solido con 8 cubetti piccoli, mentre l'ultimo esagono sembra un guscio vuoto con 0 cubetti piccoli. Se visto da destra, è vero il contrario. Il 3 °, 4 ° e 5 ° esagono e il 16 °, 17 ° e 18 ° esagoni sembrano contenere 2 o 6 cubi, e quindi si completano a vicenda in 3 dimensioni. Sono collegati tra loro in 2 dimensioni mediante un'operazione di simmetria 2 volte (rotazione 2 volte o riflessione attorno ad un asse attraverso i bordi dell'esagono). D'altra parte gli esagoni 9, 10, 11 e 12 mostrano modelli 3D che sono i loro complementi e quindi hanno una simmetria più elevata (questi sono quindi gli unici schemi con strana molteplicità).
Notare che avere (N ^ 3) / 2 cubi è una condizione necessaria per essere auto-complemento, ma in generale non è una condizione sufficiente se N> 2. Il risultato di tutto ciò è che per N dispari, i soffitti si verificano sempre in coppie (N ^ 3) / 2 cubi devono essere attentamente ispezionati.
Codice corrente (genera il totale giusto per N = 1,2,3,5. Errore come discusso per N = 4.)
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]);
}
Produzione
Il programma genera una tabella di output di 8 voci, in conformità con le 8 simmetrie del solido. Il solido può avere una delle 4 simmetrie come segue (notazione di Schoenflies)
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)
Inoltre, quando il solido ha esattamente metà delle celle con 1 e metà con 0, esiste la possibilità di capovolgere tutti gli 1 e gli 0, quindi invertire le coordinate attraverso il centro dello spazio del cubo. Questo è ciò che chiamo auto-complemento, ma un termine più matematico sarebbe "antisimmetrico rispetto a un centro di inversione".
Questa operazione di simmetria fornisce un asse di rotazione di 2 volte nella piastrellatura esagonale.
I motivi che presentano questa simmetria sono elencati in una colonna separata. Si verificano solo dove N è pari.
Il mio conteggio sembra essere leggermente fuori per N = 4. Discutendo con Peter Taylor sembra che non stia rilevando dei tetti che hanno solo una simmetria di una linea attraverso i bordi esagonali. Questo è presumibilmente perché non ho testato l'auto-complemento (antisimmetria) per operazioni diverse da (inversione) x (identità.) Test per l'auto-complemento per gli operatoni (inversione) x (riflessione) e (inversione) x (rotazione 3 volte ) può scoprire le simmetrie mancanti. Mi aspetto quindi che la prima riga dei dati per N = 4 sia simile a questa (16 in meno in c1 e 32 in più in C1):
c1 224064/12=18672 C1 534/6=89
Ciò porterebbe i totali in linea con la risposta di Peter e https://oeis.org/A066931/a066931.txt
l'uscita corrente è la seguente.
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
Elenco di cose da fare (aggiornato)
Riordina il codice attuale.
Fatto, più o meno
Implementa il controllo di simmetria per il livello corrente e passa un parametro per la simmetria del livello precedente (non ha senso verificare se l'ultimo livello era asimmetrico).
Fatto, i risultati per N dispari concordano con i dati pubblicati
Aggiungi un'opzione per sopprimere il conteggio delle figure asimmetriche (dovrebbe essere eseguito molto più velocemente)
Questo può essere fatto aggiungendo un'altra condizione alla chiamata di ricorsione: if(s1 && m<n*3-2)f(m + 1,e+d,s1)
riduce il tempo di esecuzione di N = 5 da 5 minuti a circa un secondo. Di conseguenza, la prima riga dell'output diventa immondizia totale (così come i totali complessivi) ma se il totale è già noto dall'OEIS, il numero di riquadri asimmetrici può essere ricostituito, almeno per N. dispari
Ma anche per N, il numero di solidi asimmetrici (secondo simmetrie c3v) che sono auto-complementi andrebbe perso. In questo caso, può essere utile un programma separato dedicato ai solidi con esattamente (N ** 3) / 2 celle con un 1. Con questo disponibile (e contando correttamente) potrebbe essere possibile provare N = 6, ma ci vorrà molto tempo per eseguirlo.
Implementa il conteggio delle celle per ridurre la ricerca fino a (N ^ 3) / 2 cubi.
Non fatto, il risparmio dovrebbe essere marginale
Implementare la simmetria (solido complementare) controllando gli schemi che contengono esattamente (N ^ 3) / 2 cubi.
Fatto, ma sembra avere omissioni, vedi N = 4.
Trova un modo per scegliere la figura lessicamente più bassa da una asimmetrica.
Non ci si aspetta che il risparmio sia così grande. Sopprimere le figure asimmetriche elimina gran parte di ciò. L'unica riflessione verificata è il piano attraverso l'asse y (x e z vengono calcolati successivamente moltiplicando per 3.) Le figure con solo simmetria rotazionale vengono contate in entrambe le loro forme enantiomeriche. Forse sarebbe quasi due volte più veloce se ne fosse contato solo uno.
Per facilitare ciò, possibilmente migliorare il modo in cui sono elencate le coordinate in ciascun livello (formano gruppi degeneri di 6 o 3, con possibilmente un gruppo di 1 nell'esatto centro del livello).
Interessante ma probabilmente ci sono altre domande sul sito da esplorare.
N = 6
fornisce un output superiore a 10 ^ 12, una soluzione non costruttiva è quasi certamente necessaria per arrivare così lontano.