private void EliminatePossibilitiesFromUnsetCells(SudokuGroup sudokuGroup) { HashSet <int> allNumbersPresentInGroup = new HashSet <int>(); for (int cellIndex = 0; cellIndex <= 8; cellIndex++) { int cellValue = sudokuGroup.Cells[cellIndex].Value; if (cellValue != 0) { allNumbersPresentInGroup.Add(cellValue); } } for (int cellIndex = 0; cellIndex <= 8; cellIndex++) { int cellValue = sudokuGroup.Cells[cellIndex].Value; if (cellValue == 0) { SudokuCell cell = sudokuGroup.Cells[cellIndex]; cell.RemainingPossibilities.ExceptWith(allNumbersPresentInGroup); if (cell.RemainingPossibilities.Count == 1) { cell.Value = cell.RemainingPossibilities.First(); cell.SolvingDifficulty = SolvingDifficulty.Easy; } } } }
private Sudoku() { for (int i = 0; i <= 8; i++) { sudokuCells[i] = new SudokuCell[9]; sudokuRows[i] = new SudokuGroup(i); sudokuColumns[i] = new SudokuGroup(i); sudokuBoxes[i] = new SudokuGroup(i); } //1. Initialize Cells and create row view for (int rowIndex = 0; rowIndex <= 8; rowIndex++) { for (int colIndex = 0; colIndex <= 8; colIndex++) { sudokuCells[rowIndex][colIndex] = new SudokuCell(rowIndex, colIndex); sudokuRows[rowIndex].Cells[colIndex] = sudokuCells[rowIndex][colIndex]; sudokuColumns[colIndex].Cells[rowIndex] = sudokuCells[rowIndex][colIndex]; } } //2. create box view //([0] ,[1] , [2]) //([3] ,[4] , [5]) //([6] ,[7] , [8]) for (int boxIndex = 0; boxIndex <= 8; boxIndex++) { for (int cellIndexInABox = 0; cellIndexInABox <= 8; cellIndexInABox++) { //Box,cell 0,0 == Row Col >0,0 //1,0 ==> 0,3 //2,2 ==>0,8 //3,3 ==>4,0 //8,0 ==>6,6 //8,8 ==>8,8 int firtCellRowIndex = (boxIndex - (boxIndex % 3)); int firtCellColIndex = (boxIndex % 3) * 3; int rowIndex = firtCellRowIndex + cellIndexInABox / 3; int colIndex = firtCellColIndex + cellIndexInABox % 3; sudokuBoxes[boxIndex].Cells[cellIndexInABox] = sudokuCells[rowIndex][colIndex]; } } //MessageBox.Show(message); }
private void SetADigitToOnlyAvailablePlace(SudokuGroup sudokuGroup) { var digitsYetToBePlaced = new HashSet <int>(new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }); int[] digitOccurancesMap = new int[10]; var allUnsetCells = new HashSet <SudokuCell>(); for (int cellIndex = 0; cellIndex <= 8; cellIndex++) { var cell = sudokuGroup.Cells[cellIndex]; if (cell.Value != 0) { digitsYetToBePlaced.Remove(cell.Value); } else { allUnsetCells.Add(cell); foreach (var unsetDigit in cell.RemainingPossibilities) { digitOccurancesMap[unsetDigit]++; } } } foreach (var digit in digitsYetToBePlaced) { if (digitOccurancesMap[digit] == 1) { //digit can be set only at this place. foreach (var unsetCell in allUnsetCells) { if (unsetCell.RemainingPossibilities.Contains(digit)) { unsetCell.Value = digit; unsetCell.SolvingDifficulty = SolvingDifficulty.Easy; } } } } }
private bool IsGroupValid(SudokuGroup sudokuGroup) { HashSet <int> allDigitsInGroup = new HashSet <int>(); int solvedCells = 0; foreach (var sudokuGroupCell in sudokuGroup.Cells) { if (sudokuGroupCell.Value == 0 && sudokuGroupCell.RemainingPossibilities.Count == 0) { //Unsolved cells must have remaining possibilities on valid Sudoku. return(false); } if (sudokuGroupCell.Value > 0) { solvedCells++; allDigitsInGroup.Add(sudokuGroupCell.Value); } } if (solvedCells == 9) { if (allDigitsInGroup.Count == 9 && allDigitsInGroup.Sum() == 45) { return(true); } else { return(false); } } if (allDigitsInGroup.Count == solvedCells) { return(true); } return(false); }
private void EliminatePreemptiveSetsInAGroup(SudokuGroup sudokuGroup) { int remainingPossibitySizeMax = 0; for (int cellIndex = 0; cellIndex <= 8; cellIndex++) { if (sudokuGroup.Cells[cellIndex].Value == 0) { remainingPossibitySizeMax++; } } for (int remainingPossibitySize = 2; remainingPossibitySize <= remainingPossibitySizeMax; remainingPossibitySize++) { { //1. Adjust possibilities for a Column HashSet <int> preemptiveSet = new HashSet <int>(); HashSet <int> cellsWithCommonPossilities = new HashSet <int>(); for (int cellIndex = 0; cellIndex <= 8; cellIndex++) { var remainingPossibilitiesSet = sudokuGroup.Cells[cellIndex].RemainingPossibilities; if (sudokuGroup.Cells[cellIndex].Value == 0 && remainingPossibilitiesSet.Count <= remainingPossibitySize) { var tempSet = new HashSet <int>(remainingPossibilitiesSet); tempSet.UnionWith(preemptiveSet); if (tempSet.Count <= remainingPossibitySize) { cellsWithCommonPossilities.Add(cellIndex); preemptiveSet.UnionWith(remainingPossibilitiesSet); } if (cellsWithCommonPossilities.Count == preemptiveSet.Count) { break; } } } if (cellsWithCommonPossilities.Count == preemptiveSet.Count && preemptiveSet.Count > 0) { for (int cellIndex = 0; cellIndex <= 8; cellIndex++) { SudokuCell cell = sudokuGroup.Cells[cellIndex]; if (cell.Value == 0 && !cellsWithCommonPossilities.Contains(cellIndex)) { //Reduce the possibilities. cell.RemainingPossibilities.ExceptWith(preemptiveSet); if (cell.RemainingPossibilities.Count == 1) { cell.Value = cell.RemainingPossibilities.First(); // Logger.WriteLine($"Solved a cell by preemptive Set. {cell.ColIndex},{cell.RowIndex}={cell.Value}"); if (preemptiveSet.Count == 2) { cell.SolvingDifficulty = SolvingDifficulty.Medium; } if (preemptiveSet.Count == 3) { cell.SolvingDifficulty = SolvingDifficulty.Hard; } if (preemptiveSet.Count == 4) { cell.SolvingDifficulty = SolvingDifficulty.MaxDifficulty; } } } } } } remainingPossibitySize++; } }