示例#1
0
        public void Constrain_GroupsConstraintsAsExpected()
        {
            int size    = 4;
            int boxSize = 2;

            int[] possibleValues   = new int[] { 1, 3, 5, 7 };
            var   puzzle           = new Puzzle(size);
            var   matrix           = ExactCoverGraph.Create(puzzle);
            var   squareObjectives = new HashSet <Objective>(matrix.GetUnsatisfiedRequiredObjectivesWithConcretePossibilities());

            Assert.True(new BoxUniquenessConstraint().TryConstrain(puzzle, matrix));

            Assert.Equal(
                size * possibleValues.Length + squareObjectives.Count,
                matrix.GetUnsatisfiedRequiredObjectivesWithConcretePossibilities().Count());
            Dictionary <int, HashSet <int> > boxIndicesToValues = new();

            for (int i = 0; i < size; ++i)
            {
                boxIndicesToValues[i] = new HashSet <int>();
            }
            Assert.All(matrix.GetUnsatisfiedRequiredObjectivesWithConcretePossibilities(),
                       concreteObjective =>
            {
                if (squareObjectives.Contains(concreteObjective))
                {
                    return;
                }
                IObjective objective = concreteObjective;
                var possibilities    = objective.GetUnknownDirectPossibilities().Cast <Possibility>().ToArray();
                int boxIndex         = Boxes.CalculateBoxIndex(possibilities[0].Coordinate, boxSize);
                int value            = possibilities[0].Index;
                Assert.DoesNotContain(value, boxIndicesToValues[boxIndex]);
                boxIndicesToValues[boxIndex].Add(value);
                var boxCoordinates = Boxes.YieldUnsetCoordsForBox(boxIndex, boxSize, puzzle).ToArray();
                Assert.Equal(boxCoordinates.Length, possibilities.Length);
                Assert.All(possibilities, p =>
                {
                    Assert.Contains(p.Coordinate, boxCoordinates);
                    Assert.Equal(value, p.Index);
                });
                Assert.All(boxCoordinates, c => Assert.NotNull(possibilities.SingleOrDefault(p => p.Coordinate == c)));
            });
            Assert.All(
                boxIndicesToValues.Values,
                values => Assert.Equal(new HashSet <int> {
                0, 1, 2, 3
            }, values));
        }
示例#2
0
        /// <inheritdoc/>
        public bool TryInit(IReadOnlyPuzzleWithMutablePossibleValues puzzle)
        {
            int size = puzzle.Size;

            _puzzle         = puzzle;
            _boxSize        = Boxes.IntSquareRoot(puzzle.Size);
            _unsetRowValues = new BitVector[size];
            _unsetRowValues.AsSpan().Fill(_puzzle.UniquePossibleValues);
            Span <BitVector> possibleValues = _unsetRowValues.AsSpan();

            _unsetColumnValues = possibleValues.ToArray();
            _unsetBoxValues    = possibleValues.ToArray();

            int boxIdx;

            for (int row = 0; row < size; row++)
            {
                for (int col = 0; col < size; col++)
                {
                    boxIdx = Boxes.CalculateBoxIndex(new Coordinate(row, col), _boxSize);
                    int?val = puzzle[row, col];
                    if (!val.HasValue)
                    {
                        continue;
                    }
                    if (!_unsetRowValues[row].IsBitSet(val.Value) ||
                        !_unsetColumnValues[col].IsBitSet(val.Value) ||
                        !_unsetBoxValues[boxIdx].IsBitSet(val.Value))
                    {
                        return(false);
                    }
                    _unsetRowValues[row].UnsetBit(val.Value);
                    _unsetColumnValues[col].UnsetBit(val.Value);
                    _unsetBoxValues[boxIdx].UnsetBit(val.Value);
                }
            }
            foreach (Coordinate c in puzzle.GetUnsetCoords())
            {
                _puzzle.IntersectPossibleValues(in c, _GetPossibleValues(in c));
                if (_puzzle.GetPossibleValues(in c).IsEmpty)
                {
                    return(false);
                }
            }
            return(true);
        }