April 4, 2026 Claude upgrade to Solve Griddler 260236 Illustrated Book Code


       Here’s the actual code changes Claude made. I’m still impressed that it changes the comments too!

Back to Main Page

  The fix: replace the naive "first unknown cell" with a minimum-remaining-values (MRV) heuristic — pick the row or column with

  the fewest unknown cells remaining. This ensures backtracking happens in the most constrained areas first, where wrong guesses

  contradict quickly.


Update(BoardSolverCmdLine.cpp)

  Added 52 lines, removed 19 lines

      203        if (seen.insert(clue.color).second)

      204          candidates.push_back(clue.color);

      205  

      206 -    // Find the first unknown cell.                                                                             

      207 -  for (short r = 0; r < (short)theBoard.rowCount; r++){                                                         

      206 +    // Find the most constrained unknown cell (MRV heuristic).                                                  

      207 +    // Pick the row or column with the fewest unknown cells remaining;                                          

      208 +    // guessing there triggers contradictions earliest in the search tree.                                      

      209 +  short bestR = -1, bestC = -1;                                                                                 

      210 +  {                                                                                                             

      211 +    int minUnknowns = INT_MAX;                                                                                  

      212 +                                                                                                                

      213 +    for (short r = 0; r < (short)theBoard.rowCount; r++){                                                       

      214 +      int   cnt    = 0;                                                                                         

      215 +      short firstC = -1;                                                                                        

      216 +      for (short c = 0; c < (short)theBoard.columnCount; c++){                                                  

      217 +        if (theBoard.contents[r][c] == UNKNOWN_COLOR){                                                          

      218 +          cnt++;                                                                                                

      219 +          if (firstC < 0) firstC = c;                                                                           

      220 +        }                                                                                                       

      221 +      }                                                                                                         

      222 +      if (cnt > 0 && cnt < minUnknowns){                                                                        

      223 +        minUnknowns = cnt;                                                                                      

      224 +        bestR = r;                                                                                              

      225 +        bestC = firstC;                                                                                         

      226 +      }                                                                                                         

      227 +    }                                                                                                           

      228 +                                                                                                                

      229      for (short c = 0; c < (short)theBoard.columnCount; c++){

      209 -      if (theBoard.contents[r][c] != UNKNOWN_COLOR)                                                             

      210 -        continue;                                                                                               

      230 +      int   cnt    = 0;                                                                                         

      231 +      short firstR = -1;                                                                                        

      232 +      for (short r = 0; r < (short)theBoard.rowCount; r++){                                                     

      233 +        if (theBoard.contents[r][c] == UNKNOWN_COLOR){                                                          

      234 +          cnt++;                                                                                                

      235 +          if (firstR < 0) firstR = r;                                                                           

      236 +        }                                                                                                       

      237 +      }                                                                                                         

      238 +      if (cnt > 0 && cnt < minUnknowns){                                                                        

      239 +        minUnknowns = cnt;                                                                                      

      240 +        bestR = firstR;                                                                                         

      241 +        bestC = c;                                                                                              

      242 +      }                                                                                                         

      243 +    }                                                                                                           

      244 +  }                                                                                                             

      245  

      212 -        // Save board state, then try each candidate color.                                                     

      213 -      Array2D_uchar savedBoard = theBoard;                                                                      

      246 +  if (bestR < 0)                                                                                                

      247 +    return false; // No unknown cells; IsSolved() should have caught this.                                      

      248  

      215 -      for (unsigned char color : candidates){                                                                   

      216 -        guessCount++;                                                                                           

      217 -                                                                                                                

      218 -        theBoard                    = savedBoard;                                                               

      219 -        theBoard.contents[r][c]     = color;                                                                    

      249 +    // Save board state, then try each candidate color.                                                         

      250 +  Array2D_uchar savedBoard = theBoard;                                                                          

      251  

      221 -        if (SolveWithGuessing())                                                                                

      222 -          return true;                                                                                          

      223 -      }                                                                                                         

      252 +  for (unsigned char color : candidates){                                                                       

      253 +    guessCount++;                                                                                               

      254  

      225 -        // All candidates failed contradiction at this branch.                                                

      226 -      theBoard = savedBoard;                                                                                    

      227 -      return false;                                                                                             

      228 -    }                                                                                                           

      255 +    theBoard                        = savedBoard;                                                               

      256 +    theBoard.contents[bestR][bestC] = color;                                                                    

      257 +                                                                                                                

      258 +    if (SolveWithGuessing())                                                                                    

      259 +      return true;                                                                                              

      260    }

      261  

      231 -  return false; // Unreachable if IsSolved() is accurate.                                                       

      262 +    // All candidates failed contradiction at this branch.                                                    

      263 +  theBoard = savedBoard;                                                                                        

      264 +  return false;                                                                                                 

      265  }

      266  

      267  /* ------------------------------------------------------------------------ */



Now I'll rewrite BoardSolverCmdLine.cpp to add probing:


  Read 1 file (ctrl+o to expand)


Update(BoardSolverCmdLine.cpp)

  Added 80 lines, removed 16 lines

      177  }

      178  

      179  /* ------------------------------------------------------------------------ */

      180 -//           Solve With Guessing (backtracking search)                                                                 

      180 +//           Build Candidates                                                                                          

      181  /* ------------------------------------------------------------------------ */

      182 -//   1. Run pure constraint propagation to fixed point.                                                           

      183 -//   2. If solved, return true.                                                                                   

      184 -//   3. If contradicted, return false.                                                                            

      185 -//   4. Otherwise pick the first unknown cell and try each plausible color:                                       

      186 -//            • EMPTY_COLOR first (often triggers early contradictions)                                                

      187 -//            • Then each color that actually appears in the row or column clues.                                      

      188 -//   5. For each candidate, save board state, apply guess, recurse.                                               

      189 -//      Restore on failure.                                                                                       

      182 +//   Returns the ordered list of colors to try when guessing a cell:                                              

      183 +//   EMPTY first (often triggers early contradictions), then every color that                                     

      184 +//   appears in any row clue.                                                                                     

      185  /* ------------------------------------------------------------------------ */

      191 -bool BoardSolverCmdLine::SolveWithGuessing(){                                                                   

      192 -                                                                                                                

      193 -  if (!SolveLogic()) return false;                                                                              

      194 -  if (IsSolved())    return true;                                                                               

      195 -                                                                                                                

      196 -    // Collect candidate colors to try for the guessed cell:                                                    

      197 -    // EMPTY first, then every color that appears in any clue.                                                  

      186 +vector<unsigned char> BoardSolverCmdLine::BuildCandidates() const {                                             

      187    vector<unsigned char> candidates;

      188    candidates.push_back(EMPTY_COLOR);

      189    set<unsigned char> seen;

     ...

      191      for (auto &clue : line)

      192        if (seen.insert(clue.color).second)

      193          candidates.push_back(clue.color);

      194 +  return candidates;                                                                                            

      195 +}                                                                                                               

      196  

      197 +/* ------------------------------------------------------------------------ */                                  

      198 +//           Solve With Probing                                                                                        

      199 +/* ------------------------------------------------------------------------ */                                  

      200 +//   Alternates between constraint propagation (SolveLogic) and probing.                                          

      201 +//   Probing: for each unknown cell, try each candidate color with full                                           

      202 +//   constraint propagation. If all colors except one lead to contradictions,                                     

      203 +//   the cell is forced to the non-contradicting color. Repeats until stable.                                     

      204 +//   This converts hidden forced moves into explicit ones, slashing the number                                    

      205 +//   of actual backtracking guesses needed.                                                                       

      206 +//   Returns false if a contradiction is detected at any point.                                                   

      207 +/* ------------------------------------------------------------------------ */                                  

      208 +bool BoardSolverCmdLine::SolveWithProbing(const vector<unsigned char> &candidates){                             

      209 +                                                                                                                

      210 +  while (true){                                                                                                 

      211 +    if (!SolveLogic()) return false;                                                                            

      212 +    if (IsSolved())    return true;                                                                             

      213 +                                                                                                                

      214 +    bool anyForced = false;                                                                                     

      215 +                                                                                                                

      216 +    short numRows = (short)theBoard.rowCount;                                                                   

      217 +    short numCols = (short)theBoard.columnCount;                                                                

      218 +                                                                                                                

      219 +    for (short r = 0; r < numRows; r++){                                                                        

      220 +      for (short c = 0; c < numCols; c++){                                                                      

      221 +        if (theBoard.contents[r][c] != UNKNOWN_COLOR) continue;                                                 

      222 +                                                                                                                

      223 +        unsigned char forcedColor  = UNKNOWN_COLOR;                                                             

      224 +        int           validCount   = 0;                                                                         

      225 +                                                                                                                

      226 +        for (unsigned char color : candidates){                                                                 

      227 +          Array2D_uchar savedBoard  = theBoard;                                                                 

      228 +          theBoard.contents[r][c]   = color;                                                                    

      229 +          bool ok = SolveLogic();                                                                               

      230 +          theBoard = savedBoard;                                                                                

      231 +                                                                                                                

      232 +          if (ok){                                                                                              

      233 +            forcedColor = color;                                                                                

      234 +            if (++validCount > 1) break;     // Multiple valid colors — not forced.                                 

      235 +          }                                                                                                     

      236 +        }                                                                                                       

      237 +                                                                                                                

      238 +        if (validCount == 0) return false;   // All colors contradict dead end.                                 

      239 +        if (validCount == 1){                                                                                   

      240 +            // Cell is forced to the one valid color.                                                           

      241 +          theBoard.contents[r][c] = forcedColor;                                                                

      242 +          anyForced = true;                                                                                     

      243 +        }                                                                                                       

      244 +      }                                                                                                         

      245 +    }                                                                                                           

      246 +                                                                                                                

      247 +    if (!anyForced) break;   // Probing found nothing new; hand off to backtracking.                              

      248 +  }                                                                                                             

      249 +                                                                                                                

      250 +  return true;                                                                                                  

      251 +}                                                                                                               

      252 +                                                                                                                

      253 +/* ------------------------------------------------------------------------ */                                  

      254 +//           Solve With Guessing (backtracking search)                                                                 

      255 +/* ------------------------------------------------------------------------ */                                  

      256 +//   1. Run probing (constraint propagation + look-ahead) to fixed point.                                         

      257 +//   2. If solved, return true.                                                                                   

      258 +//   3. If contradicted, return false.                                                                            

      259 +//   4. Otherwise pick the most constrained unknown cell (MRV heuristic):                                         

      260 +//            the row or column with the fewest remaining unknowns.                                                    

      261 +//   5. Try each candidate color; recurse. Restore on failure.                                                    

      262 +/* ------------------------------------------------------------------------ */                                  

      263 +bool BoardSolverCmdLine::SolveWithGuessing(){                                                                   

      264 +                                                                                                                

      265 +  vector<unsigned char> candidates = BuildCandidates();                                                         

      266 +                                                                                                                

      267 +  if (!SolveWithProbing(candidates)) return false;                                                              

      268 +  if (IsSolved())                    return true;                                                               

      269 +                                                                                                                

      270      // Find the most constrained unknown cell (MRV heuristic).

      271      // Pick the row or column with the fewest unknown cells remaining;

      272      // guessing there triggers contradictions earliest in the search tree.


Now add the declarations to the header:

                                                                                          

Update(BoardSolverCmdLine.hpp)        

  Added 12 lines, removed 2 lines                                                                                              

      61    // Returns false immediately if a contradiction is detected in any line.

      62    bool SolveLogic();                                                                                                    

      63                                                                                                                        

      64 -  // Recursive backtracking search. Calls SolveLogic(), then if stuck picks an                                          

      65 -  // unknown cell and tries each plausible color. Returns false on contradiction.                                     

      64 +  // Returns the ordered list of candidate colors to try when guessing: EMPTY                                           

      65 +  // first, then every color that appears in any row clue.                                                            

      66 +  vector<unsigned char> BuildCandidates() const;                                                                 

      67 +                                                                                                                 

      68 +  // Alternates SolveLogic with probing: forces cells whose only non-contradicting                               

      69 +  // color is determined by look-ahead. Reduces guesses needed. Returns false on                                 

      70 +  // contradiction.                                                                                              

      71 +  bool SolveWithProbing(const vector<unsigned char> &candidates);                                                

      72 +                                                                                                                 

      73 +  // Recursive backtracking search. Calls SolveWithProbing(), then if stuck picks                                

      74 +  // the most constrained unknown cell (MRV) and tries each plausible color.                                     

      75 +  // Returns false on contradiction.                                                                             

      76    bool SolveWithGuessing();

      77  

      78    void extractRow(short row,  vector<solverCell> &line) const;

 

Back to Main Page