/* c60 puzzle solver */ /*(c) Melange Corporation */ #include int try_count; /* 大域座標は図で示した大域番号のこと */ /* 局所座標と大域座標の変換テーブル 中心からみて反時計周りに */ int lgmap[12][26] = { /* 五角形[0] */ /* 各々の列の最初は距離0つまり自分の位置 */ {0, 1, 2, 3, 4, 5, /* 距離0-1のところに6個 */ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 距離2のところに10個 */ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}, /* 距離3のところに10個 */ /* 五角形[1] */ {6, 2, 1, 15, 16, 7, /* 6p on 1st circle */ 0, 5, 14, 24, 25, 26, 17, 18, 8, 3, /* 10p on 2nd circle */ 4, 12, 13, 23, 30, 31, 27, 19, 9, 10}, /* 10p on 3rd circle */ /* 五角形[2] */ {8, 3, 2, 7, 18, 9, /* 6p on 1st circle */ 0, 1, 6, 16, 17, 27, 19, 20, 10, 4, /* 10p on 2nd circle */ 5, 14, 15, 25, 26, 31, 28, 21, 11, 12}, /* 10p on 3rd circle */ /* 五角形[3] */ {10, 4, 3, 9, 20, 11, /* 6p on 1st circle */ 0, 2, 8, 18, 19, 28, 21, 22, 12, 5, /* 10p on 2nd circle */ 1, 6, 7, 17, 27, 31, 29, 23, 13, 14}, /* 10p on 3rd circle */ /* 五角形[4] */ {12, 5, 4, 11, 22, 13, /* 6p on 1st circle */ 0, 3, 10, 20, 21, 29, 23, 24, 14, 1, /* 10p on 2nd circle */ 2, 8, 9, 19, 28, 31, 30, 25, 15, 6 }, /* 10p on 3rd circle */ /* 五角形[5] */ {14, 1, 5, 13, 24, 15, /* 6p on 1st circle */ 0, 4, 12, 22, 23, 30, 25, 16, 6, 2, /* 10p on 2nd circle */ 3, 10, 11, 21, 29, 31, 26, 17, 7, 8}, /* 10p on 3rd circle */ /* 五角形[6] */ {21, 28, 29, 22, 11, 20, /* 6p on 1st circle */ 31, 30, 23, 13, 12, 4, 10, 9, 19, 27, /* 10p on 2nd circle */ 26, 17, 18, 8, 3, 0, 5, 14, 24, 25 }, /* 10p on 3rd circle */ /* 五角形[7] */ {23, 29, 30, 24, 13, 22, /* 6p on 1st circle */ 31, 26, 25, 15, 14, 5, 12, 11, 21, 28, /* 10p on 2nd circle */ 27, 19, 20, 10, 4, 0, 1, 6, 16, 17 }, /* 10p on 3rd circle */ /* 五角形[8] */ {25, 30, 26, 16, 15, 24, /* 6p on 1st circle */ 31, 27, 17, 7, 6, 1, 14, 13, 23, 29, /* 10p on 2nd circle */ 28, 21, 22, 12, 5, 0, 2, 8, 18, 19}, /* 10p on 3rd circle */ /* 五角形[9] */ {17, 26, 27, 18, 7, 16, /* 6p on 1st circle */ 31, 28, 19, 9, 8, 2, 6, 15, 25, 30, /* 10p on 2nd circle */ 29, 23, 24, 14, 1, 0, 3, 10, 20, 21 }, /* 10p on 3rd circle */ /* 五角形[10] */ {19, 27, 28, 20, 9, 18, /* 6p on 1st circle */ 31, 29, 21, 11, 10, 3, 8, 7, 17, 26, /* 10p on 2nd circle */ 30, 25, 16, 6, 2, 0, 4, 12, 22, 23 }, /* 10p on 3rd circle */ /* 五角形[11] */ {31, 29, 30, 26, 27, 28, /* 6p on 1st circle */ 21, 22, 23, 24, 25, 16, 17, 18, 19, 20, /* 10p on 2nd circle */ 11, 12, 13, 14, 15, 6, 7, 8, 9, 10}, /* 10p on 3rd circle */ }; /* ピース番号から名前への変換テーブル(0から始まる) */ char itoname[10]={'a', 'b', 'c', 'd', 'e', 'f', 'g', 'k', 'l', 'm'}; /* ピースの形状 (0を省略してあるが、それを含む形状として */ /* 10はピースの数(対称のものも含む)5は回転可能性(5角形を中心にしているので)3はピースが4つの */ /* n角形でできていることを示す */ int fill[10][5][3] = { /* alpha */ { {4, 11, 21}, {3, 9, 19}, {2, 7, 17}, {1, 15, 25}, {5, 13, 23}}, /* beta */ { {3, 4, 10}, {2, 3, 8}, {2, 1, 6}, {1, 5, 14}, {5, 4, 12}}, /* gamma */ { {1, 2, 4}, {1, 5, 3}, {5, 4, 2}, {4, 3, 1 }, {3, 2, 5}}, /* delta */ { {3, 4, 5}, {2, 3, 4}, {1, 2, 3}, { 5, 1, 2}, {4, 5, 1}}, /* epsilon */ { {4, 11, 20}, {3, 9, 18}, {2, 7, 16}, {1, 15, 24}, {5, 13, 22}}, /* nyu(1) */ { {4, 11, 10}, { 3, 9, 8}, {2, 7, 6}, {1, 15, 14}, {5, 13, 12}}, /* nyu(2) */ { {3, 4, 12}, { 2, 3, 10}, { 1, 2, 8}, {5, 1, 6}, {4, 5, 14}}, /* kai(1) */ { {4, 10, 20}, { 3, 8, 18}, { 2, 6, 16}, {1, 14, 24}, {5, 12, 22}}, /* kai(2) */ { {4, 1, 6}, {3, 5, 14}, {2, 4, 12}, {1, 3, 10}, {5, 2, 8}}, /* myu */ { {4, 11, 5}, { 3, 9, 4}, {2, 7, 3}, {1, 15, 2}, {5, 13, 1}}, }; int remain[33]; /* LOCAL==> GLOBALテーブルがバグっていないか検査する */ /* これが間違っていると意味がないのデバッグが終わったらいらない */ void check_lg_table() { int i, j, k; /* 12 は五角形の個数 */ for (i = 0; i < 12; i++) { for (k = 0; k < 32; k++) { remain[k] = 1; /* true */ /* まだどの場所も埋まっていない */ } for (j = 0; j < 26; j++) { remain[lgmap[i][j]] = 0; /* false */ for (k = 0; k < 26; k++) { if (j == k) continue; if (lgmap[i][j] == lgmap[i][k]) { printf("lgmap error: at %d %d %d\n", i, j, k); } } } printf("%d-th coord excludes: ", i); for (k = 0; k < 32; k++) { if (remain[k]) printf("%d ", k); } printf("\n"); } } #define BLANK ' ' char g[32]; char gn[32]; /* 0から31までの位置にどのピース(名前で)が入っているのかを示す */ int used[10];/* 0から9までのピースが使われてるか否か */ int seq_no; display() { int i; printf("%d: ", seq_no); for (i = 0; i < 32; i++) printf("%c ", gn[i]); printf("\n"); } init() { int i; for (i = 0; i < 32; i++) gn[i] = BLANK; /* 最初からこの位置にηを置く -- ここに置くと対象性について考える必要がなくなる */ #if 1 gn[16] = 'm'; gn[26] = 'm'; gn[30] = 'm'; gn[31] = 'm'; used[9] = 1; /* ηが使われたことを覚える */ #endif seq_no = 0; } void try(int i, int put_no ) { int L0, L1, L2, L3, g0, g1, g2, g3; int c; int j, k; try_count++; /* number of 5-angle on the surface */ for ( ;i < 10; i++) { if (gn[lgmap[i][0]] == BLANK) /* 5角形の空きが見つかった */ break; } if (i == 10) /* nothing to do */ return; /* iの位置に置けるピースの個数は固定で置いている#9を除いて0..8までの9個 */ for (j = 0; j < 9; j++) { if (used[j]) continue; if (j == 5 && used[6]) /* どちらか一方の対称系を使っている場合にはもう一方の対称形を使ってはいけない */ continue; if (j == 6 && used[5]) /* f, and g(η) */ continue; if (j == 7 && used[8]) /* k and g (μ)*/ continue; if (j == 8 && used[7]) /* g and k (μ)*/ continue; /* 五角形の周りの回転群の要素をすべて調べる */ for (k = 0; k < 5; k++) { L0 = 0; /* ピースの局所座標は0基点 .. 5 角形 */ L1 = fill[j][k][0]; /* そのピースの次のn角形のローカル座標 */ L2 = fill[j][k][1]; L3 = fill[j][k][2]; g0 = lgmap[i][L0]; /* 本当は0にいるのではなく lgmap[i][0]を基点としているので大域座標を求める */ g1 = lgmap[i][L1]; g2 = lgmap[i][L2]; g3 = lgmap[i][L3]; if (gn[g0] == BLANK && gn[g1] == BLANK && gn[g2] == BLANK && gn[g3] == BLANK) { /* この大域座標の4つのn角形の位置は未使用である==>ここに置ける */ /* ピースを置いてみる */ c = itoname[j]; gn[g0] = gn[g1] = gn[g2] = gn[g3] = c; if (put_no != 6) { /* 実際には対象性を除くと8個しか置けない.. */ /* かつ1つは固定で置いてあるので0..6の7段階が可能で6以上にはいけない */ used[j] = 1; // if (gn[0] == 'a' && gn[1] == 'c') // if (put_no > 5) // display(); try(i+1, put_no + 1); used[j] = 0;  } else { seq_no++; display(); } gn[g0] = gn[g1] = gn[g2] = gn[g3] = BLANK; } /* end of if */ } /* end of k */ } /* end of j */ } main() { check_lg_table(); init(); try(0, 0); printf("%d tries\n", try_count); }