And here's my narray-based solution to find the happiest number under
1_000_000 - it's not the shortest solution I've seen, but it's pretty
fast.  It eliminates numbers that end up in loops by setting all
looping numbers to 0.

#!/usr/bin/env ruby
require 'narray'

def dodigsum(initial, base)
  ndigits = (Math.log(initial.max)/Math.log(base)).ceil
  tmp = initial / (base ** NArray.to_na((0...ndigits).map{|x|[x]}))
  tmp = tmp % base
  tmp.mul!(tmp)
  initial.fill!(0).add!(tmp.sum(1))
end

limit  = ARGV[0] || 1_000_000
base = ARGV[1] || 10

limit = limit.to_i
base = base.to_i

check = NArray.int(limit + 1).indgen!
check_initial = check.dup
check_initial[1] = 0
dodigsum(check, base)
checkp = check.dup

onemask = check.eq(1)
# onemask now contains the location of "0 order" happy numbers
order = 0
found_ex = nil
while (check.ge(2).count_true > 0) do
  check.mul!(check.ne(check_initial))
  check = check[checkp]
  newmask = check.eq(1)
  order = order + 1
  if (not newmask == onemask)
    found_ex = [newmask.gt(onemask).where.min, order]
  end
  onemask = newmask
end
puts "Happiest is #{found_ex[0]}, with happiness order #{found_ex[1]}"
__END__


-- 
s=%q(  Daniel Martin -- martin / snowplow.org
       puts "s=%q(#{s})",s.map{|i|i}[1]       )
       puts "s=%q(#{s})",s.map{|i|i}[1]