씨
소개
David Carraher가 언급 한 것처럼, 육각형 타일링을 분석하는 가장 간단한 방법은 3 차원 영 다이어그램, 본질적으로 z 높이가 동일하게 유지되거나 증가해야하는 정수 높이 막대로 채워진 x, y 정사각형을 사용하여 동 형사상을 이용하는 것 같습니다. z 축에 접근하면
필자는 세 가지 직교 축 중 하나에 대한 편향을 기반으로하는 게시 된 알고리즘보다 대칭 계산에 더 적합한 총계를 찾기위한 알고리즘으로 시작했습니다.
연산
x, y 및 z 평면의 셀을 1로 채우는 것으로 시작하고 나머지 영역에는 0이 포함됩니다. 이 작업이 완료되면 각 레이어마다 원점에서 공통 3D 맨해튼 거리를 가진 셀이 포함 된 패턴으로 레이어별로 패턴을 만듭니다. 셀 아래에있는 3 개의 셀에도 1이 들어 있으면 셀에는 1 만 포함될 수 있습니다. 셀 중 하나에 0이 포함되어 있으면 셀은 0이어야합니다.
이러한 방식으로 패턴을 구축 할 때의 이점은 각 레이어가 x = y = z 선에 대해 대칭이라는 것입니다. 즉, 각 레이어를 독립적으로 검사하여 대칭을 확인할 수 있습니다.
대칭 검사
고체의 대칭은 다음과 같다 : x = y = z 선을 중심으로 3 배 회전-> 육각 중심을 중심으로 3 배 회전; x = y = z 라인과 육각 코너를 통한 라인에 대한 x, y, z-> 각 반사를 포함하는 3 평면에 대한 3 x 반사.
이는 최대 6 배 대칭 만 추가합니다. 육각형의 전체 대칭을 얻으려면 다른 종류의 대칭을 고려해야합니다. 각 솔리드 (1로 제작)에는 보완 솔리드 (0으로 제작)가 있습니다. N이 홀수 인 경우 보완 솔리드는 원래 솔리드와 달라야합니다 (동일한 수의 큐브를 가질 수 없기 때문). 그러나 보완적인 솔리드가 둥글게되면 다이아몬드 타일링으로 2D 표현이 원래의 솔리드와 동일하다는 것을 알 수 있습니다 (2 배 대칭 연산 제외). N이 짝수 인 경우, 고체는 자기 역전이 가능합니다.
이것은 문제의 N = 2에 대한 예에서 볼 수 있습니다. 왼쪽에서 보면 첫 번째 육각형은 8 개의 작은 큐브가있는 솔리드 큐브처럼 보이고 마지막 육각형은 0 개의 작은 큐브가있는 빈 껍질처럼 보입니다. 오른쪽에서 보면 그 반대입니다. 3, 4, 5 육각형과 16, 17, 18 육각형은 2 개 또는 6 개의 큐브를 포함하는 것처럼 보이므로 3 차원으로 서로 보완합니다. 그것들은 2 중 대칭 연산 (2 중 회전, 또는 육각형 모서리를 통한 축에 대한 반사)에 의해 2 차원에서 서로 관련됩니다. 반면에, 9, 10, 11 및 12 번째 육각형은 3D 패턴을 나타냅니다. 자신의 보완 요소이므로 더 높은 대칭성을 갖습니다 (따라서 홀수 다중성을 갖는 유일한 패턴).
(N ^ 3) / 2 큐브를 갖는 것은 자기 보완이되기 위해 필요한 조건이지만, 일반적으로 N> 2이면 충분한 조건이 아닙니다. 이 모든 결과는 홀수 N의 경우 타일링이 항상 쌍 (N ^ 3) / 2 큐브로 발생한다는 점을주의 깊게 검사해야한다는 것입니다.
현재 코드 (N = 1,2,3,5에 대한 올바른 총계를 생성합니다. 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]);
}
산출
프로그램은 솔리드의 8 가지 대칭에 따라 8 개의 항목으로 구성된 출력 테이블을 생성합니다. 솔리드는 다음과 같이 4 가지 대칭 중 하나를 가질 수 있습니다 (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)
또한, 솔리드에 정확히 1의 절반이 있고 0의 절반이있는 셀의 경우, 1과 0을 모두 뒤집은 다음 큐브 공간의 중심을 통해 좌표를 반전시킬 가능성이 있습니다. 이것이 제가 자기 보완이라고 부르는 것이지만, 더 수학적인 용어는 "반전 중심에 대한 비대칭"입니다.
이 대칭 작업은 육각 타일링에서 2 배 회전축을 제공합니다.
이 대칭을 갖는 패턴은 별도의 열에 나열됩니다. N이 짝수 인 경우에만 발생합니다.
내 수는 N = 4에서 약간 벗어난 것 같습니다. Peter Taylor와의 토론에서 육각형 모서리를 통과하는 선의 대칭 만있는 타일링을 감지하지 못하는 것 같습니다. 아마도 (inversion) x (identity) 이외의 작업에 대해 자기 보완 (비대칭)을 테스트하지 않았기 때문일 수 있습니다. )가 누락 된 대칭을 발견 할 수 있습니다. 그런 다음 N = 4에 대한 데이터의 첫 번째 줄이 다음과 같이 보일 것으로 기대합니다 (c1에서 16 줄, C1에서 32 줄).
c1 224064/12=18672 C1 534/6=89
이것은 피터의 답변과 https://oeis.org/A066931/a066931.txt에 따라 총계를 가져옵니다.
전류 출력은 다음과 같습니다.
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
할 일 목록 (업데이트 됨)
현재 코드를 정리하십시오.
다소간 완료
현재 레이어에 대한 대칭 검사를 구현하고 이전 레이어의 대칭에 대한 매개 변수를 전달합니다 (마지막 레이어가 비대칭인지 여부를 확인할 수 없음).
완료, 홀수 N에 대한 결과가 게시 된 데이터에 동의
비대칭 수치 계산을 억제하는 옵션 추가 (훨씬 빨리 실행되어야 함)
재귀 호출에 다른 조건을 추가하여 수행 할 수 있습니다. if(s1 && m<n*3-2)f(m + 1,e+d,s1)
N = 5의 실행 시간을 5 분에서 약 1 초로 줄입니다. 결과적으로 출력의 첫 번째 줄은 전체 가비지가되지만 (전체 총계와 마찬가지로) 총계가 이미 OEIS에서 알려진 경우 적어도 홀수 N에 대해 비대칭 타일링 수를 재구성 할 수 있습니다.
그러나 N조차도 자기 보완적인 비대칭 (c3v 대칭에 따라) 고체의 수는 없어 질 것입니다. 이 경우 정확히 1 (N ** 3) / 2 개의 셀이있는 솔리드 전용 프로그램이 유용 할 수 있습니다. 이것을 사용할 수 있고 올바르게 계산하면 N = 6을 시도 할 수 있지만 실행하는 데 시간이 오래 걸립니다.
검색을 최대 (N ^ 3) / 2 큐브까지 줄이기 위해 셀 수를 구현합니다.
완료되지 않음, 절감 효과는 미미할 것으로 예상
정확히 (N ^ 3) / 2 큐브를 포함하는 패턴에 대한 대칭 (보완 솔리드) 검사를 구현하십시오.
완료되었지만 생략 된 것으로 보입니다 (N = 4 참조).
비대칭 그림에서 어휘 적으로 가장 낮은 그림을 선택하는 방법을 찾으십시오.
저축이 그렇게 크지는 않을 것으로 예상됩니다. 비대칭 수치를 억제하면 대부분이 제거됩니다. 확인 된 유일한 반사는 y 축을 통한 평면입니다 (x와 z는 나중에 3을 곱하여 계산 됨). 회전 대칭 만있는 숫자는 거울상 이성질체 형태로 계산됩니다. 아마도 하나만 세면 거의 두 배나 빠르게 실행될 것입니다.
이를 용이하게하기 위해 각 레이어의 좌표가 나열되는 방식을 개선 할 수 있습니다 (층의 정확한 중심에 그룹이 1 또는 3 인 축퇴 그룹을 형성 함).
흥미롭지 만 사이트에서 다른 질문이있을 수 있습니다.
N = 6
10 ^ 12 이상의 출력을 제공하기 때문에이를 달성 하기 위해서는 비 확실한 솔루션이 거의 필요합니다.