; three simple math problems
(define-syntax fold-of
(syntax-rules (range in is)
((_ "z" f b e) (set! b (f b e)))
((_ "z" f b e (v range fst pst stp) c ...)
(let* ((x fst) (p pst) (s stp)
(le? (if (positive? s) =)))
(do ((v x (+ v s))) ((le? p v) b)
(fold-of "z" f b e c ...))))
((_ "z" f b e (v range fst pst) c ...)
(let* ((x fst) (p pst) (s (if (< x p) 1 -1)))
(fold-of "z" f b e (v range x p s) c ...)))
((_ "z" f b e (v range pst) c ...)
(fold-of "z" f b e (v range 0 pst) c ...))
((_ "z" f b e (x in xs) c ...)
(do ((t xs (cdr t))) ((null? t) b)
(let ((x (car t)))
(fold-of "z" f b e c ...))))
((_ "z" f b e (x is y) c ...)
(let ((x y)) (fold-of "z" f b e c ...)))
((_ "z" f b e p? c ...)
(if p? (fold-of "z" f b e c ...)))
((_ f i e c ...)
(let ((b i)) (fold-of "z" f b e c ...)))))
(define-syntax list-of (syntax-rules ()
((_ arg ...) (reverse (fold-of
(lambda (d a) (cons a d)) '() arg ...)))))
(define (isqrt n)
(if (not (and (positive? n) (integer? n)))
(error 'isqrt "must be positive integer")
(let loop ((x n))
(let ((y (quotient (+ x (quotient n x)) 2)))
(if (< y x) (loop y) x)))))
(define (square? n) (let ((s (isqrt n))) (= (* s s) n)))
(define (fact n) (if (zero? n) 1 (* n (fact (- n 1)))))
(display
(do ((y 10 (+ y 1)))
((square? (- (expt 2 y) 615))
(list (isqrt (- (expt 2 y) 615)) y))))
(newline)
(display
(list-of (list a b c)
(a range 1 10)
(b range 1 10)
(c range 1 10)
(= (+ (* 100 a) (* 10 b) c)
(+ (fact 1) (fact b) (fact c)))))
(newline)
(display
(list-of (list p i e)
(p range 1 10)
(i range 1 10)
(e range 1 10)
(= (+ (sqrt (+ (* 10 p) i)) e)
(sqrt (+ (* 100 p) (* 10 i) e))))
)
(newline)