public SudokuSolvingIterationAssumptionTechnique(SudokuGrid grid)
            : base(grid)
        {
            rowsOfNumbers = new SortedSet<byte>[Grid.Metrics.MaximumNumber];
            columnsOfNumbers = new SortedSet<byte>[Grid.Metrics.MaximumNumber];
            Grid.IterateLine(i =>
            {
                rowsOfNumbers[i] = new SortedSet<byte>();
                columnsOfNumbers[i] = new SortedSet<byte>();
            });
            blocksOfNumbers = new SortedSet<byte>[Grid.Metrics.MaximumNumber / Grid.Metrics.BlockHeight,
                Grid.Metrics.MaximumNumber / Grid.Metrics.BlockWidth];
            Grid.IterateBlocksXY((x, y) =>
            {
                blocksOfNumbers[y, x] = new SortedSet<byte>();
            });
            forbiddenCandidates = new SortedSet<byte>();
            Grid.CellNumberChanged += (s, e) => RegisterCellAsClue(e.Cell);

            emptyCellsCount = Grid.Metrics.CellsTotal;

            //Grid.IterateLinesXY((x, y) =>
            //{
            //    SudokuGridCell cell = Grid.Cells[y, x];
            //    if (cell.IsClue)
            //    {
            //        RegisterCellAsClue(cell);
            //    }
            //});
        }
Пример #2
0
        /// <summary>
        /// Initializes a new instance of grid cell.
        /// </summary>
        /// <param name="parentGrid">The grid including this cell.</param>
        /// <param name="position">The cell's position at the specified grid.</param>
        /// <param name="number">The number substituted into this cell.</param>
        internal SudokuGridCell(SudokuGrid parentGrid, SudokuGridPosition position, byte number)
        {
            ParentGrid = parentGrid;
            Position   = position;
            if (number == EmptyCellNumber)
            {
                this.number = number;
                Candidates  = new CandidatesSortedSet(this);
                Candidates.ContradictionFound += (s, e) => ContradictionFound = true;
                switch (parentGrid.Constraints)
                {
                case SudokuGridConstraints.Traditional:
                    for (byte i = 1; i <= parentGrid.Metrics.MaximumNumber; ++i)
                    {
                        Candidates.Add(i);
                    }
                    break;

                case SudokuGridConstraints.Diagonal:
                    break;

                case SudokuGridConstraints.Even:
                    break;

                case SudokuGridConstraints.Odd:
                    break;

                case SudokuGridConstraints.Areas:
                    break;
                }
            }
            else
            {
                Number = number;
            }
        }
Пример #3
0
        private static void ShowSolution(SudokuGrid grid)
        {
            Console.WriteLine("Found solution:");
            Console.WriteLine();

            var sb = new StringBuilder();

            char horDelim = '-';
            char vertDelim = '|';

            for (byte i = 0; i < 25; ++i)
            {
                sb.Append(horDelim);
            }
            string horDelims = sb.ToString();

            sb.Clear();
            for (int i = 0; i < 2; ++i)
            {
                sb.Append(" ");
            }
            string leftOffset = sb.ToString();

            var defaultForeColor = Console.ForegroundColor;

            Action<string> writeColoredDelim = (data) =>
            {
                Console.ForegroundColor = ConsoleColor.DarkGray;
                Console.Write(data);
                Console.ForegroundColor = defaultForeColor;
            };

            writeColoredDelim(leftOffset + horDelims + "\n");

            for (byte i = 0; i < grid.Metrics.MaximumNumber; ++i)
            {
                writeColoredDelim(leftOffset + vertDelim);
                for (byte j = 0; j < grid.Metrics.MaximumNumber; ++j)
                {
                    Console.Write(" " + grid[i, j]);
                    if ((j + 1) % 3 == 0)
                    {
                        writeColoredDelim(" " + vertDelim);
                    }
                }
                Console.WriteLine();
                if ((i + 1) % 3 == 0)
                {
                    writeColoredDelim(leftOffset + horDelims + "\n");
                }
            }

            Console.WriteLine();
        }
Пример #4
0
 // BUG: used to avoid buggy duplicate-code decision in solver classes -- get rid of as soon as possible
 internal static void AssignNewCell(SudokuGrid grid, SudokuGridCell cell)
 {
     cell.NumberChanged += (s, e) => grid.OnCellNumberChanged(new CellNumberChangedEventArgs((SudokuGridCell)s));
     grid.cells[cell.Position.Y, cell.Position.X] = cell;
 }
Пример #5
0
 // BUG: used to avoid buggy duplicate-code decision in solver classes -- get rid of as soon as possible
 internal static void AssignNewCell(SudokuGrid grid, SudokuGridCell cell)
 {
     cell.NumberChanged += (s, e) => grid.OnCellNumberChanged(new CellNumberChangedEventArgs((SudokuGridCell)s));
     grid.cells[cell.Position.Y, cell.Position.X] = cell;
 }
Пример #6
0
 protected SudokuSolvingTechnique(SudokuGrid grid)
 {
     Grid = grid;
     // BUG: the solver changes cells' collection via exactly the same pointer
     initialGridCells = grid.Cells;
 }
        private SudokuGridCell[,] MakeAssumptionInCell(ref SudokuGridPosition? minCandidatesCellPos)
        {
            if (!minCandidatesCellPos.HasValue)
            {
                // TODO: optimize: lookup that kind of cell repetitively when its number of candidates changes (decreases): compare against the minimum value from a variable (where to put it?)
                minCandidatesCellPos = FindFirstCellWithMinimumCandidates(Grid).Position;
            }
            var minCandidatesCell = Grid.Cells[minCandidatesCellPos.Value.Y, minCandidatesCellPos.Value.X];

            byte assumedNumber = minCandidatesCell.Candidates.ToArray()[0];

            assumptionsGrid = (SudokuGrid)Grid.GetType()
                .GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic,
                null, CallingConventions.HasThis, new[] { typeof(SudokuGridConstraints) }, null)
                .Invoke(new [] { (object)Grid.Constraints });

            // BUG: !!! as we use the standard grid here, which was not initially intended to be used anywhere except for decode-and-construct scenarios, by the time we reach this code the assumptionsGrid's cells are not initialized yet -- consider introducing some sort of temporary 'grid' (most probably, a kind of 'cells-only layer'). For that reason one of the ctor's code sections was moved into the Reset() method
            var assumptionsGridSolver = new SudokuSolvingIterationAssumptionTechnique(assumptionsGrid);

            // WI: cell-to-cell iteration is a very intensive process -- use cells array cloning instead with targeted minCandidatesCell... altering
            var minCandidatesCellPosCopy = minCandidatesCellPos.Value;
            assumptionsGrid.IterateLinesXY((x, y) =>
            {
                SudokuGridCell currCell;
                var currPos = new SudokuGridPosition(x, y, false);
                if (currPos.Equals(minCandidatesCellPosCopy))
                {
                    currCell = new SudokuGridCell(assumptionsGrid, currPos, assumedNumber);
                    assumptionsGridSolver.lastFilledPos = currPos;
                    assumptionsGridSolver.currCheckingPos = currPos;
                    assumptionsGridSolver.currCheckingPos.Shift(1, assumptionsGrid.Metrics);
                }
                else
                {
                    currCell = new SudokuGridCell(assumptionsGrid, currPos, Grid.Cells[y, x].Number);
                    if (currCell.Candidates != null)
                    {
                        // just to bring into accord with the latest value from the 'parent' grid
                        currCell.Candidates.IntersectWith(Grid.Cells[y, x].Candidates);
                    }
                }
                SudokuGrid.AssignNewCell(assumptionsGrid, currCell);
                //assumptionsGrid.Cells[y, x] = currCell;
            });

            //List<SudokuGridCell[,]> assumptionGridSolutuons = assumptionGridSolver.SearchSolutions();
            //if (assumptionGridSolutuons.Count > 0) // correct assumption was made
            //{
            //    return assumptionsGrid.Cells;
            //}

            //SudokuGridCell[,] solution;
            if (assumptionsGridSolver.SearchSolutionDebug()) // correct assumption was made
            {
                //return solution;
                return assumptionsGrid.Cells;
            }

            // incorrect assumption was made (executes on contradiction only)
            minCandidatesCell.Candidates.Remove(assumedNumber);
            // if there were only two candidates, with assumedNumber being one of them, then the remaining one is a clue
            if (minCandidatesCell.IsClue)
            {
                minCandidatesCellPos = null;
                var newPos = new SudokuGridPosition(minCandidatesCell.Position.X, minCandidatesCell.Position.Y, false);
                lastFilledPos = newPos;
                currCheckingPos = newPos;
                currCheckingPos.Shift(1, Grid.Metrics);
            }
            return null;
        }
 private SudokuGridCell FindFirstCellWithMinimumCandidates(SudokuGrid grid)
 {
     byte minCandidates = grid.Metrics.MaximumNumber;
     SudokuGridCell minCandidatesCell = null;
     grid.IterateLinesXY((x, y) =>
     {
         var currCell = grid.Cells[y, x];
         if (currCell.Candidates != null &&
             currCell.Candidates.Count < minCandidates)
         {
             minCandidates = (byte)currCell.Candidates.Count;
             minCandidatesCell = currCell;
         }
     });
     return minCandidatesCell;
 }
Пример #9
0
 public static byte[] ToBinary(FileStream textFile, SudokuGrid grid, 
     SudokuConvertionAlgorithm algorithm)
 {
     string content;
     textFile.Position = 0;
     using (var sr = new StreamReader(textFile))
     {
         content = sr.ReadToEnd();
     }
     textFile.Position = 0;
     return ToBinary(content, algorithm, grid.Constraints, grid.Metrics);
 }
Пример #10
0
 public static byte[] ToBinary(SudokuGrid grid, SudokuConvertionAlgorithm algorithm)
 {
     var sb = new StringBuilder(grid.Metrics.CellsTotal);
     grid.IterateLinesXY((x, y) => sb.Append(grid.Cells[y, x].Number));
     return ToBinary(sb.ToString(), algorithm, grid.Constraints, grid.Metrics);
 }