I wanted to build a function that can find numbers that are not only triagonal, pentagonal and hexagonal, but also octagonal or any-gonal kind that you`d like. The first thing I need is a function that checks if number is i-gonal or not:
(defn i-gonal-number? [n i]
(loop [sum 1 increment (inc i)]
(cond (= sum n) true
(> sum n) false
:else (recur (+ sum increment) (+ increment i)))))
n is for number that is being checked, i for the type of number I want to check. It receives 1 for triagonal, 3 for pentagonal, 4 for hexagonal and so on. The loop checks triagonal numbers and compares them to the one we need. Next, a function that creates a lazy function of all i-gonal numbers:
(defn i-gonal-numbers [i]
((fn increment [n incr]
(lazy-seq (cons n (increment (+ n incr) (+ i incr))))) 1 (inc i)))
Not much to explain here, so I`ll use this opportunity to apologize for my lame literacy. Transition from java coding conventions to clojure ones is still in the process.
Final building brick is a function that compares multiple i-gonal numbers and returns those who match all types of gonals. And there it is:
(defn find-polygonal [coll]
(let [sorted-coll (sort > coll)]
((fn [max-n rest-n]
(for [t (i-gonal-numbers max-n)
:when (not (not-every? #(i-gonal-number? t %) rest-n))]
t))
(first sorted-coll) (rest sorted-coll))))
It receives a collection of gonal-types that I want to compare. Let block sorts it in a descending order, for performance sake. The gonal-types with highest increment are checked first. In for block I used i-gonal numbers to produce lazy function of the i-gonal type with the biggest increment. Then it checks the next biggest i-gonal type, to see if it matches. When it finds the number which is all-gonal, it returns it. Finally, to print the result of the problem, I used:
(time (println (take 3 (find-for-all-numbers [1 3 4]))))
To solve euler problem it took 26 secs, so I wouldn`t try this for bigger numbers. Well, that`s it. I used recursion, lazy sequences and closures, all idiomatic for clojure, and I think the functions are readable, so my goal (making elegant code, as described in intro post) has been reached.
No comments:
Post a Comment