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)));
        }
        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)));
        }
        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 CopyWithNewReference_CreatesDeepCopy()
        {
            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));

            var   puzzleCopy = new PuzzleWithPossibleValues(puzzle);
            IRule ruleCopy   = rule.CopyWithNewReference(puzzleCopy);

            int val   = 4;
            var coord = new Coordinate(1, 1);

            ruleCopy.Update(coord, val, new CoordinateTracker(puzzle.Size));
            Assert.NotEqual(rule.GetPossibleValues(coord), ruleCopy.GetPossibleValues(coord));

            puzzleCopy[coord] = val;
            var secondCoord  = new Coordinate(1, 2);
            int secondVal    = 1;
            var coordTracker = new CoordinateTracker(puzzle.Size);

            ruleCopy.Update(secondCoord, secondVal, coordTracker);
            var originalCoordTracker = new CoordinateTracker(puzzle.Size);

            rule.Update(secondCoord, secondVal, originalCoordTracker);
            Assert.Equal(
                new HashSet <Coordinate> {
                new Coordinate(1, 0),
            },
                new HashSet <Coordinate>(coordTracker.TrackedCoords.ToArray()));
            Assert.Equal(
                new HashSet <Coordinate> {
                new Coordinate(1, 0), new Coordinate(1, 1)
            },
                new HashSet <Coordinate>(originalCoordTracker.TrackedCoords.ToArray()));
        }
        public void TryInit_NotPossible_Fails()
        {
            var puzzle = new PuzzleWithPossibleValues(new int?[][] {
                new int?[] { null, null, 6, null, null, null, null, null, null },
                new int?[] { 1, null, null, null, null, null, null, null, null },
                new int?[] { null, 3, 8, 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.False(rule.TryInit(puzzle, puzzle.UniquePossibleValues));
        }