static boolean prefixMatches(Tree target, Tree pattern) { if (pattern.isEmpty()) return true; if (target.isEmpty() || target.value() != pattern.value()) return false; return prefixMatches(target.left(), pattern.left()) && prefixMatches(target.right(), pattern.right()); }
/** * Search the tree for the first instance of `pattern`, giving preference to the left child. * * <p>`pattern` is a tree, representing a pattern of nodes. `NilNode`s should be considered * wildcards. * * <p>Example patterns ---------------- `Tree()` Matches any tree. * * <p>`Tree(3)` Matches any tree where the root node has a value of `3`. * * <p>`Tree(3, Tree(2), Tree())` Matches any tree where the root node has a value of `3`, and a * left sub-tree with a root value of `2`, and any (or no) right sub-tree. */ static Optional<Tree> find(Tree target, Tree pattern) { if (pattern.isEmpty()) return Optional.of(target); if (target.isEmpty()) return Optional.empty(); if (prefixMatches(target, pattern)) return Optional.of(target); Optional<Tree> leftMatch = find(target.left(), pattern); if (leftMatch.isPresent()) return leftMatch; return find(target.right(), pattern); }