/// <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; }
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); }
/// <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()); }
/// <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))); }