/** * Returns a finger tree which combines the integer node annotations with the * maximum function. A priority queue with integer priorities. */ public static <A> FingerTree<Integer, P2<Integer, A>> emptyIntMax() { return empty(intMaxMonoid, (P2<Integer, A> p) -> p._1()); }
/** * Creates a {@link P4} by adding the given element to the current {@link P2} * * @param el the element to append * @return A {@link P4} containing the original {@link P2} with the extra element added at the end */ public final <C, D> P4<A, B, C, D> append(P2<C, D> el) { return P.p(_1(), _2(), el._1(), el._2()); }
/** * Uncurries this function to a function on tuples. * * @return A new function that calls this function with the elements of a given tuple. */ public static <A, B, C> F<P2<A, B>, C> tuple(final F2<A, B, C> f) { return p -> f.f(p._1(), p._2()); }
/** * Creates a {@link P3} by adding the given element to the current {@link P2} * * @param el the element to append * @return A {@link P3} containing the original {@link P2} with the extra element added at the end */ public final <C> P3<A, B, C> append(C el) { return P.p(_1(), _2(), el); }
/** * Map the first element of the product. * * @param f The function to map with. * @return A product with the given function applied. */ public final <X> P2<X, B> map1(final F<A, X> f) { P2<A, B> self = this; return P.lazy(() -> f.f(self._1()), self::_2); }
/** * Adds a node with priority k and value a. This operation take O(1). */ public PriorityQueue<K, A> enqueue(P2<K, A> p) { return enqueue(p._1(), p._2()); }
/** * Transforms a curried function of arity-2 to a function of a product-2 * * @param f a curried function of arity-2 to transform into a function of a product-2 * @return The function, transformed to operate on on a product-2 */ public static <A, B, C> F<P2<A, B>, C> tuple(final F<A, F<B, C>> f) { return p -> f.f(p._1()).f(p._2()); }
/** * A lazy semigroup for binary products. * * @param sa A semigroup for the product's first type. * @param sb A semigroup for the product's second type. * @return A semigroup for binary products. */ public static <A, B> Semigroup<P2<A, B>> p2Semigroup(final Semigroup<A> sa, final Semigroup<B> sb) { return semigroupDef((a1, a2) -> P.lazy(() -> sa.sum(a1._1(), a2._1()), () -> sb.sum(a1._2(), a2._2()))); }
/** * Polyomorphic lens targeted on _2. */ public static <A, B, C> PLens<P2<A, B>, P2<A, C>, B, C> _2p() { return pLens(__2(), b -> p2 -> P.p(p2._1(), b)); }
/** * Filters the nodes based on the annotation of each node. */ public PriorityQueue<K, A> filterKeys(F<K, Boolean> f) { return priorityQueue(equal, ftree.filter(p2 -> f.f(p2._1()))); }
/** * Removes the first element that equals the given object. * To remove all matches, use <code>removeAll(e.eq(a))</code> * * @param a The element to remove * @param e An <code>Equals</code> instance for the element's type. * @return A new list whose elements do not match the given predicate. */ public final List<A> delete(final A a, final Equal<A> e) { final P2<List<A>, List<A>> p = span(compose(not, e.eq(a))); return p._2().isEmpty() ? p._1() : p._1().append(p._2().tail()); }
/** * Returns the minimum (key, value) pair in the tree if the tree is not empty. */ public Option<P2<K, V>> min() { return tree.min().map(p -> p(p._1(), p._2().some())); }
/** * Splits this sequence into a pair of sequences at the given position. This is a O(log(n)) operation. * * @return Pair: the subsequence containing elements with indices less than <code>i</code> * and the subsequence containing elements with indices greater than or equal to <code>i</code>. */ public P2<Seq<A>, Seq<A>> split(final int i) { final P2<FingerTree<Integer, A>, FingerTree<Integer, A>> lr = ftree.split(index -> index > i); return P.p(new Seq<>(lr._1()), new Seq<>(lr._2())); }
/** * Returns the position of the first element matching the given predicate, if any. * * @param p A predicate to match. * @return the position of the first element matching the given predicate, if any. */ public final Option<Integer> indexOf(final F<A, Boolean> p) { return zipIndex().find(p2 -> p.f(p2._1())).map(P2.__2()); }
/** * Inserts the element at the given index. This is an O(log(n)) operation. * * @param index The index of the element to return. * @return The sequence with the element inserted at the given index, * or throws an error if the index is out of bounds. */ public Seq<A> insert(int index, A a) { final P2<Seq<A>, Seq<A>> p = split(index); return p._1().append(single(a)).append(p._2()); }
/** * Creates a {@link P5} by adding the given element to the current {@link P2} * * @param el the element to append * @return A {@link P5} containing the original {@link P2} with the extra element added at the end */ public final <C, D, E> P5<A, B, C, D, E> append(P3<C, D, E> el) { return P.p(_1(), _2(), el._1(), el._2(), el._3()); }
/** * Creates a {@link P5} by adding the given element to the current {@link P3} * * @param el the element to append * @return A {@link P5} containing the original {@link P3} with the extra element added at the end */ public final <D, E> P5<A, B, C, D, E> append(P2<D, E> el) { return P.p(_1(), _2(), _3(), el._1(), el._2()); }
/** * Creates a {@link P6} by adding the given element to the current {@link P4} * * @param el the element to append * @return A {@link P6} containing the original {@link P4} with the extra element added at the end */ public final <E, F> P6<A, B, C, D, E, F> append(P2<E, F> el) { return P.p(_1(), _2(), _3(), _4(), el._1(), el._2()); }
/** * Creates a {@link P7} by adding the given element to the current {@link P2} * * @param el the element to append * @return A {@link P7} containing the original {@link P2} with the extra element added at the end */ public final <C, D, E, F, G> P7<A, B, C, D, E, F, G> append(P5<C, D, E, F, G> el) { return P.p(_1(), _2(), el._1(), el._2(), el._3(), el._4(), el._5()); }
/** * Returns all the elements of the queue with the highest (same) priority. */ public List<P2<K, A>> topN() { return toStream().uncons( List.nil(), top -> tail -> List.cons(top, tail._1().takeWhile(compose(equal.eq(top._1()), P2.__1())).toList()) ); }