public Sudoku(int[] numbers) { if (numbers.Length != 81) { throw new ArgumentException(); } UnsolvedTiles = Enumerable.Range(0, 81).ToHashSet(); for (int i = 0; i < 81; i++) { int number = numbers[i]; if (number == 0) { Tiles[i] = new SudokuTile(GetRowForTile(i), GetColForTile(i), GetNinthForTile(i)); } else { Tiles[i] = new SudokuTile(GetRowForTile(i), GetColForTile(i), GetNinthForTile(i), number); UnsolvedTiles.Remove(i); } } foreach (var index in UnsolvedTiles.ToArray()) { Tiles[index].SetInitialPossibleValues(this); if (Tiles[index].HasValue) { UnsolvedTiles.Remove(index); } } }
public SudokuTile WithValue(int value) { if (IsGiven) { throw new Exception("this tile is given and cannot be changed!"); } SudokuTile result = new SudokuTile(Row, Col, Ninth); result.Value = value; return(result); }
private void PopulateTiles(string[] tileDefinitions) { for (int row = 0; row < tileDefinitions.Length; row++) { string tileDefinition = tileDefinitions[row]; for (int column = 0; column < tileDefinition.Length; column++) { SudokuTile tile = _tiles[column, row]; if (tileDefinition[column] == '/') { tile.Block(); continue; } tile.Value = tileDefinition[column] == '.' ? SudokuTile.CLEARED : (int)char.GetNumericValue(tileDefinition[column]); } } }
public SudokuTile WithRemovedPossibleValues(IEnumerable <int> values) { if (PossibleValues.Intersect(values).Count() == 0) // values are not in PossibleValues { return(this); } SudokuTile result = new SudokuTile(Row, Col, Ninth); result.PossibleValues = PossibleValues.Except(values).ToHashSet(); if (result.PossibleValues.Count < 1) { throw new Exception("impossible situation encountered, there is no possible value here"); } if (result.PossibleValues.Count < 2) { result.Value = result.PossibleValues.First(); } return(result); }
public IEnumerable <SudokuBoard> Solve() { SudokuProgress Simplify() { bool valid = _rules.All(rule => rule.CheckValid()); if (!valid) { return(SudokuProgress.FAILED); } return(_rules.Aggregate(SudokuProgress.NO_PROGRESS, (progress, rule) => SudokuTile.CombineSolvedState(progress, rule.Solve()))); } // reset solution foreach (SudokuTile tile in _tiles) { tile.ResetPossibles(); } SudokuProgress simplify = SudokuProgress.PROGRESS; while (simplify == SudokuProgress.PROGRESS) { simplify = Simplify(); } if (simplify == SudokuProgress.FAILED) { yield break; } // Find one of the values with the least number of alternatives, but that still has at least 2 alternatives IEnumerable <SudokuTile> query = from rule in _rules from tile in rule where tile.PossibleCount > 1 orderby tile.PossibleCount ascending select tile; SudokuTile chosen = query.FirstOrDefault(); if (chosen == null) { // The board has been completed, we're done! yield return(this); yield break; } foreach (int value in Enumerable.Range(1, _maxValue)) { // Iterate through all the valid possibles on the chosen square and pick a number for it if (!chosen.IsValuePossible(value)) { continue; } SudokuBoard copy = new SudokuBoard(this); copy[chosen.X, chosen.Y].Fix(value, "Trial and error"); foreach (SudokuBoard innerSolution in copy.Solve()) { yield return(innerSolution); } } yield break; }