Adam D. Lopresto and Phil Bordelon independently point out a
[sgt/puzzles] / latin.c
diff --git a/latin.c b/latin.c
index fa981f2..45096e4 100644 (file)
--- a/latin.c
+++ b/latin.c
@@ -619,46 +619,46 @@ int latin_solver_diff_simple(struct latin_solver *solver)
 
 int latin_solver_diff_set(struct latin_solver *solver,
                           struct latin_solver_scratch *scratch,
-                          int *extreme)
+                          int extreme)
 {
     int x, y, n, ret, o = solver->o;
-    /*
-     * Row-wise set elimination.
-     */
-    for (y = 0; y < o; y++) {
-        ret = latin_solver_set(solver, scratch, cubepos(0,y,1), o*o, 1
+
+    if (!extreme) {
+        /*
+         * Row-wise set elimination.
+         */
+        for (y = 0; y < o; y++) {
+            ret = latin_solver_set(solver, scratch, cubepos(0,y,1), o*o, 1
 #ifdef STANDALONE_SOLVER
-                              , "set elimination, row %d", YUNTRANS(y)
+                                   , "set elimination, row %d", YUNTRANS(y)
 #endif
-                              );
-        if (ret > 0) *extreme = 0;
-        if (ret != 0) return ret;
-    }
-
-    /*
-     * Column-wise set elimination.
-     */
-    for (x = 0; x < o; x++) {
-        ret = latin_solver_set(solver, scratch, cubepos(x,0,1), o, 1
+                                  );
+            if (ret != 0) return ret;
+        }
+        /*
+         * Column-wise set elimination.
+         */
+        for (x = 0; x < o; x++) {
+            ret = latin_solver_set(solver, scratch, cubepos(x,0,1), o, 1
 #ifdef STANDALONE_SOLVER
-                              , "set elimination, column %d", x
+                                   , "set elimination, column %d", x
 #endif
-                              );
-        if (ret > 0) *extreme = 0;
-        if (ret != 0) return ret;
-    }
-
-    /*
-     * Row-vs-column set elimination on a single number.
-     */
-    for (n = 1; n <= o; n++) {
-        ret = latin_solver_set(solver, scratch, cubepos(0,0,n), o*o, o
+                                  );
+            if (ret != 0) return ret;
+        }
+    } else {
+        /*
+         * Row-vs-column set elimination on a single number
+         * (much tricker for a human to do!)
+         */
+        for (n = 1; n <= o; n++) {
+            ret = latin_solver_set(solver, scratch, cubepos(0,0,n), o*o, o
 #ifdef STANDALONE_SOLVER
-                              , "positional set elimination, number %d", n
+                                   , "positional set elimination, number %d", n
 #endif
-                              );
-        if (ret > 0) *extreme = 1;
-        if (ret != 0) return ret;
+                                  );
+            if (ret != 0) return ret;
+        }
     }
     return 0;
 }
@@ -826,7 +826,7 @@ enum { diff_simple = 1, diff_set, diff_extreme, diff_recursive };
 static int latin_solver_sub(struct latin_solver *solver, int maxdiff, void *ctx)
 {
     struct latin_solver_scratch *scratch = latin_solver_new_scratch(solver);
-    int ret, diff = diff_simple, extreme;
+    int ret, diff = diff_simple;
 
     assert(maxdiff <= diff_recursive);
     /*
@@ -859,18 +859,27 @@ static int latin_solver_sub(struct latin_solver *solver, int maxdiff, void *ctx)
         if (maxdiff <= diff_simple)
             break;
 
-        ret = latin_solver_diff_set(solver, scratch, &extreme);
+        ret = latin_solver_diff_set(solver, scratch, 0);
         if (ret < 0) {
             diff = diff_impossible;
             goto got_result;
         } else if (ret > 0) {
-            diff = max(diff, extreme ? diff_extreme : diff_set);
+            diff = max(diff, diff_set);
             goto cont;
         }
 
         if (maxdiff <= diff_set)
             break;
 
+        ret = latin_solver_diff_set(solver, scratch, 1);
+        if (ret < 0) {
+            diff = diff_impossible;
+            goto got_result;
+        } else if (ret > 0) {
+            diff = max(diff, diff_extreme);
+            goto cont;
+        }
+
         /*
          * Forcing chains.
          */
@@ -952,7 +961,7 @@ void latin_solver_debug(unsigned char *cube, int o)
 
         ls.cube = cube; ls.o = o; /* for cube() to work */
 
-        dbg = snewn(3*o*o*o, unsigned char);
+        dbg = snewn(3*o*o*o, char);
         for (y = 0; y < o; y++) {
             for (x = 0; x < o; x++) {
                 for (i = 1; i <= o; i++) {
@@ -1083,6 +1092,7 @@ digit *latin_generate(int o, random_state *rs)
        for (j = 0; j < o; j++)
            col[j] = num[j] = j;
        shuffle(col, j, sizeof(*col), rs);
+       shuffle(num, j, sizeof(*num), rs);
        /* We need the num permutation in both forward and inverse forms. */
        for (j = 0; j < o; j++)
            numinv[num[j]] = j;
@@ -1166,7 +1176,7 @@ int latin_check(digit *sq, int order)
     tree234 *dict = newtree234(latin_check_cmp);
     int c, r;
     int ret = 0;
-    lcparams *lcp, lc;
+    lcparams *lcp, lc, *aret;
 
     /* Use a tree234 as a simple hash table, go through the square
      * adding elements as we go or incrementing their counts. */
@@ -1178,7 +1188,8 @@ int latin_check(digit *sq, int order)
                lcp = snew(lcparams);
                lcp->elt = ELT(sq, c, r);
                lcp->count = 1;
-               assert(add234(dict, lcp) == lcp);
+                aret = add234(dict, lcp);
+               assert(aret == lcp);
            } else {
                lcp->count++;
            }