--- a/src/problems.lisp Tue Oct 10 21:09:53 2017 -0400
+++ b/src/problems.lisp Thu Oct 12 21:29:54 2017 -0400
@@ -8,7 +8,7 @@
(iterate (for i :from 1 :below 1000)
(when (or (dividesp i 3)
(dividesp i 5))
- (sum i))))
+ (summing i))))
(defun problem-2 ()
;; Each new term in the Fibonacci sequence is generated by adding the previous
@@ -21,7 +21,7 @@
(iterate (for n :in-fibonacci t)
(while (<= n 4000000))
(when (evenp n)
- (sum n))))
+ (summing n))))
(defun problem-3 ()
;; The prime factors of 13195 are 5, 7, 13 and 29.
@@ -664,7 +664,7 @@
(flet ((maximum-sum-for-digits (n)
(* (expt 9 5) n))
(digit-power-sum (n)
- (sum (mapcar (rcurry #'expt 5) (digits n)))))
+ (sum (digits n) :key (rcurry #'expt 5))))
(iterate
;; We want to find a limit N that's bigger than the maximum possible sum
;; for its number of digits.
@@ -814,7 +814,7 @@
(iterate (for i :from 1 :below 1000000)
(when (and (palindromep i 10)
(palindromep i 2))
- (sum i))))
+ (summing i))))
(defun problem-37 ()
;; The number 3797 has an interesting property. Being prime itself, it is
@@ -836,7 +836,7 @@
(with count = 0)
(for i :from 11 :by 2)
(when (truncatablep i)
- (sum i)
+ (summing i)
(incf count))
(while (< count 11)))))
@@ -1371,7 +1371,7 @@
(iterate
(for size :from 3 :by 2)
(for count :from 5 :by 4)
- (sum (primes-in-layer size) :into primes)
+ (summing (primes-in-layer size) :into primes)
(for ratio = (/ primes count))
(finding size :such-that (< ratio 1/10)))))
@@ -1602,7 +1602,7 @@
(while (>= maximum-possible-digits power))
(finally (return power)))))
(iterate (for n :from 1 :below (find-bound))
- (sum (score n)))))
+ (summing (score n)))))
(defun problem-69 ()
;; Euler's Totient function, φ(n) [sometimes called the phi function], is
@@ -1699,7 +1699,7 @@
;; How many chains, with a starting number below one million, contain exactly
;; sixty non-repeating terms?
(labels ((digit-factorial (n)
- (sum (mapcar #'factorial (digits n))))
+ (sum (digits n) :key #'factorial))
(term-count (n)
(iterate (for i :initially n :then (digit-factorial i))
(until (member i prev))
--- a/src/utils.lisp Tue Oct 10 21:09:53 2017 -0400
+++ b/src/utils.lisp Thu Oct 12 21:29:54 2017 -0400
@@ -340,10 +340,25 @@
i))))
-(defun factorial (n)
+(defun factorial% (n)
(iterate (for i :from 1 :to n)
(multiplying i)))
+(defun precompute-factorials (size)
+ (iterate
+ (with cache = (make-array size :element-type 'integer))
+ (for i :from 0 :below size)
+ (setf (aref cache i) (factorial% i))
+ (finally (return cache))))
+
+(defparameter *factorial-cache-size* 2000)
+(defparameter *factorial-cache* (precompute-factorials *factorial-cache-size*))
+
+(defun factorial (n)
+ (if (< n *factorial-cache-size*)
+ (aref *factorial-cache* n)
+ (factorial% n)))
+
(defun perfectp (n)
(= n (sum (proper-divisors n))))