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; } } } }
public void Apply(MutablePuzzle puzzle, RegionQueue changedRegions) { // keep scanning regions for naked singles, removing // options when digits are placed. when a digit is placed, // its box, row and column are added back to 'regions' so // they can be scanned again. while (changedRegions.TryDequeue(puzzle.Puzzle, out var region)) { ScanRegion(changedRegions, puzzle, region); } }