Last active
August 29, 2015 14:20
-
-
Save johnkelly/f491cf69abe920352e30 to your computer and use it in GitHub Desktop.
Happy Numbers - http://en.wikipedia.org/wiki/Happy_number
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 my-project.magic) | |
;; Take each digit in a number and square it, then add the sums together. Keep doing this recursively. | |
;; The sequence will either go to one or recurse infinitely. | |
;; Create a method that returns a boolean value to determine whether a number is happy | |
(defn number->digits | |
"Given a number return a sequence of digits that comprise the number" | |
[number] | |
(let [string-digits (map str (seq (str number)))] | |
(map #(Integer/parseInt %) string-digits))) | |
(defn square [digit] | |
(* digit digit)) | |
(defn happy-generator | |
"Given a number generate the next number in the happy sequence" | |
[number] | |
(let [digits (number->digits number)] | |
(reduce + (map square digits)))) | |
(defn happy-sequence | |
"Given a starting number, iterate over the sequence until a number repeats" | |
[starting-number] | |
(let [happy-seq (iterate happy-generator starting-number) | |
used-seq (atom #{}) | |
unq-number? (fn [x] | |
(when-not (@used-seq x) | |
(swap! used-seq conj x)))] | |
(take-while unq-number? happy-seq))) | |
(defn is-happy? | |
"Is a number a happy number? Returns true or false" | |
[x] | |
(= 1 (last (happy-sequence x)))) | |
(is-happy? 998);=> true | |
(is-happy? 31) ;=> true | |
(is-happy? 10) ;=> true | |
(is-happy? 4) ;=> false | |
(time (map is-happy? (range 1000))) ;=> Elapsed time: 0.047124 msecs | |
(time (map is-happy? (range 30000))) ;=> Elapsed time: 0.066306 msecs |
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
require 'set' | |
require 'benchmark' | |
class Happy | |
class << self | |
# Given a number generate the next number in the happy sequence | |
def generator(number) | |
number.to_s.split('').map(&:to_i).map { |x| x ** 2 }.reduce(:+) | |
end | |
# Given a starting number, produces recursive happy numbers up to the | |
# point where the sequence begins repeating infinitely" | |
# The sequence can terminate when a number is repeated | |
def sequence(number) | |
used_numbers = Set.new | |
loop do | |
break if used_numbers.include? number | |
used_numbers << number | |
number = generator(number) | |
end | |
used_numbers | |
end | |
# Is a number a happy number? Returns true or false | |
def is_happy?(number) | |
sequence(number).include? 1 | |
end | |
end | |
end | |
Happy.is_happy? 998 #=> true | |
Happy.is_happy? 31 #=> true | |
Happy.is_happy? 10 #=> true | |
Happy.is_happy? 4 #=> false | |
one_thousand_happy_numbers = -> { (1..1000).map{ |x| Happy.is_happy? x } } | |
thirty_thousand_happy_numbers = -> { (1..30_000).map{ |x| Happy.is_happy? x } } | |
puts Benchmark.measure { one_thousand_happy_numbers.call } #0.100000 0.000000 0.100000 ( 0.101419) | |
puts Benchmark.measure { thirty_thousand_happy_numbers.call } #3.140000 0.020000 3.160000 ( 3.177173) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment