Skip to content

Instantly share code, notes, and snippets.

@johnkelly
Last active August 29, 2015 14:20
Show Gist options
  • Save johnkelly/f491cf69abe920352e30 to your computer and use it in GitHub Desktop.
Save johnkelly/f491cf69abe920352e30 to your computer and use it in GitHub Desktop.
(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
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