Although using Conway’s Doomsday Algorithm is a fun party trick, I tend to hate calendar math. Worse, I hate Mondays too. So I guess this problem wasn’t written for me.
Still, how would we solve Project Euler Problem 19 in Clojure? Two obvious choices present themselves:
- Use a Java library that manipulates dates.
- Write a quick function by hand.
I chose option #2, although in retrospect #1 would have been a better idea.
(def days-per-mo [31 28 31 30 31 30 31 31 30 31 30 31])
(def days-per-mo-leap [31 29 31 30 31 30 31 31 30 31 30 31])
(defn leap-year? [y]
(or (zero? (mod y 400))
(and (zero? (mod y 4))
(not (zero? (mod y 100))))))
(defn accum [s]
"Returns a sequence of the sums of elements up to each element in seq s. "
(loop [e (first s)
r (rest s)
sums [0]]
(if (nil? e)
(rest sums)
(recur (first r) (rest r) (conj sums (+ e (last sums)))))))
;; Any number with a mod 7 must be a monday, if we start on a monday.
(defn euler-19 []
(count (filter #(= 0 (mod % 7))
(accum (concat [366] ;; First skip the year 1900
(mapcat #(if (leap-year? %)
days-per-mo-leap
days-per-mo)
(range 1901 2001)))))))
(euler-19)
I am not actually certain that my hand-rolled solution is actually correct in the implementation (although it gave the correct answer), and prefer gnuvince’s solution posted on clojure-euler to my own.
Can anybody think of a better way to write accum
? It looks like a useful function for other problems.