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