LMU ☀️ CMSI 2120
DATA STRUCTURES
HOMEWORK #6 PARTIAL ANSWERS
WordFinder.java
import java.util.List;
import java.util.ArrayList;

public class WordFinder {

    private static class Node {
        char character;
        boolean last;
        Node left;
        Node middle;
        Node right;

        Node(char character) {
            this.character = character;
        }

        void add(String word) {
            var first = word.charAt(0);
            var rest = word.substring(1);
            if (first < character) {
                if (left == null)
                    left = new Node(first);
                left.add(word);
            } else if (first > character) {
                if (right == null)
                    right = new Node(first);
                right.add(word);
            } else if (rest.isEmpty()) {
                last = true;
            } else {
                if (middle == null)
                    middle = new Node(rest.charAt(0));
                middle.add(rest);
            }
        }

        Node nodeFor(String word) {
            if (word.isEmpty())
                return this;
            var first = word.charAt(0);
            var rest = word.substring(1);
            if (first < character)
                return left == null ? null : left.nodeFor(word);
            if (first > character)
                return right == null ? null : right.nodeFor(word);
            if (rest.isEmpty())
                return this;
            return middle == null ? null : middle.nodeFor(rest);
        }

        void accumulateWords(String prefix, List<String> words) {
            if (left != null)
                left.accumulateWords(prefix, words);
            if (last)
                words.add(prefix + character);
            if (middle != null)
                middle.accumulateWords(prefix + character, words);
            if (right != null)
                right.accumulateWords(prefix, words);
        }
    }

    // Initializing the root to an arbitrary value saves so much null checking!
    private Node root = new Node('i');

    public void add(String word) {
        word = word.trim();
        if (word.isEmpty()) {
            throw new IllegalArgumentException("Empty word is not allowed");
        }
        root.add(word);
    }

    public boolean contains(String word) {
        // Just find the right node (if present) and see if its a "last" node
        word = word.trim();
        var node = root.nodeFor(word);
        return node != null && node.last;
    }

    public List<String> suggestions(String prefix) {
        prefix = prefix.trim();
        if (prefix.isEmpty())
            throw new IllegalArgumentException("Need at least one char for suggestions");
        var words = new ArrayList<String>();
        var node = root.nodeFor(prefix);
        if (node != null) {
            if (node.last)
                words.add(prefix);
            if (node.middle != null)
                node.middle.accumulateWords(prefix, words);
        }
        return words;
    }

    public List<String> allWords() {
        var words = new ArrayList<String>();
        root.accumulateWords("", words);
        return words;
    }
}