It's a simple kata that can be a lot of fun.
I used a mix of TDD and REPL-driven development to code it.
These are the resulting tests in Midje:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns happy-numbers.core-test | |
(:use midje.sweet) | |
(:use [happy-numbers.core])) | |
(facts | |
(facts | |
"about detecting happy numbers" | |
(happy? 1) => true | |
(happy? 4) => false | |
(happy? 7) => true | |
(happy? 10) => true | |
(happy? 31) => true) | |
(facts | |
"about happy numbers under a given number | |
(see http://mathworld.wolfram.com/HappyNumber.html)" | |
(happy-numbers-under 100) => | |
'(1 7 10 13 19 23 28 31 32 44 49 68 70 79 82 86 91 94 97))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns happy-numbers.core) | |
(defn- parse-int [ch] | |
(Integer/parseInt (str ch))) | |
(def ^:private square | |
(partial map #(* % %))) | |
(defn- digits-in [n] | |
(map parse-int (str n))) | |
(defn- sum-squares-of [digits] | |
(reduce + (square digits))) | |
(defn- one-digit? [n] | |
(= 1 (count (digits-in n)))) | |
(defn- happy-num? [n] | |
(let [sum-squared-digits (sum-squares-of (digits-in n))] | |
(if (one-digit? sum-squared-digits) | |
(= sum-squared-digits 1) | |
(recur sum-squared-digits)))) | |
(def happy? (memoize happy-num?)) | |
(defn happy-numbers-under [n] | |
(filter happy? (range 1 n))) |
You can find the commits step by step here and the code in this repository in GitHub.
I used memoize to avoid repeated computations.
In the next days I will try other suggested optimizations based on the properties of happy numbers.