private void ScanRegion(RegionQueue regions, MutablePuzzle puzzle, Region region)
        {
            var placedDigits = region.GetPlacedDigits();

            for (int i = 1; i <= Puzzle.LineLength; i++)
            {
                var digit = SudokuValues.FromHumanValue(i);

                if (placedDigits.HasAnyOptions(digit))
                {
                    continue;
                }

                var positions = region.GetPositions(digit);

                if (positions.IsSingle)
                {
                    var index  = positions.ToIndex();
                    var coords = region.GetCoordinate(index);

                    var update = new CellUpdate(digit.Invert(), coords);
                    puzzle.RemoveOptions(update);

                    regions.Enqueue(RegionType.Row, coords.Row);
                    regions.Enqueue(RegionType.Column, coords.Column);
                    regions.Enqueue(RegionType.Box, coords.Box);
                }
            }
        }
        private void ScanRegion(RegionQueue regions, MutablePuzzle puzzle, Region region)
        {
            var placedDigits = region.GetPlacedDigits();

            for (int i = 0; i < Puzzle.LineLength; i++)
            {
                var cell = region[i];

                if (!cell.IsSingle && cell.HasAnyOptions(placedDigits))
                {
                    var coords = region.GetCoordinate(i);

                    puzzle.RemoveOptions(coords, placedDigits);

                    var newCell = cell.RemoveOptions(placedDigits);
                    if (newCell.IsSingle)
                    {
                        // since we have placed a digit we must
                        // scan these regions again
                        regions.Enqueue(RegionType.Row, coords.Row);
                        regions.Enqueue(RegionType.Column, coords.Column);
                        regions.Enqueue(RegionType.Box, coords.Box);
                    }
                }
            }
        }
Esempio n. 3
0
        public void Apply(MutablePuzzle puzzle, RegionQueue changedRegions)
        {
            if (++depth > 10)
            {
                return;
            }

            while (changedRegions.TryDequeue(puzzle, out var region))
            {
                for (int i = 0; i < Puzzle.LineLength; i++)
                {
                    var value  = region[i];
                    var coords = region.GetCoordinate(i);

                    if (value.GetOptionCount() != 2)
                    {
                        continue;
                    }

                    // if there are are only 2 bits set, bitwise and
                    // with the value - 1 will return the highest option
                    var highestValue = new SudokuValues(value.Values & (value.Values - 1));

#if DEBUG
                    Program.Debugger.AddAction($"Attempting {highestValue.Invert().Intersect(value)} in {coords}");
#endif

                    var oldSolver = _solver;
                    var changeset = new SingleCellChangeSet(new CellUpdate(highestValue, coords));
                    var newSolver = new Solver(changeset, _solver);

                    _solver = newSolver;

                    var(result, _) = newSolver.Solve();

                    _solver = oldSolver;

#if DEBUG
                    Program.Debugger.AddAction($"Result: {result}");
#endif

                    switch (result)
                    {
                    case SolveResult.Success:
                        puzzle.Absorb(newSolver.Puzzle);
                        return;

                    case SolveResult.Invalid:
                        // we picked the wrong digit
                        puzzle.RemoveOptions(new CellUpdate(highestValue.Invert(), coords));
                        return;
                    }
                }
            }
        }
Esempio n. 4
0
 public void ApplyToPuzzle(MutablePuzzle puzzle)
 {
     puzzle.RemoveOptions(_update);
 }