Skip to content

Commit d321f84

Browse files
authored
feat(stdlib): Implement fromArray in PriorityQueue & ImmutablePriorityQueue modules (#1451)
feat(stdlib): Improved efficiency of constructing a PriorityQueue from a List
1 parent 943d47d commit d321f84

File tree

6 files changed

+109
-5
lines changed

6 files changed

+109
-5
lines changed

compiler/test/stdlib/immutablepriorityqueue.test.gr

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,6 @@ assert ImmutablePriorityQueue.drain(
8888
ImmutablePriorityQueue.fromList(Array.toList(lotsOfVals), (a, b) => b - a)
8989
) ==
9090
List.reverse(sortedList)
91+
92+
assert ImmutablePriorityQueue.fromList(Array.toList(lotsOfVals), compare) ==
93+
ImmutablePriorityQueue.fromArray(lotsOfVals, compare)

compiler/test/stdlib/priorityqueue.test.gr

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,6 @@ assert PriorityQueue.drain(
7878
PriorityQueue.fromList(Array.toList(lotsOfVals), (a, b) => b - a)
7979
) ==
8080
List.reverse(sortedList)
81+
82+
assert PriorityQueue.fromList(Array.toList(lotsOfVals), compare) ==
83+
PriorityQueue.fromArray(lotsOfVals, compare)

stdlib/immutablepriorityqueue.gr

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88

99
import List from "list"
10+
import Array from "array"
1011

1112
// implementation based on immutable skew binomial queue with global root optimization
1213
// as described in the paper "Optimal Purely Functional Priority Queues" by Chris Okasaki.
@@ -330,3 +331,20 @@ export let drain = pq => {
330331
export let fromList = (list, comp) => {
331332
List.reduce((pq, val) => push(val, pq), make(comp), list)
332333
}
334+
335+
/**
336+
* Constructs a new priority queue initialized with the elements in the array
337+
* using a custom comparator function, which is used to determine priority of
338+
* elements. The comparator function takes two elements and must return 0 if
339+
* both share priority, a positive number if the first has greater priority,
340+
* and a negative number if the first has less priority.
341+
*
342+
* @param array: An array of values used to initialize the priority queue
343+
* @param comp: A comparator function used to assign priority to elements
344+
* @returns A priority queue containing the elements from the array
345+
*
346+
* @since v0.5.4
347+
*/
348+
export let fromArray = (array, comp) => {
349+
Array.reduce((pq, val) => push(val, pq), make(comp), array)
350+
}

stdlib/immutablepriorityqueue.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,3 +246,33 @@ Returns:
246246
|----|-----------|
247247
|`ImmutablePriorityQueue<a>`|A priority queue containing the elements from the list|
248248

249+
### ImmutablePriorityQueue.**fromArray**
250+
251+
<details disabled>
252+
<summary tabindex="-1">Added in <code>next</code></summary>
253+
No other changes yet.
254+
</details>
255+
256+
```grain
257+
fromArray : (Array<a>, ((a, a) -> Number)) -> ImmutablePriorityQueue<a>
258+
```
259+
260+
Constructs a new priority queue initialized with the elements in the array
261+
using a custom comparator function, which is used to determine priority of
262+
elements. The comparator function takes two elements and must return 0 if
263+
both share priority, a positive number if the first has greater priority,
264+
and a negative number if the first has less priority.
265+
266+
Parameters:
267+
268+
|param|type|description|
269+
|-----|----|-----------|
270+
|`array`|`Array<a>`|An array of values used to initialize the priority queue|
271+
|`comp`|`(a, a) -> Number`|A comparator function used to assign priority to elements|
272+
273+
Returns:
274+
275+
|type|description|
276+
|----|-----------|
277+
|`ImmutablePriorityQueue<a>`|A priority queue containing the elements from the array|
278+

stdlib/priorityqueue.gr

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,29 @@ export let drain = pq => {
219219
List.reverse(drainRec([]))
220220
}
221221

222+
/**
223+
* Constructs a new priority queue initialized with the elements in the array
224+
* using a custom comparator function, which is used to determine priority of
225+
* elements. The comparator function takes two elements and must return 0 if
226+
* both share priority, a positive number if the first has greater priority,
227+
* and a negative number if the first has less priority.
228+
*
229+
* @param array: An array of values used to initialize the priority queue
230+
* @param comp: A comparator function used to assign priority to elements
231+
* @returns A priority queue containing the elements from the array
232+
*
233+
* @since v0.5.4
234+
*/
235+
export let fromArray = (array, comp) => {
236+
let size = Array.length(array)
237+
let array = Array.map(x => Some(x), array)
238+
let heap = { size, array, comp }
239+
for (let mut i = size - 1; i >= 0; i -= 1) {
240+
siftDown(i, heap)
241+
}
242+
heap
243+
}
244+
222245
/**
223246
* Constructs a new priority queue initialized with the elements in the list
224247
* using a custom comparator function, which is used to determine priority of
@@ -233,9 +256,6 @@ export let drain = pq => {
233256
* @since v0.5.3
234257
*/
235258
export let fromList = (list, comp) => {
236-
let heap = makeSized(List.length(list), comp)
237-
List.forEach(val => {
238-
push(val, heap)
239-
}, list)
240-
heap
259+
let array = Array.fromList(list)
260+
fromArray(array, comp)
241261
}

stdlib/priorityqueue.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,36 @@ Returns:
247247
|----|-----------|
248248
|`List<a>`|A list of all elements in the priority in priority order|
249249

250+
### PriorityQueue.**fromArray**
251+
252+
<details disabled>
253+
<summary tabindex="-1">Added in <code>next</code></summary>
254+
No other changes yet.
255+
</details>
256+
257+
```grain
258+
fromArray : (Array<a>, ((a, a) -> Number)) -> PriorityQueue<a>
259+
```
260+
261+
Constructs a new priority queue initialized with the elements in the array
262+
using a custom comparator function, which is used to determine priority of
263+
elements. The comparator function takes two elements and must return 0 if
264+
both share priority, a positive number if the first has greater priority,
265+
and a negative number if the first has less priority.
266+
267+
Parameters:
268+
269+
|param|type|description|
270+
|-----|----|-----------|
271+
|`array`|`Array<a>`|An array of values used to initialize the priority queue|
272+
|`comp`|`(a, a) -> Number`|A comparator function used to assign priority to elements|
273+
274+
Returns:
275+
276+
|type|description|
277+
|----|-----------|
278+
|`PriorityQueue<a>`|A priority queue containing the elements from the array|
279+
250280
### PriorityQueue.**fromList**
251281

252282
<details disabled>

0 commit comments

Comments
 (0)