Advertisement
Guest User

kakuro.c

a guest
Aug 7th, 2015
407
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.33 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdbool.h>
  4.  
  5. typedef struct constraint {
  6.     struct constraint *next;
  7.     int sum;
  8.     unsigned count;
  9.     unsigned index[];
  10. } constraint;
  11.  
  12. typedef struct kakuro {
  13.     unsigned width;
  14.     unsigned height;
  15.     constraint *constraints;
  16.     int cell[];
  17. } kakuro;
  18.  
  19. static kakuro *
  20. kakuro_load(FILE *in)
  21. {
  22.     char line[1024];
  23.     unsigned width, height;
  24.     fgets(line, sizeof(line), in);
  25.     sscanf(line, "%u %u", &width, &height);
  26.     kakuro *k = malloc(sizeof(*k) + sizeof(k->cell[0]) * width * height);
  27.     k->width = width;
  28.     k->height = height;
  29.     k->constraints = NULL;
  30.     for (unsigned i = 0; i < width * height; i++)
  31.         k->cell[i] = -1;
  32.     /* Read in each constraint. */
  33.     while (fgets(line, sizeof(line), in)) {
  34.         unsigned count = 0;
  35.         for (char *p = line; *p; p++)
  36.             if (*p == ' ')
  37.                 count++;
  38.         constraint *c = malloc(sizeof(*c) + sizeof(c->index[0]) * count);
  39.         c->next = k->constraints;
  40.         c->count = count;
  41.         char *p;
  42.         c->sum = strtol(line, &p, 10);
  43.         for (unsigned i = 0; i < count; i++) {
  44.             unsigned x = p[1] - 'A';
  45.             unsigned y = strtol(p + 2, &p, 10) - 1;
  46.             unsigned index = y * width + x;
  47.             c->index[i] = index;
  48.             k->cell[index] = 0;
  49.         }
  50.         k->constraints = c;
  51.     }
  52.     return k;
  53. }
  54.  
  55. static void
  56. kakuro_free(kakuro *k)
  57. {
  58.     while (k->constraints) {
  59.         constraint *dead = k->constraints;
  60.         k->constraints = dead->next;
  61.         free(dead);
  62.     }
  63.     free(k);
  64. }
  65.  
  66. static bool
  67. kakuro_is_valid(const kakuro *k)
  68. {
  69.     for (constraint *c = k->constraints; c; c = c->next) {
  70.         int sum = 0;
  71.         int set[10] = {1};
  72.         for (unsigned j = 0; j < c->count; j++) {
  73.             int value = k->cell[c->index[j]];
  74.             if (set[value])
  75.                 return false;
  76.             set[value] = 1;
  77.             sum += value;
  78.         }
  79.         if (sum != c->sum)
  80.             return false;
  81.     }
  82.     return true;
  83. }
  84.  
  85. static void
  86. kakuro_solve(kakuro *k, unsigned cell, void(*cb)(kakuro *, void *), void *arg)
  87. {
  88.     if (cell >= k->width * k->height) {
  89.         if (kakuro_is_valid(k))
  90.             cb(k, arg);
  91.     } else if (k->cell[cell] < 0) {
  92.         kakuro_solve(k, cell + 1, cb, arg); // skip
  93.     } else {
  94.         for (int i = 1; i < 9; i++) {
  95.             k->cell[cell] = i;
  96.             kakuro_solve(k, cell + 1, cb, arg);
  97.         }
  98.         k->cell[cell] = 0;
  99.     }
  100. }
  101.  
  102. static void
  103. kakuro_draw(const kakuro *k, FILE *out)
  104. {
  105.     /* Initialize grid */
  106.     int grid[k->width + 1][k->height + 1][2];
  107.     for (unsigned y = 0; y < k->height + 1; y++)
  108.         for (unsigned x = 0; x < k->width + 1; x++)
  109.             grid[x][y][0] = grid[x][y][1] = -1;
  110.     /* Fill in constraints */
  111.     for (const constraint *c = k->constraints; c; c = c->next) {
  112.         for (unsigned i = 0; i < c->count; i++) {
  113.             unsigned x = c->index[i] % k->width;
  114.             unsigned y = c->index[i] / k->width;
  115.             grid[x + 1][y + 1][0] = 0;
  116.             grid[x + 1][y + 1][1] = 0;
  117.         }
  118.         unsigned x0 = c->index[0] % k->width;
  119.         unsigned y0 = c->index[0] / k->width;
  120.         unsigned x1 = c->index[1] % k->width;
  121.         if (x0 == x1)
  122.             grid[x0 + 1][y0][1] = c->sum;
  123.         else
  124.             grid[x0][y0 + 1][0] = c->sum;
  125.     }
  126.  
  127.     unsigned cellsize = 100;
  128.     fprintf(out, "<svg width='%u' height='%u'>\n",
  129.             (k->width + 1) * cellsize, (k->height + 1) * cellsize);
  130.     /* Place triangles/squares */
  131.     for (unsigned y = 0; y < k->height + 1; y++)
  132.         for (unsigned x = 0; x < k->width + 1; x++) {
  133.             if (grid[x][y][0] == 0 && grid[x][y][1] == 0) {
  134.                 fprintf(out, "<rect x='%u' y='%u' width='%u' height='%u' "
  135.                         "style='fill: white; stroke: black'/>\n",
  136.                         x * cellsize, y * cellsize,
  137.                         cellsize, cellsize);
  138.             } else {
  139.                 for (int s = 0; s < 2; s++) {
  140.                     const char *style;
  141.                     if (grid[x][y][s] == -1) {
  142.                         style = "fill: black; stroke: black";
  143.                     } else {
  144.                         style = "fill: white; stroke: black";
  145.                     }
  146.                     fprintf(out,
  147.                             "<polygon points='%u,%u %u,%u %u,%u' "
  148.                             "style='%s'/>\n",
  149.                             (x + 0) * cellsize, (y + 0) * cellsize,
  150.                             (x + 1 - s) * cellsize, (y + s * 1) * cellsize,
  151.                             (x + 1) * cellsize, (y + 1) * cellsize,
  152.                             style);
  153.                 }
  154.             }
  155.         }
  156.     /* Place text labels */
  157.     for (unsigned y = 0; y < k->height + 1; y++)
  158.         for (unsigned x = 0; x < k->width + 1; x++) {
  159.             unsigned i = (y - 1) * k->width + (x - 1);
  160.             if (x > 0 && y > 0 && k->cell[i] > 0) {
  161.                 fprintf(out, "<text x='%u' y='%u' "
  162.                         "style='font-size: %u; "
  163.                                "fill: darkred; "
  164.                                "font-family: sans-serif' "
  165.                         "text-anchor='middle'>%u</text>\n",
  166.                         x * cellsize + cellsize / 2,
  167.                         (y + 1) * cellsize - cellsize / 4,
  168.                         2 * cellsize / 3,
  169.                         k->cell[i]);
  170.             }
  171.             for (int s = 0; s < 2; s++) {
  172.                 if (grid[x][y][s] > 0) {
  173.                     fprintf(out, "<text x='%u' y='%u' "
  174.                             "style='font-size: %upx; font-family: sans-serif' "
  175.                             "text-anchor='%s'>%u</text>",
  176.                             x * cellsize +
  177.                               (s ? (cellsize / 10) : cellsize - cellsize / 10),
  178.                             (y + 1) * cellsize -
  179.                               (s ? cellsize / 10 : (2 * cellsize) / 3),
  180.                             cellsize / 3,
  181.                             s ? "start" : "end",
  182.                             grid[x][y][s]);
  183.                 }
  184.             }
  185.         }
  186.     fprintf(out, "</svg>\n");
  187. }
  188.  
  189. int
  190. main(void)
  191. {
  192.     kakuro *k = kakuro_load(stdin);
  193.     kakuro_solve(k, 0, (void *)kakuro_draw, stdout);
  194.     kakuro_free(k);
  195.     return 0;
  196. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement