Skip to content

Commit f21c310

Browse files
committed
Add PriorityQueue.unqueue and use it to implement some other methods.
+ some other minor refactoring.
1 parent 3812a83 commit f21c310

File tree

1 file changed

+32
-22
lines changed

1 file changed

+32
-22
lines changed

core/src/main/java/fj/data/PriorityQueue.java

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@
22

33
import fj.Equal;
44
import fj.F;
5+
import fj.F2;
56
import fj.Monoid;
67
import fj.Ord;
78
import fj.P;
89
import fj.P2;
9-
import fj.P3;
1010
import fj.Show;
1111
import fj.data.fingertrees.FingerTree;
1212

13-
import static fj.data.List.list;
13+
import static fj.Function.compose;
14+
import static fj.data.Option.none;
15+
import static fj.data.Option.some;
1416

1517
/**
1618
* A priority queue implementation backed by a
@@ -91,22 +93,17 @@ public boolean isEmpty() {
9193
* If the tree is not empty, returns the node with highest priority otherwise returns nothing.
9294
*/
9395
public Option<P2<K, A>> top() {
94-
K top = ftree.measure();
95-
P2<FingerTree<K, P2<K, A>>, FingerTree<K, P2<K, A>>> p = ftree.split(k -> equal.eq(top, k));
96-
return p._2().headOption();
96+
return unqueue(none(), (top, tail) -> some(top));
9797
}
9898

9999
/**
100100
* Returns all the elements of the queue with the highest (same) priority.
101101
*/
102102
public List<P2<K, A>> topN() {
103-
Stream<P2<K, A>> s = toStream();
104-
if (s.isEmpty()) {
105-
return List.nil();
106-
} else {
107-
final K k = s.head()._1();
108-
return s.takeWhile(p -> equal.eq(k, p._1())).toList();
109-
}
103+
return toStream().uncons(
104+
List.nil(),
105+
top -> tail -> List.cons(top, tail._1().takeWhile(compose(equal.eq(top._1()), P2.__1())).toList())
106+
);
110107
}
111108

112109
/**
@@ -127,7 +124,7 @@ public PriorityQueue<K, A> enqueue(List<P2<K, A>> list) {
127124
* Does the priority k exist already?
128125
*/
129126
public boolean contains(final K k) {
130-
return !ftree.split(k2 -> equal.eq(k, k2))._2().isEmpty();
127+
return !ftree.split(equal.eq(k))._2().isEmpty();
131128
}
132129

133130
/**
@@ -152,17 +149,30 @@ public PriorityQueue<K, A> enqueue(P2<K, A> p) {
152149
* Removes the node with the highest priority.
153150
*/
154151
public PriorityQueue<K, A> dequeue() {
155-
K top = ftree.measure();
156-
P2<FingerTree<K, P2<K, A>>, FingerTree<K, P2<K, A>>> p = ftree.split(k -> equal.eq(k, top));
157-
FingerTree<K, P2<K, A>> right = p._2();
158-
return right.isEmpty() ? this : priorityQueue(equal, p._1().append(right.tail()));
152+
return unqueue(this, (top, tail) -> tail);
159153
}
160154

161155
/**
162156
* Returns a tuple of the node with the highest priority and the rest of the priority queue.
163157
*/
164158
public P2<Option<P2<K, A>>, PriorityQueue<K, A>> topDequeue() {
165-
return P.p(top(), dequeue());
159+
return unqueue(P.p(none(), this), (top, tail) -> P.p(some(top), tail));
160+
}
161+
162+
/**
163+
* Performs a reduction on this priority queue using the given arguments.
164+
*
165+
* @param empty The value to return if this queue is empty.
166+
* @param topDequeue The function to apply to the top priority element and the tail of the queue (without its top element).
167+
* @return A reduction on this queue.
168+
*/
169+
public <B> B unqueue(B empty, F2<P2<K, A>, PriorityQueue<K, A>, B> topDequeue) {
170+
K top = ftree.measure();
171+
P2<FingerTree<K, P2<K, A>>, FingerTree<K, P2<K, A>>> p = ftree.split(equal.eq(top));
172+
return p._2().uncons(
173+
empty,
174+
(head, tail) -> topDequeue.f(head, priorityQueue(equal, p._1().append(tail)))
175+
);
166176
}
167177

168178
/**
@@ -182,22 +192,22 @@ public PriorityQueue<K, A> dequeue(int n) {
182192
* Does the top of the queue have lower priority than k?
183193
*/
184194
public boolean isLessThan(Ord<K> ok, K k) {
185-
return top().map(p -> ok.isLessThan(p._1(), k)).orSome(true);
195+
return top().option(true, p -> ok.isLessThan(p._1(), k));
186196
}
187197

188198
public boolean isGreaterThan(Ord<K> ok, K k) {
189-
return top().map(p -> ok.isGreaterThan(p._1(), k)).orSome(false);
199+
return top().option(false, p -> ok.isGreaterThan(p._1(), k));
190200
}
191201

192202
public boolean isEqual(Ord<K> ok, K k) {
193-
return top().map(p -> ok.eq(p._1(), k)).orSome(false);
203+
return top().option(false, p -> ok.eq(p._1(), k));
194204
}
195205

196206
/**
197207
* Returns a stream of products with priority k and value a.
198208
*/
199209
public Stream<P2<K, A>> toStream() {
200-
return top().map(p -> Stream.cons(p, () -> dequeue().toStream())).orSome(() -> Stream.nil());
210+
return unqueue(Stream.nil(), (top, tail) -> Stream.cons(top, () -> tail.toStream()));
201211
}
202212

203213
/**

0 commit comments

Comments
 (0)