public void Solve_WithInvalidPuzzle_Throws(int?[][] matrix)
        {
            var puzzle = new PuzzleWithPossibleValues(matrix);
            var solver = StandardPuzzles.CreateSolver();

            Assert.Throws <ArgumentException>(() => solver.Solve(puzzle));
        }
        public void Revert_RevertsSpecifiedCoordinate()
        {
            var puzzle = new PuzzleWithPossibleValues(new int?[][] {
                new int?[] { 1, null /* 4 */, null /* 3 */, 2 },
                new int?[] { null /* 2 */, null /* 3 */, 1, null /* 4 */ },
                new int?[] { null /* 4 */, null /* 1 */, null /* 2 */, null /* 3 */ },
                new int?[] { 3, 2, 4, 1 }
            });
            var rules = new IRule[]
            {
                new RowUniquenessRule(),
                new ColumnUniquenessRule(),
                new BoxUniquenessRule()
            };
            var ruleKeeper = new DynamicRuleKeeper(rules);

            Assert.True(ruleKeeper.TryInit(puzzle));
            IDictionary <Coordinate, BitVector> initialPossibleValues = _RetrieveAllUnsetPossibleValues(puzzle);
            var coord = new Coordinate(1, 1);
            int val   = 3;

            Assert.True(ruleKeeper.TrySet(in coord, val));

            ruleKeeper.Unset(in coord, val);

            foreach (Coordinate c in puzzle.GetUnsetCoords())
            {
                Assert.Equal(initialPossibleValues[c], puzzle.GetPossibleValues(in c));
            }
        }
        public void Update_UpdatesSpecifiedBox()
        {
            var puzzle = new PuzzleWithPossibleValues(new int?[][] {
                new int?[] { 1, null /* 4 */, null /* 3 */, 2 },
                new int?[] { null /* 2 */, 3, null /* 1 */, null /* 4 */ },
                new int?[] { null /* 4 */, null /* 1 */, 2, 3 },
                new int?[] { null /* 3 */, null /* 2 */, 4, 1 }
            });
            var rule = new BoxUniquenessRule();

            Assert.True(rule.TryInit(puzzle, puzzle.UniquePossibleValues));
            var coordTracker = new CoordinateTracker(puzzle.Size);
            var coord        = new Coordinate(1, 2);
            int val          = 1;

            rule.Update(coord, val, coordTracker);

            Assert.Equal(
                new HashSet <Coordinate> {
                new Coordinate(0, 2), new Coordinate(1, 3)
            },
                new HashSet <Coordinate>(coordTracker.TrackedCoords.ToArray()));
            Assert.Equal(new BitVector(0b10100), rule.GetPossibleValues(new Coordinate(0, 0)));
            Assert.Equal(new BitVector(0b11000), rule.GetPossibleValues(new Coordinate(0, 2)));
            Assert.Equal(new BitVector(0b11110), rule.GetPossibleValues(new Coordinate(2, 0)));
            Assert.Equal(new BitVector(0b00000), rule.GetPossibleValues(new Coordinate(2, 2)));
        }
        public void UpdateAll_ModifiesRelevantPossibles()
        {
            var puzzle = new PuzzleWithPossibleValues(new int?[][] {
                new int?[] { 1, null /* 4 */, null /* 3 */, 2 },
                new int?[] { null /* 2 */, null /* 3 */, null /* 1 */, 4 },
                new int?[] { null /* 4 */, null /* 1 */, null /* 2 */, 3 },
                new int?[] { 3, 2, null /* 4 */, 1 }
            });
            var ruleKeeper = new StandardRuleKeeper();

            Assert.True(ruleKeeper.TryInit(puzzle));
            var heuristic = new UniqueInColumnHeuristic(
                (IMissingColumnValuesTracker)ruleKeeper.GetRules()[0]);

            Assert.True(heuristic.TryInitFor(puzzle));

            Assert.Equal(new BitVector(0b11000), puzzle.GetPossibleValues(new Coordinate(0, 1))); // Pre-modified
            Assert.Equal(new BitVector(0b10010), puzzle.GetPossibleValues(new Coordinate(2, 1))); // Pre-modified
            Assert.Equal(new BitVector(0b01010), puzzle.GetPossibleValues(new Coordinate(1, 2))); // Pre-modified
            Assert.Equal(new BitVector(0b10100), puzzle.GetPossibleValues(new Coordinate(2, 2))); // Pre-modified

            heuristic.UpdateAll();

            Assert.Equal(new BitVector(0b00100), puzzle.GetPossibleValues(new Coordinate(1, 0)));
            Assert.Equal(new BitVector(0b10000), puzzle.GetPossibleValues(new Coordinate(2, 0)));
            Assert.Equal(new BitVector(0b10000), puzzle.GetPossibleValues(new Coordinate(0, 1))); // Modified
            Assert.Equal(new BitVector(0b01000), puzzle.GetPossibleValues(new Coordinate(1, 1)));
            Assert.Equal(new BitVector(0b00010), puzzle.GetPossibleValues(new Coordinate(2, 1))); // Modified
            Assert.Equal(new BitVector(0b01000), puzzle.GetPossibleValues(new Coordinate(0, 2)));
            Assert.Equal(new BitVector(0b00010), puzzle.GetPossibleValues(new Coordinate(1, 2))); // Modified
            Assert.Equal(new BitVector(0b00100), puzzle.GetPossibleValues(new Coordinate(2, 2))); // Modified
            Assert.Equal(new BitVector(0b10000), puzzle.GetPossibleValues(new Coordinate(3, 2)));
        }
        public void TrySet_WithValidValue_Succeeds()
        {
            var puzzle = new PuzzleWithPossibleValues(new int?[][] {
                new int?[] { 1, null /* 4 */, null /* 3 */, 2 },
                new int?[] { null /* 2 */, null /* 3 */, 1, null /* 4 */ },
                new int?[] { null /* 4 */, null /* 1 */, null /* 2 */, null /* 3 */ },
                new int?[] { 3, 2, 4, 1 }
            });
            var rules = new IRule[]
            {
                new RowUniquenessRule(),
                new ColumnUniquenessRule(),
                new BoxUniquenessRule()
            };
            var ruleKeeper = new DynamicRuleKeeper(rules);

            Assert.True(ruleKeeper.TryInit(puzzle));
            var coord = new Coordinate(1, 1);
            int val   = 3;

            Assert.True(ruleKeeper.TrySet(coord, val));

            puzzle[coord] = val;
            Assert.Equal(new BitVector(0b10000), puzzle.GetPossibleValues(new Coordinate(0, 1)));
            Assert.Equal(new BitVector(0b10100), puzzle.GetPossibleValues(new Coordinate(1, 0)));
            Assert.Equal(new BitVector(0b10000), puzzle.GetPossibleValues(new Coordinate(1, 3)));
            Assert.Equal(new BitVector(0b10010), puzzle.GetPossibleValues(new Coordinate(2, 1)));
        }
        public void TryInit_FiltersCorrectly()
        {
            var puzzle = new PuzzleWithPossibleValues(new int?[][] {
                new int?[] { null, null, 9, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, 3, 5, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
            });
            var magicSquares = new Box[] {
                new Box(new Coordinate(0, 0), 3),
            };
            var rule = new MagicSquaresRule(puzzle.Size, magicSquares, includeDiagonals: false);

            Assert.True(rule.TryInit(puzzle, puzzle.UniquePossibleValues));

            Assert.Equal(new BitVector(0b0000110110), rule.GetPossibleValues(new Coordinate(0, 0)));
            Assert.Equal(new BitVector(0b0000110000), rule.GetPossibleValues(new Coordinate(0, 1)));
            Assert.Equal(new BitVector(0b1111111110), rule.GetPossibleValues(new Coordinate(1, 0)));
            Assert.Equal(new BitVector(0b0110110000), rule.GetPossibleValues(new Coordinate(1, 1)));
            Assert.Equal(new BitVector(0b0000000010), rule.GetPossibleValues(new Coordinate(1, 2)));
            Assert.Equal(new BitVector(0b0010000000), rule.GetPossibleValues(new Coordinate(2, 0)));
            Assert.Equal(new BitVector(0b1111111110), rule.GetPossibleValues(new Coordinate(3, 0)));
        }
Beispiel #7
0
        public void Revert_RevertsSpecifiedColumn()
        {
            var puzzle = new PuzzleWithPossibleValues(new int?[][] {
                new int?[] { 1, null /* 4 */, null /* 3 */, 2 },
                new int?[] { null /* 2 */, null /* 3 */, null /* 1 */, 4 },
                new int?[] { null /* 4 */, 1, null /* 2 */, 3 },
                new int?[] { 3, null /* 2 */, null /* 4 */, 1 }
            });
            var rule = new ColumnUniquenessRule();

            Assert.True(rule.TryInit(puzzle, puzzle.UniquePossibleValues));
            IList <BitVector> initialPossibleValuesByColumn = _GetPossibleValuesByColumn(puzzle.Size, rule);
            var updatedCoordTracker = new CoordinateTracker(puzzle.Size);
            var coord = new Coordinate(1, 1);
            int val   = 3;

            rule.Update(coord, val, updatedCoordTracker);

            var revertedCoordTracker = new CoordinateTracker(puzzle.Size);

            rule.Revert(coord, val, revertedCoordTracker);

            Assert.Equal(
                updatedCoordTracker.TrackedCoords.ToArray(),
                revertedCoordTracker.TrackedCoords.ToArray());
            for (int column = 0; column < initialPossibleValuesByColumn.Count; column++)
            {
                Assert.Equal(
                    initialPossibleValuesByColumn[column],
                    rule.GetMissingValuesForColumn(column));
            }
        }
Beispiel #8
0
        public void Revert_WithoutAffectedList_RevertsSpecifiedRow()
        {
            var p = new Puzzle(
                new int?[][] {
                new int?[] { 1, null /* 2 */, null /* 3 */, 2 },
                new int?[] { null /* 2 */, null /* 3 */, 1, null /* 2 */ },
                new int?[] { null /* 2 */, null /* 1 */, null /* 2 */, null /* 3 */ },
                new int?[] { 3, 2, 2, 1 },
            }, new int[] { 1, 2, 2, 3 });
            var puzzle = new PuzzleWithPossibleValues(p);
            var rule   = new MaxCountPerColumnRule();

            Assert.True(rule.TryInit(puzzle, puzzle.UniquePossibleValues));
            IList <BitVector> initialPossibleValuesByColumn = _GetPossibleValuesByColumn(puzzle.Size, rule);
            var coord = new Coordinate(1, 1);
            int val   = 3;

            rule.Update(coord, val, new CoordinateTracker(puzzle.Size));

            rule.Revert(coord, val);

            for (int column = 0; column < initialPossibleValuesByColumn.Count; column++)
            {
                Assert.Equal(
                    initialPossibleValuesByColumn[column], rule.GetMissingValuesForColumn(column));
            }
        }
Beispiel #9
0
        public void UpdateAndRevert_WithDuplicatePossibleValue()
        {
            var p = new Puzzle(
                new int?[][] {
                new int?[] { 1, null /* 2 */, null /* 3 */, 2 },
                new int?[] { null /* 2 */, null /* 3 */, 1, null /* 2 */ },
                new int?[] { null /* 2 */, null /* 1 */, null /* 2 */, null /* 3 */ },
                new int?[] { 3, 2, 2, 1 },
            }, new int[] { 1, 2, 2, 3 });
            var puzzle = new PuzzleWithPossibleValues(p);
            var rule   = new MaxCountPerRowRule();

            Assert.True(rule.TryInit(puzzle, puzzle.UniquePossibleValues));
            var coordTracker = new CoordinateTracker(puzzle.Size);

            rule.Update(new Coordinate(1, 0), 2, coordTracker);
            Assert.Equal(new BitVector(0b1100), rule.GetPossibleValues(new Coordinate(1, 0)));
            rule.Update(new Coordinate(1, 3), 2, coordTracker);
            Assert.Equal(new BitVector(0b1000), rule.GetPossibleValues(new Coordinate(1, 0)));

            rule.Revert(new Coordinate(1, 3), 2, coordTracker);
            Assert.Equal(new BitVector(0b1100), rule.GetPossibleValues(new Coordinate(1, 0)));
            rule.Revert(new Coordinate(1, 0), 2, coordTracker);
            Assert.Equal(new BitVector(0b1100), rule.GetPossibleValues(new Coordinate(1, 0)));
        }
Beispiel #10
0
        public void Revert_RevertsSpecifiedDiagonal()
        {
            var puzzle = new PuzzleWithPossibleValues(new int?[][] {
                new int?[] { 1, null, null, 4 },
                new int?[] { null, null, 3, 2 },
                new int?[] { 2, null, null, null },
                new int?[] { null, null, null, null }
            });
            var rule = new DiagonalUniquenessRule();

            Assert.True(rule.TryInit(puzzle, puzzle.UniquePossibleValues));
            BitVector[,] initialPossibles = _GetPossibleValues(puzzle.Size, rule);
            var updatedCoordTracker = new CoordinateTracker(puzzle.Size);
            var coord = new Coordinate(2, 2);
            int val   = 4;

            rule.Update(in coord, val, updatedCoordTracker);

            var revertedCoordTracker = new CoordinateTracker(puzzle.Size);

            rule.Revert(coord, val, revertedCoordTracker);

            Assert.Equal(
                revertedCoordTracker.TrackedCoords.ToArray(),
                updatedCoordTracker.TrackedCoords.ToArray());
            for (int row = 0; row < puzzle.Size; row++)
            {
                for (int col = 0; col < puzzle.Size; col++)
                {
                    Assert.Equal(
                        initialPossibles[row, col],
                        rule.GetPossibleValues(new Coordinate(row, col)));
                }
            }
        }
Beispiel #11
0
        public void Revert_OnNonDiagonal_DoesNothing()
        {
            var puzzle = new PuzzleWithPossibleValues(new int?[][] {
                new int?[] { 1, null, null, 4 },
                new int?[] { null, null, 3, 2 },
                new int?[] { 2, null, null, null },
                new int?[] { null, null, null, null }
            });
            var rule = new DiagonalUniquenessRule();

            Assert.True(rule.TryInit(puzzle, puzzle.UniquePossibleValues));
            BitVector[,] previousPossibles = _GetPossibleValues(puzzle.Size, rule);
            var coordTracker = new CoordinateTracker(puzzle.Size);
            var coord        = new Coordinate(0, 1);
            int val          = 2;

            rule.Update(in coord, val, new CoordinateTracker(puzzle.Size));

            rule.Revert(coord, val, coordTracker);

            Assert.Equal(0, coordTracker.NumTracked);
            for (int row = 0; row < puzzle.Size; row++)
            {
                for (int col = 0; col < puzzle.Size; col++)
                {
                    Assert.Equal(
                        previousPossibles[row, col],
                        rule.GetPossibleValues(new Coordinate(row, col)));
                }
            }
        }
Beispiel #12
0
        public void Update_OnDiagonal_UpdatesSpecifiedDiagonal()
        {
            var puzzle = new PuzzleWithPossibleValues(new int?[][] {
                new int?[] { 1, null, null, 4 },
                new int?[] { null, null, 3, 2 },
                new int?[] { 2, null, null, null },
                new int?[] { null, null, null, null }
            });
            var rule = new DiagonalUniquenessRule();

            Assert.True(rule.TryInit(puzzle, puzzle.UniquePossibleValues));
            var coordTracker = new CoordinateTracker(puzzle.Size);
            var coord        = new Coordinate(2, 2);
            int val          = 4;

            rule.Update(coord, val, coordTracker);

            Assert.Equal(
                new HashSet <Coordinate> {
                new Coordinate(1, 1), new Coordinate(3, 3)
            },
                new HashSet <Coordinate>(coordTracker.TrackedCoords.ToArray()));
            Assert.Equal(new BitVector(0b01100), rule.GetPossibleValues(new Coordinate(1, 1)));
            Assert.Equal(new BitVector(0b00110), rule.GetPossibleValues(new Coordinate(1, 2)));
            Assert.Equal(new BitVector(0b11110), rule.GetPossibleValues(new Coordinate(0, 2)));
        }
Beispiel #13
0
        public void TrySolve_MegaPuzzle_Solves()
        {
            var puzzle = new PuzzleWithPossibleValues(new int?[][] {
                new int?[] { null, null, null, null, 10, 1, null, 8, null, 15, 3, 11, null, 2, 16, null },
                new int?[] { 14, null, 2, null, null, 4, 3, null, null, 13, 8, null, null, 12, null, null },
                new int?[] { null, null, null, 12, null, null, null, 15, null, null, null, 7, null, null, 9, 10 },
                new int?[] { 1, 10, 15, null, 6, null, null, null, null, 14, null, null, null, null, null, 11 },
                new int?[] { null, 11, 14, 6, null, null, null, 9, 13, 8, null, null, null, null, 2, 3 },
                new int?[] { 12, null, null, null, 4, null, 7, 3, 11, 6, null, null, 16, null, 5, null },
                new int?[] { 13, 16, null, 2, null, null, null, 1, null, null, 5, null, 10, 9, null, null },
                new int?[] { null, 4, null, null, 13, null, 2, null, null, null, 16, 3, 11, null, null, null },
                new int?[] { null, null, null, 10, 3, 6, null, null, null, 9, null, 12, null, null, 4, null },
                new int?[] { null, null, 12, 15, null, 9, null, null, 7, null, null, null, 1, null, 3, 14 },
                new int?[] { null, 1, null, 4, null, null, 5, 12, 3, 10, null, 8, null, null, null, 2 },
                new int?[] { 3, 6, null, null, null, null, 15, 10, 4, null, null, null, 12, 5, 7, null },
                new int?[] { 2, null, null, null, null, null, 4, null, null, null, null, 15, null, 16, 11, 9 },
                new int?[] { 4, 14, null, null, 16, null, null, null, 2, null, null, null, 6, null, null, null },
                new int?[] { null, null, 16, null, null, 7, 8, null, null, 4, 10, null, null, 14, null, 5 },
                new int?[] { null, 3, 6, null, 9, 12, 14, null, 8, null, 13, 16, null, null, null, null }
            });
            var rowRule      = new RowUniquenessRule();
            var columnRule   = new ColumnUniquenessRule();
            var boxRule      = new BoxUniquenessRule();
            var diagonalRule = new DiagonalUniquenessRule();
            var ruleKeeper   = new DynamicRuleKeeper(
                new IRule[] { rowRule, columnRule, boxRule, diagonalRule });
            var heuristic = new StandardHeuristic(
                rowRule, columnRule, boxRule);
            var solver = new PuzzleSolver <PuzzleWithPossibleValues>(ruleKeeper, heuristic);

            Assert.True(solver.TrySolve(puzzle));
            _AssertMegaPuzzleSolved(puzzle);
        }
Beispiel #14
0
        public void TrySolve_WithInvalidPuzzle_ReturnsFalse(int?[][] matrix)
        {
            var puzzle = new PuzzleWithPossibleValues(matrix);
            var solver = StandardPuzzles.CreateSolver();

            Assert.False(solver.TrySolve(puzzle));
        }
        public void TryInit_WithDiagonals_FiltersCorrectly()
        {
            var puzzle = new PuzzleWithPossibleValues(new int?[][] {
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, 6, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, 3, 8, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
            });
            var magicSquares = new Box[] {
                new Box(new Coordinate(3, 3), 3),
            };
            var rule = new MagicSquaresRule(puzzle.Size, magicSquares, includeDiagonals: true);

            Assert.True(rule.TryInit(puzzle, puzzle.UniquePossibleValues));

            Assert.Equal(new BitVector(0b0000110110), rule.GetPossibleValues(new Coordinate(3, 3)));
            Assert.Equal(new BitVector(0b0110110000), rule.GetPossibleValues(new Coordinate(3, 4)));
            Assert.Equal(new BitVector(0b1111111110), rule.GetPossibleValues(new Coordinate(4, 3)));
            Assert.Equal(new BitVector(0b0000110000), rule.GetPossibleValues(new Coordinate(4, 4)));
            Assert.Equal(new BitVector(0b0000000010), rule.GetPossibleValues(new Coordinate(4, 5)));
            Assert.Equal(new BitVector(0b0000010000), rule.GetPossibleValues(new Coordinate(5, 3)));
            Assert.Equal(new BitVector(0b1111111110), rule.GetPossibleValues(new Coordinate(6, 3)));
        }
Beispiel #16
0
        public void Revert_RevertsSpecifiedRow()
        {
            var p = new Puzzle(
                new int?[][] {
                new int?[] { 1, null /* 2 */, null /* 3 */, 2 },
                new int?[] { null /* 2 */, null /* 3 */, 1, null /* 2 */ },
                new int?[] { null /* 2 */, null /* 1 */, null /* 2 */, null /* 3 */ },
                new int?[] { 3, 2, 2, 1 },
            }, new int[] { 1, 2, 2, 3 });
            var puzzle = new PuzzleWithPossibleValues(p);
            var rule   = new MaxCountPerRowRule();

            Assert.True(rule.TryInit(puzzle, puzzle.UniquePossibleValues));
            IList <BitVector> initialPossibleValuesByRow = _GetPossibleValuesByRow(puzzle.Size, rule);
            var updatedCoordTracker  = new CoordinateTracker(puzzle.Size);
            var revertedCoordTracker = new CoordinateTracker(puzzle.Size);
            var coord = new Coordinate(1, 1);
            int val   = 3;

            rule.Update(coord, val, updatedCoordTracker);

            rule.Revert(coord, val, revertedCoordTracker);

            Assert.Equal(
                updatedCoordTracker.TrackedCoords.ToArray(),
                revertedCoordTracker.TrackedCoords.ToArray());
            for (int row = 0; row < initialPossibleValuesByRow.Count; row++)
            {
                Assert.Equal(
                    initialPossibleValuesByRow[row],
                    rule.GetMissingValuesForRow(row));
            }
        }
        public void HasUniqueSolution_WithOneSolutionUsingDiagonals_IsTrue()
        {
            var puzzle = new PuzzleWithPossibleValues(new int?[][] {
                new int?[] { null, null, null, null, null, null, null, 1, 2 },
                new int?[] { null, 5, null, null, 9, null, null, null, null },
                new int?[] { null, null, null, null, null, 8, null, null, null },
                new int?[] { null, 3, null, null, null, null, 5, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, 9, null },
                new int?[] { null, null, null, null, 4, 3, 9, null, null },
                new int?[] { 6, null, 1, null, null, null, 7, null, null },
                new int?[] { 2, null, null, null, null, null, null, null, null },
            });
            var magicSquares = new Box[] {
                new Box(new Coordinate(3, 3), 3),
            };
            var solver = new PuzzleSolver <PuzzleWithPossibleValues>(
                new DynamicRuleKeeper(
                    new IRule[] {
                new RowUniquenessRule(),
                new ColumnUniquenessRule(),
                new BoxUniquenessRule(),
                new MagicSquaresRule(puzzle.Size, magicSquares, includeDiagonals: true),
            }));

            Assert.True(solver.HasUniqueSolution(puzzle));
        }
Beispiel #18
0
        public void Update_UpdatesSpecifiedRow()
        {
            var p = new Puzzle(
                new int?[][] {
                new int?[] { 1, null /* 2 */, null /* 3 */, 2 },
                new int?[] { null /* 2 */, null /* 3 */, 1, null /* 2 */ },
                new int?[] { null /* 2 */, null /* 1 */, null /* 2 */, null /* 3 */ },
                new int?[] { 3, 2, 2, 1 },
            }, new int[] { 1, 2, 2, 3 });
            var puzzle = new PuzzleWithPossibleValues(p);
            var rule   = new MaxCountPerRowRule();

            Assert.True(rule.TryInit(puzzle, puzzle.UniquePossibleValues));
            var coordTracker = new CoordinateTracker(puzzle.Size);
            var coord        = new Coordinate(1, 1);
            int val          = 3;

            rule.Update(coord, val, coordTracker);

            Assert.Equal(
                new HashSet <Coordinate> {
                new Coordinate(1, 0), new Coordinate(1, 3)
            },
                new HashSet <Coordinate>(coordTracker.TrackedCoords.ToArray()));
            Assert.Equal(new BitVector(0b1100), rule.GetPossibleValues(new Coordinate(0, 0)));
            Assert.Equal(new BitVector(0b0100), rule.GetPossibleValues(new Coordinate(1, 0)));
            Assert.Equal(new BitVector(0b1110), rule.GetPossibleValues(new Coordinate(2, 0)));
            Assert.Equal(new BitVector(0b0000), rule.GetPossibleValues(new Coordinate(3, 0)));
        }
        public int SudokuSpice()
        {
            var generator = new StandardPuzzleGenerator();
            PuzzleWithPossibleValues puzzle = generator.Generate(9, 30, TimeSpan.FromSeconds(10));

            return(puzzle.NumEmptySquares);
        }
        public void Update_UpdatesSpecifiedRow()
        {
            var puzzle = new PuzzleWithPossibleValues(new int?[][] {
                new int?[] { null, null, 9, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, 3, 5, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
            });
            var magicSquares = new Box[] {
                new Box(new Coordinate(0, 0), 3),
            };
            var rule = new MagicSquaresRule(puzzle.Size, magicSquares, includeDiagonals: false);

            Assert.True(rule.TryInit(puzzle, puzzle.UniquePossibleValues));

            int val   = 4;
            var coord = new Coordinate(0, 1);
            var affectedCoordinates = new CoordinateTracker(puzzle.Size);

            rule.Update(coord, val, affectedCoordinates);
            Assert.Equal(
                new HashSet <Coordinate>()
            {
                new Coordinate(0, 0), new Coordinate(1, 1)
            },
                new HashSet <Coordinate>(affectedCoordinates.TrackedCoords.ToArray()));
            Assert.Equal(new BitVector(0b0000000100), rule.GetPossibleValues(new Coordinate(0, 0)));
            Assert.Equal(new BitVector(0b0100000000), rule.GetPossibleValues(new Coordinate(1, 1)));
        }
        public void CopyWithNewReferences_CreatesDeepCopy()
        {
            var puzzle = new PuzzleWithPossibleValues(new int?[][] {
                new int?[] { 1, null /* 4 */, null /* 3 */, 2 },
                new int?[] { null /* 2 */, null /* 3 */, null /* 1 */, 4 },
                new int?[] { null /* 4 */, null /* 1 */, null /* 2 */, 3 },
                new int?[] { 3, 2, null /* 4 */, 1 }
            });
            var ruleKeeper = new StandardRuleKeeper();

            Assert.True(ruleKeeper.TryInit(puzzle));
            var heuristic = new UniqueInColumnHeuristic(
                (IMissingColumnValuesTracker)ruleKeeper.GetRules()[0]);

            Assert.True(heuristic.TryInitFor(puzzle));
            var puzzleCopy = new PuzzleWithPossibleValues(puzzle);

            var ruleKeeperCopy = (StandardRuleKeeper)ruleKeeper.CopyWithNewReferences(
                puzzleCopy);
            IHeuristic heuristicCopy = heuristic.CopyWithNewReferences(
                puzzleCopy, ruleKeeperCopy.GetRules());

            var       coord = new Coordinate(0, 1);
            BitVector originalPossibleValues = puzzle.GetPossibleValues(coord);

            Assert.Equal(originalPossibleValues, puzzleCopy.GetPossibleValues(coord));
            heuristicCopy.UpdateAll();
            Assert.Equal(originalPossibleValues, puzzle.GetPossibleValues(coord));
            Assert.NotEqual(originalPossibleValues, puzzleCopy.GetPossibleValues(coord));
        }
        public void Revert_RevertsSpecifiedRow()
        {
            var puzzle = new PuzzleWithPossibleValues(new int?[][] {
                new int?[] { 1, null /* 4 */, null /* 3 */, 2 },
                new int?[] { null /* 2 */, null /* 3 */, 1, null /* 4 */ },
                new int?[] { null /* 4 */, null /* 1 */, null /* 2 */, null /* 3 */ },
                new int?[] { 3, 2, 4, 1 }
            });
            var rule = new RowUniquenessRule();

            Assert.True(rule.TryInit(puzzle, puzzle.UniquePossibleValues));
            BitVector[] initialPossibleValues = new BitVector[] {
                rule.GetPossibleValues(new Coordinate(0, 0)),
                rule.GetPossibleValues(new Coordinate(1, 1)),
            };
            int val   = 4;
            var coord = new Coordinate(0, 1);
            var updatedCoordinates = new CoordinateTracker(puzzle.Size);

            rule.Update(coord, val, updatedCoordinates);

            var revertedCoordinates = new CoordinateTracker(puzzle.Size);

            rule.Revert(coord, val, revertedCoordinates);

            Assert.Equal(
                revertedCoordinates.TrackedCoords.ToArray(),
                updatedCoordinates.TrackedCoords.ToArray());
            Assert.Equal(
                initialPossibleValues[0],
                rule.GetPossibleValues(new Coordinate(0, 0)));
            Assert.Equal(
                initialPossibleValues[1],
                rule.GetPossibleValues(new Coordinate(1, 1)));
        }
        public void TryInitFor_UpdatesPossibles()
        {
            var puzzle = new PuzzleWithPossibleValues(new int?[][] {
                new int?[] { 1, null /* 4 */, null /* 3 */, 2 },
                new int?[] { null /* 2 */, null /* 3 */, 1, null /* 4 */ },
                new int?[] { null /* 4 */, null /* 1 */, null /* 2 */, null /* 3 */ },
                new int?[] { 3, 2, 4, 1 }
            });
            var rules = new IRule[]
            {
                new RowUniquenessRule(),
                new ColumnUniquenessRule(),
                new BoxUniquenessRule()
            };
            var ruleKeeper = new DynamicRuleKeeper(rules);

            Assert.True(ruleKeeper.TryInit(puzzle));

            Assert.NotNull(ruleKeeper);
            Assert.Equal(new BitVector(0b11000), puzzle.GetPossibleValues(new Coordinate(0, 1)));
            Assert.Equal(new BitVector(0b01000), puzzle.GetPossibleValues(new Coordinate(0, 2)));
            Assert.Equal(new BitVector(0b10100), puzzle.GetPossibleValues(new Coordinate(1, 0)));
            Assert.Equal(new BitVector(0b11000), puzzle.GetPossibleValues(new Coordinate(1, 1)));
            Assert.Equal(new BitVector(0b11000), puzzle.GetPossibleValues(new Coordinate(1, 3)));
            Assert.Equal(new BitVector(0b10000), puzzle.GetPossibleValues(new Coordinate(2, 0)));
            Assert.Equal(new BitVector(0b10010), puzzle.GetPossibleValues(new Coordinate(2, 1)));
            Assert.Equal(new BitVector(0b01100), puzzle.GetPossibleValues(new Coordinate(2, 2)));
            Assert.Equal(new BitVector(0b01000), puzzle.GetPossibleValues(new Coordinate(2, 3)));
        }
        public void Solve_WithManySolutions_Works()
        {
            var puzzle = new PuzzleWithPossibleValues(new int?[][] {
                new int?[] { null, null, 9, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, 3, 5, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
            });
            var magicSquares = new Box[] {
                new Box(new Coordinate(0, 0), 3),
                new Box(new Coordinate(3, 3), 3),
                new Box(new Coordinate(6, 6), 3),
            };
            var solver = new PuzzleSolver <PuzzleWithPossibleValues>(
                new DynamicRuleKeeper(
                    new IRule[] {
                new RowUniquenessRule(),
                new MagicSquaresRule(puzzle.Size, magicSquares, includeDiagonals: false),
            }));

            var solution = solver.Solve(puzzle);

            Assert.Equal(0, solution.NumEmptySquares);
            MagicSquareTests.AssertMagicSquaresSatisfied(
                solution, magicSquares, expectedSum: 15, verifyDiagonals: false);
        }
        public void TrySet_WithValueThatCausesNoPossiblesForOtherSquare_FailsAndLeavesUnchanged()
        {
            var puzzle = new PuzzleWithPossibleValues(new int?[][] {
                new int?[] { 1, null /* 4 */, null /* 3 */, 2 },
                new int?[] { null /* 2 */, null /* 3 */, 1, null /* 4 */ },
                new int?[] { null /* 4 */, null /* 1 */, null /* 2 */, null /* 3 */ },
                new int?[] { 3, 2, 4, 1 }
            });
            var rules = new IRule[]
            {
                new RowUniquenessRule(),
                new ColumnUniquenessRule(),
                new BoxUniquenessRule()
            };
            var ruleKeeper = new DynamicRuleKeeper(rules);

            Assert.True(ruleKeeper.TryInit(puzzle));
            IDictionary <Coordinate, BitVector> initialPossibleValues = _RetrieveAllUnsetPossibleValues(puzzle);
            var coord = new Coordinate(1, 0);
            int val   = 4;

            Assert.False(ruleKeeper.TrySet(coord, val));

            foreach (Coordinate c in puzzle.GetUnsetCoords())
            {
                Assert.Equal(initialPossibleValues[c], puzzle.GetPossibleValues(in c));
            }
        }
        public void Solve_WithOneSolutionUsingDiagonals_Works()
        {
            var puzzle = new PuzzleWithPossibleValues(new int?[][] {
                new int?[] { null, null, null, null, null, null, null, 1, 2 },
                new int?[] { null, 5, null, null, 9, null, null, null, null },
                new int?[] { null, null, null, null, null, 8, null, null, null },
                new int?[] { null, 3, null, null, null, null, 5, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, 9, null },
                new int?[] { null, null, null, null, 4, 3, 9, null, null },
                new int?[] { 6, null, 1, null, null, null, 7, null, null },
                new int?[] { 2, null, null, null, null, null, null, null, null },
            });
            var magicSquares = new Box[] {
                new Box(new Coordinate(3, 3), 3),
            };
            var solver = new PuzzleSolver <PuzzleWithPossibleValues>(
                new DynamicRuleKeeper(
                    new IRule[] {
                new RowUniquenessRule(),
                new ColumnUniquenessRule(),
                new BoxUniquenessRule(),
                new MagicSquaresRule(puzzle.Size, magicSquares, includeDiagonals: true),
            }));

            var solution = solver.Solve(puzzle);

            PuzzleTestUtils.AssertStandardPuzzleSolved(solution);
            MagicSquareTests.AssertMagicSquaresSatisfied(
                solution, magicSquares, expectedSum: 15, verifyDiagonals: false);
        }
        public void Revert_RevertsSpecifiedBox()
        {
            var puzzle = new PuzzleWithPossibleValues(new int?[][] {
                new int?[] { 1, null /* 4 */, null /* 3 */, 2 },
                new int?[] { null /* 2 */, 3, null /* 1 */, null /* 4 */ },
                new int?[] { null /* 4 */, null /* 1 */, 2, 3 },
                new int?[] { null /* 3 */, null /* 2 */, 4, 1 }
            });
            var rule = new BoxUniquenessRule();

            Assert.True(rule.TryInit(puzzle, puzzle.UniquePossibleValues));
            IList <BitVector> initialPossibleValuesByBox = _GetPossibleValuesByBox(puzzle.Size, rule);
            var updatedCoordTracker = new CoordinateTracker(puzzle.Size);
            var coord = new Coordinate(1, 2);
            int val   = 1;

            rule.Update(in coord, val, updatedCoordTracker);

            var revertedCoordTracker = new CoordinateTracker(puzzle.Size);

            rule.Revert(coord, val, revertedCoordTracker);

            Assert.Equal(
                updatedCoordTracker.TrackedCoords.ToArray(),
                revertedCoordTracker.TrackedCoords.ToArray());
            for (int box = 0; box < initialPossibleValuesByBox.Count; box++)
            {
                Assert.Equal(
                    initialPossibleValuesByBox[box],
                    rule.GetMissingValuesForBox(box));
            }
        }
        public void HasUniqueSolution_WithManySolutions_IsFalse()
        {
            var puzzle = new PuzzleWithPossibleValues(new int?[][] {
                new int?[] { null, null, 9, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, 3, 5, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
            });
            var magicSquares = new Box[] {
                new Box(new Coordinate(0, 0), 3),
                new Box(new Coordinate(3, 3), 3),
                new Box(new Coordinate(6, 6), 3),
            };
            var solver = new PuzzleSolver <PuzzleWithPossibleValues>(
                new DynamicRuleKeeper(
                    new IRule[] {
                new RowUniquenessRule(),
                new MagicSquaresRule(puzzle.Size, magicSquares, includeDiagonals: false),
            }));

            Assert.False(solver.HasUniqueSolution(puzzle));
        }
Beispiel #29
0
        public bool SudokuSpice(PuzzleSampleCollection sampleCollection)
        {
            var puzzle = PuzzleWithPossibleValues.CopyFrom(sampleCollection.Random().NullableJaggedMatrix);
            var solver = RuleBased.StandardPuzzles.CreateSolver();

            return(solver.TrySolve(puzzle));
        }
Beispiel #30
0
        public void HasUniqueSolution_WithUniqueSolution_ReturnsTrue(int?[][] matrix)
        {
            var puzzle = new PuzzleWithPossibleValues(matrix);
            var solver = StandardPuzzles.CreateSolver();

            Assert.True(solver.HasUniqueSolution(puzzle));
        }