Пример #1
0
        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);
                }
            }
        }
Пример #2
0
        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);
        }
Пример #3
0
        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]);
                }
            }
        }
Пример #4
0
        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);
        }
Пример #5
0
        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;
        }