-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathproblem156.arc
58 lines (48 loc) · 1.56 KB
/
problem156.arc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
;; Don't have integer division built in, so we reconstruct it from
;; modulo :)
(def div (x y)
(/ (- x (mod x y)) y))
(def ^ (x y)
(if (is y 0)
1
(* x (^ x (- y 1)))))
(def to-num (xs)
(if (cdr xs)
(reduce (fn (a b) (+ (* 10 a) b)) xs)
(if xs
(car xs)
0)))
(def from-num (n)
(rev (from-num-acc n)))
(def from-num-acc (n)
(if (is n 0)
nil
(cons (mod n 10) (from-num-acc (div n 10)))))
(def f-list (ns d)
(if ns
(let k (- (len ns) 1)
(let below (if (is k 0) 0 (* (car ns) k (^ 10 (- k 1))))
(let current (if (is (car ns) d)
(+ 1 (to-num (cdr ns)))
(if (> (car ns) d)
(^ 10 k)
0))
(let recursive (f-list (cdr ns) d)
(+ below current recursive)))))
0))
(def f (n d)
(f-list (from-num n) d))
(def find-all-fixed-points (lower upper d)
(if (>= lower upper)
0
(if (is lower (- upper 1))
(if (is lower (f lower d)) lower 0)
(let midpoint (div (+ upper lower) 2)
(let f-lower (f lower d)
(let f-upper (f upper d)
(let f-midpoint (f midpoint d)
(let lower-sum (if (or (> f-lower midpoint) (< f-midpoint lower)) 0 (find-all-fixed-points lower midpoint d))
(let upper-sum (if (or (> f-midpoint upper) (< f-upper midpoint)) 0 (find-all-fixed-points midpoint upper d))
(+ lower-sum upper-sum))))))))))
(def upper-limit () (^ 10 11))
(write (sum (fn (d) (find-all-fixed-points 0 (upper-limit) d)) (range 1 9)))