Beispiel #1
0
 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);
                         }
                     }
                 }
             }
         }
     }
 }
Beispiel #2
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);
     }
 }
Beispiel #3
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);
                     }
                 }
             }
         }
     }
 }
Beispiel #4
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;
 }
Beispiel #5
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;
        }