include #define MAX_N 30 int n; int v[MAX_N]; void fill(int e, int max, int i); int main(int argc, char *argv[]) { for (n = 12; n < MAX_N; n++) { int e = n - 12; for (int i = 0; i < n; i++) v[i] = 0; int m = e < 5 ? e : 5; for (int a = m; a >= 0; a--) { v[0] = a; fill(e - a, a, 1); } } return 0; } void check_unique(); void fill(int e, int max, int i) { if (e == 0 || i == n) { if (i < n) check_unique(); return; } if (e > max * (n - i)) return; int m = e < max ? e : max; for (int a = m; a >= 0; a--) { v[i] = a; fill(e - a, max, i+1); } } void check_closed(); void check_unique() { bool greater = true; for (int s = 1; s < n && greater; s++) { int c = 0; for (int i = 0; i < n && c == 0; i++) c = v[i] - v[(i + s)%n]; if (c < 0) greater = false; } for (int s = 0; s < n && greater; s++) { int c = 0; for (int i = 0; i < n && c == 0; i++) c = v[i] - v[(n - i + s)%n]; if (c < 0) greater = false; } if (greater) check_closed(); } struct { int at; int v; } vec_dir[12] = { { 0, 1 }, { 3, 1 }, { 1, -1 }, { 4, -1 }, { 2, 1 }, { 5, 1 }, { 0, -1 }, { 3, -1 }, { 1, 1 }, { 4, 1 }, { 2, -1 }, { 5, -1 }, }; void check_inside_border(); void check_closed() { int dir = 0; int pos[6] = { 0, 0, 0, 0, 0, 0 }; for (int i = 0; i < n; i++) { pos[vec_dir[dir].at] += vec_dir[dir].v; dir = (dir + v[i] + 11) % 12; } if ( pos[0] == pos[1] && pos[1] == pos[2] && pos[3] == pos[4] && pos[4] == pos[5]) check_inside_border(); } void find_inside_ords(int i, int v); void check_inside_border() { bool ord = 0; bool poss = false; for (int i = 0; i < n && !poss; i++) if (v[i] == 3 || v[i] == 5) poss = true; else if (v[i] == 0 || v[i] == 2) ord = 1 - ord; if (poss || ord == 0) find_inside_ords(0, 0); } int kind[MAX_N]; bool filter(); int count_fill_inside(int ord); void find_inside_ords(int i, int ord) { for (; i < n; i++) { kind[i] = ord; if (v[i] == 3 || v[i] == 5) { find_inside_ords(i + 1, 0); find_inside_ords(i + 1, 1); return; } if (v[i] == 0 || v[i] == 2) ord = 1 - ord; } if (ord == 0) { for (int j = 0; j < n; j++) printf("%c %d ", kind[j] ? 's' : 't', v[j]); printf("\n"); int nr_0 = count_fill_inside(0); int nr_1 = count_fill_inside(1); if (nr_0 > 0 && nr_1 > 0 && filter()) { //printf("%s %d %d: ", nr_0 > 0 && nr_1 > 0 ? "Found" : "Skipped", nr_0, nr_1); char c = '['; for (int j = 0; j < n; j++) { printf("%c%d", c, v[j]); c = ','; } printf("],\n"); } } } #define MAX_M (3*MAX_N) int count_fill_remain(int *pattern, int len); int count_fill_inside(int ord) { int pattern[MAX_M]; for (int i = 0; i < n; i++) pattern[i] = v[i] + 5; int len = n; printf("Init: "); for (int i = 0; i < len; i++) printf(" %d", pattern[i]); printf("\n"); for (int i = n - 1; i >= 0; i--) { if (kind[(i + 1) % n] == ord) { // add square printf("Add sq: "); pattern[i] -= 3; pattern[(i + 1) % len] -= 3; if (i + 2 < len && pattern[i + 1] == 0) { pattern[i + 2] = (9 + pattern[i + 2]) % 12; pattern[i + 1] = 9; } else { for (int j = len - 1; j > i; j--) pattern[j + 2] = pattern[j]; len += 2; pattern[i + 1] = 9; pattern[i + 2] = 9; } } else { // add triangle printf("Add tr: "); pattern[i] -= 2; pattern[(i + 1) % len] -= 2; if (i + 2 < len && pattern[i + 1] == 0) { pattern[i + 1] = (10 + pattern[i + 2]) % 12; len--; for (int j = i + 2; j < len; j++) pattern[j] = pattern[j + 1]; } else { for (int j = len - 1; j > i; j--) pattern[j + 1] = pattern[j]; len += 1; pattern[i + 1] = 10; } } //printf("init: "); for (int i = 0; i < len; i++) printf(" %d", pattern[i]); printf("\n"); } if (pattern[0] == 0) { pattern[0] = (pattern[1] + pattern[len - 1]) % 12; len -= 2; for (int j = 1; j < len; j++) pattern[j] = pattern[j + 1]; } printf("Last: "); for (int i = 0; i < len; i++) printf(" %d", pattern[i]); printf("\n"); return count_fill_remain(pattern, len); } int count_fill_remain(int *pattern, int len) { for (;;) { if (len == 3) return pattern[0] == 2 && pattern[1] == 2 && pattern[3] == 2 ? 1 : 0; if (len == 4 && pattern[0] == 3 && pattern[1] == 3 && pattern[2] == 3 && pattern[3] == 3) return 1; int smallest = pattern[0]; int min_i = 0; for (int i = 0; i < len && smallest > 0; i++) if (pattern[i] == 1) { printf("impossible\n"); return 0; } else if (pattern[i] < smallest) { smallest = pattern[i]; min_i = i; } while (min_i == 0) { printf("rot\n"); int last = pattern[len - 1]; for (int j = len - 1; j > 0; j--) pattern[j] = pattern[j - 1]; pattern[0] = last; min_i = 1; } printf("%d %d ", min_i, smallest); int next_i = (min_i + 1) % len; if (smallest == 0) { printf("zero: "); pattern[next_i] = (pattern[min_i - 1] + pattern[next_i]) % 12; len -= 2; for (int j = min_i - 1; j < len; j++) pattern[j] = pattern[j + 2]; } else if (smallest == 2) { printf("tri: "); int next_i = (min_i + 1) % len; pattern[min_i - 1] -= 2; pattern[next_i] -= 2; len--; for (int j = min_i; j < len; j++) pattern[j] = pattern[j + 1]; } else if (smallest == 3) { printf("sq: "); pattern[min_i - 1] -= 3; pattern[next_i] -= 3; pattern[min_i] = 9; } else if (smallest == 4) { printf("2tri: "); pattern[min_i - 1] -= 2; pattern[next_i] -= 2; pattern[min_i] = 8; } else if (smallest == 5) { printf("split\n"); int sum = 0; int s_pattern[MAX_M]; for (int j = 0; j < len; j++) s_pattern[j] = pattern[j]; s_pattern[min_i - 1] -= 2; s_pattern[next_i] -= 3; s_pattern[min_i] = 7; sum += count_fill_remain(s_pattern, len); for (int j = 0; j < len; j++) s_pattern[j] = pattern[j]; s_pattern[min_i - 1] -= 3; s_pattern[next_i] -= 2; s_pattern[min_i] = 7; sum += count_fill_remain(s_pattern, len); return sum; } else { printf("Impossible\n"); return 0; } for (int i = 0; i < len; i++) printf(" %d", pattern[i]); printf("\n"); } return 0; } bool filter() { return true; /* int nr_at_least_3 = 0; for (int i = 0; i < n; i++) if (v[i] >= 3) nr_at_least_3++; return nr_at_least_3 >= 2; */ }