apl: primes sieve (2=+⌿0=A∘.|A)/A←⍳N + apl-compress (+11 tests, 280/280)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 1m6s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 1m6s
This commit is contained in:
@@ -13,7 +13,7 @@ if [ ! -x "$SX_SERVER" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SUITES=(structural operators dfn tradfn valence)
|
||||
SUITES=(structural operators dfn tradfn valence programs)
|
||||
|
||||
OUT_JSON="lib/apl/scoreboard.json"
|
||||
OUT_MD="lib/apl/scoreboard.md"
|
||||
|
||||
@@ -796,6 +796,34 @@
|
||||
((result (filter (fn (x) (not (index-of b-ravel x))) a-ravel)))
|
||||
(make-array (list (len result)) result)))))
|
||||
|
||||
(define
|
||||
apl-compress
|
||||
(fn
|
||||
(mask arr)
|
||||
(let
|
||||
((mask-ravel (get mask :ravel)) (arr-ravel (get arr :ravel)))
|
||||
(let
|
||||
((kept (filter (fn (i) (not (= 0 (nth mask-ravel i)))) (range 0 (len arr-ravel)))))
|
||||
(let
|
||||
((picked (map (fn (i) (nth arr-ravel i)) kept)))
|
||||
(make-array (list (len picked)) picked))))))
|
||||
|
||||
(define
|
||||
apl-primes
|
||||
(fn
|
||||
(n)
|
||||
(let
|
||||
((a (apl-iota (apl-scalar n))))
|
||||
(let
|
||||
((mod-table (apl-outer apl-mod a a)))
|
||||
(let
|
||||
((zero-mask (apl-eq (apl-scalar 0) mod-table)))
|
||||
(let
|
||||
((divisor-counts (apl-reduce-first apl-add zero-mask)))
|
||||
(let
|
||||
((prime-mask (apl-eq (apl-scalar 2) divisor-counts)))
|
||||
(apl-compress prime-mask a))))))))
|
||||
|
||||
(define
|
||||
apl-reduce
|
||||
(fn
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
"operators": {"pass": 117, "fail": 0},
|
||||
"dfn": {"pass": 24, "fail": 0},
|
||||
"tradfn": {"pass": 20, "fail": 0},
|
||||
"valence": {"pass": 14, "fail": 0}
|
||||
"valence": {"pass": 14, "fail": 0},
|
||||
"programs": {"pass": 11, "fail": 0}
|
||||
},
|
||||
"total_pass": 269,
|
||||
"total_pass": 280,
|
||||
"total_fail": 0,
|
||||
"total": 269
|
||||
"total": 280
|
||||
}
|
||||
|
||||
@@ -9,7 +9,8 @@ _Generated by `lib/apl/conformance.sh`_
|
||||
| dfn | 24 | 0 | 24 |
|
||||
| tradfn | 20 | 0 | 20 |
|
||||
| valence | 14 | 0 | 14 |
|
||||
| **Total** | **269** | **0** | **269** |
|
||||
| programs | 11 | 0 | 11 |
|
||||
| **Total** | **280** | **0** | **280** |
|
||||
|
||||
## Notes
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ cat > "$TMPFILE" << 'EPOCHS'
|
||||
(load "lib/apl/tests/dfn.sx")
|
||||
(load "lib/apl/tests/tradfn.sx")
|
||||
(load "lib/apl/tests/valence.sx")
|
||||
(load "lib/apl/tests/programs.sx")
|
||||
(epoch 4)
|
||||
(eval "(list apl-test-pass apl-test-fail)")
|
||||
EPOCHS
|
||||
|
||||
58
lib/apl/tests/programs.sx
Normal file
58
lib/apl/tests/programs.sx
Normal file
@@ -0,0 +1,58 @@
|
||||
; Tests for classic APL programs (lib/apl/tests/programs/*.apl).
|
||||
; Programs are showcase APL source; runtime impl is in lib/apl/runtime.sx.
|
||||
|
||||
(define mkrv (fn (arr) (get arr :ravel)))
|
||||
(define mksh (fn (arr) (get arr :shape)))
|
||||
|
||||
; ===== primes (Sieve of Eratosthenes) =====
|
||||
|
||||
(apl-test "primes 1 → empty" (mkrv (apl-primes 1)) (list))
|
||||
|
||||
(apl-test "primes 2 → just 2" (mkrv (apl-primes 2)) (list 2))
|
||||
|
||||
(apl-test "primes 10 → 2 3 5 7" (mkrv (apl-primes 10)) (list 2 3 5 7))
|
||||
|
||||
(apl-test
|
||||
"primes 20 → 2 3 5 7 11 13 17 19"
|
||||
(mkrv (apl-primes 20))
|
||||
(list 2 3 5 7 11 13 17 19))
|
||||
|
||||
(apl-test
|
||||
"primes 30"
|
||||
(mkrv (apl-primes 30))
|
||||
(list 2 3 5 7 11 13 17 19 23 29))
|
||||
|
||||
(apl-test
|
||||
"primes 50"
|
||||
(mkrv (apl-primes 50))
|
||||
(list 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47))
|
||||
|
||||
(apl-test "primes 7 length" (first (mksh (apl-primes 7))) 4)
|
||||
|
||||
(apl-test "primes 100 has 25 primes" (first (mksh (apl-primes 100))) 25)
|
||||
|
||||
; ===== compress helper sanity =====
|
||||
|
||||
(apl-test
|
||||
"compress 1 0 1 0 1 / 10 20 30 40 50"
|
||||
(mkrv
|
||||
(apl-compress
|
||||
(make-array (list 5) (list 1 0 1 0 1))
|
||||
(make-array (list 5) (list 10 20 30 40 50))))
|
||||
(list 10 30 50))
|
||||
|
||||
(apl-test
|
||||
"compress all-zero mask → empty"
|
||||
(mkrv
|
||||
(apl-compress
|
||||
(make-array (list 3) (list 0 0 0))
|
||||
(make-array (list 3) (list 1 2 3))))
|
||||
(list))
|
||||
|
||||
(apl-test
|
||||
"compress all-one mask → full vector"
|
||||
(mkrv
|
||||
(apl-compress
|
||||
(make-array (list 3) (list 1 1 1))
|
||||
(make-array (list 3) (list 1 2 3))))
|
||||
(list 1 2 3))
|
||||
16
lib/apl/tests/programs/primes.apl
Normal file
16
lib/apl/tests/programs/primes.apl
Normal file
@@ -0,0 +1,16 @@
|
||||
⍝ Sieve of Eratosthenes — the classic APL one-liner
|
||||
⍝ primes ← (2=+⌿0=A∘.|A)/A←⍳N
|
||||
⍝
|
||||
⍝ Read right-to-left:
|
||||
⍝ A ← ⍳N : A is 1..N
|
||||
⍝ A∘.|A : outer-product residue table — M[i,j] = A[j] mod A[i]
|
||||
⍝ 0=... : boolean — true where A[i] divides A[j]
|
||||
⍝ +⌿... : column sums — count of divisors per A[j]
|
||||
⍝ 2=... : true for numbers with exactly 2 divisors (1 and self) → primes
|
||||
⍝ .../A : compress — select A[j] where mask[j] is true
|
||||
⍝
|
||||
⍝ Examples:
|
||||
⍝ primes 10 → 2 3 5 7
|
||||
⍝ primes 30 → 2 3 5 7 11 13 17 19 23 29
|
||||
|
||||
primes ← {(2=+⌿0=⍵∘.|⍵)/⍵←⍳⍵}
|
||||
Reference in New Issue
Block a user