Ruby Quiz wrote:
> The three rules of Ruby Quiz:
>
> 1.  Please do not post any solutions or spoiler discussion for this quiz until
> 48 hours have passed from the time on this message.
>
> 2.  Support Ruby Quiz by submitting ideas as often as you can:
>
> http://www.rubyquiz.com/
>
> 3.  Enjoy!
>
> Suggestion:  A [QUIZ] in the subject of emails about the problem helps everyone
> on Ruby Talk follow the discussion.  Please reply to the original quiz message,
> if you can.
>
> -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
>
> by Shane Emmons
>
> Write a program that tells whether a given integer is happy. A happy number is
> found using the following process: Take the sum of the squares of its digits,
> and continue iterating this process until it yields 1, or produces an infinite
> loop. 
>
> For example the number 7:
>
> 	7^2 = 49
> 	4^2 + 9^2 = 97
> 	9^2 + 7^2 = 130
> 	1^2 + 3^2 + 0^2 = 10
> 	1^2 + 0^2 = 1
>
> If a number is not happy than it is obviously unhappy. Now that you have this
> program, what is the largest happy number you can find? What is the happiest
> number between 1 and 1,000,000. I define the happiest number as the smallest
> number that finds the most other happy numbers with it, i.e. 7 found four other
> numbers (49, 97, 130, and 10) making it a rank 4 in happiness.
>
> If you find all these examples trivial, write you program so that it will find
> happy numbers in other bases such as base 2 or 16. From there you can extend the
> program so that it finds happy bases (other than 2 and 4). A happy bases is a
> base where all numbers are happy. Good luck. 
>   

#! /usr/bin/env ruby

def sum_dig_sq(ival)
  sum = 0
  while ival > 0 do
    ival,dig = ival.divmod(10)
    sum += (dig * dig)
  end
  return sum
end

def happy?(ival)
# sad #s from http://mathworld.wolfram.com/HappyNumber.html
sad = [0, 4, 16, 20, 37, 42, 58, 89, 145]
rank = 0
while true do
  return -1 if sad.include?(ival) # check sad 1st - ~87% are sad
  ival = sum_dig_sq(ival)
  return rank if ival == 1
  rank += 1
end
end

if ARGV[0].to_i <= 0
  warn "usage: #{$0} <number>\n  number must be > 0"
  exit
end

processed = []
happiest = []
(0..ARGV[0].to_i).each {|cur_num|
  base = cur_num.to_s.split('').sort.join.to_i
  processed[base] = happy?(cur_num) unless processed[base]
  rank = processed[base]
  next if rank  < 0

  puts "#{cur_num} is happy - rank #{rank}"
  happiest[rank] = cur_num unless happiest[rank]
}

happiest.each_with_index do |val, ndx|
  puts "Happiest number of rank #{ndx} is #{val}"
end