protected override void OperateOn(SudokuModel model)
 {
     for (var iType = 0; iType < 3; ++iType) {
         var type = (RegionType)iType;
         for (var i = 0; i < model.Size; ++i) {
             var region = new Region(type, i);
             var tuple = new Tuple<SudokuModel, Region>(model, region);
             if (GetCheckedIteration(tuple) < model.GetLastChangedIterRegion(type, i)) {
                 _checkedIteration[tuple] = model.ChangeCount;
                 foreach (var unsolved in model.GetUnsolvedValues(type, i)) {
                     var timesFound = 0;
                     Cell? foundAt = null;
                     foreach (var cell in model.GetCells(type, i)) {
                         if ((model.GetPossibilitySetCell(cell.Column, cell.Row) & (1 << unsolved)) != 0) {
                             ++timesFound;
                             foundAt = cell;
                             if (timesFound > 1) {
                                 break;
                             }
                         }
                     }
                     if (timesFound == 1) {
                         if (foundAt != null) {
                             model.SetValueOptimized(foundAt.Value.Column, foundAt.Value.Row, unsolved, type, i);
                         }
                     }
                 }
             }
         }
     }
 }
 protected override void OperateOn(SudokuModel model)
 {
     for (var row = 0; row < model.Size; ++row) {
         for (var col = 0; col < model.Size; ++col) {
             EliminateDuplicates(model, col, row);
         }
     }
 }
Exemple #3
0
 public Solver(SudokuModel model)
 {
     _model = model;
     var multiStrategy = new MultiStrategy(
         new LoneRemainingCell(),
         new SetIsolation(),
         new TrialAndError(new LoneRemainingCell()));
     multiStrategy.ContainedStrategyFinished += HandleScanFinished;
     _eliminationStrategy = multiStrategy;
 }
Exemple #4
0
 public void Run(SudokuModel model)
 {
     var initTime = DateTime.Now;
     var initElim = model.EliminatedCount;
     OperateOn(model);
     TimeLastRun = DateTime.Now - initTime;
     TotalTime += TimeLastRun;
     EliminatedLastRun = model.EliminatedCount - initElim;
     TotalEliminated += EliminatedLastRun;
     ++Runs;
 }
 public static void EliminateDuplicates(SudokuModel model, int col, int row)
 {
     if (model.IsSolved(col, row)) {
         var value = model.GetValue(col, row);
         foreach (var region in model.GetIntersectingRegions(col, row)) {
             foreach (var other in model.GetCells(region.Type, region.I)) {
                 if (other.Column != col || other.Row != row) {
                     model.Eliminate(other.Column, other.Row, value);
                 }
             }
         }
     }
 }
Exemple #6
0
 protected override void OperateOn(SudokuModel model)
 {
     if (_strategies.Length == 0) {
         return;
     }
     var i = 0;
     do {
         var strategy = _strategies[i];
         strategy.Run(model);
         if (ContainedStrategyFinished != null) {
             ContainedStrategyFinished(strategy);
         }
         // If we've eliminated something, jump back to the first strategy; otherwise
         // go to the next strategy.
         i = (strategy.EliminatedLastRun != 0) ? 0 : (i + 1);
     } while (i < _strategies.Length);
 }
Exemple #7
0
 static void IsolateSet(int set, Region region, SudokuModel model)
 {
     var cells = model.GetCells(region.Type, region.I);
     var cellsNotContainedBySet = cells.Where(cell => (model.GetPossibilitySetCell(cell.Column, cell.Row) | set) != set).ToList();
     var numCellsContainedBySet = cells.Length - cellsNotContainedBySet.Count;
     if (numCellsContainedBySet != set.HiBitCount()) {
         return;
     }
     // we now know that each of the numbers in the set must be exclusively in
     // one of the contained cells, so we eliminate that set from all other cells'
     // possibility bits.
     var mask = ~set;
     foreach (var cell in cellsNotContainedBySet) {
         var poss = model.GetPossibilitySetCell(cell.Column, cell.Row);
         model.SetPossibilitySetCell(cell.Column, cell.Row, poss & mask);
     }
 }
Exemple #8
0
 protected override void OperateOn(SudokuModel model)
 {
     // We could look at all 2^N possible sets on all 3N of the model's regions,
     // but it is more efficient to only use the
     // possiblity set of each cell, and isolate that set on each intersecting region.
     for (var row = 0; row < model.Size; ++row) {
         for (var col = 0; col < model.Size; ++col) {
             if (!model.IsSolved(col, row)) {
                 foreach (var region in model.GetIntersectingRegions(col, row)) {
                     var checkedIter = GetCheckedIteration(region);
                     if (checkedIter < model.GetLastChangedIterRegion(region.Type, region.I)) {
                         _checkedIteration[region] = checkedIter;
                         IsolateSet(model.GetPossibilitySetCell(col, row), region, model);
                     }
                 }
             }
         }
     }
 }
Exemple #9
0
 bool OperateOn(int col, int row, SudokuModel model)
 {
     if (!model.IsSolved(col, row)) {
         // obviously can't eliminate anything in a solved cell.
         // try each int i that is a possibility for the cell, and see if an error results
         foreach (var i in model.GetPossibilitySetCell(col, row).HighBitPositions()) {
             var clone = new SudokuModel(model);
             clone.SetValue(col, row, i);
             _elimStrategy.Run(clone);
             if (clone.IsConsistent()) {
                 continue;
             }
             // If so, we can eliminate that from the original model.
             model.Eliminate(col, row, i);
             return true;
             // return immediately after eliminating something, since
             // this is a slow algorithm, and we want our faster
             // algorithms to see if they make some more eliminations first.
         }
     }
     return false;
 }
Exemple #10
0
 void tOperateOn(SudokuModel model)
 {
     // we retain the index, as it's more efficient
     // to keep operating in the same area than to start over at cell[0,0]
     // every time.
     var sz = model.SizeSquared;
     for (int i = 0; i < sz; ++i) {
         int index;
         lock (this) {
             index = _index;
             _index += 36;
             _index %= sz;
         }
         var col = index % 25;
         var row = index / 25;
         if (OperateOn(col, row, model)) {
             return;
         }
         // go to the next cell
     }
     // if we've gone through the whole model
     // without eliminating anything, then there's no use
     // trying anymore.
 }
Exemple #11
0
 protected override void OperateOn(SudokuModel model)
 {
     // we retain the index, as it's more efficient
     // to keep operating in the same area than to start over at cell[0,0]
     // every time.
     var sz = model.SizeSquared;
     Parallel.For(0, 625, (i, loopState) => {
         int index;
         lock (this) {
             index = _index;
             _index += 36;
             _index %= sz;
         }
         var col = index % 25;
         var row = index / 25;
         if (OperateOn(col, row, model)) {
             loopState.Stop();
         }
         // go to the next cell
     });
     // if we've gone through the whole model
     // without eliminating anything, then there's no use
     // trying anymore.
 }
Exemple #12
0
        void OpenFile(string name)
        {
            _name = name;
            // Open and read the file
            try {
                TextReader reader = new FileInfo(name).OpenText();
                var text = reader.ReadToEnd();
                reader.Dispose();
                var lines = text.Split(new[] {"\r\n"}, StringSplitOptions.RemoveEmptyEntries);

                // Create a new model and solver, and add event listeners
                if (_model != null) {
                    _model.ModelChanged -= HandleModelModelChanged;
                    _solver.ScanFinished -= HandleSolverScanFinished;
                    _solver.Finished -= HandleSolverFinished;
                }
                _model = new SudokuModel(lines.Length);
                _solver = new Solver(_model);
                _model.ModelChanged += HandleModelModelChanged;
                _solver.ScanFinished += HandleSolverScanFinished;
                _solver.Finished += HandleSolverFinished;

                // Update the screen
                _grid.Model = _model;
                _txtProgress.Clear();

                // Load data into the model
                for (var row = 0; row < lines.Length; ++row) {
                    var cells = lines[row].Split(',');
                    for (var col = 0; col < lines.Length; ++col) {
                        if (!string.IsNullOrEmpty(cells[col])) {
                            _model.SetValue(col, row, cells[col][0] - 'A');
                        }
                    }
                }
            } catch (FileNotFoundException) {}
        }
Exemple #13
0
 protected abstract void OperateOn(SudokuModel model);
Exemple #14
0
        /// <summary>
        ///   Copy constructor
        /// </summary>
        /// <param name = "model"></param>
        public SudokuModel(SudokuModel model)
        {
            // Initialize our variables
            var size = model.Size;
            _size = size;
            _sizeSqrt = Convert.ToInt32(Math.Sqrt(size));
            _sizeSquared = size * size;
            _sizeCubed = _sizeSquared * size;
            _possibilitySetModel = (1 << _size) - 1;
            _possibilitySetCell = new int[Size, Size];
            _remainingPossibilityCount = new int[Size, Size];
            _value = new int[Size, Size];
            _lastChangedIterCell = new int[Size, Size];

            // Initialize the Cell objects, and the cache values
            for (var col = 0; col < size; ++col) {
                for (var row = 0; row < size; ++row) {
                    _possibilitySetCell[col, row] = model.GetPossibilitySetCell(col, row);
                    _remainingPossibilityCount[col, row] = model.GetRemainingPossibilityCount(col, row);
                    _value[col, row] = model.GetValue(col, row);
                    _lastChangedIterCell[col, row] = model.GetLastChangedIterCell(col, row);
                    CellChanged = null;
                }
            }
            CellChanged += HandleCellChanged;

            _solved = new int[3, _size];
            _lastChangedIterRegion = new int[3, _size];
            _cellsRegion = new Cell[3, _size][];
            _intersectingRegions = new Region[Size, Size][];
            for (var i = 0; i < _size; ++i) {
                _lastChangedIterRegion[0, i] = model._lastChangedIterRegion[0, i];
                _lastChangedIterRegion[1, i] = model._lastChangedIterRegion[0, i];
                _lastChangedIterRegion[2, i] = model._lastChangedIterRegion[0, i];
                SetLastChangedIterRegion(RegionType.Column, i, -1);
                SetLastChangedIterRegion(RegionType.Row, i, -1);
                SetLastChangedIterRegion(RegionType.Square, i, -1);
                _solved[0, i] = model._solved[0, i];
                _solved[1, i] = model._solved[1, i];
                _solved[2, i] = model._solved[2, i];
                var colCells = new Cell[_size];
                for (var j = 0; j < _size; ++j) {
                    colCells[j] = new Cell(i, j);
                }
                _cellsRegion[(int)RegionType.Column, i] = colCells;
                var rowCells = new Cell[_size];
                for (var j = 0; j < _size; ++j) {
                    rowCells[j] = new Cell(j, i);
                }
                _cellsRegion[(int)RegionType.Row, i] = rowCells;
                var sqCells = new Cell[_size];
                var sqrCol = i % _sizeSqrt;
                var sqrRow = i / _sizeSqrt;
                var startCol = sqrCol * _sizeSqrt;
                var startRow = sqrRow * _sizeSqrt;
                for (var c = 0; c < _sizeSqrt; ++c) {
                    for (var r = 0; r < _sizeSqrt; ++r) {
                        sqCells[r * _sizeSqrt + c] = new Cell(c + startCol, r + startRow);
                    }
                }
                _cellsRegion[(int)RegionType.Square, i] = sqCells;
            }
            SolvedCount = model.SolvedCount;
            EliminatedCount = model.EliminatedCount;
            ChangeCount = model.ChangeCount;
            LastChangedCell = model.LastChangedCell;
        }