; test_huge.lisp — broad workout for the interpreter. Each section ; defines a set of helpers and then exercises them, so the same ; program touches arithmetic, list-building, closures, recursion, ; tail calls, and a few short-loop computations. ; ; Run: cat test_huge.lisp | ./lisp ; Profile: valgrind --tool=massif --pages-as-heap=yes ./lisp < test_huge.lisp ;; -- core helpers -------------------------------------------------------- (define inc (lambda (n) (+ n 1))) (define dec (lambda (n) (- n 1))) (define neg (lambda (n) (- 0 n))) (define abs (lambda (n) (if (< n 0) (- 0 n) n))) (define square (lambda (n) (* n n))) (define cube (lambda (n) (* n n n))) (define even? (lambda (n) (= 0 (mod n 2)))) (define odd? (lambda (n) (not (even? n)))) ;; -- list utilities ------------------------------------------------------ (define len (lambda (l) (if (null? l) 0 (+ 1 (len (cdr l)))))) (define nth (lambda (l n) (if (= n 0) (car l) (nth (cdr l) (- n 1))))) (define last (lambda (l) (if (null? (cdr l)) (car l) (last (cdr l))))) (define reverse-onto (lambda (l acc) (if (null? l) acc (reverse-onto (cdr l) (cons (car l) acc))))) (define reverse (lambda (l) (reverse-onto l '()))) (define append2 (lambda (a b) (if (null? a) b (cons (car a) (append2 (cdr a) b))))) (define map (lambda (f l) (if (null? l) '() (cons (f (car l)) (map f (cdr l)))))) (define filter (lambda (p l) (if (null? l) '() (if (p (car l)) (cons (car l) (filter p (cdr l))) (filter p (cdr l)))))) (define reduce (lambda (f acc l) (if (null? l) acc (reduce f (f acc (car l)) (cdr l))))) (define iota (lambda (n) (if (= n 0) '() (cons n (iota (- n 1)))))) (define range (lambda (n) (reverse (iota n)))) ;; -- numeric helpers ----------------------------------------------------- (define max2 (lambda (a b) (if (> a b) a b))) (define min2 (lambda (a b) (if (< a b) a b))) (define max-list (lambda (l) (reduce max2 (car l) (cdr l)))) (define min-list (lambda (l) (reduce min2 (car l) (cdr l)))) (define sum (lambda (l) (reduce + 0 l))) (define product (lambda (l) (reduce * 1 l))) (define gcd (lambda (a b) (if (= b 0) a (gcd b (mod a b))))) (define lcm (lambda (a b) (/ (* a b) (gcd a b)))) ;; -- recursive showpieces ------------------------------------------------ (define fact (lambda (n) (if (<= n 1) 1 (* n (fact (- n 1)))))) (define fib (lambda (n) (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2)))))) (define ack (lambda (m n) (if (= m 0) (+ n 1) (if (= n 0) (ack (- m 1) 1) (ack (- m 1) (ack m (- n 1))))))) ;; -- closures (let / let-over-lambda) ----------------------------------- (define adder (lambda (k) (lambda (x) (+ x k)))) (define muller (lambda (k) (lambda (x) (* x k)))) (define counter (lambda () (begin (define c 0) (lambda () (begin (set! c (+ c 1)) c))))) (define add1 (adder 1)) (define add10 (adder 10)) (define add100 (adder 100)) (define dbl (muller 2)) (define triple (muller 3)) ;; -- exercise the helpers ----------------------------------------------- (map inc '(1 2 3 4 5)) ; => (2 3 4 5 6) (map square '(1 2 3 4 5 6 7 8 9 10)) ; => (1 4 9 ... 100) (filter even? '(1 2 3 4 5 6 7 8 9 10)) ; => (2 4 6 8 10) (filter odd? (range 12)) ; => (1 3 5 7 9 11) (sum (range 100)) ; => 5050 (sum (map square (range 10))) ; => 385 (product '(1 2 3 4 5 6 7)) ; => 5040 (max-list '(3 1 4 1 5 9 2 6 5 3 5)) ; => 9 (min-list '(3 1 4 1 5 9 2 6 5 3 5)) ; => 1 (len (range 50)) ; => 50 (nth (range 30) 17) ; => 18 (last (range 25)) ; => 25 (reverse (range 8)) ; => (8 7 6 5 4 3 2 1) (append2 '(1 2 3) '(a b c)) ; => (1 2 3 a b c) (append2 (range 4) (reverse (range 4))) ; => (1 2 3 4 4 3 2 1) ;; -- gcd / lcm batch ---------------------------------------------------- (gcd 1024 768) ; => 256 (gcd 12345 54321) ; => 3 (gcd 1000003 1000033) ; => 1 (lcm 12 18) ; => 36 (lcm 7 11) ; => 77 ;; -- factorials ---------------------------------------------------------- (fact 1) ; => 1 (fact 5) ; => 120 (fact 10) ; => 3628800 (fact 15) ; => 1307674368000 (fact 20) ; => 2432902008176640000 ;; -- fibonacci (exponential — sized for ~few sec under massif) --------- (fib 5) ; => 5 (fib 10) ; => 55 (fib 15) ; => 610 (fib 18) ; => 2584 ;; -- ackermann ----------------------------------------------------------- (ack 2 2) ; => 7 (ack 2 4) ; => 11 (ack 3 3) ; => 61 ;; -- closure exercise --------------------------------------------------- (add1 41) ; => 42 (add10 92) ; => 102 (add100 1) ; => 101 (dbl 21) ; => 42 (triple 14) ; => 42 (map add10 '(1 2 3 4 5)) ; => (11 12 13 14 15) (map dbl (range 6)) ; => (2 4 6 8 10 12) ;; -- mixed pipeline (filter → map → reduce) ----------------------------- (define pipeline (lambda (l) (reduce + 0 (map square (filter even? l))))) (pipeline (range 10)) ; even squares 1..10 = 4+16+36+64+100 = 220 (pipeline (range 20)) ; even squares 1..20 (pipeline (range 30)) ;; -- tail-recursive spin ------------------------------------------------- (define spin (lambda (n acc) (if (= n 0) acc (spin (- n 1) (+ acc 1))))) (spin 200 0) ; => 200 (spin 500 0) ; => 500 (spin 1000 0) ; => 1000 ;; -- mutual-flavored recursion ------------------------------------------ (define ev? (lambda (n) (if (= n 0) #t (od? (- n 1))))) (define od? (lambda (n) (if (= n 0) #f (ev? (- n 1))))) (ev? 12) ; => #t (od? 13) ; => #t (ev? 27) ; => #f ;; -- final sanity ------------------------------------------------------- (+ (fact 6) (fib 14) (gcd 60 24)) ; 720 + 377 + 12 = 1109 (reduce + 0 (map (lambda (n) (* n n)) (range 20))) ; 1+4+9+...+400 = 2870 "all done"