Beispiel #1
0
 /// <summary>
 /// Constructs a solver with the given rules and optional heuristic.
 ///
 /// This solver can be used to solve multiple puzzles.
 /// </summary>
 /// <param name="ruleKeeper">The rule keeper to satisfy when solving puzzles.</param>
 /// <param name="heuristic">
 /// A heuristic to use to solve this puzzle efficiently. Can be set to null to skip using
 /// heuristics.
 /// Note that only one heuristic can be provided. To use multiple heuristics, create a
 /// wrapper heuristic like <see cref="StandardHeuristic"/>.
 /// </param>
 public PuzzleSolver(
     IRuleKeeper ruleKeeper,
     IHeuristic?heuristic = null)
 {
     _ruleKeeper = ruleKeeper;
     _heuristic  = heuristic;
 }
Beispiel #2
0
 private SquareTracker(
     TPuzzle puzzle,
     IRuleKeeper ruleKeeper,
     IHeuristic?heuristic = null)
 {
     _puzzle     = puzzle;
     _ruleKeeper = ruleKeeper;
     _heuristic  = heuristic;
     _setCoords  = new Stack <Coordinate>(puzzle.NumEmptySquares);
     _coordsThatUsedHeuristics = _heuristic is null ? null : new Stack <Coordinate>(puzzle.NumEmptySquares);
 }
Beispiel #3
0
 /// <summary>
 /// Creates a deep copy of this tracker in its current state.
 /// </summary>
 internal SquareTracker(SquareTracker <TPuzzle> existing)
 {
     _puzzle    = existing._puzzle.DeepCopy();
     _setCoords = new Stack <Coordinate>(existing._setCoords);
     if (existing._coordsThatUsedHeuristics is not null)
     {
         _coordsThatUsedHeuristics = new Stack <Coordinate>(existing._coordsThatUsedHeuristics !);
     }
     _ruleKeeper = existing._ruleKeeper.CopyWithNewReferences(_puzzle);
     _heuristic  = existing._heuristic?.CopyWithNewReferences(
         _puzzle, _ruleKeeper.GetRules());
 }
Beispiel #4
0
 /// <summary>
 /// Tries to construct and initialize a tracker for the given puzzle, rules, and heuristics.
 /// </summary>
 /// <param name="puzzle">The puzzle to solve.</param>
 /// <param name="ruleKeeper">The rule-keeper to satisfy.</param>
 /// <param name="heuristic">An optional heuristic to user.</param>
 /// <param name="tracker">
 /// An <c>out</c> param where the tracker will be created. Set to null if initialization
 /// fails (i.e. this method returns false).
 /// </param>
 /// <returns>
 /// False if initialization fails, for example if the puzzle violates a rule, else true.
 /// </returns>
 internal static bool TryInit(
     TPuzzle puzzle,
     IRuleKeeper ruleKeeper,
     IHeuristic?heuristic,
     out SquareTracker <TPuzzle>?tracker)
 {
     if (!ruleKeeper.TryInit(puzzle) ||
         (!heuristic?.TryInitFor(puzzle) ?? false))
     {
         tracker = null;
         return(false);
     }
     tracker = new SquareTracker <TPuzzle>(puzzle, ruleKeeper, heuristic);
     return(true);
 }
        public void CopyWithNewReferences_CreatesDeepCopy()
        {
            var puzzle = new PuzzleWithPossibleValues(new int?[][] {
                new int?[] { 1, null /* 4 */, null /* 3 */, 2 },
                new int?[] { null /* 2 */, null /* 3 */, 1, null /* 4 */ },
                new int?[] { null /* 4 */, null /* 1 */, null /* 2 */, null /* 3 */ },
                new int?[] { 3, 2, 4, 1 }
            });
            var rules = new IRule[]
            {
                new RowUniquenessRule(),
                new ColumnUniquenessRule(),
                new BoxUniquenessRule()
            };
            var ruleKeeper = new DynamicRuleKeeper(rules);

            Assert.True(ruleKeeper.TryInit(puzzle));

            var         puzzleCopy     = new PuzzleWithPossibleValues(puzzle);
            IRuleKeeper ruleKeeperCopy = ruleKeeper.CopyWithNewReferences(puzzleCopy);

            var rulesCopy = ruleKeeperCopy.GetRules();

            Assert.Equal(rules.Length, rulesCopy.Length);
            for (int i = 0; i < rules.Length; i++)
            {
                Assert.NotSame(rules[i], rulesCopy[i]);
                Type originalType = rules[i].GetType();
                Type copiedType   = rulesCopy[i].GetType();
                Assert.Equal(originalType, copiedType);
            }
            var coord = new Coordinate(0, 1);
            int val   = 4;

            Assert.True(ruleKeeperCopy.TrySet(coord, val));
            Assert.Equal(new BitVector(0b11000), puzzle.GetPossibleValues(new Coordinate(1, 1)));
            Assert.Equal(new BitVector(0b01000), puzzleCopy.GetPossibleValues(new Coordinate(1, 1)));
        }