From 8187f024bae57267af514c5dcb730de09e573e41 Mon Sep 17 00:00:00 2001 From: Carlo Zancanaro Date: Mon, 1 Jun 2015 11:41:16 +1000 Subject: Move packages, make lists shrink in size, generate lists instead of arrays as the 'primitive' operation (issues with generics) --- .../java/au/id/zancanaro/javacheck/RoseTree.java | 105 +++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 src/main/java/au/id/zancanaro/javacheck/RoseTree.java (limited to 'src/main/java/au/id/zancanaro/javacheck/RoseTree.java') diff --git a/src/main/java/au/id/zancanaro/javacheck/RoseTree.java b/src/main/java/au/id/zancanaro/javacheck/RoseTree.java new file mode 100644 index 0000000..d9fb508 --- /dev/null +++ b/src/main/java/au/id/zancanaro/javacheck/RoseTree.java @@ -0,0 +1,105 @@ +package au.id.zancanaro.javacheck; + +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.function.Function; +import java.util.function.Predicate; + +public class RoseTree { + private final T value; + private final Iterable> children; + + public RoseTree(T value, Iterable> children) { + this.value = value; + this.children = children; + } + + public T getValue() { + return value; + } + + public Iterator> getChildren() { + return children.iterator(); + } + + public static RoseTree pure(T value) { + return new RoseTree<>(value, Collections.emptyList()); + } + + public static RoseTree join(RoseTree> tree) { + return new RoseTree<>( + tree.getValue().getValue(), + () -> Iterators.concat( + Iterators.mappingIterator(RoseTree::join, tree.children.iterator()), + tree.getValue().children.iterator())); + } + + public static Iterator[]> permutations(RoseTree[] trees) { + return Iterators.flatten(Iterators.rangeIterator(trees.length, index -> + Iterators.mappingIterator(child -> { + @SuppressWarnings("unchecked") + RoseTree[] result = (RoseTree[]) new RoseTree[trees.length]; + for (int i = 0; i < trees.length; ++i) { + result[i] = (i == index ? child : trees[i]); + } + return result; + }, trees[index].getChildren()) + )); + } + + public static RoseTree zip(Function, R> fn, RoseTree[] trees) { + @SuppressWarnings("unchecked") + List heads = new ArrayList(trees.length); + for (int i = 0; i < trees.length; ++i) { + heads.add(trees[i].getValue()); + } + return new RoseTree<>( + fn.apply(heads), + () -> Iterators.mappingIterator( + roses -> RoseTree.zip(fn, roses), + RoseTree.permutations(trees))); + } + + public RoseTree fmap(Function f) { + return new RoseTree<>( + f.apply(this.value), + () -> Iterators.mappingIterator(tree -> tree.fmap(f), this.children.iterator())); + } + + public RoseTree flatmap(Function> f) { + return RoseTree.join(this.fmap(f)); + } + + public RoseTree filter(Predicate predicate) { + if (predicate.test(this.getValue())) { + return new RoseTree<>( + this.getValue(), + () -> Iterators.mappingIterator(tree -> tree.filter(predicate), + Iterators.filteringIterator( + tree -> predicate.test(tree.getValue()), + this.getChildren()))); + } else { + throw new IllegalArgumentException("Current value doesn't match predicate: whoops!"); + } + } + + @SuppressWarnings("unused") + public void print(Writer output) throws IOException { + print(output, Object::toString); + } + + @SuppressWarnings("unused") + public void print(Writer output, Function toString) throws IOException { + output.write(toString.apply(this.getValue())); + output.write('['); + for (RoseTree child : children) { + child.print(output, toString); + } + output.write(']'); + output.flush(); + } +} -- cgit v1.2.3