(module number-theory mzscheme
(provide (all-defined))
(require (lib "include.ss"))
(require (lib "27.ss" "srfi"))
(require (only (lib "etc.ss") compose rec)
(only (lib "list.ss") filter mergesort) )
(define first car)
(define second cadr)
(define rest cdr)
(define empty '())
(define ^ expt)
(define (interval m n)
(if (> m n)
'()
(cons m (interval (+ m 1) n))))
(define (square z)
(* z z))
(define (product xs)
(apply * xs))
(define (sum xs)
(apply + xs))
(define (boolify x)
(if x #t #f))
(define big-random random-integer)
(define (random-integer-in-interval from to)
(+ from (random-integer (- to from))))
(define (divides? a b)
(= (remainder b a) 0))
(define (gcd-euclid a b)
(define (loop a b) (let ([r (remainder a b)])
(if (= r 0)
b
(loop b r))))
(loop (max (abs a) (abs b))
(min (abs a) (abs b))))
(define (bezout-binary a b)
(define (loop a b ua va ub vb) (let ([r (remainder a b)]
[q (quotient a b)])
(if (= r 0)
(list ub vb)
(loop b r ub vb (- ua (* q ub)) (- va (* q vb))))))
(if (> a b)
(loop a b 1 0 0 1)
(loop b a 0 1 1 0)))
(define (bezout a . bs)
(if (null? bs)
(list 1)
(let ([uvs (apply bezout bs)]
[st (bezout-binary (apply gcd bs) a)])
(let ([s (first st)]
[t (second st)])
(cons t (map (lambda (u) (* s u))
uvs))))))
(define (coprime? a . bs)
(= 1 (apply gcd (cons a bs))))
(define (pairwise-coprime? a . bs)
(cond
[(null? bs) #t]
[else (and (andmap (lambda (b)
(coprime? a b))
bs)
(apply pairwise-coprime? bs))]))
(define relatively-prime? coprime?)
(define pairwise-relatively-prime? pairwise-coprime?)
(define (odd-prime? n)
(and (odd? n) (prime? n)))
(define (positive-divisors n)
(positive-divisors-of-n-below n n))
(define (positive-divisors-of-n-below n m)
(cond
[(<= m 0) empty]
[(divides? m n) (cons m (positive-divisors-of-n-below n (- m 1)))]
[else (positive-divisors-of-n-below n (- m 1))]))
(define (cyclotomic p x)
(if (= p 1)
1
(+ 1 (* x (cyclotomic (- p 1) x)))))
(define (max-dividing-power p n)
(define (loop p-to-e e)
(if (divides? p-to-e n)
(loop (* p p-to-e) (+ e 1))
(- e 1)))
(loop 1 0))
(define (prime-power n)
(let ([factorization (prime-divisors/exponents n)])
(if (= (length factorization) 1)
(first (prime-divisors/exponents n))
#f)))
(define (prime-power? n)
(boolify (prime-power n)))
(define (odd-prime-power? n)
(let ([p/e (prime-power n)])
(and p/e
(odd? (first p/e)))))
(define (nth-prime n)
(define (next c) (+ c 2))
(define (loop candidate m)
(if (prime? candidate)
(if (= m n)
candidate
(loop (next candidate) (+ m 1)))
(loop (next candidate) m)))
(if (= n 1)
2
(loop 3 2)))
(define (fermat n)
(+ 1 (expt 2 (expt 2 n))))
(define (mersenne p)
(- (expt 2 p) 1))
(define (inverse a n)
(if (coprime? a n)
(modulo (first (bezout a n)) n)
#f))
(define-syntax (with-modulus stx)
(syntax-case stx ()
[(with-modulus e form ...)
(with-syntax ([+ (datum->syntax-object (syntax with-modulus) '+)]
[- (datum->syntax-object (syntax with-modulus) '-)]
[* (datum->syntax-object (syntax with-modulus) '*)]
[^ (datum->syntax-object (syntax with-modulus) '^)]
[mod (datum->syntax-object (syntax with-modulus) 'mod)]
[inv (datum->syntax-object (syntax with-modulus) 'inv)])
(syntax (let* ([n e]
[mod (lambda (x) (modulo x n))]
[inv (lambda (x) (inverse x n))]
[+ (compose mod +)]
[- (compose mod -)]
[* (compose mod *)]
[square (lambda (x) (* x x))]
[^ (rec ^ (lambda (a b)
(cond
[(= b 0) 1]
[(even? b) (square (^ a (/ b 2)))]
[else (* a (^ a (sub1 b)))])))])
form ...)))]))
(define (solve-chinese as ns)
(let* ([n (product ns)]
[cs (map (lambda (ni) (/ n ni)) ns)]
[ds (map inverse cs ns)])
(modulo (sum (map * as cs ds)) n)))
(define (prime-wilson? n)
(with-modulus n
(define (fac x)
(if (= 0 x)
1
(* x (fac (sub1 x)))))
(= (mod (fac (- n 1)))
(mod -1))))
(define (phi n)
(* n (product
(map (lambda (p)
(- 1 (/ 1 p)))
(prime-divisors n)))))
(define totient phi)
(define (unit-group n)
(filter (lambda (m)
(coprime? m n))
(interval 1 (- n 1))))
(define (order g n)
(if (not (coprime? g n))
(error "In (order g n) the g and n must me coprime")
(with-modulus n
(let loop ([k 1]
[a g])
(if (= a 1)
k
(loop (+ k 1) (* a g)))))))
(define (orders n)
(map (lambda (m) (order m n))
(unit-group n)))
(define (primitive-root? g n)
(if (not (coprime? g n))
(error "In (primitive-root? g n) the g and n must me coprime")
(= (order g n) (phi n))))
(define (exists-primitive-root? n)
(cond
[(member n '(1 2 4)) #t]
[(odd? n) (odd-prime-power? n)]
[else (odd-prime-power? (quotient n 2))]))
(define (primitive-root? g n)
(if (not (coprime? g n))
(error "In (primitive-root? g n) the g and n must me coprime")
(let ([phi-n (phi n)])
(with-modulus n
(andmap (lambda (x) x)
(map (lambda (q)
(not (= (^ g (/ phi-n q)) 1)))
(prime-divisors phi-n)))))))
(define (primitive-root n)
(and (exists-primitive-root? n)
(let* ([phi-n (phi n)]
[qs (prime-divisors phi-n)])
(define (primitive-root? g)
(with-modulus n
(andmap (lambda (x) x)
(map (lambda (q)
(not (= (^ g (/ phi-n q)) 1)))
qs))))
(let loop ([g 1])
(cond
[(= g n) #f]
[(not (coprime? g n)) (loop (+ g 1))]
[(primitive-root? g) g]
[else (loop (+ g 1))])))))
(define (primitive-roots n)
(if (not (exists-primitive-root? n))
empty
(let* ([phi-n (phi n)]
[qs (prime-divisors phi-n)])
(define (primitive-root? g)
(with-modulus n
(andmap (lambda (x) x)
(map (lambda (q)
(not (= (^ g (/ phi-n q)) 1)))
qs))))
(let loop ([g 1]
[roots empty])
(cond
[(= g n) (reverse roots)]
[(not (coprime? g n)) (loop (+ g 1) roots)]
[(primitive-root? g) (loop (+ g 1) (cons g roots))]
[else (loop (+ g 1) roots)])))))
(define (primitive-root n)
(and (exists-primitive-root? n)
(cond
[(and (odd-prime-power? n)
(not (prime? n))) (let* ([p (first (prime-power n))]
[g (primitive-root p)])
(if (= (order g (* p p)) (phi (* p p)))
g
(modulo (+ g p) n)))]
[(and (even? n)
(odd-prime? (quotient n 2))) (let ([g (primitive-root (quotient n 2))])
(if (odd? g)
g
(modulo (+ g (quotient n 2)) n)))]
[else (let* ([phi-n (phi n)]
[qs (prime-divisors phi-n)])
(define (primitive-root? g)
(with-modulus n
(andmap (lambda (x) x)
(map (lambda (q)
(not (= (^ g (/ phi-n q)) 1)))
qs))))
(let loop ([g 1])
(cond
[(= g n) #f]
[(not (coprime? g n)) (loop (+ g 1))]
[(primitive-root? g) g]
[else (loop (+ g 1))])))])))
(define (legendre a p)
(let ([l (with-modulus p
(^ a (/ (- p 1) 2)))])
(if (<= 0 l 1)
l
-1)))
(define (quadratic-residue? a n)
(let* ([ps (prime-divisors n)]
[odd-ps (if (= (first ps) 2)
(rest ps)
ps)])
(and (andmap (lambda (p)
(= (legendre a p) 1))
odd-ps)
(cond
[(divides? 8 n) (= (modulo a 8) 1)]
[(divides? 4 n) (= (modulo a 4) 1)]
[else #t]))))
(define (prime-fermat? n)
(cond
[(= n 2) #t]
[else (let* ([a (random-integer-in-interval 2 (- n 1))]
[b (with-modulus n
(^ a (- n 1)))])
(if (= b 1)
'possibly-prime
#f))]))
(define (prime-strong-pseudo-single? n)
(cond
[(= n 2) #t]
[(= n 3) #t]
[(< n 2) #f]
[else (let* ([a (random-integer-in-interval 2 (- n 1))]
[g (gcd a n)])
(if (> g 1)
g
(let loop ([ny 0]
[m (- n 1)])
(if (even? m)
(loop (add1 ny) (/ m 2))
(let ([b (with-modulus n (^ a m))])
(if (= b 1)
'probably-prime
(let loop ([i 0]
[b b]
[b-old b])
(if (< i ny)
(loop (add1 i)
(with-modulus n (* b b))
b)
(if (= b 1)
(let ([g (gcd (+ b-old 1) n)])
(if (or (= g 1) (= g n))
'probably-prime
g))
'composite)))))))))]))
(define integer-log2
(let ([log2 (log 2)])
(lambda (n)
(/ (log n) log2))))
(define (big-log2 n)
(define (loop n l)
(if (<= n 1)
l
(loop (quotient n 2) (add1 l))))
(loop n 0))
(define prime-strong-pseudo-certainty 1/10000000)
(define prime-strong-pseudo-trials (inexact->exact (ceiling (integer-log2 (/ 1 prime-strong-pseudo-certainty)))))
(define (prime-strong-pseudo/explanation n)
(if #f (error "prime-strong-pseudo: n must be 'large'" n)
(let loop ([trials prime-strong-pseudo-trials]
[result (prime-strong-pseudo-single? n)])
(if (= trials 0)
'very-probably-prime
(cond
[(equal? result 'probably-prime) (loop (sub1 trials) (prime-strong-pseudo-single? n))]
[else result])))))
(define (prime-strong-pseudo? n)
(let ([explanation (prime-strong-pseudo/explanation n)])
(if (or (equal? explanation 'very-probably-prime)
(equal? explanation #t))
#t
#f)))
(require (lib "42.ss" "srfi"))
(define *SMALL-PRIME-LIMIT* 1000000)
(define prime?
(let ()
(define N *SMALL-PRIME-LIMIT*) (define ps (make-vector (+ N 1) #t))
(define ! vector-set!)
(! ps 0 #f)
(! ps 1 #f)
(do-ec (: n 2 (+ N 1))
(if (vector-ref ps n))
(: m (+ n n) (+ N 1) n)
(! ps m #f))
(lambda (n)
(if (< n N)
(vector-ref ps n)
(prime-strong-pseudo? n)))))
(define (next-prime n)
(cond
[(< n 2) 2]
[(= n 2) 3]
[(even? n) (let ([n+1 (add1 n)])
(if (prime? n+1)
n+1
(next-prime n+1)))]
[else (let ([n+2 (+ n 2)])
(if (prime? n+2)
n+2
(next-prime n+2)))]))
(define (prev-prime n)
(cond
[(= n 3) 2]
[(< n 3) #f]
[(even? n) (let ([n-1 (sub1 n)])
(if (prime? n-1)
n-1
(prev-prime n-1)))]
[else (let ([n-2 (- n 2)])
(if (prime? n-2)
n-2
(prev-prime n-2)))]))
(define (next-primes n primes-wanted)
(if (= primes-wanted 0)
'()
(let ([next (next-prime n)])
(if next
(cons next (next-primes next (sub1 primes-wanted)))
'()))))
(define (prev-primes n primes-wanted)
(if (= primes-wanted 0)
'()
(let ([prev (prev-prime n)])
(if prev
(cons prev (prev-primes prev (sub1 primes-wanted)))
'()))))
(define (floyd-detect-cycle f x0)
(do ([xi x0 (f xi)]
[yi x0 (f (f yi))]
[i 0 (add1 i)])
[(= xi yi) i]))
(define (pollard n)
(let ([x0 (big-random n)])
(do ([xi x0 (remainder (+ (* xi xi) 1) n)]
[yi x0 (remainder (+ (square (+ (* yi yi) 1)) 1) n)]
[i 0 (add1 i)]
[g 1 (gcd (- xi yi) n)])
[(or (< 1 g n)
(> i (sqrt n))
) (if (< 1 g n)
g
#f)]
)))
(define (pollard-factorize n)
(if (< n 10000) (factorize-small n)
(cond
[(= n 1) '()]
[(prime? n) `((, n 1))]
[(even? n) `((2 1) ,@(pollard-factorize (quotient n 2)))]
[(divides? 3 n) `((3 1) ,@(pollard-factorize (quotient n 3)))]
[(perfect-power n) => (lambda (base-and-exp)
(cond
[(prime? (car base-and-exp)) (list base-and-exp)]
[else (map (lambda (b-and-e)
(list (car b-and-e) (* (cadr base-and-exp)
(cadr b-and-e))))
(pollard-factorize (car base-and-exp)))]))]
[else (let loop ([divisor (pollard n)])
(if divisor
(append (pollard-factorize divisor)
(pollard-factorize (quotient n divisor)))
(loop (pollard n))))])))
(define (base-and-exponenent<? x y)
(let ([id-or-first
(lambda (x)
(if (number? x)
x
(first x)))])
(<= (id-or-first x) (id-or-first y))))
(define (factorize n)
(if (< n *SMALL-PRIME-LIMIT*) (factorize-small n)
(factorize-large n)))
(require (only (lib "1.ss" "srfi") find-tail))
(define (small-prime-factors-over n p)
(cond
[(< n p) '()]
[(= n p) (list (list p 1))]
[(prime? n) (list (list n 1))]
[(divides? p n) (let ([m (max-dividing-power p n)])
(cons (list p m)
(small-prime-factors-over
(quotient n (expt p m))
(next-prime p))))]
[else (small-prime-factors-over n (next-prime p))]))
(define (factorize-small n)
(small-prime-factors-over n 2))
(define (combine-same-base list-of-base-and-exponents)
(let ([l list-of-base-and-exponents])
(cond
[(null? l) '()]
[(null? (cdr l)) l]
[else (let ([b1 (first (first l))]
[e1 (second (first l))]
[b2 (first (second l))]
[e2 (second (second l))]
[more (cddr l)])
(if (= b1 b2)
(combine-same-base (cons (list b1 (+ e1 e2))
(cdr (cdr list-of-base-and-exponents))))
(cons (car list-of-base-and-exponents)
(combine-same-base (cdr list-of-base-and-exponents)))))])))
(define (factorize-large n)
(combine-same-base
(mergesort
(pollard-factorize n)
base-and-exponenent<?)))
(define prime-divisors/exponents factorize)
(define (prime-divisors n)
(map car (prime-divisors/exponents n)))
(define (prime-exponents n)
(map cadr (factorize n)))
(define (p-adic-newton-iteration phi Dphi p l g0 s0)
(let ([r (inexact->exact (ceiling (integer-log2 l)))])
(let loop ([i 1]
[gi g0]
[si s0])
(cond
[(< i r) (let ([g_i+1 (modulo (- gi (* (phi gi) si)) (expt p (expt 2 i)))])
(loop (+ i 1)
g_i+1
(modulo (- (* 2 si) (* (Dphi g_i+1) si si)) (expt p (expt 2 i)))))]
[else (modulo (- gi (* (phi gi) si)) (expt p l))]))))
(define (is-nth-root a n candidate)
(if (= (expt candidate n) a)
candidate
#f))
(define (integer-root/odd-odd a n)
(unless (and (odd? a) (odd? n))
(error "integer-root/odd-odd: Both a and n must be odd; given " a n))
(let ([candidate
(let* ([k (do ([k 1 (add1 k)])
[(> (expt 2 (* n k)) a) k])]
[r (inexact->exact (ceiling (integer-log2 k)))])
(let loop ([i 1]
[gi 1]
[si 1]
[ti 1])
(cond
[(< i r) (let* ([g_i+1 (modulo (- gi (* (- (* gi ti) a) si))
(expt 2 (expt 2 i)))]
[t_i+1 (modulo (expt g_i+1 (- n 1))
(expt 2 (expt 2 (+ i 1))))])
(loop (+ i 1)
g_i+1
(modulo (- (* 2 si) (* n t_i+1 si si))
(expt 2 (expt 2 i)))
t_i+1))]
[else (modulo (- gi (* (- (* gi ti) a) si))
(expt 2 (expt 2 i)))])))])
(is-nth-root a n candidate)))
(define (integer-root/power-of-two a n)
(let ([phi (lambda (y) (- (expt y n) a))]
[Dphi (lambda (y) (* n (expt y (- n 1))))])
(let ([candidate1 (p-adic-newton-iteration phi Dphi 3 11 1 (inverse (Dphi 1) 3))])
(if (= (expt candidate1 n) a)
candidate1
(let ([candidate2 (p-adic-newton-iteration phi Dphi 3 11 2 (inverse (Dphi 2) 3))])
(is-nth-root a n candidate2))))))
(define (integer-root-factor a n)
(let* ([d (max-dividing-power 2 a)]
[e (max-dividing-power 3 a)]
[b-to-r (quotient a (* (expt 2 d) (expt 3 e)))]
[f (max-dividing-power 2 n)]
[two-to-f (expt 2 f)]
[c (quotient n two-to-f)]
[b (integer-root/power-of-two
(integer-root/odd-odd b-to-r c)
two-to-f)]
[r (max-dividing-power b b-to-r)])
(list d e b r)))
(define (integer-root a n)
(if (= n 1)
a
(let ([d (max-dividing-power 2 a)])
(if (not (divides? n d))
#f
(let ([e (max-dividing-power 3 a)])
(if (not (divides? n e))
#f
(let* ([b-to-r (quotient a (* (expt 2 d) (expt 3 e)))]
[f (max-dividing-power 2 n)]
[two-to-f (expt 2 f)]
[c (quotient n two-to-f)])
(cond
[(integer-root/odd-odd b-to-r c)
=> (lambda (cth-root--of--b-to-r)
(cond
[(integer-root/power-of-two cth-root--of--b-to-r two-to-f)
=> (lambda (nth-root--of--b-to-r)
(* (expt 2 (quotient d n))
(expt 3 (quotient e n))
nth-root--of--b-to-r))]
[else #f]))]
[else #f]))))))))
(define (as-power a)
(let loop ([n (+ (big-log2 a) 1)])
(let ([root (integer-root a (add1 n))])
(if root
(values root (add1 n))
(loop (sub1 n))))))
(define (perfect-power? a)
(let-values ([(base n) (as-power a)])
(and (> n 1) (> a 1))))
(define (perfect-power a)
(let-values ([(base n) (as-power a)])
(if (and (> n 1) (> a 1))
(list base n)
#f)))
(define (powers-of a n)
(let loop ([i 0]
[a^i 1])
(if (<= i n)
(cons a^i (loop (+ i 1) (* a^i a)))
'())))
(define (factorization->divisors f)
(cond
[(null? f) '(1)]
[else (let ([p (first (first f))]
[n (second (first f))]
[g (rest f)])
(let ([divisors-of-g (factorization->divisors g)])
(apply append
(map (lambda (p^i)
(map (lambda (d) (* p^i d))
divisors-of-g))
(powers-of p n)))))]))
(define (divisors n)
(factorization->divisors (factorize n)))
(require (only (lib "1.ss" "srfi") every))
(define (one? n)
(= n 1))
(define euler-phi phi)
(define (moebius-mu n)
(let* ([f (factorize n)]
[primes (map first f)]
[exponents (map second f)])
(if (every one? exponents)
(if (even? (length primes))
1
-1)
0)))
(define divisor-sum
(case-lambda
[(n) (divisor-sum n 1)]
[(n k) (let loop ([sum 0] [ds (divisors n)])
(if (null? ds)
sum
(loop (+ sum (expt (car ds) k))
(cdr ds))))]))
(require (lib "42.ss" "srfi"))
(define (bernoulli n)
(let ([b (make-vector (max (+ n 1) 2) #f)])
(vector-set! b 0 1)
(vector-set! b 1 -1/2)
(let ()
(define (next-binom old x k)
(* old
(/ (* k (- k 1) (- k 2) (- k 3) (- k 4) (- k 5) )
(* (- x (- k 1)) (- x (- k 2)) (- x (- k 3)) (- x (- k 4)) (- x (- k 5)) (- x (- k 6))))))
(define (A m M)
(if (< M 1)
0
(sum-ec (:parallel
(: j 1 (+ M 1))
(:do ([bin (binomial (+ m 3) (- m 6))]) #t ((next-binom bin (+ m 3) (- m (* 6 j))))))
(* bin
(bern (- m (* 6 j)))))))
(define (bern n)
(let ([bn (vector-ref b n)])
(if bn
bn
(let ([bn
(cond
[(odd? n) 0]
[(= (remainder n 6) 0) (/ (- (/ (+ n 3) 3) (A n (/ n 6))) (binomial (+ n 3) n))]
[(= (remainder n 6) 2) (/ (- (/ (+ n 3) 3) (A n (/ (- n 2) 6))) (binomial (+ n 3) n))]
[(= (remainder n 6) 4) (/ (- (/ (+ n 3) -6) (A n (/ (- n 4) 6))) (binomial (+ n 3) n))])])
(vector-set! b n bn)
bn))))
(bern n))))
(define (tangent-number n)
(let ([T (make-vector (+ n 2) 0)])
(vector-set! T 1 1)
(do-ec (: k (+ n 1))
(begin
(do-ec (: i (+ k 1))
(vector-set! T i
(* (+ i 1) (vector-ref T (+ i 1)))))
(do-ec (: i (+ k 1) 1 -1)
(vector-set! T i
(+ (vector-ref T i)
(vector-ref T (- i 2)))))))
(vector-ref T 0)))
(define (bernoulli/tangent n)
(cond
[(= n 0) 1]
[(= n 1) -1/2]
[(= n 2) 1/6]
[(odd? n) 0]
[else (let ([m (/ n 2)])
(* (tangent-number (- n 1))
(/ n
(let ([4^m (expt 4 m)])
(* 4^m (- 4^m 1))))
(if (even? m)
-1
1)))]))
(define (binomial n k)
(cond
[(= k 0) 1]
[(= k 1) n]
[(= k 2) (/ (* n (- n 1)) 2)]
[(> k (/ n 2)) (binomial n (- n k))]
[else (* (+ n (- k) 1)
(product-ec (:range i 2 (+ k 1))
(/ (+ n (- k) i)
i)))]))
(define (factorial n)
(define (fact-small n)
(if (= n 1)
1
(* n (factorial (- n 1)))))
(define (fact-big n)
(let ([n/2 (quotient n 2)])
(product (append
(list-ec (:range i 1 n/2) i)
(reverse (list-ec (:range i n/2 (+ n 1)) i))))))
(cond
[(= n 0) 1]
[(< n 400) (fact-small n)]
[else (fact-big n)]))
(define (euler-number n k)
(if (= k 0)
1
(let ([E (make-vector (max (+ k 1) (+ n 1)) 0)])
(vector-set! E 0 1) (do-ec (: i 1 (+ n 1))
(do-ec (:range j (- i 1) 0 -1)
(vector-set! E j
(+ (* (+ j 1) (vector-ref E j))
(* (- i j) (vector-ref E (- j 1)))))))
(vector-ref E k))))
(list-ec (: n 10) (list-ec (: k 10) (euler-number n k)))
(define (perfect-square n)
(let ([sqrt-n (integer-sqrt n)])
(if (= (* sqrt-n sqrt-n) n)
sqrt-n
#f)))
(define (second-degree-solutions a b c)
(let ([d (- (* b b) (* 4 a c))])
(cond
[(< d 0)
'()]
[(= d 0)
(list (/ b (* -2 a)))]
[else
(let ([sqrt-d (sqrt d)])
(list (/ (- (- b) sqrt-d) (* 2 a))
(/ (+ (- b) sqrt-d) (* 2 a))))])))
(define (second-degree-integer-solutions a b c)
(filter integer? (second-degree-solutions a b c)))
(define (natural? n)
(and (integer? n)
(positive? n)))
(define (second-degree-natural-solutions a b c)
(filter natural? (second-degree-solutions a b c)))
(define (triangle n)
(quotient (* n (+ n 1)) 2))
(define (triangle? n)
(not (null? (second-degree-natural-solutions 1/2 1/2 (- n)))))
(define (square? n)
(perfect-square n))
(define (pentagonal n)
(quotient (* n (- (* 3 n) 1)) 2))
(define (pentagonal? n)
(not (null? (second-degree-natural-solutions 3/2 -1/2 (- n)))))
(define (hexagonal n)
(* n (- (* 2 n) 1)))
(define (hexagonal? n)
(not (null? (second-degree-natural-solutions 2 -1 (- n)))))
(define (heptagonal n)
(quotient (* n (- (* 5 n) 3)) 2))
(define (heptagonal? n)
(not (null? (second-degree-natural-solutions 5/2 -3/2 (- n)))))
(define (octagonal n)
(* n (- (* 3 n) 2)))
(define (octagonal? n)
(not (null? (second-degree-natural-solutions 3 -2 (- n)))))
(require (planet "memoize.ss" ("dherman" "memoize.plt" 2 1)))
(define (partitions n)
(define p
(memo-lambda* (n)
(cond
[(< n 0) 0]
[(= n 0) 1]
[else (sum-ec (:range k 1 (add1 (inexact->exact (floor (/ (+ 1.0 (sqrt (+ 1.0 (* 24.0 n)))) 6.0)))))
(* (if (odd? k) 1 -1)
(+ (p (- n (quotient (* k (- (* 3 k) 1)) 2)))
(p (- n (quotient (* k (+ (* 3 k) 1)) 2))))))])))
(p n))
(define (digits n)
(define (d x)
(if (< x 10)
(list x)
(cons (remainder x 10)
(d (quotient x 10)))))
(unless (integer? n)
(error 'digits "expected an integer, got: n"))
(reverse (d (if (negative? n) (- n) n))))
(define (digits->number ds)
(define (rev-digits->number ds)
(if (null? ds)
0
(+ (car ds)
(* 10 (rev-digits->number (cdr ds))))))
(rev-digits->number (reverse ds)))
(define (number-append x y)
(unless (and (natural? x) (natural? y))
(error 'number-append "expected two natural numbers, got: " x y))
(string->number
(string-append
(number->string x)
(number->string y))))
(define (number-reverse n)
(digits->number
(reverse
(digits n))))
(define (palindromic? n)
(let ([ds (digits n)])
(equal? ds (reverse ds))))
(define (number-length n)
(unless (and (integer? n) (not (negative? n)))
(error 'number-lengh "expected non-negative integer, got: " n))
(let ([len (inexact->exact (floor (/ (log n) (log 10))))])
(let loop ([len len])
(if (< (- (expt 10 len) 1) n (expt 10 (+ len 1)))
(+ len 1)
(loop (+ len 1))))))
(define (generator a b p q count)
(cond ((= count 0) b)
((even? count)
(generator a
b
(+ (* p p) (* q q))
(+ (* 2 p q) (* q q))
(quotient count 2)))
(else (generator (+ (* b q) (* a q) (* a p))
(+ (* b p) (* a q))
p
q
(- count 1)))))
(define (fibonacci n)
(generator 1 0 0 1 n))
(define (lucas n)
(generator 1 3 0 1 n))
(define (fibonacci-mod n mod)
(define (generator a b p q count)
(cond ((= count 0) b)
((even? count)
(generator a
b
(remainder (+ (* p p) (* q q)) mod)
(remainder (+ (* 2 p q) (* q q)) mod)
(quotient count 2)))
(else (generator (remainder (+ (* b q) (* a q) (* a p)) mod)
(remainder (+ (* b p) (* a q)) mod)
p
q
(- count 1)))))
(generator 1 0 0 1 n))
(require (planet "memoize.ss" ("dherman" "memoize.plt")))
(define (mediant x y)
(/ (+ (numerator x) (numerator y))
(+ (denominator x) (denominator y))))
(require (only (lib "list.ss") sort))
(define farey
(memo-lambda* (d)
(define (delete-last xs)
(reverse! (cdr (reverse xs))))
(define (successive? x y)
(= (- (* (denominator x) (numerator y))
(* (denominator y) (numerator x)))
1))
(cond
[(= d 1) (list 0 1)]
[else (let ([fs (farey (- d 1))])
(sort (append fs
(filter {lambda (x) (<= (denominator x) d)}
(map mediant
(delete-last fs) (rest fs))))
<))])))
)