@Override default <U> Tree<Tuple2<T, U>> zipAll(Iterable<U> that, T thisElem, U thatElem) { Objects.requireNonNull(that, "that is null"); if (isEmpty()) { return Iterator.ofAll(that).map(elem -> Tuple.of(thisElem, elem)).toTree(); } else { final java.util.Iterator<U> thatIter = that.iterator(); final Tree<Tuple2<T, U>> tree = ZipAll.apply((Node<T>) this, thatIter, thatElem); if (thatIter.hasNext()) { final Iterable<Node<Tuple2<T, U>>> remainder = Iterator.ofAll(thatIter).map(elem -> Tree.of(Tuple.of(thisElem, elem))); return new Node<>(tree.getValue(), tree.getChildren().appendAll(remainder)); } else { return tree; } } }
private static String toLispString(Tree<?> tree) { final String value = String.valueOf(tree.getValue()); if (tree.isLeaf()) { return value; } else { return String.format( "(%s %s)", value, tree.getChildren().map(Node::toLispString).mkString(" ")); } }
static <T> Stream<T> levelOrder(Tree<T> tree) { Stream<T> result = Stream.empty(); final java.util.Queue<Tree<T>> queue = new java.util.LinkedList<>(); queue.add(tree); while (!queue.isEmpty()) { final Tree<T> next = queue.remove(); result = result.prepend(next.getValue()); queue.addAll(next.getChildren().toJavaList()); } return result.reverse(); }
static <T> Stream<T> inOrder(Tree<T> tree) { if (tree.isLeaf()) { return Stream.of(tree.getValue()); } else { final List<Node<T>> children = tree.getChildren(); return children .tail() .foldLeft(Stream.<T>empty(), (acc, child) -> acc.appendAll(inOrder(child))) .prepend(tree.getValue()) .prependAll(inOrder(children.head())); } }
@SuppressWarnings("unchecked") static <T, U> Tree<U> apply( Node<T> node, Function<? super T, ? extends Iterable<? extends U>> mapper) { final Tree<U> mapped = Tree.ofAll(mapper.apply(node.getValue())); if (mapped.isEmpty()) { return Tree.empty(); } else { final List<Node<U>> children = (List<Node<U>>) (Object) node.getChildren() .map(child -> FlatMap.apply(child, mapper)) .filter(Tree::isDefined); return Tree.of(mapped.getValue(), children.prependAll(mapped.getChildren())); } }
@Override default Tree<T> clear() { return Tree.empty(); }
/** * Returns a Tree containing {@code n} values supplied by a given Supplier {@code s}. * * @param <T> Component type of the Tree * @param n The number of elements in the Tree * @param s The Supplier computing element values * @return A Tree of size {@code n}, where each element contains the result supplied by {@code s}. * @throws NullPointerException if {@code s} is null */ static <T> Tree<T> fill(int n, Supplier<? extends T> s) { Objects.requireNonNull(s, "s is null"); return Collections.fill(n, s, Tree.empty(), Tree::of); }
/** * Returns a Tree containing {@code n} values of a given Function {@code f} over a range of * integer values from 0 to {@code n - 1}. * * @param <T> Component type of the Tree * @param n The number of elements in the Tree * @param f The Function computing element values * @return A Tree consisting of elements {@code f(0),f(1), ..., f(n - 1)} * @throws NullPointerException if {@code f} is null */ static <T> Tree<T> tabulate(int n, Function<? super Integer, ? extends T> f) { Objects.requireNonNull(f, "f is null"); return Collections.tabulate(n, f, Tree.empty(), Tree::of); }
static <T> Stream<T> postOrder(Tree<T> tree) { return tree.getChildren() .foldLeft(Stream.<T>empty(), (acc, child) -> acc.appendAll(postOrder(child))) .append(tree.getValue()); }
static <T> Stream<T> preOrder(Tree<T> tree) { return tree.getChildren() .foldLeft(Stream.of(tree.getValue()), (acc, child) -> acc.appendAll(preOrder(child))); }