chiark / gitweb /
Patch from James H to fix the occasional generation of puzzles
authorSimon Tatham <anakin@pobox.com>
Mon, 15 Jan 2007 20:07:18 +0000 (20:07 +0000)
committerSimon Tatham <anakin@pobox.com>
Mon, 15 Jan 2007 20:07:18 +0000 (20:07 +0000)
harder than requested.

[originally from svn r7113]

latin.c
latin.h
unequal.c

diff --git a/latin.c b/latin.c
index 4f6e1f37a00af6686f17409eb5c17a08475d0f13..22488a744bf66c6cf0a2bfb9ff54a3214e398fd1 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.
          */
diff --git a/latin.h b/latin.h
index f312cf93f1edd80a8a14abe7ea682418f753db41..decf2d7f9ad6418ee3340bc0e092fcf9cf75229a 100644 (file)
--- a/latin.h
+++ b/latin.h
@@ -86,7 +86,7 @@ int latin_solver_diff_simple(struct latin_solver *solver);
  * the more difficult single-number elimination. */
 int latin_solver_diff_set(struct latin_solver *solver,
                           struct latin_solver_scratch *scratch,
-                          int *extreme);
+                          int extreme);
 
 typedef int (latin_solver_callback)(digit *, int, int, void*);
 /* Use to provide a standard way of dealing with solvers which can recurse;
index 74eba79976f5b49bef3dab95e7b74f8e2fce7613..81720e47232ef3f8df2b808ea81fe3c9446a5919 100644 (file)
--- a/unequal.c
+++ b/unequal.c
@@ -631,7 +631,7 @@ static int solver_grid(digit *grid, int o, int maxdiff, void *ctx)
     game_solver *solver;
     struct latin_solver *lsolver;
     struct latin_solver_scratch *scratch;
-    int ret, diff = DIFF_LATIN, extreme;
+    int ret, diff = DIFF_LATIN;
 
     assert(maxdiff <= DIFF_RECURSIVE);
 
@@ -668,18 +668,28 @@ cont:
         if (maxdiff <= DIFF_EASY)
             break;
 
-        ret = latin_solver_diff_set(lsolver, scratch, &extreme);
+        /* Row- and column-wise set elimination */
+        ret = latin_solver_diff_set(lsolver, 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(lsolver, scratch, 1);
+        if (ret < 0) {
+            diff = DIFF_IMPOSSIBLE;
+            goto got_result;
+        } else if (ret > 0) {
+            diff = max(diff, DIFF_EXTREME);
+            goto cont;
+        }
+
         /*
          * Forcing chains.
          */