Skip to content

Commit 78d562d

Browse files
committed
feat(list): ARK-315, adding list:select and list:permutations
1 parent 58e282c commit 78d562d

File tree

2 files changed

+146
-65
lines changed

2 files changed

+146
-65
lines changed

List.ark

Lines changed: 122 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -220,50 +220,6 @@
220220
(/ (+ (@ _s (- (/ _n 2) 1)) (@ _s (/ _n 2))) 2)
221221
(@ _s (/ _n 2))) }) }))
222222

223-
# @brief Drop the first n elements of a list
224-
# @param _L the list to work on
225-
# @param _n the number of elements to drop
226-
# @details The original list is not modified.
227-
# =begin
228-
# (let cool-stuff [1 2 3 4 5 6 7 8 9])
229-
# (print (list:drop cool-stuff 4)) # [5 6 7 8 9]
230-
# =end
231-
# @author https://github.com/rstefanic, https://github.com/SuperFola
232-
(let drop (fun ((ref _L) _n)
233-
(if (< _n (/ (len _L) 2))
234-
(if (> _n 0)
235-
(drop (tail _L) (- _n 1))
236-
_L)
237-
{
238-
(mut _index (math:max 0 _n))
239-
(mut _output [])
240-
241-
(while (< _index (len _L)) {
242-
(append! _output (@ _L _index))
243-
(set _index (+ 1 _index)) })
244-
_output })))
245-
246-
# @brief Drop the first elements of a list, while they match a given predicate
247-
# @param _L the list to work on
248-
# @param _f the predicate
249-
# @details The original list is not modified.
250-
# =begin
251-
# (let cool-stuff [1 2 3 4 5 6 7 8 9])
252-
# (print (list:dropWhile cool-stuff (fun (a) (< a 4)))) # [4 5 6 7 8 9]
253-
# =end
254-
# @author https://github.com/SuperFola
255-
(let dropWhile (fun ((ref _L) _f) {
256-
(mut _index 0)
257-
(mut _output [])
258-
259-
(while (< _index (len _L))
260-
(if (_f (@ _L _index))
261-
(set _index (+ 1 _index))
262-
(while (< _index (len _L)) {
263-
(append! _output (@ _L _index))
264-
(set _index (+ 1 _index)) })))
265-
_output }))
266-
267223
# @brief Keep elements in a given list if they follow a predicate
268224
# @param _L the list to work on
269225
# @param _f the predicate
@@ -323,6 +279,25 @@
323279
(set _index (+ 1 _index)) })
324280
_output }))
325281

282+
# @brief Fold a given list, starting from the left side
283+
# @param _L the list to work on
284+
# @param _init an init value
285+
# @param _f a function to apply to the list
286+
# @details The original list is not modified.
287+
# =begin
288+
# (let a [1 2 3 4])
289+
# (print (list:foldLeft a 0 (fun (a b) (+ a b)))) # 10
290+
# =end
291+
# @author https://github.com/SuperFola
292+
(let foldLeft (fun ((ref _L) _init _f) {
293+
(mut _index 0)
294+
(mut _val _init)
295+
296+
(while (< _index (len _L)) {
297+
(set _val (_f _val (@ _L _index)))
298+
(set _index (+ 1 _index)) })
299+
_val }))
300+
326301
# @brief Apply a function to the elements of a list to reduce it
327302
# @param _L the list to work on
328303
# @param _f the function to apply
@@ -423,6 +398,50 @@
423398
(set _continue false)))
424399
_output }))
425400

401+
# @brief Drop the first n elements of a list
402+
# @param _L the list to work on
403+
# @param _n the number of elements to drop
404+
# @details The original list is not modified.
405+
# =begin
406+
# (let cool-stuff [1 2 3 4 5 6 7 8 9])
407+
# (print (list:drop cool-stuff 4)) # [5 6 7 8 9]
408+
# =end
409+
# @author https://github.com/rstefanic, https://github.com/SuperFola
410+
(let drop (fun ((ref _L) _n)
411+
(if (< _n (/ (len _L) 2))
412+
(if (> _n 0)
413+
(drop (tail _L) (- _n 1))
414+
_L)
415+
{
416+
(mut _index (math:max 0 _n))
417+
(mut _output [])
418+
419+
(while (< _index (len _L)) {
420+
(append! _output (@ _L _index))
421+
(set _index (+ 1 _index)) })
422+
_output })))
423+
424+
# @brief Drop the first elements of a list, while they match a given predicate
425+
# @param _L the list to work on
426+
# @param _f the predicate
427+
# @details The original list is not modified.
428+
# =begin
429+
# (let cool-stuff [1 2 3 4 5 6 7 8 9])
430+
# (print (list:dropWhile cool-stuff (fun (a) (< a 4)))) # [4 5 6 7 8 9]
431+
# =end
432+
# @author https://github.com/SuperFola
433+
(let dropWhile (fun ((ref _L) _f) {
434+
(mut _index 0)
435+
(mut _output [])
436+
437+
(while (< _index (len _L))
438+
(if (_f (@ _L _index))
439+
(set _index (+ 1 _index))
440+
(while (< _index (len _L)) {
441+
(append! _output (@ _L _index))
442+
(set _index (+ 1 _index)) })))
443+
_output }))
444+
426445
# @brief Partition a list in two, given a predicate
427446
# @param _L the list to work on
428447
# @param _f the predicate, accepting the value and its index
@@ -527,25 +546,6 @@
527546
(set _index (+ 1 _index)) })
528547
_output }))
529548

530-
# @brief Fold a given list, starting from the left side
531-
# @param _L the list to work on
532-
# @param _init an init value
533-
# @param _f a function to apply to the list
534-
# @details The original list is not modified.
535-
# =begin
536-
# (let a [1 2 3 4])
537-
# (print (list:foldLeft a 0 (fun (a b) (+ a b)))) # 10
538-
# =end
539-
# @author https://github.com/SuperFola
540-
(let foldLeft (fun ((ref _L) _init _f) {
541-
(mut _index 0)
542-
(mut _val _init)
543-
544-
(while (< _index (len _L)) {
545-
(set _val (_f _val (@ _L _index)))
546-
(set _index (+ 1 _index)) })
547-
_val }))
548-
549549
# @brief Check if a condition is verified for all elements of a list
550550
# @param _L the list to work on
551551
# @param _f the condition
@@ -784,3 +784,62 @@
784784
(set _i (+ 1 _i)) })
785785

786786
(builtin__dict:keys _vals) }))
787+
788+
# @brief Create a new list from a list of values and indices to get from the first list
789+
# @details The original list is not modified.
790+
# @param _L list to get values from
791+
# @param _indices list of indices of values in _L
792+
# =begin
793+
# (let data [1 1 2 3 4 3 4 5])
794+
# (print (list:select data [0 0 0])) # [1 1 1]
795+
# (print (list:select data [0 2 3 4])) # [1 2 3 4]
796+
# =end
797+
# @author https://github.com/SuperFola
798+
(let select (fun ((ref _L) (ref _indices)) {
799+
(mut _output [])
800+
(mut _i 0)
801+
(while (< _i (len _indices)) {
802+
(let _idx (@ _indices _i))
803+
(if (< _idx (len _L))
804+
(append! _output (@ _L _idx)))
805+
(set _i (+ 1 _i)) })
806+
_output }))
807+
808+
# @brief Compute permutations of length _r from a given list
809+
# @details The original list is not modified.
810+
# @param _L list to get values from
811+
# @param _r number of elements per permutation
812+
# @param _f function to call on each permutation. It can return list:stopIteration to stop iteration early
813+
# =begin
814+
# (let data [0 1 2 3])
815+
# (list:permutations data 3 (fun (perm) (print perm)))
816+
# # [0 1 2]
817+
# # [0 1 3]
818+
# # [0 2 3]
819+
# # [1 2 3]
820+
# =end
821+
# @author https://github.com/SuperFola
822+
(let permutations (fun ((ref _L) _r _f) {
823+
(let _len (len _L))
824+
(if (and (<= _r _len) (> _r 0))
825+
{
826+
(mut _indices (iota 0 _r))
827+
(if (!= stopIteration (_f (select _L _indices)))
828+
{
829+
(mut _continue true)
830+
(let _reversed_indices (reverse _indices))
831+
(while _continue {
832+
(mut _i nil)
833+
(if
834+
(forEach _reversed_indices (fun (_val) {
835+
(set _i _val)
836+
(if (!= (@ _indices _i) (+ _i _len (* -1 _r))) stopIteration) }))
837+
{
838+
(@= _indices _i (+ 1 (@ _indices _i)))
839+
(mut _j (+ 1 _i))
840+
(while (< _j _r) {
841+
(@= _indices _j (+ 1 (@ _indices (- _j 1))))
842+
(set _j (+ 1 _j)) })
843+
(if (= stopIteration (_f (select _L _indices)))
844+
(set _continue false)) }
845+
(set _continue false)) }) }) }) }))

tests/list-tests.ark

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,5 +216,27 @@
216216
(test:eq (list:unique []) [])
217217
(test:eq (list:unique [1 1 1 1]) [1])
218218
(test:eq (list:unique [1 -1 1 -1]) [1 -1])
219-
(test:eq (list:unique ["a" "b" "a" "b" "c" "d"]) ["a" "b" "c" "d"]) }) })
220-
219+
(test:eq (list:unique ["a" "b" "a" "b" "c" "d"]) ["a" "b" "c" "d"]) })
220+
221+
(test:case "select" {
222+
(test:eq (list:select [] [0 1 2]) [])
223+
(test:eq (list:select [1 2 3] [0 0 0]) [1 1 1])
224+
(test:eq (list:select [1 2 3] [0]) [1])
225+
(test:eq (list:select [1 2 3] [0 4]) [1]) })
226+
227+
(test:case "permutations" {
228+
(mut perms [])
229+
(list:permutations "ABCD" 2 (fun (data) (append! perms data)))
230+
(test:eq perms [["A" "B"] ["A" "C"] ["A" "D"] ["B" "C"] ["B" "D"] ["C" "D"]])
231+
232+
(set perms [])
233+
(list:permutations [0 1 2 3] 3 (fun (data) (append! perms data)))
234+
(test:eq perms [[0 1 2] [0 1 3] [0 2 3] [1 2 3]])
235+
236+
(set perms [])
237+
(list:permutations [0 1 2 3] 5 (fun (data) (append! perms data)))
238+
(test:eq perms [])
239+
240+
(set perms [])
241+
(list:permutations [] 0 (fun (data) (append! perms data)))
242+
(test:eq perms []) }) })

0 commit comments

Comments
 (0)