public PseudoSolver(List <PuzzleConstraint> constraints, PseudoBoard board) { CurrentStep = new SolverStep { SolverStepId = 1, StepComment = "Starting Board State", BoardState = new SolverState { BoardCells = board.BoardCells, SolvedState = false } }; CurrentBoard = board; SolverMethods.Add(new HiddenSingle()); SolverMethods.Add(new ConjugatePair()); foreach (var constraint in constraints) { switch (constraint) { case PuzzleConstraint.BoxUnique: BoardValidators.Add(new BoxUnique()); break; case PuzzleConstraint.ColumnUnique: BoardValidators.Add(new ColumnUnique()); break; case PuzzleConstraint.RowUnique: BoardValidators.Add(new RowUnique()); break; case PuzzleConstraint.KnightUnique: BoardValidators.Add(new KnightUnique()); break; case PuzzleConstraint.KingUnique: BoardValidators.Add(new KingUnique()); break; default: throw new ArgumentOutOfRangeException(); } } }
static void Main(string[] args) { var quitResponse = ""; do { Console.WriteLine("Welcome to PsuedoSolver"); var puzzleConstraints = new List <PuzzleConstraint>(); Helpers.WriteBreak(); var numColumn = GetGridColumns(); var numRow = GetGridRows(); var gridString = GetGridString(numColumn, numRow, SudokuGridString, KnightsGridString, KingsGridString, puzzleConstraints); if (!puzzleConstraints.Any()) { GetConstraints(puzzleConstraints); } Helpers.WriteBreak(); if (VerifyPuzzleParameters(numRow, numColumn, puzzleConstraints, gridString)) { continue; } Helpers.WriteBreak(); Console.WriteLine("Current Board State"); var board = new PseudoBoard(numRow, numColumn, gridString); board.PrintBoard(); Helpers.WriteBreak(); Console.WriteLine("(S)tep Solve or (N)ormal Solve?"); var solver = new PseudoSolver(puzzleConstraints, board); var solveResponse = Console.ReadLine(); if (solveResponse.ToUpperInvariant() != "S") { Console.WriteLine("You selected Normal Solve, or an invalid method was chosen.\nNormal Solve will be used.\n \nPress any key to begin"); Console.ReadLine(); solver.SolveComplete(); } else if (solveResponse.ToUpperInvariant() == "S") { Console.WriteLine("You have selected step solve."); var timer = new Stopwatch(); timer.Start(); var status = SolveStatus.BoardStart; do { status = solver.StepSolve(); if (status == SolveStatus.BoardSolved) { timer.Stop(); solver.CurrentBoard.PrintBoard(); Helpers.WriteBreak(); Console.WriteLine($"Completed Puzzle String"); Console.WriteLine(solver.CurrentBoard.SerialiseBoardToPuzzleString()); Helpers.WriteBreak(); Console.WriteLine($"Puzzle Solved in {timer.Elapsed}\nTotal Steps Taken (Validators & Solve Methods) {solver.SolverSteps.Count()}" + $"\nTotal Validator Steps Taken {solver.SolverSteps.Where(x => x.StepType == SolverStepType.ValidatorStep).Count()}" + $"\nTotal Method Steps Taken {solver.SolverSteps.Where(x => x.StepType == SolverStepType.MethodStep).Count()}" + $"\nTotal Actions Taken (Validators & Solve Methods w/ Legal Move Available) {solver.SolverSteps.Count() - solver.SolverSteps.Where(x => x.StepType == SolverStepType.FailStep).Count()}"); } //do this to capture the last solved step in the list of states } while (status != SolveStatus.NoStateChange && status != SolveStatus.BoardSolved); } Console.WriteLine("Enter any key to select a different puzzle, except for (Q).\nEnter (Q) to quit"); quitResponse = Console.ReadLine(); }while (string.IsNullOrWhiteSpace(quitResponse) || quitResponse.ToUpper() != "Q"); }
public SolveStatus StepSolve() { var boardStateChanged = false; var solvableCells = CurrentBoard.BoardCells.Where(x => !x.SolvedCell).ToList(); var noChangeMade = 0; var solveMessage = ""; var stepType = SolverStepType.FailStep; while (!boardStateChanged && !CurrentBoard.PuzzleSolved) { var baseDifficulty = 1; var validatorSuccess = false; foreach (var validator in BoardValidators.Where(x => x.ValidatorDifficulty <= baseDifficulty).ToList()) { if (validatorSuccess) { break; } foreach (var cell in solvableCells) { if (validator.ValidatePotentialCellValues(cell, CurrentBoard, out solveMessage)) { validatorSuccess = true; stepType = SolverStepType.ValidatorStep; break; } } } if (validatorSuccess) { boardStateChanged = true; noChangeMade = 0; continue; } var methodSuccess = false; foreach (var method in SolverMethods.Where(x => x.MethodDifficulty <= baseDifficulty).ToList()) { if (methodSuccess) { break; } foreach (var cell in solvableCells) { if (method.ApplyMethod(cell, CurrentBoard, out solveMessage)) { methodSuccess = true; stepType = SolverStepType.MethodStep; break; } } } if (methodSuccess) { boardStateChanged = true; noChangeMade = 0; continue; } baseDifficulty++; noChangeMade++; if (noChangeMade >= 100) { Console.WriteLine("No Board State change for 100 iterations. Solve could not complete."); Console.WriteLine($"Total Steps = {CurrentStep.SolverStepId}"); return(SolveStatus.NoStateChange); } } SolverSteps.Add(CurrentStep); var nextStep = new SolverStep { SolverStepId = CurrentStep.SolverStepId + 1, StepComment = solveMessage, StepType = stepType, BoardState = new SolverState { BoardCells = CurrentBoard.BoardCells.ToList(), SolvedState = false } }; CurrentStep = nextStep; CurrentBoard = new PseudoBoard(CurrentBoard.BoardCells.ToList()); CurrentBoard.PrintBoard(); if (!string.IsNullOrEmpty(solveMessage)) { Console.WriteLine(solveMessage); } Console.WriteLine($"Total Steps = {CurrentStep.SolverStepId}"); if (CurrentBoard.PuzzleSolved) { return(SolveStatus.BoardSolved); } return(SolveStatus.StateChange); }
public void Solve(PseudoBoard board) { var currentFailures = 0; var totalFailures = 0; var totalSteps = 0; var methodSteps = 0; var validatorSteps = 0; var timer = new Stopwatch(); timer.Start(); while (!board.PuzzleSolved) { var solvableCells = board.BoardCells.Where(x => !x.SolvedCell).ToList(); foreach (var cell in solvableCells) { var validatorSuccess = false; var methodSuccess = false; foreach (var validator in BoardValidators.OrderBy(x => x.ValidatorDifficulty)) { validatorSuccess = validator.ValidatePotentialCellValues(cell, board); if (!validatorSuccess) { currentFailures++; totalFailures++; } else { currentFailures = 0; } validatorSteps++; totalSteps++; } if (!validatorSuccess) { foreach (var method in SolverMethods.OrderBy(x => x.MethodDifficulty)) { methodSuccess = method.ApplyMethod(cell, board); if (!methodSuccess) { currentFailures++; totalFailures++; } else { currentFailures = 0; } methodSteps++; totalSteps++; } } } board.PuzzleSolved = solvableCells.All(x => x.SolvedCell); } timer.Stop(); board.PrintBoard(); Console.WriteLine(); Console.WriteLine($"Puzzle Solved in {timer.Elapsed}\nTotal Steps Taken (Validators & Solve Methods) {totalSteps}" + $"\nTotal Validator Steps Taken {validatorSteps}" + $"\nTotal Method Steps Taken {methodSteps}" + $"\nTotal Actions Taken (Validators & Solve Methods w/ Legal Move Available) {totalSteps-totalFailures}"); }
static void Main(string[] args) { var quitResponse = ""; do { Console.WriteLine("Welcome to PsuedoSolver"); var sudokuGridString = "005003060000580104300900050450039700100075000930000540500104093000358072003200600"; var knightsGridString = "003608100040000070200000003600090008000102000700060004400000001060000020005409800"; var kingsGridString = "070003000009000507010070020800205000006000400000908005050030040201000800000500090"; var puzzleConstraints = new List <PuzzleConstraint>(); WriteBreak(); var numColumn = GetGridColumns(); var numRow = GetGridRows(); var gridString = GetGridString(numColumn, numRow, sudokuGridString, knightsGridString, kingsGridString, puzzleConstraints); if (!puzzleConstraints.Any()) { GetConstraints(puzzleConstraints); } WriteBreak(); Console.WriteLine("Please verify the dimensions, constraints, and puzzle string are correct."); Console.WriteLine($"Puzzle Dimension : {numRow} Rows by {numColumn} Columns"); WriteBreak(); Console.WriteLine($"Constrains Chosen:"); foreach (var c in puzzleConstraints) { switch (c) { case PuzzleConstraint.NormalSudoku: Console.WriteLine("Normal Sudoku Rules"); break; case PuzzleConstraint.KnightsMove: Console.WriteLine("Knight's move Constraint"); break; case PuzzleConstraint.KingsMove: Console.WriteLine("King's Move Constraint"); break; default: throw new ArgumentOutOfRangeException(); } } WriteBreak(); Console.WriteLine("Puzzle String"); Console.WriteLine(gridString); WriteBreak(); Console.WriteLine("Enter any key to continue, except for (S).\nEnter (S) to start from the beginning."); if (Console.ReadLine().ToUpper() == "S") { continue; } WriteBreak(); Console.WriteLine("Current Board State"); var board = new PseudoBoard(numRow, numColumn, gridString); board.PrintBoard(); WriteBreak(); Console.WriteLine("Press any key to solve the puzzle."); Console.ReadLine(); var solver = new Solver(puzzleConstraints); solver.Solve(board); Console.WriteLine("Enter any key to select a different puzzle, except for (Q).\nEnter (Q) to quit"); quitResponse = Console.ReadLine(); }while (string.IsNullOrWhiteSpace(quitResponse) || quitResponse.ToUpper() != "Q"); }