; 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))

(apl-test
  "life: empty 5x5 stays empty"
  (mkrv
    (apl-life-step
      (make-array
        (list 5 5)
        (list 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0))))
  (list 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0))

(apl-test
  "life: horizontal blinker → vertical blinker"
  (mkrv
    (apl-life-step
      (make-array
        (list 5 5)
        (list 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0))))
  (list 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0))

(apl-test
  "life: vertical blinker → horizontal blinker"
  (mkrv
    (apl-life-step
      (make-array
        (list 5 5)
        (list 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0))))
  (list 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0))

(apl-test
  "life: blinker has period 2"
  (mkrv
    (apl-life-step
      (apl-life-step
        (make-array
          (list 5 5)
          (list 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0)))))
  (list 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0))

(apl-test
  "life: 2x2 block stable on 5x5"
  (mkrv
    (apl-life-step
      (make-array
        (list 5 5)
        (list 0 0 0 0 0 0 1 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0))))
  (list 0 0 0 0 0 0 1 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0))

(apl-test
  "life: shape preserved"
  (mksh
    (apl-life-step
      (make-array
        (list 5 5)
        (list 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0))))
  (list 5 5))

(apl-test
  "life: glider on 6x6 advances"
  (mkrv
    (apl-life-step
      (make-array
        (list 6 6)
        (list
          0
          0
          0
          0
          0
          0
          0
          0
          1
          0
          0
          0
          0
          0
          0
          1
          0
          0
          0
          1
          1
          1
          0
          0
          0
          0
          0
          0
          0
          0
          0
          0
          0
          0
          0
          0))))
  (list
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    1
    0
    1
    0
    0
    0
    0
    1
    1
    0
    0
    0
    0
    1
    0
    0
    0
    0
    0
    0
    0
    0
    0))

(apl-test
  "mandelbrot c=0 stays bounded"
  (mkrv (apl-mandelbrot-1d (make-array (list 1) (list 0)) 100))
  (list 100))

(apl-test
  "mandelbrot c=-1 cycle bounded"
  (mkrv (apl-mandelbrot-1d (make-array (list 1) (list -1)) 100))
  (list 100))

(apl-test
  "mandelbrot c=-2 boundary stays bounded"
  (mkrv (apl-mandelbrot-1d (make-array (list 1) (list -2)) 100))
  (list 100))

(apl-test
  "mandelbrot c=0.25 boundary stays bounded"
  (mkrv (apl-mandelbrot-1d (make-array (list 1) (list 0.25)) 100))
  (list 100))

(apl-test
  "mandelbrot c=1 escapes at iter 3"
  (mkrv (apl-mandelbrot-1d (make-array (list 1) (list 1)) 100))
  (list 3))

(apl-test
  "mandelbrot c=0.5 escapes at iter 5"
  (mkrv (apl-mandelbrot-1d (make-array (list 1) (list 0.5)) 100))
  (list 5))

(apl-test
  "mandelbrot batched grid (rank-polymorphic)"
  (mkrv (apl-mandelbrot-1d (make-array (list 5) (list -2 -1 0 1 2)) 10))
  (list 10 10 10 3 2))

(apl-test
  "mandelbrot batched preserves shape"
  (mksh (apl-mandelbrot-1d (make-array (list 5) (list -2 -1 0 1 2)) 10))
  (list 5))

(apl-test
  "mandelbrot c=-1.5 stays bounded"
  (mkrv (apl-mandelbrot-1d (make-array (list 1) (list -1.5)) 100))
  (list 100))

(apl-test "queens 1 → 1 solution" (mkrv (apl-queens 1)) (list 1))

(apl-test "queens 2 → 0 solutions" (mkrv (apl-queens 2)) (list 0))

(apl-test "queens 3 → 0 solutions" (mkrv (apl-queens 3)) (list 0))

(apl-test "queens 4 → 2 solutions" (mkrv (apl-queens 4)) (list 2))

(apl-test "queens 5 → 10 solutions" (mkrv (apl-queens 5)) (list 10))

(apl-test "queens 6 → 4 solutions" (mkrv (apl-queens 6)) (list 4))

(apl-test "queens 7 → 40 solutions" (mkrv (apl-queens 7)) (list 40))

(apl-test "queens 8 → 92 solutions" (mkrv (apl-queens 8)) (list 92))

(apl-test "permutations of 3 has 6" (len (apl-permutations 3)) 6)

(apl-test "permutations of 4 has 24" (len (apl-permutations 4)) 24)

(apl-test
  "quicksort empty"
  (mkrv (apl-quicksort (make-array (list 0) (list))))
  (list))

(apl-test
  "quicksort single"
  (mkrv (apl-quicksort (make-array (list 1) (list 42))))
  (list 42))

(apl-test
  "quicksort already sorted"
  (mkrv (apl-quicksort (make-array (list 5) (list 1 2 3 4 5))))
  (list 1 2 3 4 5))

(apl-test
  "quicksort reverse sorted"
  (mkrv (apl-quicksort (make-array (list 5) (list 5 4 3 2 1))))
  (list 1 2 3 4 5))

(apl-test
  "quicksort with duplicates"
  (mkrv (apl-quicksort (make-array (list 7) (list 3 1 4 1 5 9 2))))
  (list 1 1 2 3 4 5 9))

(apl-test
  "quicksort all equal"
  (mkrv (apl-quicksort (make-array (list 5) (list 7 7 7 7 7))))
  (list 7 7 7 7 7))

(apl-test
  "quicksort negatives"
  (mkrv (apl-quicksort (make-array (list 5) (list -3 1 -1 2 0))))
  (list -3 -1 0 1 2))

(apl-test
  "quicksort 11-element pi"
  (mkrv
    (apl-quicksort (make-array (list 11) (list 3 1 4 1 5 9 2 6 5 3 5))))
  (list 1 1 2 3 3 4 5 5 5 6 9))

(apl-test
  "quicksort preserves length"
  (first
    (mksh (apl-quicksort (make-array (list 7) (list 3 1 4 1 5 9 2)))))
  7)
