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); } } }
private StandardRules(StandardRules existing, IReadOnlyBoxPuzzle puzzle) { _puzzle = puzzle; _unsetRowValues = existing._unsetRowValues.AsSpan().ToArray(); _unsetColValues = existing._unsetColValues.AsSpan().ToArray(); _unsetBoxValues = existing._unsetBoxValues.AsSpan().ToArray(); }
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); }
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(); }
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); }
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)); } }
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); } } }
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; }