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; } } } } }
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 } } } }