public IEnumerable <BottlesState> GetStates(BottlesState currentState) { var options = new List <BottlesState>(); // Bottle 1 --> Bottle 2 if (currentState.Bottle1 > 0 && currentState.Bottle2 < _bottle2Max) { int bottle2 = currentState.Bottle2 + currentState.Bottle1; var overflow = bottle2 - _bottle2Max; // Om vi inte får plats, låt det överflödiga ligga kvar int bottle1 = overflow > 0 ? overflow : 0; // Om vi inte får plats, fyll flaskan. bottle2 = bottle2 > _bottle2Max ? _bottle2Max : bottle2; options.Add(new BottlesState(bottle1, bottle2)); } // Bottle 2 --> Bottle 1 if (currentState.Bottle2 > 0 && currentState.Bottle1 < _bottle1Max) { int bottle1 = currentState.Bottle1 + currentState.Bottle2; var overflow = bottle1 - _bottle1Max; // Om vi inte får plats, låt det överflödiga ligga kvar int bottle2 = overflow > 0 ? System.Math.Abs(overflow) : 0; // Om vi inte får plats, fyll flaskan. bottle1 = bottle1 > _bottle1Max ? _bottle1Max : bottle1; options.Add(new BottlesState(bottle1, bottle2)); } // Bottle 1 --> Empty if (currentState.Bottle1 > 0) { options.Add(new BottlesState(0, currentState.Bottle2)); } // Bottle 2 --> Empty if (currentState.Bottle2 > 0) { options.Add(new BottlesState(currentState.Bottle1, 0)); } // Bottle 1 --> Fill if (currentState.Bottle1 < _bottle1Max) { options.Add(new BottlesState(_bottle1Max, currentState.Bottle2)); } // Bottle 2 --> Fill if (currentState.Bottle2 < _bottle2Max) { options.Add(new BottlesState(currentState.Bottle2, _bottle2Max)); } return(options); }
public static IEnumerable <BottlesState> FindPath(BottleGraph map, BottlesState start, Func <BottlesState, bool> isDone) { var foundPath = new List <BottlesState>(); int nodesChecked = 0; bool found = false; var toVisit = new Queue <BottlesState> (); toVisit.Enqueue(start); var cameFrom = new Dictionary <Tuple <int, int>, BottlesState> (); cameFrom.Add(Tuple.Create(start.Bottle1, start.Bottle2), null); var costs = new Dictionary <Tuple <int, int>, int> (); costs.Add(Tuple.Create(start.Bottle1, start.Bottle2), 0); var foundGoal = toVisit.First(); while (toVisit.Count > 0) { var current = toVisit.Dequeue(); if (isDone(current)) { found = true; foundGoal = current; break; } var neighbours = map.GetStates(current).ToArray(); foreach (var next in neighbours) { int newCost = costs[Tuple.Create(current.Bottle1, current.Bottle2)] + 1; if (!costs.ContainsKey(Tuple.Create(next.Bottle1, next.Bottle2)) || newCost < costs [Tuple.Create(next.Bottle1, next.Bottle2)]) { costs [Tuple.Create(next.Bottle1, next.Bottle2)] = newCost; toVisit.Enqueue(next); cameFrom [Tuple.Create(next.Bottle1, next.Bottle2)] = current; } } nodesChecked++; } if (!found) { return(foundPath); } var reverseCurrent = foundGoal; var path = new Queue <BottlesState> (new[] { reverseCurrent }); while (reverseCurrent != start) { reverseCurrent = cameFrom [Tuple.Create(reverseCurrent.Bottle1, reverseCurrent.Bottle2)]; path.Enqueue(reverseCurrent); } foundPath = path.Reverse().ToList(); return(foundPath); }