예제 #1
0
        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;
            }
        }
예제 #2
0
 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 }));
 }
예제 #3
0
        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());
        }
예제 #4
0
        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;
                    }
                }
            }
        }
예제 #5
0
        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));
        }
예제 #6
0
        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 }));
        }
예제 #7
0
        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);
        }
예제 #8
0
        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);
        }
예제 #9
0
        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));
        }
예제 #10
0
        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);
        }
예제 #11
0
        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));
            }
        }
예제 #12
0
        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);
        }
예제 #13
0
        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);
        }
예제 #14
0
 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
     }));
 }
예제 #15
0
 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
     }));
 }
예제 #16
0
        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
            }));
        }
예제 #17
0
        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
            }));
        }
예제 #18
0
        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);
                }
            }
        }
예제 #19
0
        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);
        }
예제 #20
0
        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));
        }
예제 #21
0
 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;
 }
예제 #22
0
 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());
 }
예제 #23
0
 public static void Output(SudokuPuzzle puzzle)
 {
     System.Console.Write(puzzle.ToString());
 }
예제 #24
0
 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;
 }
예제 #25
0
        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;
                    }
                }
            }
        }
예제 #26
0
        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;
        }
예제 #27
0
 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));
 }
예제 #28
0
 public static void Output(SudokuPuzzle puzzle)
 {
     System.Console.Write(puzzle.ToString());
 }
예제 #29
0
        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));
        }