diff --git a/lib/apl/runtime.sx b/lib/apl/runtime.sx index 165234db..4bfd91e9 100644 --- a/lib/apl/runtime.sx +++ b/lib/apl/runtime.sx @@ -688,3 +688,47 @@ (map (fn (j) (nth ravel (+ start j))) (range 0 slice-size))))))))))) + +(define + apl-grade + (fn + (arr ascending) + (let + ((ravel (get arr :ravel)) (n (len (get arr :ravel)))) + (let + ((pairs (map (fn (i) (list (nth ravel i) (+ i apl-io))) (range 0 n)))) + (define ins nil) + (set! + ins + (fn + (x sorted) + (if + (= (len sorted) 0) + (list x) + (let + ((xv (first x)) + (xi (nth x 1)) + (hd (first sorted)) + (sv (first hd)) + (si (nth hd 1))) + (if + (if + ascending + (or (< xv sv) (and (= xv sv) (< xi si))) + (or (> xv sv) (and (= xv sv) (< xi si)))) + (cons x sorted) + (cons hd (ins x (rest sorted)))))))) + (define isort nil) + (set! + isort + (fn + (lst) + (if + (= (len lst) 0) + (list) + (ins (first lst) (isort (rest lst)))))) + (make-array (list n) (map (fn (p) (nth p 1)) (isort pairs))))))) + +(define apl-grade-up (fn (arr) (apl-grade arr true))) + +(define apl-grade-down (fn (arr) (apl-grade arr false))) diff --git a/lib/apl/tests/structural.sx b/lib/apl/tests/structural.sx index 204905dc..9ad71b99 100644 --- a/lib/apl/tests/structural.sx +++ b/lib/apl/tests/structural.sx @@ -434,4 +434,44 @@ (apl-test "squad partial 3d slice shape" (sh (apl-squad (apl-scalar 1) (make-array (list 2 3 4) (range 1 25)))) - (list 3 4)) \ No newline at end of file + (list 3 4)) + +(apl-test + "grade-up basic" + (rv (apl-grade-up (make-array (list 5) (list 3 1 4 1 5)))) + (list 2 4 1 3 5)) + +(apl-test + "grade-up shape" + (sh (apl-grade-up (make-array (list 4) (list 4 1 3 2)))) + (list 4)) + +(apl-test + "grade-up no duplicates" + (rv (apl-grade-up (make-array (list 4) (list 4 1 3 2)))) + (list 2 4 3 1)) + +(apl-test + "grade-up already sorted" + (rv (apl-grade-up (make-array (list 3) (list 1 2 3)))) + (list 1 2 3)) + +(apl-test + "grade-up reverse sorted" + (rv (apl-grade-up (make-array (list 3) (list 3 2 1)))) + (list 3 2 1)) + +(apl-test + "grade-down basic" + (rv (apl-grade-down (make-array (list 5) (list 3 1 4 1 5)))) + (list 5 3 1 2 4)) + +(apl-test + "grade-down no duplicates" + (rv (apl-grade-down (make-array (list 4) (list 4 1 3 2)))) + (list 1 3 4 2)) + +(apl-test + "grade-up single element" + (rv (apl-grade-up (make-array (list 1) (list 42)))) + (list 1)) \ No newline at end of file