Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 1m4s
30 new source-string idioms via apl-run: triangulars, factorial, running sum/product, parity counts, identity matrix, mult-table, dot product, ∧.= equality, take/drop/reverse, tally, ravel, count-of-value, etc. Side-fix: tokenizer's apl-glyph-set was missing ≢ and ≡ — they were silently skipped. Added them and to apl-parse-fn-glyphs.
360 lines
8.0 KiB
Plaintext
360 lines
8.0 KiB
Plaintext
; APL idiom corpus — classic Roger Hui / Phil Last idioms expressed
|
||
; through our runtime primitives. Each test names the APL one-liner
|
||
; and verifies the equivalent runtime call.
|
||
|
||
(define mkrv (fn (arr) (get arr :ravel)))
|
||
(define mksh (fn (arr) (get arr :shape)))
|
||
|
||
; ---------- reductions ----------
|
||
|
||
(apl-test
|
||
"+/⍵ — sum"
|
||
(mkrv (apl-reduce apl-add (make-array (list 5) (list 1 2 3 4 5))))
|
||
(list 15))
|
||
|
||
(apl-test
|
||
"(+/⍵)÷⍴⍵ — mean"
|
||
(mkrv
|
||
(apl-div
|
||
(apl-reduce apl-add (make-array (list 5) (list 1 2 3 4 5)))
|
||
(apl-scalar 5)))
|
||
(list 3))
|
||
|
||
(apl-test
|
||
"⌈/⍵ — max"
|
||
(mkrv (apl-reduce apl-max (make-array (list 6) (list 3 1 4 1 5 9))))
|
||
(list 9))
|
||
|
||
(apl-test
|
||
"⌊/⍵ — min"
|
||
(mkrv (apl-reduce apl-min (make-array (list 6) (list 3 1 4 1 5 9))))
|
||
(list 1))
|
||
|
||
(apl-test
|
||
"(⌈/⍵)-⌊/⍵ — range"
|
||
(mkrv
|
||
(apl-sub
|
||
(apl-reduce apl-max (make-array (list 6) (list 3 1 4 1 5 9)))
|
||
(apl-reduce apl-min (make-array (list 6) (list 3 1 4 1 5 9)))))
|
||
(list 8))
|
||
|
||
(apl-test
|
||
"×/⍵ — product"
|
||
(mkrv (apl-reduce apl-mul (make-array (list 4) (list 1 2 3 4))))
|
||
(list 24))
|
||
|
||
(apl-test
|
||
"+\\⍵ — running sum"
|
||
(mkrv (apl-scan apl-add (make-array (list 5) (list 1 2 3 4 5))))
|
||
(list 1 3 6 10 15))
|
||
|
||
; ---------- sort / order ----------
|
||
|
||
(apl-test
|
||
"⍵[⍋⍵] — sort ascending"
|
||
(mkrv (apl-quicksort (make-array (list 5) (list 3 1 4 1 5))))
|
||
(list 1 1 3 4 5))
|
||
|
||
(apl-test
|
||
"⌽⍵ — reverse"
|
||
(mkrv (apl-reverse (make-array (list 5) (list 1 2 3 4 5))))
|
||
(list 5 4 3 2 1))
|
||
|
||
(apl-test
|
||
"⊃⌽⍵ — last element"
|
||
(mkrv
|
||
(apl-disclose (apl-reverse (make-array (list 4) (list 10 20 30 40)))))
|
||
(list 40))
|
||
|
||
(apl-test
|
||
"1↑⍵ — first element"
|
||
(mkrv
|
||
(apl-take (apl-scalar 1) (make-array (list 4) (list 10 20 30 40))))
|
||
(list 10))
|
||
|
||
(apl-test
|
||
"1↓⍵ — drop first"
|
||
(mkrv
|
||
(apl-drop (apl-scalar 1) (make-array (list 4) (list 10 20 30 40))))
|
||
(list 20 30 40))
|
||
|
||
(apl-test
|
||
"¯1↓⍵ — drop last"
|
||
(mkrv
|
||
(apl-drop (apl-scalar -1) (make-array (list 4) (list 10 20 30 40))))
|
||
(list 10 20 30))
|
||
|
||
; ---------- counts / membership ----------
|
||
|
||
(apl-test
|
||
"≢⍵ — tally"
|
||
(mkrv (apl-tally (make-array (list 7) (list 9 8 7 6 5 4 3))))
|
||
(list 7))
|
||
|
||
(apl-test
|
||
"+/⍵=v — count occurrences of v"
|
||
(mkrv
|
||
(apl-reduce
|
||
apl-add
|
||
(apl-eq (make-array (list 7) (list 1 2 3 2 1 3 2)) (apl-scalar 2))))
|
||
(list 3))
|
||
|
||
(apl-test
|
||
"0=N|M — divisibility test"
|
||
(mkrv (apl-eq (apl-scalar 0) (apl-mod (apl-scalar 3) (apl-scalar 12))))
|
||
(list 1))
|
||
|
||
; ---------- shape constructors ----------
|
||
|
||
(apl-test
|
||
"N⍴1 — vector of N ones"
|
||
(mkrv (apl-reshape (apl-scalar 5) (apl-scalar 1)))
|
||
(list 1 1 1 1 1))
|
||
|
||
(apl-test
|
||
"(N N)⍴0 — N×N zero matrix"
|
||
(mkrv (apl-reshape (make-array (list 2) (list 3 3)) (apl-scalar 0)))
|
||
(list 0 0 0 0 0 0 0 0 0))
|
||
|
||
(apl-test
|
||
"⍳∘.=⍳ — N×N identity matrix"
|
||
(mkrv
|
||
(apl-outer apl-eq (apl-iota (apl-scalar 3)) (apl-iota (apl-scalar 3))))
|
||
(list 1 0 0 0 1 0 0 0 1))
|
||
|
||
(apl-test
|
||
"⍳∘.×⍳ — multiplication table"
|
||
(mkrv
|
||
(apl-outer apl-mul (apl-iota (apl-scalar 3)) (apl-iota (apl-scalar 3))))
|
||
(list 1 2 3 2 4 6 3 6 9))
|
||
|
||
; ---------- numerical idioms ----------
|
||
|
||
(apl-test
|
||
"+\\⍳N — triangular numbers"
|
||
(mkrv (apl-scan apl-add (apl-iota (apl-scalar 5))))
|
||
(list 1 3 6 10 15))
|
||
|
||
(apl-test
|
||
"+/⍳N=N×(N+1)÷2 — sum of 1..N"
|
||
(mkrv (apl-reduce apl-add (apl-iota (apl-scalar 10))))
|
||
(list 55))
|
||
|
||
(apl-test
|
||
"×/⍳N — factorial via iota"
|
||
(mkrv (apl-reduce apl-mul (apl-iota (apl-scalar 5))))
|
||
(list 120))
|
||
|
||
(apl-test
|
||
"2|⍵ — parity (1=odd)"
|
||
(mkrv (apl-mod (apl-scalar 2) (make-array (list 5) (list 1 2 3 4 5))))
|
||
(list 1 0 1 0 1))
|
||
|
||
(apl-test
|
||
"+/2|⍵ — count odd"
|
||
(mkrv
|
||
(apl-reduce
|
||
apl-add
|
||
(apl-mod (apl-scalar 2) (make-array (list 5) (list 1 2 3 4 5)))))
|
||
(list 3))
|
||
|
||
; ---------- boolean idioms ----------
|
||
|
||
(apl-test
|
||
"∧/⍵ — all-true"
|
||
(mkrv (apl-reduce apl-and (make-array (list 4) (list 1 1 1 1))))
|
||
(list 1))
|
||
|
||
(apl-test
|
||
"∧/⍵ — all-true with zero is false"
|
||
(mkrv (apl-reduce apl-and (make-array (list 4) (list 1 1 0 1))))
|
||
(list 0))
|
||
|
||
(apl-test
|
||
"∨/⍵ — any-true"
|
||
(mkrv (apl-reduce apl-or (make-array (list 4) (list 0 0 1 0))))
|
||
(list 1))
|
||
|
||
(apl-test
|
||
"∨/⍵ — any-true all zero is false"
|
||
(mkrv (apl-reduce apl-or (make-array (list 4) (list 0 0 0 0))))
|
||
(list 0))
|
||
|
||
; ---------- selection / scaling ----------
|
||
|
||
(apl-test
|
||
"⍵×⍵ — square each"
|
||
(mkrv
|
||
(apl-mul
|
||
(make-array (list 4) (list 1 2 3 4))
|
||
(make-array (list 4) (list 1 2 3 4))))
|
||
(list 1 4 9 16))
|
||
|
||
(apl-test
|
||
"+/⍵×⍵ — sum of squares"
|
||
(mkrv
|
||
(apl-reduce
|
||
apl-add
|
||
(apl-mul
|
||
(make-array (list 4) (list 1 2 3 4))
|
||
(make-array (list 4) (list 1 2 3 4)))))
|
||
(list 30))
|
||
|
||
(apl-test
|
||
"⍵-(+/⍵)÷⍴⍵ — mean-centered"
|
||
(mkrv
|
||
(apl-sub
|
||
(make-array (list 5) (list 2 4 6 8 10))
|
||
(apl-div
|
||
(apl-reduce apl-add (make-array (list 5) (list 2 4 6 8 10)))
|
||
(apl-scalar 5))))
|
||
(list -4 -2 0 2 4))
|
||
|
||
; ---------- shape / structure ----------
|
||
|
||
(apl-test
|
||
",⍵ — ravel"
|
||
(mkrv (apl-ravel (make-array (list 2 3) (list 1 2 3 4 5 6))))
|
||
(list 1 2 3 4 5 6))
|
||
|
||
(apl-test
|
||
"⍴⍴⍵ — rank"
|
||
(mkrv
|
||
(apl-shape (apl-shape (make-array (list 2 3) (list 1 2 3 4 5 6)))))
|
||
(list 2))
|
||
|
||
(apl-test
|
||
"src: +/⍳N → triangular(N)"
|
||
(mkrv (apl-run "+/⍳100"))
|
||
(list 5050))
|
||
|
||
(apl-test "src: ×/⍳N → N!" (mkrv (apl-run "×/⍳6")) (list 720))
|
||
|
||
(apl-test
|
||
"src: ⌈/V — max"
|
||
(mkrv (apl-run "⌈/3 1 4 1 5 9 2 6"))
|
||
(list 9))
|
||
|
||
(apl-test
|
||
"src: ⌊/V — min"
|
||
(mkrv (apl-run "⌊/3 1 4 1 5 9 2 6"))
|
||
(list 1))
|
||
|
||
(apl-test
|
||
"src: range = (⌈/V) - ⌊/V"
|
||
(mkrv (apl-run "(⌈/3 1 4 1 5 9 2 6) - ⌊/3 1 4 1 5 9 2 6"))
|
||
(list 8))
|
||
|
||
(apl-test
|
||
"src: +\\V — running sum"
|
||
(mkrv (apl-run "+\\1 2 3 4 5"))
|
||
(list 1 3 6 10 15))
|
||
|
||
(apl-test
|
||
"src: ×\\V — running product"
|
||
(mkrv (apl-run "×\\1 2 3 4 5"))
|
||
(list 1 2 6 24 120))
|
||
|
||
(apl-test
|
||
"src: V × V — squares"
|
||
(mkrv (apl-run "(⍳5) × ⍳5"))
|
||
(list 1 4 9 16 25))
|
||
|
||
(apl-test
|
||
"src: +/V × V — sum of squares"
|
||
(mkrv (apl-run "+/(⍳5) × ⍳5"))
|
||
(list 55))
|
||
|
||
(apl-test "src: ∧/V — all-true" (mkrv (apl-run "∧/1 1 1 1")) (list 1))
|
||
|
||
(apl-test "src: ∨/V — any-true" (mkrv (apl-run "∨/0 0 1 0")) (list 1))
|
||
|
||
(apl-test "src: 0 = N|M — divides" (mkrv (apl-run "0 = 3 | 12")) (list 1))
|
||
|
||
(apl-test
|
||
"src: 2 | V — parity"
|
||
(mkrv (apl-run "2 | 1 2 3 4 5 6"))
|
||
(list 1 0 1 0 1 0))
|
||
|
||
(apl-test
|
||
"src: +/2|V — count odd"
|
||
(mkrv (apl-run "+/2 | 1 2 3 4 5 6"))
|
||
(list 3))
|
||
|
||
(apl-test "src: ⍴ V" (mkrv (apl-run "⍴ 1 2 3 4 5")) (list 5))
|
||
|
||
(apl-test
|
||
"src: ⍴⍴ M — rank"
|
||
(mkrv (apl-run "⍴ ⍴ (2 3) ⍴ ⍳6"))
|
||
(list 2))
|
||
|
||
(apl-test
|
||
"src: N⍴1 — vector of ones"
|
||
(mkrv (apl-run "5 ⍴ 1"))
|
||
(list 1 1 1 1 1))
|
||
|
||
(apl-test
|
||
"src: ⍳N ∘.= ⍳N — identity matrix"
|
||
(mkrv (apl-run "(⍳3) ∘.= ⍳3"))
|
||
(list 1 0 0 0 1 0 0 0 1))
|
||
|
||
(apl-test
|
||
"src: ⍳N ∘.× ⍳N — multiplication table"
|
||
(mkrv (apl-run "(⍳3) ∘.× ⍳3"))
|
||
(list 1 2 3 2 4 6 3 6 9))
|
||
|
||
(apl-test
|
||
"src: V +.× V — dot product"
|
||
(mkrv (apl-run "1 2 3 +.× 4 5 6"))
|
||
(list 32))
|
||
|
||
(apl-test
|
||
"src: ∧.= V — vectors equal?"
|
||
(mkrv (apl-run "1 2 3 ∧.= 1 2 3"))
|
||
(list 1))
|
||
|
||
(apl-test
|
||
"src: V[1] — first element"
|
||
(mkrv (apl-run "(10 20 30 40)[1]"))
|
||
(list 10))
|
||
|
||
(apl-test
|
||
"src: 1↑V — first via take"
|
||
(mkrv (apl-run "1 ↑ 10 20 30 40"))
|
||
(list 10))
|
||
|
||
(apl-test
|
||
"src: 1↓V — drop first"
|
||
(mkrv (apl-run "1 ↓ 10 20 30 40"))
|
||
(list 20 30 40))
|
||
|
||
(apl-test
|
||
"src: ¯1↓V — drop last"
|
||
(mkrv (apl-run "¯1 ↓ 10 20 30 40"))
|
||
(list 10 20 30))
|
||
|
||
(apl-test
|
||
"src: ⌽V — reverse"
|
||
(mkrv (apl-run "⌽ 1 2 3 4 5"))
|
||
(list 5 4 3 2 1))
|
||
|
||
(apl-test
|
||
"src: ≢V — tally"
|
||
(mkrv (apl-run "≢ 9 8 7 6 5 4 3 2 1"))
|
||
(list 9))
|
||
|
||
(apl-test
|
||
"src: ,M — ravel"
|
||
(mkrv (apl-run ", (2 3) ⍴ ⍳6"))
|
||
(list 1 2 3 4 5 6))
|
||
|
||
(apl-test
|
||
"src: A=V — count occurrences"
|
||
(mkrv (apl-run "+/2 = 1 2 3 2 1 3 2"))
|
||
(list 3))
|
||
|
||
(apl-test
|
||
"src: ⌈/(V × V) — max squared"
|
||
(mkrv (apl-run "⌈/(1 2 3 4 5) × 1 2 3 4 5"))
|
||
(list 25))
|