From 3dc9f04650742e45ed0bd6ede47f7b18f8110b8a Mon Sep 17 00:00:00 2001 From: Drew Galbraith Date: Mon, 17 Apr 2023 16:48:38 -0700 Subject: [PATCH] Update Sudoku Solver to check for naked singles. --- solver.cpp | 5 +++++ solver/cell.cpp | 5 +++++ solver/cell.h | 2 ++ solver/puzzle.cpp | 25 +++++++++++++++++++++++++ solver/puzzle.h | 3 +++ 5 files changed, 40 insertions(+) diff --git a/solver.cpp b/solver.cpp index b71947e..a4d2241 100644 --- a/solver.cpp +++ b/solver.cpp @@ -6,6 +6,11 @@ int main(int argc, char** argv) { Puzzle puzzle = Puzzle::FromString( "3..4.162.1...8.4....5.2.83..578........7..5.3..29.4..748.53..1.2.3.9...." ".7...6.9."); + while (puzzle.ApplyNextStep()) + ; + if (!puzzle.IsSolved()) { + std::cout << "Error! Couldn't Solve" << std::endl; + } std::cout << "https://tiramisu.one/sudoku.html?p=" << puzzle.CurrentState() << "&m=" << puzzle.PencilMarkState() << std::endl; } diff --git a/solver/cell.cpp b/solver/cell.cpp index c777c10..38a8bbf 100644 --- a/solver/cell.cpp +++ b/solver/cell.cpp @@ -1,5 +1,6 @@ #include "cell.h" +#include #include Cell::Cell() @@ -15,3 +16,7 @@ void Cell::Restrict(uint8_t value) { assert(value >= 1 && value <= 9); possibilities_[value - 1] = false; } + +uint8_t Cell::NumPossibilities() { + return std::count(possibilities_.begin(), possibilities_.end(), true); +} diff --git a/solver/cell.h b/solver/cell.h index 7396577..814e920 100644 --- a/solver/cell.h +++ b/solver/cell.h @@ -15,6 +15,8 @@ class Cell { void Restrict(uint8_t value); + uint8_t NumPossibilities(); + bool IsSolved() const { return state_ == Solved; } uint8_t value() const { return value_; } bool IsPossible(uint8_t v) const { return possibilities_[v - 1]; } diff --git a/solver/puzzle.cpp b/solver/puzzle.cpp index 808f8eb..f77c226 100644 --- a/solver/puzzle.cpp +++ b/solver/puzzle.cpp @@ -1,5 +1,6 @@ #include "puzzle.h" +#include #include #include #include @@ -63,6 +64,30 @@ std::string Puzzle::PencilMarkState() { return temp; } +bool Puzzle::IsSolved() { + return std::all_of(cells_.begin(), cells_.end(), + [](const Cell& c) { return c.IsSolved(); }); +} + +bool Puzzle::ApplyNextStep() { + // Search for a naked single. + for (int i = 0; i < 81; i++) { + if (cells_[i].IsSolved()) { + continue; + } + + if (cells_[i].NumPossibilities() == 1) { + for (uint8_t v = 1; v <= 9; v++) { + if (cells_[i].IsPossible(v)) { + AssignSquare(i, v); + } + } + return true; + } + } + return false; +} + void Puzzle::AssignSquare(uint8_t id, uint8_t value) { assert(id < 81); assert(value >= 0 && value <= 9); diff --git a/solver/puzzle.h b/solver/puzzle.h index c67c2f8..9138c69 100644 --- a/solver/puzzle.h +++ b/solver/puzzle.h @@ -12,6 +12,9 @@ class Puzzle { std::string CurrentState(); std::string PencilMarkState(); + bool IsSolved(); + bool ApplyNextStep(); + void AssignSquare(uint8_t id, uint8_t value); private: