public static int[] CreateClues(SudokuPuzzle input, int maxClues = 0) { //Get a unique solution for the input puzzle, in case it wasn't already var puzzle = input.Solve(); if (puzzle == null) throw new ArgumentException("Can't create clues from an unsolvable puzzle!"); //This is the list of clues we work on. It can be reconstituted into a new puzzle object by way of a constructor int[] Clues = puzzle.Cells.Select(c => c[0]).ToArray(); var rand = new Random(); while (true) { //Pick a random cell to blank int ClueCell = rand.Next(Clues.Length); if (Clues[ClueCell] == 0) continue; var workingClues = Clues.ToArray(); workingClues[ClueCell] = 0; if (MultiSolve(new SudokuPuzzle(workingClues), 2).Count() > 1) { if (maxClues == 0) return Clues; else continue; } Clues = workingClues; if (Clues.Count(c => c != 0) <= maxClues) return Clues; } }
public static void FindSingularizedCellsTest() { var puzzle = new SudokuPuzzle("1234567.........................................................................."); var puzzle2 = puzzle.PlaceValue(7, 8); var ConstrainedCellIndexes = SudokuPuzzle.FindSingularizedCells(puzzle, puzzle2, 7); Debug.Assert(ConstrainedCellIndexes.SequenceEqual(new int[] { 8 })); }
public static void RandomGridTest() { var puzzle = SudokuPuzzle.RandomGrid(9); Debug.Assert(puzzle.Cells.All(c => c.Length == 1)); //var puzzle2 = new SudokuPuzzle(puzzle.Cells.Select(c => c.Single()).ToArray()); }
public static SudokuPuzzle RandomGrid(int size) { SudokuPuzzle puzzle = new SudokuPuzzle(size); var rand = new Random(); while (true) { int[] UnsolvedCellIndexes = puzzle.Cells .Select((cands, index) => new { cands, index }) //Project to a new sequence of candidates and index (an anonymous type behaving like a tuple) .Where(t => t.cands.Length >= 2) //Filter to cells with at least 2 candidates .Select(u => u.index) //Project the tuple to only the index .ToArray(); int cellIndex = UnsolvedCellIndexes[rand.Next(UnsolvedCellIndexes.Length)]; int candidateValue = puzzle.Cells[cellIndex][rand.Next(puzzle.Cells[cellIndex].Length)]; SudokuPuzzle workingPuzzle = puzzle.PlaceValue(cellIndex, candidateValue); if (workingPuzzle != null) { var Solutions = MultiSolve(workingPuzzle, 2); switch (Solutions.Count) { case 0: continue; case 1: return(Solutions.Single()); default: puzzle = workingPuzzle; break; } } } }
public static void TestPeers() { var p = new SudokuPuzzle(9); var peers = p.Peers(40); var expectedResult = new int[] { 4, 13, 22, 30, 31, 32, 36, 37, 38, 39, 41, 42, 43, 44, 48, 49, 50, 58, 67, 76 }; Debug.Assert(peers.SequenceEqual(expectedResult)); }
public static void MultiSolveTest() { var puzzle = new SudokuPuzzle(" 456789679813245548927136 594678857361492964782513 648957796135824485279361"); var solutions = SudokuPuzzle.MultiSolve(puzzle); Debug.Assert(solutions.Count() == 12); solutions = SudokuPuzzle.MultiSolve(puzzle, 2); Debug.Assert(solutions.Count() == 2); }
public static void ApplyConstraintsTest() { int cell = 0; int value = 1; var puzzle = new SudokuPuzzle(9).ApplyConstraints(cell, value); Debug.Assert(puzzle.Cells[cell].Single() == value); foreach (int peerIndex in puzzle.Peers(cell)) Debug.Assert(!puzzle.Cells[peerIndex].Contains(value)); }
public static List <SudokuPuzzle> MultiSolve(SudokuPuzzle input, int MaximumSolutions = -1) { var Solutions = new List <SudokuPuzzle>(); input.Solve(p => { Solutions.Add(p); return(Solutions.Count() < MaximumSolutions || MaximumSolutions == -1); }); return(Solutions); }
public static void ApplyConstraintsTest() { int cell = 0; int value = 1; var puzzle = new SudokuPuzzle(9).ApplyConstraints(cell, value); Debug.Assert(puzzle.Cells[cell].Single() == value); foreach (int peerIndex in puzzle.Peers(cell)) { Debug.Assert(!puzzle.Cells[peerIndex].Contains(value)); } }
public virtual object Clone() { var clone = new SudokuPuzzle(this.Length); clone.Cells = new int[this.Cells.Length][]; for (int i = 0; i < this.Cells.Length; i++) { clone.Cells[i] = new int[this.Cells[i].Length]; Buffer.BlockCopy(this.Cells[i], 0, clone.Cells[i], 0, Buffer.ByteLength(this.Cells[i])); } return(clone); }
public static List <int> FindSingularizedCells(SudokuPuzzle puzzle1, SudokuPuzzle puzzle2, int cellIndex) { Debug.Assert(puzzle1.Length == puzzle2.Length); var result = new List <int>(); foreach (int i in puzzle1.Peers(cellIndex)) { if (puzzle1.Cells[i].Length > 1 && puzzle2.Cells[i].Length == 1) { result.Add(i); } } return(result); }
public static void SimpleTest() { var p = new SudokuPuzzle(TestPuzzle); p = p.Solve(); Debug.Assert(p.Cells.Select(c => c[0]).SequenceEqual(new int[] { 4, 8, 3, 9, 2, 1, 6, 5, 7, 9, 6, 7, 3, 4, 5, 8, 2, 1, 2, 5, 1, 8, 7, 6, 4, 9, 3, 5, 4, 8, 1, 3, 2, 9, 7, 6, 7, 2, 9, 5, 6, 4, 1, 3, 8, 1, 3, 6, 7, 9, 8, 2, 4, 5, 3, 7, 2, 6, 8, 9, 5, 1, 4, 8, 1, 4, 2, 5, 3, 7, 6, 9, 6, 9, 5, 4, 1, 7, 3, 8, 2 })); }
public static void SimpleTest2() { var p = new SudokuPuzzle("53..7....6..195....98....6.8...6...34..8.3..17...2...6.6....28....419..5....8..79"); p = p.Solve(); Debug.Assert(p.Cells.Select(c => c[0]).SequenceEqual(new int[] { 5, 3, 4, 6, 7, 8, 9, 1, 2, 6, 7, 2, 1, 9, 5, 3, 4, 8, 1, 9, 8, 3, 4, 2, 5, 6, 7, 8, 5, 9, 7, 6, 1, 4, 2, 3, 4, 2, 6, 8, 5, 3, 7, 9, 1, 7, 1, 3, 9, 2, 4, 8, 5, 6, 9, 6, 1, 5, 3, 7, 2, 8, 4, 2, 8, 7, 4, 1, 9, 6, 3, 5, 3, 4, 5, 2, 8, 6, 1, 7, 9 })); }
public static int[] CreateClues(SudokuPuzzle input, int maxClues = 0) { //Get a unique solution for the input puzzle, in case it wasn't already var puzzle = input.Solve(); if (puzzle == null) { throw new ArgumentException("Can't create clues from an unsolvable puzzle!"); } //This is the list of clues we work on. It can be reconstituted into a new puzzle object by way of a constructor int[] Clues = puzzle.Cells.Select(c => c[0]).ToArray(); var rand = new Random(); while (true) { //Pick a random cell to blank int ClueCell = rand.Next(Clues.Length); if (Clues[ClueCell] == 0) { continue; } var workingClues = Clues.ToArray(); workingClues[ClueCell] = 0; if (MultiSolve(new SudokuPuzzle(workingClues), 2).Count() > 1) { if (maxClues == 0) { return(Clues); } else { continue; } } Clues = workingClues; if (Clues.Count(c => c != 0) <= maxClues) { return(Clues); } } }
public virtual SudokuPuzzle ApplyConstraints(int cellIndex, int value) { SudokuPuzzle puzzle = (SudokuPuzzle)this.Clone(); //Standard Sudoku constraint logic: Set this cell to one and only one candidate, and remove this value from the candidate list of all its peers puzzle.Cells[cellIndex] = new int[] { value }; foreach (int peerIndex in puzzle.Peers(cellIndex)) { var newPeers = puzzle.Cells[peerIndex].Except(new int[] { value }).ToArray(); if (!newPeers.Any()) { return(null); } puzzle.Cells[peerIndex] = newPeers; } return(puzzle); }
public static void Top95TimedTest() { var stream = new StreamReader("top95.txt"); var puzzles = new List <String>(); while (!stream.EndOfStream) { puzzles.Add(stream.ReadLine()); } stream.Close(); var times = puzzles.Select(p => { DateTime start = DateTime.Now; var puz = new SudokuPuzzle(p).Solve(); SudokuPuzzle.Output(puz); return(DateTime.Now - start); }).ToList(); Console.WriteLine("Average: " + times.Average(ts => ts.TotalSeconds)); Console.WriteLine("Worst: " + times.Max(ts => ts.TotalSeconds)); }
public static List<int> FindSingularizedCells(SudokuPuzzle puzzle1, SudokuPuzzle puzzle2, int cellIndex) { Debug.Assert(puzzle1.Length == puzzle2.Length); var result = new List<int>(); foreach (int i in puzzle1.Peers(cellIndex)) { if (puzzle1.Cells[i].Length > 1 && puzzle2.Cells[i].Length == 1) result.Add(i); } return result; }
public static void RandomGridTest() { var puzzle = SudokuPuzzle.RandomGrid(9); Debug.Assert(puzzle.Cells.All(c => c.Length == 1)); var puzzle2 = new SudokuPuzzle(puzzle.Cells.Select(c => c.Single()).ToArray()); }
public static void Output(SudokuPuzzle puzzle) { System.Console.Write(puzzle.ToString()); }
public static List<SudokuPuzzle> MultiSolve(SudokuPuzzle input, int MaximumSolutions = -1) { var Solutions = new List<SudokuPuzzle>(); input.Solve(p => { Solutions.Add(p); return Solutions.Count() < MaximumSolutions || MaximumSolutions == -1; }); return Solutions; }
public static SudokuPuzzle RandomGrid(int size) { SudokuPuzzle puzzle = new SudokuPuzzle(size); var rand = new Random(); while (true) { int[] UnsolvedCellIndexes = puzzle.Cells .Select((cands, index) => new { cands, index }) //Project to a new sequence of candidates and index (an anonymous type behaving like a tuple) .Where(t => t.cands.Length >= 2) //Filter to cells with at least 2 candidates .Select(u => u.index) //Project the tuple to only the index .ToArray(); int cellIndex = UnsolvedCellIndexes[rand.Next(UnsolvedCellIndexes.Length)]; int candidateValue = puzzle.Cells[cellIndex][rand.Next(puzzle.Cells[cellIndex].Length)]; SudokuPuzzle workingPuzzle = puzzle.PlaceValue(cellIndex, candidateValue); if (workingPuzzle != null) { var Solutions = MultiSolve(workingPuzzle, 2); switch (Solutions.Count) { case 0: continue; case 1: return Solutions.Single(); default: puzzle = workingPuzzle; break; } } } }
public virtual object Clone() { var clone = new SudokuPuzzle(this.Length); clone.Cells = new int[this.Cells.Length][]; for (int i = 0; i < this.Cells.Length; i++) { clone.Cells[i] = new int[this.Cells[i].Length]; Buffer.BlockCopy(this.Cells[i], 0, clone.Cells[i], 0, Buffer.ByteLength(this.Cells[i])); } return clone; }
public static void Top95TimedTest() { var stream = new StreamReader("top95.txt"); var puzzles = new List<String>(); while (!stream.EndOfStream) puzzles.Add(stream.ReadLine()); stream.Close(); var times = puzzles.Select(p => { DateTime start = DateTime.Now; var puz = new SudokuPuzzle(p).Solve(); SudokuPuzzle.Output(puz); return (DateTime.Now - start); }).ToList(); Console.WriteLine("Average: " + times.Average(ts => ts.TotalSeconds)); Console.WriteLine("Worst: " + times.Max(ts => ts.TotalSeconds)); }