public SubProblem Prune(KenKenBoard prune) { // Prune this solution set given a board state. SubProblem ret = new SubProblem(Operator, Value); ret.mSolutions = new List<List<int>>(); ret.mSquares = mSquares; // Iterate through every solution. foreach (var sol in Solutions) { bool success = true; // See if we can place this solution on the board. for (int i = 0; i < mSquares.Count; i++) { if (!prune.CanPlace(mSquares[i], sol[i])) { success = false; break; } } if (success) ret.mSolutions.Add(sol); } // No solutions = fail! if (mSolutions.Count == 0) return null; return ret; }
public KenKenBoard Solve(KenKenBoard board) { if (0 == mAll.Count) return board; // Get the next SubProblem that we want to try. var subproblem = mAll[0]; var squares = subproblem.Squares; // Iterate through all the solutions. foreach (var solution in subproblem.Solutions) { for (int i = 0; i < solution.Count; i++) { // No ned to check the result, since the solution // set is pruned to only valid solutions. board.TryPlace(squares[i], solution[i]); } // Prune the board with this solution. var newProb = Prune(board); if (newProb != null) { // Resort based on the new pruned solutions. newProb.Sort(); var ret = newProb.Solve(board); if (ret != null) return ret; } // Undo board state change. foreach (Point p in squares) board.UnsetPlace(p); } // No solution in this branch! return null; }
public void Solve() { // Just do some sanity checking to make sure every cell is part of a subproblem. for (int x = 0; x < 9; x++) { for (int y = 0; y < 9; y++) { if (mSubProblems[x, y] == null) Console.WriteLine("{0} {1}", x, y); Debug.Assert(mSubProblems[x, y] != null); mSubProblems[x, y].Squares.Add(new Point(x, y)); } } // Generate the solution set for each SubProblem. for (int x = 0; x < 9; x++) { for (int y = 0; y < 9; y++) { mSubProblems[x, y].GenerateSolutions(); } } // Grab all the unique subproblems from the 9 by 9 board. Dictionary<SubProblem, int> subProblems = new Dictionary<SubProblem, int>(); for (int x = 0; x < 9; x++) { for (int y = 0; y < 9; y++) { if (!subProblems.ContainsKey(mSubProblems[x, y])) { var sub = mSubProblems[x, y]; subProblems.Add(sub, sub.Squares.Count); } } } // Add the unique subproblems to a list. mAll = new List<SubProblem>(); foreach (var val in subProblems.Keys) { var squares = val.Squares; // Filter out invalid solutions, ie, 6+ = 2 2 2 would never be valid. foreach (var solution in new List<List<int>>(val.Solutions)) { KenKenBoard test = new KenKenBoard(); for (int i = 0; i < solution.Count; i++) { if (!test.TryPlace(squares[i], solution[i])) { val.Solutions.Remove(solution); break; } } } mAll.Add(val); } // Sort the list in order of increasing number of possible solutions. Sort(); // Attempt to solve with a empty KenKenBoard. var ret = Solve(new KenKenBoard()); if (ret != null) ret.Print(); else Console.WriteLine("fail"); }
public Problem Prune(KenKenBoard board) { // Prune out solutions that are no longer valid // given the current board. Problem ret = new Problem(); ret.mAll = new List<SubProblem>(); for (int i = 1; i < mAll.Count; i++) { SubProblem sub = mAll[i]; SubProblem s = sub.Prune(board); // If there are no solutions for this pruned SubProblem, this Problem failed. if (s == null) return null; ret.mAll.Add(s); } return ret; }