A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1#include <assert.h>
2#include <string.h>
3#include <stdarg.h>
4
5#include "puzzles.h"
6#include "tree234.h"
7#include "matching.h"
8
9#ifdef STANDALONE_LATIN_TEST
10#define STANDALONE_SOLVER
11#endif
12
13#include "latin.h"
14
15/* --------------------------------------------------------
16 * Solver.
17 */
18
19static int latin_solver_top(struct latin_solver *solver, int maxdiff,
20 int diff_simple, int diff_set_0, int diff_set_1,
21 int diff_forcing, int diff_recursive,
22 usersolver_t const *usersolvers, validator_t valid,
23 void *ctx, ctxnew_t ctxnew, ctxfree_t ctxfree);
24
25#ifdef STANDALONE_SOLVER
26int solver_show_working, solver_recurse_depth;
27#endif
28
29/*
30 * Function called when we are certain that a particular square has
31 * a particular number in it. The y-coordinate passed in here is
32 * transformed.
33 */
34void latin_solver_place(struct latin_solver *solver, int x, int y, int n)
35{
36 int i, o = solver->o;
37
38 assert(n <= o);
39 assert(cube(x,y,n));
40
41 /*
42 * Rule out all other numbers in this square.
43 */
44 for (i = 1; i <= o; i++)
45 if (i != n)
46 cube(x,y,i) = false;
47
48 /*
49 * Rule out this number in all other positions in the row.
50 */
51 for (i = 0; i < o; i++)
52 if (i != y)
53 cube(x,i,n) = false;
54
55 /*
56 * Rule out this number in all other positions in the column.
57 */
58 for (i = 0; i < o; i++)
59 if (i != x)
60 cube(i,y,n) = false;
61
62 /*
63 * Enter the number in the result grid.
64 */
65 solver->grid[y*o+x] = n;
66
67 /*
68 * Cross out this number from the list of numbers left to place
69 * in its row, its column and its block.
70 */
71 solver->row[y*o+n-1] = solver->col[x*o+n-1] = true;
72}
73
74int latin_solver_elim(struct latin_solver *solver, int start, int step
75#ifdef STANDALONE_SOLVER
76 , const char *fmt, ...
77#endif
78 )
79{
80 int o = solver->o;
81#ifdef STANDALONE_SOLVER
82 char **names = solver->names;
83#endif
84 int fpos, m, i;
85
86 /*
87 * Count the number of set bits within this section of the
88 * cube.
89 */
90 m = 0;
91 fpos = -1;
92 for (i = 0; i < o; i++)
93 if (solver->cube[start+i*step]) {
94 fpos = start+i*step;
95 m++;
96 }
97
98 if (m == 1) {
99 int x, y, n;
100 assert(fpos >= 0);
101
102 n = 1 + fpos % o;
103 y = fpos / o;
104 x = y / o;
105 y %= o;
106
107 if (!solver->grid[y*o+x]) {
108#ifdef STANDALONE_SOLVER
109 if (solver_show_working) {
110 va_list ap;
111 printf("%*s", solver_recurse_depth*4, "");
112 va_start(ap, fmt);
113 vprintf(fmt, ap);
114 va_end(ap);
115 printf(":\n%*s placing %s at (%d,%d)\n",
116 solver_recurse_depth*4, "", names[n-1],
117 x+1, y+1);
118 }
119#endif
120 latin_solver_place(solver, x, y, n);
121 return +1;
122 }
123 } else if (m == 0) {
124#ifdef STANDALONE_SOLVER
125 if (solver_show_working) {
126 va_list ap;
127 printf("%*s", solver_recurse_depth*4, "");
128 va_start(ap, fmt);
129 vprintf(fmt, ap);
130 va_end(ap);
131 printf(":\n%*s no possibilities available\n",
132 solver_recurse_depth*4, "");
133 }
134#endif
135 return -1;
136 }
137
138 return 0;
139}
140
141struct latin_solver_scratch {
142 unsigned char *grid, *rowidx, *colidx, *set;
143 int *neighbours, *bfsqueue;
144#ifdef STANDALONE_SOLVER
145 int *bfsprev;
146#endif
147};
148
149int latin_solver_set(struct latin_solver *solver,
150 struct latin_solver_scratch *scratch,
151 int start, int step1, int step2
152#ifdef STANDALONE_SOLVER
153 , const char *fmt, ...
154#endif
155 )
156{
157 int o = solver->o;
158#ifdef STANDALONE_SOLVER
159 char **names = solver->names;
160#endif
161 int i, j, n, count;
162 unsigned char *grid = scratch->grid;
163 unsigned char *rowidx = scratch->rowidx;
164 unsigned char *colidx = scratch->colidx;
165 unsigned char *set = scratch->set;
166
167 /*
168 * We are passed a o-by-o matrix of booleans. Our first job
169 * is to winnow it by finding any definite placements - i.e.
170 * any row with a solitary 1 - and discarding that row and the
171 * column containing the 1.
172 */
173 memset(rowidx, true, o);
174 memset(colidx, true, o);
175 for (i = 0; i < o; i++) {
176 int count = 0, first = -1;
177 for (j = 0; j < o; j++)
178 if (solver->cube[start+i*step1+j*step2])
179 first = j, count++;
180
181 if (count == 0) return -1;
182 if (count == 1)
183 rowidx[i] = colidx[first] = false;
184 }
185
186 /*
187 * Convert each of rowidx/colidx from a list of 0s and 1s to a
188 * list of the indices of the 1s.
189 */
190 for (i = j = 0; i < o; i++)
191 if (rowidx[i])
192 rowidx[j++] = i;
193 n = j;
194 for (i = j = 0; i < o; i++)
195 if (colidx[i])
196 colidx[j++] = i;
197 assert(n == j);
198
199 /*
200 * And create the smaller matrix.
201 */
202 for (i = 0; i < n; i++)
203 for (j = 0; j < n; j++)
204 grid[i*o+j] = solver->cube[start+rowidx[i]*step1+colidx[j]*step2];
205
206 /*
207 * Having done that, we now have a matrix in which every row
208 * has at least two 1s in. Now we search to see if we can find
209 * a rectangle of zeroes (in the set-theoretic sense of
210 * `rectangle', i.e. a subset of rows crossed with a subset of
211 * columns) whose width and height add up to n.
212 */
213
214 memset(set, 0, n);
215 count = 0;
216 while (1) {
217 /*
218 * We have a candidate set. If its size is <=1 or >=n-1
219 * then we move on immediately.
220 */
221 if (count > 1 && count < n-1) {
222 /*
223 * The number of rows we need is n-count. See if we can
224 * find that many rows which each have a zero in all
225 * the positions listed in `set'.
226 */
227 int rows = 0;
228 for (i = 0; i < n; i++) {
229 bool ok = true;
230 for (j = 0; j < n; j++)
231 if (set[j] && grid[i*o+j]) {
232 ok = false;
233 break;
234 }
235 if (ok)
236 rows++;
237 }
238
239 /*
240 * We expect never to be able to get _more_ than
241 * n-count suitable rows: this would imply that (for
242 * example) there are four numbers which between them
243 * have at most three possible positions, and hence it
244 * indicates a faulty deduction before this point or
245 * even a bogus clue.
246 */
247 if (rows > n - count) {
248#ifdef STANDALONE_SOLVER
249 if (solver_show_working) {
250 va_list ap;
251 printf("%*s", solver_recurse_depth*4,
252 "");
253 va_start(ap, fmt);
254 vprintf(fmt, ap);
255 va_end(ap);
256 printf(":\n%*s contradiction reached\n",
257 solver_recurse_depth*4, "");
258 }
259#endif
260 return -1;
261 }
262
263 if (rows >= n - count) {
264 bool progress = false;
265
266 /*
267 * We've got one! Now, for each row which _doesn't_
268 * satisfy the criterion, eliminate all its set
269 * bits in the positions _not_ listed in `set'.
270 * Return +1 (meaning progress has been made) if we
271 * successfully eliminated anything at all.
272 *
273 * This involves referring back through
274 * rowidx/colidx in order to work out which actual
275 * positions in the cube to meddle with.
276 */
277 for (i = 0; i < n; i++) {
278 bool ok = true;
279 for (j = 0; j < n; j++)
280 if (set[j] && grid[i*o+j]) {
281 ok = false;
282 break;
283 }
284 if (!ok) {
285 for (j = 0; j < n; j++)
286 if (!set[j] && grid[i*o+j]) {
287 int fpos = (start+rowidx[i]*step1+
288 colidx[j]*step2);
289#ifdef STANDALONE_SOLVER
290 if (solver_show_working) {
291 int px, py, pn;
292
293 if (!progress) {
294 va_list ap;
295 printf("%*s", solver_recurse_depth*4,
296 "");
297 va_start(ap, fmt);
298 vprintf(fmt, ap);
299 va_end(ap);
300 printf(":\n");
301 }
302
303 pn = 1 + fpos % o;
304 py = fpos / o;
305 px = py / o;
306 py %= o;
307
308 printf("%*s ruling out %s at (%d,%d)\n",
309 solver_recurse_depth*4, "",
310 names[pn-1], px+1, py+1);
311 }
312#endif
313 progress = true;
314 solver->cube[fpos] = false;
315 }
316 }
317 }
318
319 if (progress) {
320 return +1;
321 }
322 }
323 }
324
325 /*
326 * Binary increment: change the rightmost 0 to a 1, and
327 * change all 1s to the right of it to 0s.
328 */
329 i = n;
330 while (i > 0 && set[i-1])
331 set[--i] = 0, count--;
332 if (i > 0)
333 set[--i] = 1, count++;
334 else
335 break; /* done */
336 }
337
338 return 0;
339}
340
341/*
342 * Look for forcing chains. A forcing chain is a path of
343 * pairwise-exclusive squares (i.e. each pair of adjacent squares
344 * in the path are in the same row, column or block) with the
345 * following properties:
346 *
347 * (a) Each square on the path has precisely two possible numbers.
348 *
349 * (b) Each pair of squares which are adjacent on the path share
350 * at least one possible number in common.
351 *
352 * (c) Each square in the middle of the path shares _both_ of its
353 * numbers with at least one of its neighbours (not the same
354 * one with both neighbours).
355 *
356 * These together imply that at least one of the possible number
357 * choices at one end of the path forces _all_ the rest of the
358 * numbers along the path. In order to make real use of this, we
359 * need further properties:
360 *
361 * (c) Ruling out some number N from the square at one end
362 * of the path forces the square at the other end to
363 * take number N.
364 *
365 * (d) The two end squares are both in line with some third
366 * square.
367 *
368 * (e) That third square currently has N as a possibility.
369 *
370 * If we can find all of that lot, we can deduce that at least one
371 * of the two ends of the forcing chain has number N, and that
372 * therefore the mutually adjacent third square does not.
373 *
374 * To find forcing chains, we're going to start a bfs at each
375 * suitable square, once for each of its two possible numbers.
376 */
377int latin_solver_forcing(struct latin_solver *solver,
378 struct latin_solver_scratch *scratch)
379{
380 int o = solver->o;
381#ifdef STANDALONE_SOLVER
382 char **names = solver->names;
383#endif
384 int *bfsqueue = scratch->bfsqueue;
385#ifdef STANDALONE_SOLVER
386 int *bfsprev = scratch->bfsprev;
387#endif
388 unsigned char *number = scratch->grid;
389 int *neighbours = scratch->neighbours;
390 int x, y;
391
392 for (y = 0; y < o; y++)
393 for (x = 0; x < o; x++) {
394 int count, t, n;
395
396 /*
397 * If this square doesn't have exactly two candidate
398 * numbers, don't try it.
399 *
400 * In this loop we also sum the candidate numbers,
401 * which is a nasty hack to allow us to quickly find
402 * `the other one' (since we will shortly know there
403 * are exactly two).
404 */
405 for (count = t = 0, n = 1; n <= o; n++)
406 if (cube(x, y, n))
407 count++, t += n;
408 if (count != 2)
409 continue;
410
411 /*
412 * Now attempt a bfs for each candidate.
413 */
414 for (n = 1; n <= o; n++)
415 if (cube(x, y, n)) {
416 int orign, currn, head, tail;
417
418 /*
419 * Begin a bfs.
420 */
421 orign = n;
422
423 memset(number, o+1, o*o);
424 head = tail = 0;
425 bfsqueue[tail++] = y*o+x;
426#ifdef STANDALONE_SOLVER
427 bfsprev[y*o+x] = -1;
428#endif
429 number[y*o+x] = t - n;
430
431 while (head < tail) {
432 int xx, yy, nneighbours, xt, yt, i;
433
434 xx = bfsqueue[head++];
435 yy = xx / o;
436 xx %= o;
437
438 currn = number[yy*o+xx];
439
440 /*
441 * Find neighbours of yy,xx.
442 */
443 nneighbours = 0;
444 for (yt = 0; yt < o; yt++)
445 neighbours[nneighbours++] = yt*o+xx;
446 for (xt = 0; xt < o; xt++)
447 neighbours[nneighbours++] = yy*o+xt;
448
449 /*
450 * Try visiting each of those neighbours.
451 */
452 for (i = 0; i < nneighbours; i++) {
453 int cc, tt, nn;
454
455 xt = neighbours[i] % o;
456 yt = neighbours[i] / o;
457
458 /*
459 * We need this square to not be
460 * already visited, and to include
461 * currn as a possible number.
462 */
463 if (number[yt*o+xt] <= o)
464 continue;
465 if (!cube(xt, yt, currn))
466 continue;
467
468 /*
469 * Don't visit _this_ square a second
470 * time!
471 */
472 if (xt == xx && yt == yy)
473 continue;
474
475 /*
476 * To continue with the bfs, we need
477 * this square to have exactly two
478 * possible numbers.
479 */
480 for (cc = tt = 0, nn = 1; nn <= o; nn++)
481 if (cube(xt, yt, nn))
482 cc++, tt += nn;
483 if (cc == 2) {
484 bfsqueue[tail++] = yt*o+xt;
485#ifdef STANDALONE_SOLVER
486 bfsprev[yt*o+xt] = yy*o+xx;
487#endif
488 number[yt*o+xt] = tt - currn;
489 }
490
491 /*
492 * One other possibility is that this
493 * might be the square in which we can
494 * make a real deduction: if it's
495 * adjacent to x,y, and currn is equal
496 * to the original number we ruled out.
497 */
498 if (currn == orign &&
499 (xt == x || yt == y)) {
500#ifdef STANDALONE_SOLVER
501 if (solver_show_working) {
502 const char *sep = "";
503 int xl, yl;
504 printf("%*sforcing chain, %s at ends of ",
505 solver_recurse_depth*4, "",
506 names[orign-1]);
507 xl = xx;
508 yl = yy;
509 while (1) {
510 printf("%s(%d,%d)", sep, xl+1,
511 yl+1);
512 xl = bfsprev[yl*o+xl];
513 if (xl < 0)
514 break;
515 yl = xl / o;
516 xl %= o;
517 sep = "-";
518 }
519 printf("\n%*s ruling out %s at (%d,%d)\n",
520 solver_recurse_depth*4, "",
521 names[orign-1],
522 xt+1, yt+1);
523 }
524#endif
525 cube(xt, yt, orign) = false;
526 return 1;
527 }
528 }
529 }
530 }
531 }
532
533 return 0;
534}
535
536struct latin_solver_scratch *latin_solver_new_scratch(struct latin_solver *solver)
537{
538 struct latin_solver_scratch *scratch = snew(struct latin_solver_scratch);
539 int o = solver->o;
540 scratch->grid = snewn(o*o, unsigned char);
541 scratch->rowidx = snewn(o, unsigned char);
542 scratch->colidx = snewn(o, unsigned char);
543 scratch->set = snewn(o, unsigned char);
544 scratch->neighbours = snewn(3*o, int);
545 scratch->bfsqueue = snewn(o*o, int);
546#ifdef STANDALONE_SOLVER
547 scratch->bfsprev = snewn(o*o, int);
548#endif
549 return scratch;
550}
551
552void latin_solver_free_scratch(struct latin_solver_scratch *scratch)
553{
554#ifdef STANDALONE_SOLVER
555 sfree(scratch->bfsprev);
556#endif
557 sfree(scratch->bfsqueue);
558 sfree(scratch->neighbours);
559 sfree(scratch->set);
560 sfree(scratch->colidx);
561 sfree(scratch->rowidx);
562 sfree(scratch->grid);
563 sfree(scratch);
564}
565
566bool latin_solver_alloc(struct latin_solver *solver, digit *grid, int o)
567{
568 int x, y;
569
570 solver->o = o;
571 solver->cube = snewn(o*o*o, unsigned char);
572 solver->grid = grid; /* write straight back to the input */
573 memset(solver->cube, 1, o*o*o);
574
575 solver->row = snewn(o*o, unsigned char);
576 solver->col = snewn(o*o, unsigned char);
577 memset(solver->row, 0, o*o);
578 memset(solver->col, 0, o*o);
579
580#ifdef STANDALONE_SOLVER
581 solver->names = NULL;
582#endif
583
584 for (x = 0; x < o; x++) {
585 for (y = 0; y < o; y++) {
586 int n = grid[y*o+x];
587 if (n) {
588 if (cube(x, y, n))
589 latin_solver_place(solver, x, y, n);
590 else
591 return false; /* puzzle is already inconsistent */
592 }
593 }
594 }
595
596 return true;
597}
598
599void latin_solver_free(struct latin_solver *solver)
600{
601 sfree(solver->cube);
602 sfree(solver->row);
603 sfree(solver->col);
604}
605
606int latin_solver_diff_simple(struct latin_solver *solver)
607{
608 int x, y, n, ret, o = solver->o;
609#ifdef STANDALONE_SOLVER
610 char **names = solver->names;
611#endif
612
613 /*
614 * Row-wise positional elimination.
615 */
616 for (y = 0; y < o; y++)
617 for (n = 1; n <= o; n++)
618 if (!solver->row[y*o+n-1]) {
619 ret = latin_solver_elim(solver, cubepos(0,y,n), o*o
620#ifdef STANDALONE_SOLVER
621 , "positional elimination,"
622 " %s in row %d", names[n-1],
623 y+1
624#endif
625 );
626 if (ret != 0) return ret;
627 }
628 /*
629 * Column-wise positional elimination.
630 */
631 for (x = 0; x < o; x++)
632 for (n = 1; n <= o; n++)
633 if (!solver->col[x*o+n-1]) {
634 ret = latin_solver_elim(solver, cubepos(x,0,n), o
635#ifdef STANDALONE_SOLVER
636 , "positional elimination,"
637 " %s in column %d", names[n-1], x+1
638#endif
639 );
640 if (ret != 0) return ret;
641 }
642
643 /*
644 * Numeric elimination.
645 */
646 for (x = 0; x < o; x++)
647 for (y = 0; y < o; y++)
648 if (!solver->grid[y*o+x]) {
649 ret = latin_solver_elim(solver, cubepos(x,y,1), 1
650#ifdef STANDALONE_SOLVER
651 , "numeric elimination at (%d,%d)",
652 x+1, y+1
653#endif
654 );
655 if (ret != 0) return ret;
656 }
657 return 0;
658}
659
660int latin_solver_diff_set(struct latin_solver *solver,
661 struct latin_solver_scratch *scratch,
662 bool extreme)
663{
664 int x, y, n, ret, o = solver->o;
665#ifdef STANDALONE_SOLVER
666 char **names = solver->names;
667#endif
668
669 if (!extreme) {
670 /*
671 * Row-wise set elimination.
672 */
673 for (y = 0; y < o; y++) {
674 ret = latin_solver_set(solver, scratch, cubepos(0,y,1), o*o, 1
675#ifdef STANDALONE_SOLVER
676 , "set elimination, row %d", y+1
677#endif
678 );
679 if (ret != 0) return ret;
680 }
681 /*
682 * Column-wise set elimination.
683 */
684 for (x = 0; x < o; x++) {
685 ret = latin_solver_set(solver, scratch, cubepos(x,0,1), o, 1
686#ifdef STANDALONE_SOLVER
687 , "set elimination, column %d", x+1
688#endif
689 );
690 if (ret != 0) return ret;
691 }
692 } else {
693 /*
694 * Row-vs-column set elimination on a single number
695 * (much tricker for a human to do!)
696 */
697 for (n = 1; n <= o; n++) {
698 ret = latin_solver_set(solver, scratch, cubepos(0,0,n), o*o, o
699#ifdef STANDALONE_SOLVER
700 , "positional set elimination on %s",
701 names[n-1]
702#endif
703 );
704 if (ret != 0) return ret;
705 }
706 }
707 return 0;
708}
709
710/*
711 * Returns:
712 * 0 for 'didn't do anything' implying it was already solved.
713 * -1 for 'impossible' (no solution)
714 * 1 for 'single solution'
715 * >1 for 'multiple solutions' (you don't get to know how many, and
716 * the first such solution found will be set.
717 *
718 * and this function may well assert if given an impossible board.
719 */
720static int latin_solver_recurse
721 (struct latin_solver *solver, int diff_simple, int diff_set_0,
722 int diff_set_1, int diff_forcing, int diff_recursive,
723 usersolver_t const *usersolvers, validator_t valid, void *ctx,
724 ctxnew_t ctxnew, ctxfree_t ctxfree)
725{
726 int best, bestcount;
727 int o = solver->o, x, y, n;
728#ifdef STANDALONE_SOLVER
729 char **names = solver->names;
730#endif
731
732 best = -1;
733 bestcount = o+1;
734
735 for (y = 0; y < o; y++)
736 for (x = 0; x < o; x++)
737 if (!solver->grid[y*o+x]) {
738 int count;
739
740 /*
741 * An unfilled square. Count the number of
742 * possible digits in it.
743 */
744 count = 0;
745 for (n = 1; n <= o; n++)
746 if (cube(x,y,n))
747 count++;
748
749 /*
750 * We should have found any impossibilities
751 * already, so this can safely be an assert.
752 */
753 assert(count > 1);
754
755 if (count < bestcount) {
756 bestcount = count;
757 best = y*o+x;
758 }
759 }
760
761 if (best == -1)
762 /* we were complete already. */
763 return 0;
764 else {
765 int i, j;
766 digit *list, *ingrid, *outgrid;
767 int diff = diff_impossible; /* no solution found yet */
768
769 /*
770 * Attempt recursion.
771 */
772 y = best / o;
773 x = best % o;
774
775 list = snewn(o, digit);
776 ingrid = snewn(o*o, digit);
777 outgrid = snewn(o*o, digit);
778 memcpy(ingrid, solver->grid, o*o);
779
780 /* Make a list of the possible digits. */
781 for (j = 0, n = 1; n <= o; n++)
782 if (cube(x,y,n))
783 list[j++] = n;
784
785#ifdef STANDALONE_SOLVER
786 if (solver_show_working) {
787 const char *sep = "";
788 printf("%*srecursing on (%d,%d) [",
789 solver_recurse_depth*4, "", x+1, y+1);
790 for (i = 0; i < j; i++) {
791 printf("%s%s", sep, names[list[i]-1]);
792 sep = " or ";
793 }
794 printf("]\n");
795 }
796#endif
797
798 /*
799 * And step along the list, recursing back into the
800 * main solver at every stage.
801 */
802 for (i = 0; i < j; i++) {
803 int ret;
804 void *newctx;
805 struct latin_solver subsolver;
806
807 memcpy(outgrid, ingrid, o*o);
808 outgrid[y*o+x] = list[i];
809
810#ifdef STANDALONE_SOLVER
811 if (solver_show_working)
812 printf("%*sguessing %s at (%d,%d)\n",
813 solver_recurse_depth*4, "", names[list[i]-1], x+1, y+1);
814 solver_recurse_depth++;
815#endif
816
817 if (ctxnew) {
818 newctx = ctxnew(ctx);
819 } else {
820 newctx = ctx;
821 }
822 if (latin_solver_alloc(&subsolver, outgrid, o)) {
823#ifdef STANDALONE_SOLVER
824 subsolver.names = solver->names;
825#endif
826 ret = latin_solver_top(&subsolver, diff_recursive,
827 diff_simple, diff_set_0, diff_set_1,
828 diff_forcing, diff_recursive,
829 usersolvers, valid, newctx,
830 ctxnew, ctxfree);
831 } else {
832 ret = diff_impossible;
833 }
834 latin_solver_free(&subsolver);
835 if (ctxnew)
836 ctxfree(newctx);
837
838#ifdef STANDALONE_SOLVER
839 solver_recurse_depth--;
840 if (solver_show_working) {
841 printf("%*sretracting %s at (%d,%d)\n",
842 solver_recurse_depth*4, "", names[list[i]-1], x+1, y+1);
843 }
844#endif
845 /* we recurse as deep as we can, so we should never find
846 * find ourselves giving up on a puzzle without declaring it
847 * impossible. */
848 assert(ret != diff_unfinished);
849
850 /*
851 * If we have our first solution, copy it into the
852 * grid we will return.
853 */
854 if (diff == diff_impossible && ret != diff_impossible)
855 memcpy(solver->grid, outgrid, o*o);
856
857 if (ret == diff_ambiguous)
858 diff = diff_ambiguous;
859 else if (ret == diff_impossible)
860 /* do not change our return value */;
861 else {
862 /* the recursion turned up exactly one solution */
863 if (diff == diff_impossible)
864 diff = diff_recursive;
865 else
866 diff = diff_ambiguous;
867 }
868
869 /*
870 * As soon as we've found more than one solution,
871 * give up immediately.
872 */
873 if (diff == diff_ambiguous)
874 break;
875 }
876
877 sfree(outgrid);
878 sfree(ingrid);
879 sfree(list);
880
881 if (diff == diff_impossible)
882 return -1;
883 else if (diff == diff_ambiguous)
884 return 2;
885 else {
886 assert(diff == diff_recursive);
887 return 1;
888 }
889 }
890}
891
892static int latin_solver_top(struct latin_solver *solver, int maxdiff,
893 int diff_simple, int diff_set_0, int diff_set_1,
894 int diff_forcing, int diff_recursive,
895 usersolver_t const *usersolvers, validator_t valid,
896 void *ctx, ctxnew_t ctxnew, ctxfree_t ctxfree)
897{
898 struct latin_solver_scratch *scratch = latin_solver_new_scratch(solver);
899 int ret, diff = diff_simple;
900
901 assert(maxdiff <= diff_recursive);
902 /*
903 * Now loop over the grid repeatedly trying all permitted modes
904 * of reasoning. The loop terminates if we complete an
905 * iteration without making any progress; we then return
906 * failure or success depending on whether the grid is full or
907 * not.
908 */
909 while (1) {
910 int i;
911
912 cont:
913
914 latin_solver_debug(solver->cube, solver->o);
915
916 for (i = 0; i <= maxdiff; i++) {
917 if (usersolvers[i])
918 ret = usersolvers[i](solver, ctx);
919 else
920 ret = 0;
921 if (ret == 0 && i == diff_simple)
922 ret = latin_solver_diff_simple(solver);
923 if (ret == 0 && i == diff_set_0)
924 ret = latin_solver_diff_set(solver, scratch, false);
925 if (ret == 0 && i == diff_set_1)
926 ret = latin_solver_diff_set(solver, scratch, true);
927 if (ret == 0 && i == diff_forcing)
928 ret = latin_solver_forcing(solver, scratch);
929
930 if (ret < 0) {
931 diff = diff_impossible;
932 goto got_result;
933 } else if (ret > 0) {
934 diff = max(diff, i);
935 goto cont;
936 }
937 }
938
939 /*
940 * If we reach here, we have made no deductions in this
941 * iteration, so the algorithm terminates.
942 */
943 break;
944 }
945
946 /*
947 * Last chance: if we haven't fully solved the puzzle yet, try
948 * recursing based on guesses for a particular square. We pick
949 * one of the most constrained empty squares we can find, which
950 * has the effect of pruning the search tree as much as
951 * possible.
952 */
953 if (maxdiff == diff_recursive) {
954 int nsol = latin_solver_recurse(solver,
955 diff_simple, diff_set_0, diff_set_1,
956 diff_forcing, diff_recursive,
957 usersolvers, valid, ctx,
958 ctxnew, ctxfree);
959 if (nsol < 0) diff = diff_impossible;
960 else if (nsol == 1) diff = diff_recursive;
961 else if (nsol > 1) diff = diff_ambiguous;
962 /* if nsol == 0 then we were complete anyway
963 * (and thus don't need to change diff) */
964 } else {
965 /*
966 * We're forbidden to use recursion, so we just see whether
967 * our grid is fully solved, and return diff_unfinished
968 * otherwise.
969 */
970 int x, y, o = solver->o;
971
972 for (y = 0; y < o; y++)
973 for (x = 0; x < o; x++)
974 if (!solver->grid[y*o+x])
975 diff = diff_unfinished;
976 }
977
978 got_result:
979
980#ifdef STANDALONE_SOLVER
981 if (solver_show_working) {
982 if (diff != diff_impossible && diff != diff_unfinished &&
983 diff != diff_ambiguous) {
984 int x, y;
985
986 printf("%*sone solution found:\n", solver_recurse_depth*4, "");
987
988 for (y = 0; y < solver->o; y++) {
989 printf("%*s", solver_recurse_depth*4+1, "");
990 for (x = 0; x < solver->o; x++) {
991 int val = solver->grid[y*solver->o+x];
992 assert(val);
993 printf(" %s", solver->names[val-1]);
994 }
995 printf("\n");
996 }
997 } else {
998 printf("%*s%s found\n",
999 solver_recurse_depth*4, "",
1000 diff == diff_impossible ? "no solution (impossible)" :
1001 diff == diff_unfinished ? "no solution (unfinished)" :
1002 "multiple solutions");
1003 }
1004 }
1005#endif
1006
1007 if (diff != diff_impossible && diff != diff_unfinished &&
1008 diff != diff_ambiguous && valid && !valid(solver, ctx)) {
1009#ifdef STANDALONE_SOLVER
1010 if (solver_show_working) {
1011 printf("%*ssolution failed final validation!\n",
1012 solver_recurse_depth*4, "");
1013 }
1014#endif
1015 diff = diff_impossible;
1016 }
1017
1018 latin_solver_free_scratch(scratch);
1019
1020 return diff;
1021}
1022
1023int latin_solver_main(struct latin_solver *solver, int maxdiff,
1024 int diff_simple, int diff_set_0, int diff_set_1,
1025 int diff_forcing, int diff_recursive,
1026 usersolver_t const *usersolvers, validator_t valid,
1027 void *ctx, ctxnew_t ctxnew, ctxfree_t ctxfree)
1028{
1029 int diff;
1030#ifdef STANDALONE_SOLVER
1031 int o = solver->o;
1032 char *text = NULL, **names = NULL;
1033#endif
1034
1035#ifdef STANDALONE_SOLVER
1036 if (!solver->names) {
1037 char *p;
1038 int i;
1039
1040 text = snewn(40 * o, char);
1041 p = text;
1042
1043 solver->names = snewn(o, char *);
1044
1045 for (i = 0; i < o; i++) {
1046 solver->names[i] = p;
1047 p += 1 + sprintf(p, "%d", i+1);
1048 }
1049 }
1050#endif
1051
1052 diff = latin_solver_top(solver, maxdiff,
1053 diff_simple, diff_set_0, diff_set_1,
1054 diff_forcing, diff_recursive,
1055 usersolvers, valid, ctx, ctxnew, ctxfree);
1056
1057#ifdef STANDALONE_SOLVER
1058 sfree(names);
1059 sfree(text);
1060#endif
1061
1062 return diff;
1063}
1064
1065int latin_solver(digit *grid, int o, int maxdiff,
1066 int diff_simple, int diff_set_0, int diff_set_1,
1067 int diff_forcing, int diff_recursive,
1068 usersolver_t const *usersolvers, validator_t valid,
1069 void *ctx, ctxnew_t ctxnew, ctxfree_t ctxfree)
1070{
1071 struct latin_solver solver;
1072 int diff;
1073
1074 if (latin_solver_alloc(&solver, grid, o))
1075 diff = latin_solver_main(&solver, maxdiff,
1076 diff_simple, diff_set_0, diff_set_1,
1077 diff_forcing, diff_recursive,
1078 usersolvers, valid, ctx, ctxnew, ctxfree);
1079 else
1080 diff = diff_impossible;
1081 latin_solver_free(&solver);
1082 return diff;
1083}
1084
1085void latin_solver_debug(unsigned char *cube, int o)
1086{
1087#ifdef STANDALONE_SOLVER
1088 if (solver_show_working > 1) {
1089 struct latin_solver ls, *solver = &ls;
1090 char *dbg;
1091 int x, y, i, c = 0;
1092
1093 ls.cube = cube; ls.o = o; /* for cube() to work */
1094
1095 dbg = snewn(3*o*o*o, char);
1096 for (y = 0; y < o; y++) {
1097 for (x = 0; x < o; x++) {
1098 for (i = 1; i <= o; i++) {
1099 if (cube(x,y,i))
1100 dbg[c++] = i + '0';
1101 else
1102 dbg[c++] = '.';
1103 }
1104 dbg[c++] = ' ';
1105 }
1106 dbg[c++] = '\n';
1107 }
1108 dbg[c++] = '\n';
1109 dbg[c++] = '\0';
1110
1111 printf("%s", dbg);
1112 sfree(dbg);
1113 }
1114#endif
1115}
1116
1117void latin_debug(digit *sq, int o)
1118{
1119#ifdef STANDALONE_SOLVER
1120 if (solver_show_working) {
1121 int x, y;
1122
1123 for (y = 0; y < o; y++) {
1124 for (x = 0; x < o; x++) {
1125 printf("%2d ", sq[y*o+x]);
1126 }
1127 printf("\n");
1128 }
1129 printf("\n");
1130 }
1131#endif
1132}
1133
1134/* --------------------------------------------------------
1135 * Generation.
1136 */
1137
1138digit *latin_generate(int o, random_state *rs)
1139{
1140 digit *sq;
1141 int *adjdata, *adjsizes, *matching;
1142 int **adjlists;
1143 void *scratch;
1144 int i, j, k;
1145 digit *row;
1146
1147 /*
1148 * To efficiently generate a latin square in such a way that
1149 * all possible squares are possible outputs from the function,
1150 * we make use of a theorem which states that any r x n latin
1151 * rectangle, with r < n, can be extended into an (r+1) x n
1152 * latin rectangle. In other words, we can reliably generate a
1153 * latin square row by row, by at every stage writing down any
1154 * row at all which doesn't conflict with previous rows, and
1155 * the theorem guarantees that we will never have to backtrack.
1156 *
1157 * To find a viable row at each stage, we can make use of the
1158 * support functions in matching.c.
1159 */
1160
1161 sq = snewn(o*o, digit);
1162
1163 /*
1164 * matching.c will take care of randomising the generation of each
1165 * row of the square, but in case this entire method of generation
1166 * introduces a really subtle top-to-bottom directional bias,
1167 * we'll also generate the rows themselves in random order.
1168 */
1169 row = snewn(o, digit);
1170 for (i = 0; i < o; i++)
1171 row[i] = i;
1172 shuffle(row, i, sizeof(*row), rs);
1173
1174 /*
1175 * Set up the infrastructure for the matching subroutine.
1176 */
1177 scratch = smalloc(matching_scratch_size(o, o));
1178 adjdata = snewn(o*o, int);
1179 adjlists = snewn(o, int *);
1180 adjsizes = snewn(o, int);
1181 matching = snewn(o, int);
1182
1183 /*
1184 * Now generate each row of the latin square.
1185 */
1186 for (i = 0; i < o; i++) {
1187 /*
1188 * Make adjacency lists for a bipartite graph joining each
1189 * column to all the numbers not yet placed in that column.
1190 */
1191 for (j = 0; j < o; j++) {
1192 int *p, *adj = adjdata + j*o;
1193 for (k = 0; k < o; k++)
1194 adj[k] = 1;
1195 for (k = 0; k < i; k++)
1196 adj[sq[row[k]*o + j] - 1] = 0;
1197 adjlists[j] = p = adj;
1198 for (k = 0; k < o; k++)
1199 if (adj[k])
1200 *p++ = k;
1201 adjsizes[j] = p - adjlists[j];
1202 }
1203
1204 /*
1205 * Run the matching algorithm.
1206 */
1207 j = matching_with_scratch(scratch, o, o, adjlists, adjsizes,
1208 rs, matching, NULL);
1209 assert(j == o); /* by the above theorem, this must have succeeded */
1210
1211 /*
1212 * And use the output to set up the new row of the latin
1213 * square.
1214 */
1215 for (j = 0; j < o; j++)
1216 sq[row[i]*o + j] = matching[j] + 1;
1217 }
1218
1219 /*
1220 * Done. Free our internal workspaces...
1221 */
1222 sfree(matching);
1223 sfree(adjlists);
1224 sfree(adjsizes);
1225 sfree(adjdata);
1226 sfree(scratch);
1227 sfree(row);
1228
1229 /*
1230 * ... and return our completed latin square.
1231 */
1232 return sq;
1233}
1234
1235digit *latin_generate_rect(int w, int h, random_state *rs)
1236{
1237 int o = max(w, h), x, y;
1238 digit *latin, *latin_rect;
1239
1240 latin = latin_generate(o, rs);
1241 latin_rect = snewn(w*h, digit);
1242
1243 for (x = 0; x < w; x++) {
1244 for (y = 0; y < h; y++) {
1245 latin_rect[y*w + x] = latin[y*o + x];
1246 }
1247 }
1248
1249 sfree(latin);
1250 return latin_rect;
1251}
1252
1253/* --------------------------------------------------------
1254 * Checking.
1255 */
1256
1257typedef struct lcparams {
1258 digit elt;
1259 int count;
1260} lcparams;
1261
1262static int latin_check_cmp(void *v1, void *v2)
1263{
1264 lcparams *lc1 = (lcparams *)v1;
1265 lcparams *lc2 = (lcparams *)v2;
1266
1267 if (lc1->elt < lc2->elt) return -1;
1268 if (lc1->elt > lc2->elt) return 1;
1269 return 0;
1270}
1271
1272#define ELT(sq,x,y) (sq[((y)*order)+(x)])
1273
1274/* returns true if sq is not a latin square. */
1275bool latin_check(digit *sq, int order)
1276{
1277 tree234 *dict = newtree234(latin_check_cmp);
1278 int c, r;
1279 bool ret = false;
1280 lcparams *lcp, lc, *aret;
1281
1282 /* Use a tree234 as a simple hash table, go through the square
1283 * adding elements as we go or incrementing their counts. */
1284 for (c = 0; c < order; c++) {
1285 for (r = 0; r < order; r++) {
1286 lc.elt = ELT(sq, c, r); lc.count = 0;
1287 lcp = find234(dict, &lc, NULL);
1288 if (!lcp) {
1289 lcp = snew(lcparams);
1290 lcp->elt = ELT(sq, c, r);
1291 lcp->count = 1;
1292 aret = add234(dict, lcp);
1293 assert(aret == lcp);
1294 } else {
1295 lcp->count++;
1296 }
1297 }
1298 }
1299
1300 /* There should be precisely 'order' letters in the alphabet,
1301 * each occurring 'order' times (making the OxO tree) */
1302 if (count234(dict) != order) ret = true;
1303 else {
1304 for (c = 0; (lcp = index234(dict, c)) != NULL; c++) {
1305 if (lcp->count != order) ret = true;
1306 }
1307 }
1308 for (c = 0; (lcp = index234(dict, c)) != NULL; c++)
1309 sfree(lcp);
1310 freetree234(dict);
1311
1312 return ret;
1313}
1314
1315/* vim: set shiftwidth=4 tabstop=8: */