private BucketPuzzleSolveOutcome Solve(BucketPuzzle problem, int limit)
        {
            var frontier = new Stack <BucketPuzzle>();

            frontier.Push(problem);

            var explored = new List <BucketPuzzle>();

            do
            {
                var candidate = frontier.Pop();
                if (candidate.IsASolution)
                {
                    return(BucketPuzzleSolveOutcome.Solution(candidate));
                }

                explored.Add(candidate);
                var childStates = candidate.Expand(limit);
                foreach (var childState in childStates)
                {
                    if (!explored.Any(e => e.IsSame(childState)) &&
                        !frontier.Any(f => f.IsSame(childState)))
                    {
                        frontier.Push(childState);
                    }
                }
            } while (frontier.Count > 0);

            return(BucketPuzzleSolveOutcome.CutOff(problem));
        }