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;
                        }
                    }
                }
            }
        }
        public void Apply(MutablePuzzle puzzle, RegionQueue changedRegions)
        {
            while (changedRegions.TryDequeue(puzzle, out var region))
            {
                var placedDigits = region.GetPlacedDigits();

                FindTuple(puzzle, changedRegions, region, placedDigits);
            }
        }
        private void FindTuple(MutablePuzzle puzzle, RegionQueue regions, Region region, SudokuValues placedDigits)
        {
            var combinations = Helpers.GetCombinationIndices(Puzzle.LineLength, _size);

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

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

                var positions = region.GetPositions(comb);

                if (positions.GetOptionCount() != _size)
                {
                    // these digits are placeable in more than tupleSize spots, so not hidden tuple
                    continue;
                }

                // we found a hidden tuple!
                var options = ArrayPool <int> .Shared.Rent(Puzzle.LineLength);

                var count      = positions.CopyIndices(options);
                var opposite   = comb.Invert();
                var anyChanged = false;

                for (var index = 0; index < count; index++)
                {
                    var cell = region[options[index]];

                    if (!cell.IsSingle && cell.HasAnyOptions(opposite))
                    {
                        var update = region.RemoveOptions(options[index], opposite);
                        puzzle.RemoveOptions(update);
                        anyChanged = true;

                        regions.Enqueue(RegionType.Row, update.Coordinate.Row);
                        regions.Enqueue(RegionType.Column, update.Coordinate.Column);
                        regions.Enqueue(RegionType.Box, update.Coordinate.Box);
                    }
                }

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

                if (anyChanged)
                {
#if DEBUG
                    Program.Debugger.AddAction($"Hidden {comb} tuple in {region}");
#endif
                    return;
                }
            }
        }
示例#4
0
 public void EnqueueAll(RegionQueue other)
 {
     _currentValues   |= other._currentValues;
     _lastDequeueIndex = 0;
 }
示例#5
0
 public void ApplyToRegionQueue(RegionQueue queue)
 {
     queue.EnqueueAll(Queue);
 }
示例#6
0
 public void Absorb(MutablePuzzle other)
 {
     Array.Copy(other._cells, _cells, _cells.Length);
     _currentChangeSet.Queue.EnqueueAll(RegionQueue.GetFull());
 }
示例#7
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
                    }
                }
            }
        }