С
Введение
Как прокомментировал Дэвид Каррахер, простейший способ анализа мозаики шестиугольника, по-видимому, заключается в том, чтобы воспользоваться его изоморфизмом с трехмерной диаграммой Юнга, по существу, квадратом x, y, заполненным целочисленными столбцами высоты, высота которых z должна оставаться неизменной или увеличиваться по мере приближения к оси Z.
Я начал с алгоритма нахождения итогов, который более приспособлен к адаптации для подсчета симметрии, чем опубликованный алгоритм, который основан на смещении к одной из трех декартовых осей.
Алгоритм
Я начинаю с заполнения ячеек плоскостей x, y и z единицами, а остальная часть области содержит нули. Как только это будет сделано, я создаю шаблон слой за слоем, где каждый слой содержит ячейки, которые имеют общее трехмерное манхэттенское расстояние от начала координат. Ячейка может содержать только 1, если три ячейки под ней также содержат 1. Если любая из них содержит 0, то ячейка должна быть 0.
Преимущество построения шаблона таким образом состоит в том, что каждый слой является симметричным относительно линии x = y = z. Это означает, что каждый слой можно проверить независимо на симметрию.
Проверка симметрии
Симметрии тела следующие: 3-кратное вращение вокруг линии x = y = z -> 3-кратное вращение вокруг центра шестиугольника; и 3 отражения по 3 плоскостям, содержащим линию x = y = z и каждую из осей x, y, z -> отражение по линиям через углы шестиугольника.
Это добавляет только 6-кратную симметрию. Чтобы получить полную симметрию шестиугольника, необходимо рассмотреть другой вид симметрии. Каждое тело (построено из 1) имеет дополнительное тело (построено из 0). Там, где N нечетно, дополнительное тело должно отличаться от исходного тела (потому что они не могут иметь одинаковое количество кубов). Тем не менее, когда дополнительное тело поворачивается, обнаруживается, что его двумерное представление в виде ромбовидной мозаики идентично (за исключением операции симметрии в 2 раза) исходному телу. Если N четное, тело может быть самообращенным.
Это можно увидеть в примерах для N = 2 в вопросе. Если смотреть слева, первый шестиугольник выглядит как сплошной куб с 8 маленькими кубиками, а последний шестиугольник выглядит как пустая оболочка с 0 маленькими кубиками. Если смотреть справа, обратное верно. 3-й, 4-й и 5-й шестиугольники и 16-й, 17-й и 18-й шестиугольники выглядят так, как будто они содержат либо 2, либо 6 кубов, и, таким образом, они дополняют друг друга в 3 измерениях. Они связаны друг с другом в двух измерениях с помощью операции симметрии в 2 раза (2-кратное вращение или отражение вокруг оси через края шестиугольника.) С другой стороны, 9-й, 10-й, 11-й и 12-й шестиугольники показывают трехмерные структуры, которые являются их собственными дополнениями и, следовательно, имеют более высокую симметрию (следовательно, это единственные модели с нечетной кратностью).
Обратите внимание, что наличие (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. В разговоре с Питером Тейлором выясняется, что я не обнаруживаю наклоны, которые имеют симметрию только линии, проходящей через ребра шестиугольника. Вероятно, это связано с тем, что я не проверял самодополнение (антисимметрию) для операций, отличных от (инверсия) x (тождество.) ) может раскрыть недостающие симметрии. Тогда я бы ожидал, что первая строка данных для N = 4 будет выглядеть следующим образом (на 16 меньше в c1 и еще 32 в C1):
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 минут до примерно секунды. В результате первая строка выходных данных становится общим мусором (как и общие итоги), но если итог уже известен из OEIS, число асимметричных значений может быть восстановлено, по крайней мере, для нечетного N.
Но даже для N число асимметричных (в соответствии с c3v-симметриями) тел, которые являются самодополняемыми, будет потеряно. Для этого случая может быть полезна отдельная программа, посвященная твердым телам с точно (N ** 3) / 2 ячейками с 1. Имея это в наличии (и считая правильно), можно попробовать N = 6, но для запуска потребуется много времени.
Реализовать подсчет ячеек, чтобы сократить количество запросов до (N ^ 3) / 2 кубов.
Не сделано, сбережения, как ожидается, будут незначительными
Реализуйте проверку симметрии (дополняющее тело) для шаблонов, содержащих ровно (N ^ 3) / 2 куба.
Готово, но, похоже, есть пропуски, см. N = 4.
Найдите способ выбрать лексически низкую фигуру из асимметричной.
Ожидается, что сбережения не будут такими большими. Подавление асимметричных фигур устраняет большинство из этого. Единственное отражение, которое проверяется, - это плоскость, проходящая через ось y (x и z вычисляются позже путем умножения на 3.) Фигуры только с симметрией вращения учитываются в обеих их энантиомерных формах. Возможно, он будет работать почти вдвое быстрее, если считать только один.
Чтобы облегчить это, возможно, улучшите способ перечисления координат в каждом слое (они образуют вырожденные группы из 6 или 3, возможно, с группой 1 в точном центре слоя).
Интересно, но, вероятно, есть другие вопросы на сайте для изучения.
N = 6
выдает результат более 10 ^ 12, неконструктивное решение почти наверняка необходимо для достижения этой цели.