public BoxUniquenessRule(IReadOnlyBoxPuzzle puzzle, BitVector allUniqueValues, bool skipMatchingRowAndCol)
        {
            Debug.Assert(puzzle.Size == allUniqueValues.Count,
                         $"Can't enforce box uniqueness for mismatched puzzle size {puzzle.Size} and number of unique values {allUniqueValues.Count}");
            _puzzle         = puzzle;
            _unsetBoxValues = new BitVector[puzzle.Size];
            _unsetBoxValues.AsSpan().Fill(allUniqueValues);
            _skipMatchingRowAndCol = skipMatchingRowAndCol;
            int boxIdx = -1;

            for (int row = 0; row < puzzle.Size; row++)
            {
                for (int col = 0; col < puzzle.Size; col++)
                {
                    if (col == 0)
                    {
                        boxIdx = (row / puzzle.BoxSize) * puzzle.BoxSize;
                    }
                    else if (col % puzzle.BoxSize == 0)
                    {
                        boxIdx++;
                    }
                    int?val = puzzle[row, col];
                    if (!val.HasValue)
                    {
                        continue;
                    }
                    if (!_unsetBoxValues[boxIdx].IsBitSet(val.Value))
                    {
                        throw new ArgumentException($"Puzzle has duplicate value in box at ({row}, {col}).");
                    }
                    _unsetBoxValues[boxIdx].UnsetBit(val.Value);
                }
            }
        }
Example #2
0
 private StandardRules(StandardRules existing, IReadOnlyBoxPuzzle puzzle)
 {
     _puzzle         = puzzle;
     _unsetRowValues = existing._unsetRowValues.AsSpan().ToArray();
     _unsetColValues = existing._unsetColValues.AsSpan().ToArray();
     _unsetBoxValues = existing._unsetBoxValues.AsSpan().ToArray();
 }
Example #3
0
 public UniqueInBoxHeuristic(IReadOnlyBoxPuzzle puzzle, PossibleValues possibleValues, IMissingBoxValuesTracker rule)
 {
     _puzzle                 = puzzle;
     _possibleValues         = possibleValues;
     _boxTracker             = rule;
     _possiblesToCheckInBox  = new BitVector[puzzle.Size];
     _previousPossiblesStack = new Stack <IReadOnlyDictionary <Coordinate, BitVector> >();
 }
 public StandardHeuristic(IReadOnlyBoxPuzzle puzzle, PossibleValues possibleValues,
                          IMissingRowValuesTracker rowRule, IMissingColumnValuesTracker columnRule, IMissingBoxValuesTracker boxRule)
 {
     _rowHeuristic     = new UniqueInRowHeuristic(puzzle, possibleValues, rowRule);
     _columnHeuristic  = new UniqueInColumnHeuristic(puzzle, possibleValues, columnRule);
     _boxHeuristic     = new UniqueInBoxHeuristic(puzzle, possibleValues, boxRule);
     _numHeuristicsRan = new Stack <int>(puzzle.NumEmptySquares);
 }
Example #5
0
 private StandardRuleKeeper(
     StandardRuleKeeper existing, IReadOnlyBoxPuzzle puzzle, PossibleValues possibleValues)
 {
     _puzzle            = puzzle;
     _possibleValues    = possibleValues;
     _unsetRowValues    = existing._unsetRowValues.AsSpan().ToArray();
     _unsetColumnValues = existing._unsetColumnValues.AsSpan().ToArray();
     _unsetBoxValues    = existing._unsetBoxValues.AsSpan().ToArray();
 }
Example #6
0
 private UniqueInBoxHeuristic(
     UniqueInBoxHeuristic existing,
     IReadOnlyBoxPuzzle puzzle,
     PossibleValues possibleValues,
     IMissingBoxValuesTracker rule)
 {
     _puzzle                 = puzzle;
     _possibleValues         = possibleValues;
     _boxTracker             = rule;
     _possiblesToCheckInBox  = (BitVector[])existing._possiblesToCheckInBox.Clone();
     _previousPossiblesStack = new Stack <IReadOnlyDictionary <Coordinate, BitVector> >(
         existing._previousPossiblesStack);
 }
Example #7
0
        public StandardRuleKeeper(IReadOnlyBoxPuzzle puzzle, PossibleValues possibleValues)
        {
            _puzzle         = puzzle;
            _possibleValues = possibleValues;
            _unsetRowValues = new BitVector[puzzle.Size];
            _unsetRowValues.AsSpan().Fill(possibleValues.AllPossible);
            _unsetColumnValues = _unsetRowValues.AsSpan().ToArray();
            _unsetBoxValues    = _unsetRowValues.AsSpan().ToArray();

            int boxIdx = 0;

            for (int row = 0; row < puzzle.Size; row++)
            {
                for (int col = 0; col < puzzle.Size; col++)
                {
                    if (col == 0)
                    {
                        boxIdx = (row / puzzle.BoxSize) * puzzle.BoxSize;
                    }
                    else if (col % puzzle.BoxSize == 0)
                    {
                        boxIdx++;
                    }
                    int?val = puzzle[row, col];
                    if (!val.HasValue)
                    {
                        continue;
                    }
                    if (!_unsetRowValues[row].IsBitSet(val.Value))
                    {
                        throw new ArgumentException($"Puzzle violates the unique-in-row rule at ({row}, {col}).");
                    }
                    if (!_unsetColumnValues[col].IsBitSet(val.Value))
                    {
                        throw new ArgumentException($"Puzzle violates the unique-in-column rule at ({row}, {col}).");
                    }
                    if (!_unsetBoxValues[boxIdx].IsBitSet(val.Value))
                    {
                        throw new ArgumentException($"Puzzle violates the unique-in-box rule at ({row}, {col}).");
                    }
                    _unsetRowValues[row].UnsetBit(val.Value);
                    _unsetColumnValues[col].UnsetBit(val.Value);
                    _unsetBoxValues[boxIdx].UnsetBit(val.Value);
                }
            }
            foreach (Coordinate c in puzzle.GetUnsetCoords())
            {
                _possibleValues.Intersect(in c, _GetPossibleValues(in c));
            }
        }
Example #8
0
        public StandardRules(IReadOnlyBoxPuzzle puzzle, BitVector allUniqueValues)
        {
            _puzzle         = puzzle;
            _unsetRowValues = new BitVector[puzzle.Size];
            _unsetRowValues.AsSpan().Fill(allUniqueValues);
            _unsetColValues = _unsetRowValues.AsSpan().ToArray();
            _unsetBoxValues = _unsetRowValues.AsSpan().ToArray();

            int boxIdx = 0;

            for (int row = 0; row < puzzle.Size; row++)
            {
                for (int col = 0; col < puzzle.Size; col++)
                {
                    if (col == 0)
                    {
                        boxIdx = (row / puzzle.BoxSize) * puzzle.BoxSize;
                    }
                    else if (col % puzzle.BoxSize == 0)
                    {
                        boxIdx++;
                    }
                    int?val = puzzle[row, col];
                    if (!val.HasValue)
                    {
                        continue;
                    }
                    if (!_unsetRowValues[row].IsBitSet(val.Value))
                    {
                        throw new ArgumentException($"Puzzle does not satisfy rule at ({row}, {col}).");
                    }
                    if (!_unsetColValues[col].IsBitSet(val.Value))
                    {
                        throw new ArgumentException($"Puzzle does not satisfy rule at ({row}, {col}).");
                    }
                    if (!_unsetBoxValues[boxIdx].IsBitSet(val.Value))
                    {
                        throw new ArgumentException($"Puzzle does not satisfy rule at ({row}, {col}).");
                    }
                    _unsetRowValues[row].UnsetBit(val.Value);
                    _unsetColValues[col].UnsetBit(val.Value);
                    _unsetBoxValues[boxIdx].UnsetBit(val.Value);
                }
            }
        }
Example #9
0
        private static void _AppendConstraintHeadersInBox(
            int box, IReadOnlyBoxPuzzle puzzle, ExactCoverMatrix matrix)
        {
            Coordinate startCoord = puzzle.GetStartingBoxCoordinate(box);
            var        endCoord   = new Coordinate(
                startCoord.Row + puzzle.BoxSize, startCoord.Column + puzzle.BoxSize);
            Span <Coordinate> boxCoordinates = stackalloc Coordinate[puzzle.Size];
            int i = 0;

            for (int row = startCoord.Row; row < endCoord.Row; row++)
            {
                for (int col = startCoord.Column; col < endCoord.Column; col++)
                {
                    boxCoordinates[i++] = new Coordinate(row, col);
                }
            }
            ConstraintUtil.ImplementUniquenessConstraintForSquares(puzzle, boxCoordinates, matrix);
        }
 private BoxUniquenessRule(BoxUniquenessRule existing, IReadOnlyBoxPuzzle puzzle)
 {
     _puzzle                = puzzle;
     _unsetBoxValues        = existing._unsetBoxValues.AsSpan().ToArray();
     _skipMatchingRowAndCol = existing._skipMatchingRowAndCol;
 }