patternMinor
Bringing Clojure to project Euler 19
Viewed 0 times
projectclojureeulerbringing
Problem
I recently began learning Clojure for fun, and after completing the koans, I decide that project Euler would provide my next challenge. Here is the problem statement:
(If someone knows how to put this in spolier tags with out breaking the formatting, please feel free to edit or comment and let me know how to fix it.)
Counting Sundays
You are given the following information, but you may prefer to do some research for yourself.
How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?
This is the code I used to arrive at the solution. Note that I purposely avoided the date/time APIs so I could try more of the language features out.
```
(ns euler.n19)
(def week-days (cycle [:mon :tue :wed :thr :fri :sat :sun]))
(defn leap-year?
([year] (if (= 0 (mod year 100))
(= 0 (mod year 400))
(= 0 (mod year 4)))))
(def months [:jan :feb :mar :apr :may :jun :jul :agu :sep :oct :nov :dec])
(def month-length {:jan 31 :feb 28 :mar 31 :apr 30
:may 31 :jun 30 :jul 31 :agu 31
:sep 30 :oct 31 :nov 30 :dec 31})
(def leap-year-month-length (assoc month-length :feb 29))
(def years (->> (range 1901 2001)
(map (fn [yr] (if (leap-year? yr)
leap-year-month-length
month-length)))))
(defn zip
([coll-1 coll-2] map list coll-1 coll-2))
(defn count-number-of-times-day-on-nth-of-month
([day date]
(->> years
(map (fn [month-len] (map #(% month-len) months)))
(flatten)
(reduce (fn [[week-days num-
(If someone knows how to put this in spolier tags with out breaking the formatting, please feel free to edit or comment and let me know how to fix it.)
Counting Sundays
Problem 19You are given the following information, but you may prefer to do some research for yourself.
- 1 Jan 1900 was a Monday.
- Thirty days has September,
- April, June and November.
- All the rest have thirty-one,
- Saving February alone,
- Which has twenty-eight, rain or shine.
- And on leap years, twenty-nine.
- A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400.
How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?
This is the code I used to arrive at the solution. Note that I purposely avoided the date/time APIs so I could try more of the language features out.
```
(ns euler.n19)
(def week-days (cycle [:mon :tue :wed :thr :fri :sat :sun]))
(defn leap-year?
([year] (if (= 0 (mod year 100))
(= 0 (mod year 400))
(= 0 (mod year 4)))))
(def months [:jan :feb :mar :apr :may :jun :jul :agu :sep :oct :nov :dec])
(def month-length {:jan 31 :feb 28 :mar 31 :apr 30
:may 31 :jun 30 :jul 31 :agu 31
:sep 30 :oct 31 :nov 30 :dec 31})
(def leap-year-month-length (assoc month-length :feb 29))
(def years (->> (range 1901 2001)
(map (fn [yr] (if (leap-year? yr)
leap-year-month-length
month-length)))))
(defn zip
([coll-1 coll-2] map list coll-1 coll-2))
(defn count-number-of-times-day-on-nth-of-month
([day date]
(->> years
(map (fn [month-len] (map #(% month-len) months)))
(flatten)
(reduce (fn [[week-days num-
Solution
A function that gives you the sequence of month lengths in a given
... is all that your
The result is ...
For example,
Odds and ends
the argument list and body.
For example,
Edited to correct a sign error in dealing with the
year: (defn month-seq [year]
(map
(if (leap-year? year) leap-year-month-length month-length)
months))... is all that your
count-number-of-times-day-on-nth-of-month function needs. - I've extended it to accept a
year-rangeas well asdayand
date.- I've replaced
flattenwith the simplermapcatand
reducewithreductions, to simplify the algorithm.
The result is ...
(defn count-number-of-times-day-on-nth-of-month
[year-range day date]
{:pre [(>= (first year-range) 1900)]}
(let [month-lengths (mapcat month-seq (range 1900 (inc (last year-range))))
day-seqs (reductions
(fn [s n] (drop n s))
week-days
month-lengths)
first-days (map first day-seqs)]
(->> first-days
(drop (+ (* 12 (- (first year-range) 1900)) date))
butlast
frequencies
day)))For example,
(count-number-of-times-day-on-nth-of-month (range 1901 2001) :sun 0)Odds and ends
- Your
zipfunction (unused) andmainfunction are each missing a pair of parentheses.
- If there is only one arity, there is no need for parentheses around
the argument list and body.
For example,
(defn zip
[coll-1 coll-2] (map list coll-1 coll-2))Edited to correct a sign error in dealing with the
date argument to count-number-of-times-day-on-nth-of-month.Code Snippets
(defn month-seq [year]
(map
(if (leap-year? year) leap-year-month-length month-length)
months))(defn count-number-of-times-day-on-nth-of-month
[year-range day date]
{:pre [(>= (first year-range) 1900)]}
(let [month-lengths (mapcat month-seq (range 1900 (inc (last year-range))))
day-seqs (reductions
(fn [s n] (drop n s))
week-days
month-lengths)
first-days (map first day-seqs)]
(->> first-days
(drop (+ (* 12 (- (first year-range) 1900)) date))
butlast
frequencies
day)))(count-number-of-times-day-on-nth-of-month (range 1901 2001) :sun 0)(defn zip
[coll-1 coll-2] (map list coll-1 coll-2))Context
StackExchange Code Review Q#158163, answer score: 2
Revisions (0)
No revisions yet.