diff --git a/SudoScript.Core.Test/SolverTests.cs b/SudoScript.Core.Test/SolverTests.cs index 5797310..a0281b4 100644 --- a/SudoScript.Core.Test/SolverTests.cs +++ b/SudoScript.Core.Test/SolverTests.cs @@ -6,17 +6,7 @@ namespace SudoScript.Core.Test; internal sealed class SolverTests { - [Test()] - public void CanSolveEmptySudoku() - { - Board board = Util.CreateStandardEmpty(); - Assert.DoesNotThrow(() => board = Solver.Solve(board)); - Assert.IsTrue(board.ValidateRules()); - Assert.IsFalse(board.Cells().Any(c => c.Digit == Cell.EmptyDigit)); - } - - [Test] - public void CanSolveGeneratedSudoku() + public Board CreateEasyBoard() { Board board = Util.CreateStandardEmpty(); // Sudoku givens generated by https://sudoku.com/ @@ -39,6 +29,7 @@ public void CanSolveGeneratedSudoku() board[8, 4].Digit = 8; board[3, 5].Digit = 4; + board[4, 7].Digit = 2; board[3, 6].Digit = 6; board[5, 6].Digit = 7; @@ -50,6 +41,7 @@ public void CanSolveGeneratedSudoku() board[8, 7].Digit = 3; board[9, 7].Digit = 5; + board[3, 9].Digit = 1; board[2, 8].Digit = 9; board[4, 8].Digit = 7; board[5, 8].Digit = 4; @@ -59,6 +51,23 @@ public void CanSolveGeneratedSudoku() board[7, 9].Digit = 9; board[8, 9].Digit = 7; + return board; + } + + [Test()] + public void CanSolveEmptySudoku() + { + Board board = Util.CreateStandardEmpty(); + Assert.DoesNotThrow(() => board = Solver.Solve(board)); + Assert.IsTrue(board.ValidateRules()); + Assert.IsFalse(board.Cells().Any(c => c.Digit == Cell.EmptyDigit)); + } + + [Test] + public void CanSolveGeneratedSudoku() + { + Board board = CreateEasyBoard(); + Console.WriteLine(board.ToString()); Console.WriteLine("-------------------------------------------------"); @@ -68,4 +77,21 @@ public void CanSolveGeneratedSudoku() Console.WriteLine(board.ToString()); } + + [Test] + public void IsSatisfactoryTest() + { + Board board = CreateEasyBoard(); + + Assert.IsTrue(Solver.IsSatisfactory(board)); + } + + [Test] + public void IsNotSatisfactoryTest() + { + Board board = Util.CreateStandardEmpty(); + + Assert.IsFalse(Solver.IsSatisfactory(board)); + } + } diff --git a/SudoScript.Core/Solver.cs b/SudoScript.Core/Solver.cs index ffcccf0..4bc9726 100644 --- a/SudoScript.Core/Solver.cs +++ b/SudoScript.Core/Solver.cs @@ -20,7 +20,7 @@ public static Board Solve(Board board) private static bool SolveRec(Board board, [NotNullWhen(true)] out Board? solvedBoard) { - // Eliminate candidates from all rules untill nothing changes. + // Eliminate candidates from all rules until nothing changes. while (board.EliminateCandidates()) ; // We hit an invalid state, and must backtrack. @@ -42,14 +42,14 @@ private static bool SolveRec(Board board, [NotNullWhen(true)] out Board? solvedB orderedCells = orderedCells.SkipWhile(c => c.CandidateCount <= 1); // The first cell contains the smallest amount of candidates. int lowestCandidateCount = orderedCells.FirstOrDefault()?.CandidateCount ?? 1; - // Take all cells with the least amount of candidates. - orderedCells = orderedCells.TakeWhile(c => c.CandidateCount == lowestCandidateCount); // If there are no cells with more than 1 candidate, the board is solved. if (lowestCandidateCount == 1) { solvedBoard = board; return true; } + // Take all cells with the least amount of candidates. + orderedCells = orderedCells.TakeWhile(c => c.CandidateCount == lowestCandidateCount); Cell cell = orderedCells.First(); foreach (int candidate in cell.Candidates()) @@ -76,9 +76,17 @@ public static Board GenerateSolveable(Board board) throw new NotImplementedException(); } - public static bool IsSatisfactory(Board board) + /// + /// Checks if the board can be solved by just using the EliminateCandidates methods from units. + /// + /// + /// True if the board can be solved without trial and error guessing. + public static bool IsSatisfactory(Board board) // Certain methods for eliminating candidates using inference are not currently implemented. Implementing them would make this function more acurate. { - throw new NotImplementedException(); + // Eliminate candidates from all rules untill nothing changes. + while (board.EliminateCandidates()); + // If the board is solved, it does not require trial and error. + return board.IsSolved(); } public static bool IsProper(Board board)