Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <wchar.h>
- #include <errno.h>
- #define SHOW 1
- #define CLEAR 0
- #define LABELS 0
- int opt_show = SHOW;
- int opt_clear = CLEAR;
- int opt_labels = LABELS;
- typedef struct {
- int y; /* row */
- int x; /* col */
- int pips; /* -1 if empty, # of pips if not empty */
- char * group; /* name of group */
- int neighbors[4];
- int (*constraint)();
- } Square;
- typedef struct {
- int nA; /* # of pips on A end */
- int nB; /* # of pips on B end */
- int sA; /* where A end is placed (-1 if not placed) */
- int sB; /* where B end is placed (-1 if not placed) */
- } Tile;
- typedef struct {
- char * group;
- int y;
- int x;
- } Group_Base;
- char *** rows = 0;
- int solution_count = 0;
- int c_none();
- int c_0_1();
- int c_2_8();
- int c_3_9();
- int c_4_5_6_11_19_25();
- int c_7();
- int c_10();
- int c_12_13_14_15_16_17();
- int c_18_24();
- int c_20_21();
- int c_22_26();
- int c_23();
- int c_27_31();
- int c_28_29();
- Group_Base group_base[] = {
- {"12", 0, 1},
- {"6", 1, 6},
- {"4", 1, 7},
- {"=", 4, 1},
- {"0", 1, 5},
- {"0", 2, 0},
- {"=", 2, 7},
- {"=", 4, 0},
- {"=", 3, 4},
- {"5", 4, 6},
- {"0", 3, 7},
- {"=", 5, 7},
- {"12", 5, 1},
- };
- Square board[32] = {
- /* 0*/ {0, 0, -1, "A", { 1, 4, -1, -1}, c_0_1},
- /* 1*/ {0, 1, -1, "A", { 0, 5, -1, -1}, c_0_1},
- /* 2*/ {0, 6, -1, "B", { 3, 8, -1, -1}, c_2_8},
- /* 3*/ {0, 7, -1, "C", { 2, 9, -1, -1}, c_3_9},
- /* 4*/ {1, 0, -1, "D", { 0, 5, 10, -1}, c_4_5_6_11_19_25},
- /* 5*/ {1, 1, -1, "D", { 1, 4, 6, 11}, c_4_5_6_11_19_25},
- /* 6*/ {1, 2, -1, "D", { 5, 12, -1, -1}, c_4_5_6_11_19_25},
- /* 7*/ {1, 5, -1, "E", { 8, 15, -1, -1}, c_7},
- /* 8*/ {1, 6, -1, "B", { 2, 7, 9, 16}, c_2_8},
- /* 9*/ {1, 7, -1, "C", { 3, 8, 17, -1}, c_3_9},
- /*10*/ {2, 0, -1, "F", { 4, 11, 18, -1}, c_10},
- /*11*/ {2, 1, -1, "D", { 5, 10, 12, 19}, c_4_5_6_11_19_25},
- /*12*/ {2, 2, -1, "G", { 6, 11, 13, -1}, c_12_13_14_15_16_17},
- /*13*/ {2, 3, -1, "G", {12, 14, 20, -1}, c_12_13_14_15_16_17},
- /*14*/ {2, 4, -1, "G", {13, 15, 21, -1}, c_12_13_14_15_16_17},
- /*15*/ {2, 5, -1, "G", { 7, 14, 16, -1}, c_12_13_14_15_16_17},
- /*16*/ {2, 6, -1, "G", { 8, 15, 17, 22}, c_12_13_14_15_16_17},
- /*17*/ {2, 7, -1, "G", { 9, 16, 23, -1}, c_12_13_14_15_16_17},
- /*18*/ {3, 0, -1, "H", {10, 19, 24, -1}, c_18_24},
- /*19*/ {3, 1, -1, "D", {11, 18, 25, -1}, c_4_5_6_11_19_25},
- /*20*/ {3, 3, -1, "I", {13, 21, -1, -1}, c_20_21},
- /*21*/ {3, 4, -1, "I", {14, 20, -1, -1}, c_20_21},
- /*22*/ {3, 6, -1, "J", {16, 23, 26, -1}, c_22_26},
- /*23*/ {3, 7, -1, "K", {17, 22, 27, -1}, c_23},
- /*24*/ {4, 0, -1, "H", {18, 25, 28, -1}, c_18_24},
- /*25*/ {4, 1, -1, "D", {19, 24, 29, -1}, c_4_5_6_11_19_25},
- /*26*/ {4, 6, -1, "J", {22, 27, 30, -1}, c_22_26},
- /*27*/ {4, 7, -1, "L", {23, 26, 31, -1}, c_27_31},
- /*28*/ {5, 0, -1, "M", {24, 29, -1, -1}, c_28_29},
- /*29*/ {5, 1, -1, "M", {25, 28, -1, -1}, c_28_29},
- /*30*/ {5, 6, -1, " ", {26, 31, -1, -1}, c_none},
- /*31*/ {5, 7, -1, "L", {27, 30, -1, -1}, c_27_31},
- };
- #define ROWS 6
- #define COLS 8
- #define SQ0 board[0].pips
- #define SQ1 board[1].pips
- #define SQ2 board[2].pips
- #define SQ3 board[3].pips
- #define SQ4 board[4].pips
- #define SQ5 board[5].pips
- #define SQ6 board[6].pips
- #define SQ7 board[7].pips
- #define SQ8 board[8].pips
- #define SQ9 board[9].pips
- #define SQ10 board[10].pips
- #define SQ11 board[11].pips
- #define SQ12 board[12].pips
- #define SQ13 board[13].pips
- #define SQ14 board[14].pips
- #define SQ15 board[15].pips
- #define SQ16 board[16].pips
- #define SQ17 board[17].pips
- #define SQ18 board[18].pips
- #define SQ19 board[19].pips
- #define SQ20 board[20].pips
- #define SQ21 board[21].pips
- #define SQ22 board[22].pips
- #define SQ23 board[23].pips
- #define SQ24 board[24].pips
- #define SQ25 board[25].pips
- #define SQ26 board[26].pips
- #define SQ27 board[27].pips
- #define SQ28 board[28].pips
- #define SQ29 board[29].pips
- #define SQ30 board[30].pips
- #define SQ31 board[31].pips
- int c_none()
- {
- return 1;
- }
- int c_0_1()
- {
- if (SQ0 == -1 || SQ1 == -1) return 1;
- if (SQ0 + SQ1 == 12) return 1;
- else return 0;
- }
- int c_2_8()
- {
- if (SQ2 == -1 || SQ8 == -1) return 1;
- if (SQ2 + SQ8 == 6) return 1;
- else return 0;
- }
- int c_3_9()
- {
- if (SQ3 == -1 || SQ9 == -1) return 1;
- if (SQ3 + SQ9 == 4) return 1;
- else return 0;
- }
- int c_4_5_6_11_19_25()
- {
- if (SQ4 == -1 || SQ5 == -1 || SQ6 == -1 || SQ11 == -1 || SQ19 == -1 || SQ25 == -1) return 1;
- if (SQ4 == SQ5 && SQ4 == SQ6 && SQ4 == SQ11 && SQ4 == SQ19 && SQ4 == SQ25) return 1;
- else return 0;
- }
- int c_7()
- {
- if (SQ7 == -1) return 1;
- if (SQ7 == 0) return 1;
- else return 0;
- }
- int c_10()
- {
- if (SQ10 == -1) return 1;
- if (SQ10 == 0) return 1;
- else return 0;
- }
- int c_12_13_14_15_16_17()
- {
- if (SQ12 == -1 || SQ13 == -1 || SQ14 == -1 || SQ15 == -1 || SQ16 == -1 || SQ17 == -1) return 1;
- if (SQ12 == SQ13 && SQ12 == SQ14 && SQ12 == SQ15 && SQ12 == SQ16 && SQ12 == SQ17) return 1;
- else return 0;
- }
- int c_18_24()
- {
- if (SQ18 == -1 || SQ24 == -1) return 1;
- if (SQ18 == SQ24) return 1;
- else return 0;
- }
- int c_20_21()
- {
- if (SQ20 == -1 || SQ21 == -1) return 1;
- if (SQ20 == SQ21) return 1;
- else return 0;
- }
- int c_22_26()
- {
- if (SQ22 == -1 || SQ26 == -1) return 1;
- if (SQ22 + SQ26 == 5) return 1;
- else return 0;
- }
- int c_23()
- {
- if (SQ23 == -1) return 1;
- if (SQ23 == 0) return 1;
- else return 0;
- }
- int c_27_31()
- {
- if (SQ27 == -1 || SQ31 == -1) return 1;
- if (SQ27 == SQ31) return 1;
- else return 0;
- }
- int c_28_29()
- {
- if (SQ28 == -1 || SQ29 == -1) return 1;
- if (SQ28 + SQ29 == 12) return 1;
- else return 0;
- }
- Tile tiles[16] = {
- {2, 2, -1, -1},
- {1, 2, -1, -1},
- {4, 4, -1, -1},
- {4, 0, -1, -1},
- {0, 5, -1, -1},
- {3, 5, -1, -1},
- {6, 6, -1, -1},
- {3, 0, -1, -1},
- {3, 2, -1, -1},
- {2, 5, -1, -1},
- {4, 3, -1, -1},
- {3, 6, -1, -1},
- {5, 4, -1, -1},
- {3, 1, -1, -1},
- {4, 6, -1, -1},
- {5, 5, -1, -1},
- };
- void show_tiles_graphic(void);
- void show_tiles_text(void);
- int place(char * lp, char * cp, int pos);
- void solve(int depth);
- void draw_square(int y, int x, int pips, int up);
- void erase_line(int py, int px, int dy, int dx, int n, char * what);
- void draw_tile(int y, int x, int pips1, int pips2,
- char * g1, char * g2, int dir);
- void label_square(int y, int x, char * label);
- int main(int argc, char *argv[]) {
- for (int i = 1; i < argc; ++i) {
- if (strcmp(argv[i], "-c") == 0) { opt_clear = 1; }
- if (strcmp(argv[i], "-l") == 0) { opt_labels = 1; }
- if (strcmp(argv[i], "-q") == 0) { opt_show = 0; }
- }
- solve(0);
- printf("Solutions: %d\n", solution_count);
- return 0;
- }
- #define TL "┌"
- #define TR "┐"
- #define BL "└"
- #define BR "┘"
- #define TT "┬"
- #define BT "┴"
- #define LT "├"
- #define RT "┤"
- #define HL "─"
- #define VL "│"
- #define CC "┼"
- #define PIP "◎";
- #define SQ_X 7
- #define SQ_Y 3
- #define PIX_X ((SQ_X+1)*COLS+1)
- #define PIX_Y ((SQ_Y+1)*ROWS+1)
- #define PX 2
- #define PY 1
- void show_tiles_text(void)
- {
- char * sep = "";
- for (int t = 0; t < sizeof tiles / sizeof(Tile); ++t) {
- printf("%s%d/%d(%d,%d)", sep, tiles[t].nA, tiles[t].nB,
- tiles[t].sA, tiles[t].sB);
- sep = " ";
- }
- printf("\n");
- }
- void show_tiles_graphic(void)
- {
- static int inited = 0;
- printf("board is %d rows x %d cols\n", PIX_Y, PIX_X);
- if (! inited) rows = (char ***)malloc(PIX_Y * sizeof(char *));
- for (int i = 0; i < PIX_Y; ++i) {
- char ** line = inited ? rows[i] : (char **)malloc(PIX_X * sizeof(char *));
- for (int j = 0; j < PIX_X; ++j) {
- line[j] = " ";
- }
- rows[i] = line;
- }
- inited = 1;
- for (int t = 0; t < sizeof tiles / sizeof(Tile); ++t) {
- int dir = 0;
- int rA = board[tiles[t].sA].y;
- int cA = board[tiles[t].sA].x;
- int nA = tiles[t].nA;
- char * gA = board[tiles[t].sA].group;
- int rB = board[tiles[t].sB].y;
- int cB = board[tiles[t].sB].x;
- int nB = tiles[t].nB;
- char * gB = board[tiles[t].sB].group;
- if (rA > rB) dir = 0;
- else if (rA < rB) dir = 2;
- else if (cA < cB) dir = 3;
- else dir = 1;
- draw_tile(rA, cA, nA, nB, gA, gB, dir);
- }
- if (opt_labels) {
- for (int i = 0; i < sizeof group_base / sizeof(group_base[0]); ++i) {
- label_square(group_base[i].y, group_base[i].x, group_base[i].group);
- }
- }
- for (int i = 0; i < PIX_Y; ++i) {
- for (int j = 0; j < PIX_X; ++j) {
- printf("%s", rows[i][j]);
- }
- putchar('\n');
- }
- putchar('\n');
- if (opt_clear) {
- exit(0);
- }
- }
- void label_square(int y, int x, char * label)
- {
- int px = 1 + x * (SQ_X + 1);
- int py = 1 + y * (SQ_Y + 1);
- int n = strlen(label);
- if (n == 1) {
- rows[py + SQ_Y][px + SQ_X] = label;
- } else {
- for (int i = 0; i < n; ++i) {
- char * one = (char *)malloc(2); //TODO: when does this get freed?
- one[0] = label[i];
- one[1] = '\0';
- rows[py + SQ_Y][px + SQ_X + i] = one;
- }
- }
- }
- /* dir: 0 == up, 1 == left, 2 == down, 3 == right */
- void draw_tile(int y, int x, int pips1, int pips2,
- char * g1, char * g2, int dir)
- {
- if (opt_clear) {
- pips1 = pips2 = 0;
- }
- char * what = (strcmp(g1, g2) == 0) ? " " : ".";
- int px = 1 + x * (SQ_X + 1);
- int py = 1 + y * (SQ_Y + 1);
- draw_square(y, x, pips1, (dir == 0 || dir == 2) ? 1 : 0);
- switch (dir) {
- case 0: --y; break;
- case 1: --x; break;
- case 2: ++y; break;
- case 3: ++x; break;
- }
- int px2 = 1 + x * (SQ_X + 1);
- int py2 = 1 + y * (SQ_Y + 1);
- draw_square(y, x, pips2, (dir == 0 || dir == 2) ? 1 : 0);
- switch (dir) {
- case 0:
- erase_line(py-1, px, 0, 1, 7, what);
- break;
- case 1:
- erase_line(py, px-1, 1, 0, 3, what);
- break;
- case 2:
- erase_line(py2-1, px, 0, 1, 7, what);
- break;
- case 3:
- erase_line(py2, px2-1, 1, 0, 3, what);
- break;
- }
- }
- void erase_line(int py, int px, int dy, int dx, int n, char * what)
- {
- if (! opt_clear) {
- while (n-- > 0) {
- if (px > 0 && py > 0)
- rows[py][px] = what;
- else {
- printf("Internal error: out of bounds\n");
- exit(1);
- }
- py += dy;
- px += dx;
- }
- }
- }
- void draw_square(int y, int x, int pips, int up)
- {
- int i, j;
- x = 1 + x * (SQ_X + 1);
- y = 1 + y * (SQ_Y + 1);
- for (i = y; i < y+SQ_Y; ++i)
- for (j = x; j < x+SQ_X; ++j)
- rows[i][j] = " ";
- // frame top and bottom
- for (j = x; j < x+SQ_X; ++j) {
- rows[y-1][j] = HL;
- rows[y+SQ_Y][j] = HL;
- }
- // frame the sides
- for (i = y; i < y+SQ_Y; ++i) {
- rows[i][x-1] = VL;
- rows[i][x+SQ_X] = VL;
- }
- // corners
- rows[y-1][x-1] = TL;
- rows[y+SQ_Y][x-1] = BL;
- rows[y+SQ_Y][x+SQ_X] = BR;
- rows[y-1][x+SQ_X] = TR;
- x += 1;
- switch (pips) {
- case 1:
- rows[y+PY][x+PX] = PIP;
- break;
- case 2:
- if (up) {
- rows[y][x] = PIP;
- rows[y+2*PY][x+2*PX] = PIP;
- } else {
- rows[y][x+2*PX] = PIP;
- rows[y+2*PY][x] = PIP;
- }
- break;
- case 3:
- rows[y+PY][x+PX] = PIP;
- if (up) {
- rows[y][x] = PIP;
- rows[y+2*PY][x+2*PX] = PIP;
- } else {
- rows[y][x+2*PX] = PIP;
- rows[y+2*PY][x] = PIP;
- }
- break;
- case 4:
- rows[y][x] = PIP;
- rows[y+2*PY][x] = PIP;
- rows[y][x+2*PX] = PIP;
- rows[y+2*PY][x+2*PX] = PIP;
- break;
- case 5:
- rows[y+PY][x+PX] = PIP;
- rows[y][x] = PIP;
- rows[y+2*PY][x] = PIP;
- rows[y][x+2*PX] = PIP;
- rows[y+2*PY][x+2*PX] = PIP;
- break;
- case 6:
- if (up) {
- rows[y][x] = PIP;
- rows[y+PY][x] = PIP;
- rows[y+2*PY][x] = PIP;
- rows[y][x+2*PX] = PIP;
- rows[y+PY][x+2*PX] = PIP;
- rows[y+2*PY][x+2*PX] = PIP;
- } else {
- rows[y][x] = PIP;
- rows[y][x+PX] = PIP;
- rows[y][x+2*PX] = PIP;
- rows[y+2*PY][x] = PIP;
- rows[y+2*PY][x+PX] = PIP;
- rows[y+2*PY][x+2*PX] = PIP;
- }
- break;
- }
- }
- void indent(int depth)
- {
- if (depth > 0) {
- for (int i = 0; i < 2*depth; ++i) putchar('_');
- }
- }
- void solve(int depth)
- {
- int sq;
- int i;
- int t;
- /* find an empty square */
- sq = sizeof board / sizeof(Square);
- while (--sq >= 0) {
- if (board[sq].pips == -1) break;
- }
- if ( sq < 0) {
- ++solution_count;
- if (opt_show) {
- show_tiles_graphic();
- show_tiles_text();
- }
- return;
- }
- for (i = 0; i < 4; ++i) {
- int ad = board[sq].neighbors[i];
- if (ad >= 0 && board[ad].pips == -1) {
- for (t = 0; t < sizeof tiles / sizeof(Tile); ++t) {
- if (tiles[t].sA != -1) continue;
- board[sq].pips = tiles[t].nA;
- board[ad].pips = tiles[t].nB;
- tiles[t].sA = sq;
- tiles[t].sB = ad;
- //indent(depth); printf("Try %d%d on %d/%d\n", board[sq].pips, board[ad].pips, sq, ad);
- if ((*board[sq].constraint)() && (*board[ad].constraint)()) {
- solve(depth+1);
- }
- if (tiles[t].nA != tiles[t].nB) {
- board[sq].pips = tiles[t].nB;
- board[ad].pips = tiles[t].nA;
- tiles[t].sB = sq;
- tiles[t].sA = ad;
- //indent(depth); printf("Try %d%d on %d/%d\n", board[sq].pips, board[ad].pips, sq, ad);
- if ((*board[sq].constraint)() && (*board[ad].constraint)()) {
- solve(depth+1);
- }
- }
- board[sq].pips = -1;
- board[ad].pips = -1;
- tiles[t].sA = -1;
- tiles[t].sB = -1;
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment