public void Apply(MutablePuzzle puzzle, RegionQueue changedRegions)
        {
            while (changedRegions.TryDequeueOfType(RegionType.Box, out int boxIndex))
            {
                var box          = puzzle.Puzzle.Boxes[boxIndex];
                var placedDigits = box.GetPlacedDigits();

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

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

                    var rows = SudokuValues.None;
                    var cols = SudokuValues.None;

                    for (var i = 0; i < Puzzle.LineLength; i++)
                    {
                        var cellValue = box[i];
                        var cellCoord = box.GetCoordinate(i);

                        if (!cellValue.IsSingle && cellValue.HasAnyOptions(value))
                        {
                            rows = rows.AddOptions(SudokuValues.FromIndex(cellCoord.Row));
                            cols = cols.AddOptions(SudokuValues.FromIndex(cellCoord.Column));
                        }
                    }

                    if (rows.IsSingle)
                    {
                        var region     = puzzle.Puzzle.Rows[rows.ToIndex()];
                        var anyChanged = RemoveFromOtherBoxesInRegion(puzzle, region, value, boxIndex);

                        if (anyChanged)
                        {
#if DEBUG
                            Program.Debugger.AddAction($"{digit}s in {box} remove others in {region}.");
#endif
                            return;
                        }
                    }
                    if (cols.IsSingle)
                    {
                        var region     = puzzle.Puzzle.Columns[cols.ToIndex()];
                        var anyChanged = RemoveFromOtherBoxesInRegion(puzzle, region, value, boxIndex);

                        if (anyChanged)
                        {
#if DEBUG
                            Program.Debugger.AddAction($"{digit}s in {box} remove others in {region}.");
#endif
                            return;
                        }
                    }
                }
            }
        }
示例#2
0
        private void FindTuple(MutablePuzzle puzzle, RegionQueue regions, Region region, SudokuValues placedDigits)
        {
            var combinations = Helpers.GetCombinationIndices(Puzzle.LineLength, _size);

            for (int j = 0; j < combinations.Length; j++)
            {
                var comb = combinations[j];

                if (placedDigits.HasAnyOptions(comb))
                {
                    // skip any tuples that include placed digits
                    continue;
                }

                var indices = ArrayPool <int> .Shared.Rent(_size);

                var count          = comb.CopyIndices(indices);
                var possibleValues = SudokuValues.None;

                for (int i = 0; i < count; i++)
                {
                    var cell = region[indices[i]];
                    possibleValues = possibleValues.AddOptions(cell);
                }

                ArrayPool <int> .Shared.Return(indices);

                var optionsCount = possibleValues.GetOptionCount();

                if (optionsCount == _size)
                {
                    // we found a tuple!

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

                        if (otherCell.IsSingle)
                        {
                            continue;
                        }

                        if (!otherCell.HasAnyOptions(possibleValues))
                        {
                            continue;
                        }

                        if (comb.HasAnyOptions(SudokuValues.FromIndex(i)))
                        {
                            continue;
                        }

                        var newCell = region.RemoveOptions(i, possibleValues);
                        puzzle.RemoveOptions(newCell);

                        regions.Enqueue(RegionType.Row, newCell.Coordinate.Row);
                        regions.Enqueue(RegionType.Column, newCell.Coordinate.Column);
                        regions.Enqueue(RegionType.Box, newCell.Coordinate.Box);
#if DEBUG
                        Program.Debugger.AddAction($"{possibleValues} tuple in {region}.");
#endif
                    }
                }
            }
        }