@Override
    public Solution findSolution(T firstStep, T target) {
        HashMap<T, T> foundNodes = new HashMap<>();
        List<T> path = new ArrayList<>();
        int score = evaluator.evaluate(target, firstStep);
        firstStep.setScore(score);
        path.add(firstStep);

        while ( ! path.isEmpty() ) {
            Collections.sort(path, SCORE_COMPARATOR);
            T node = path.remove(0);
            foundNodes.put(node, node);
            boolean targetFound = node.equals(target);
            if ( targetFound ) {
                return createSolution(node, foundNodes.values(), path);
            }

            for ( Node obj : node.nextSteps() ) {
                T next = (T) obj;
                int newScore = evaluator.evaluate(target, next);
                next.setScore(newScore);
                boolean exists = foundNodes.containsKey(next);
                if  ( exists ) {
                    T prior = foundNodes.get(next);
                    boolean scoreImproved = prior.getScore() > next.getScore();
                    if ( scoreImproved ) {
                        foundNodes.remove(next);
                        path.add(next);
                    }
                } else {
                    foundNodes.put(next, next);
                    path.add(next);
                }
            }
        }

        return null;
    }