From: Daniel Martin Date: 2006-09-06T23:57:12+09:00 Subject: [QUIZ SOLUTION] Happy Numbers (#93) - happy bases Here's my solution to find happy bases - note that I don't find any happy bases (aside from 2 and 4) before I run out of memory, somewhere near base 1700. It wouldn't surprise me if no other happy bases exist. The program checks up to 2*(base-1)*(base-1) for numbers that fall into an infinite loop (that is not '1' forever) when applying the digit-square-sum function. This is all that's needed, as it can easily be shown that any number will eventually get less than that. There's almost certainly some stuff I could do to be more parsimonious with memory, chief among them finding a copy of narray that has the .mod! method. (I may revisit this and use a combination of div!, mul! and sbt! to cut down on temporary arrays) However, this program as it stands very quickly checks much farther out than I would have thought necessary if there really were other happy bases out there to be found. #!/usr/bin/env ruby require 'narray' def dodigsum(base, initial) tmp = initial / (base ** NArray.to_na([[0],[1],[2]])) # I would use mod!, but my copy of narray doesn't have mod! tmp = tmp % base tmp.mul!(tmp) initial.fill!(0).add!(tmp.sum(1)) end def checkbase(base = 10) base = base.to_i checklimit = 2*(base-1)*(base-1) check = NArray.int(checklimit + 1).indgen! check_initial = check.dup while true do dodigsum(base,check) if check.eq(check_initial).count_true > 2 #Gobs of debugging info # lp = check.mul!(check.eq(check_initial)).mask(check.ge(2)).min # puts "#{base} has a loop on #{lp}" break end if check.le(1).count_true > checklimit puts "#{base} is a happy base" break end end end 2.upto(3000) { |b| begin checkbase(b) rescue Interrupt puts "Checking #{b}" checkbase(b) rescue Error => e puts "Bailing on #{b}" raise e end } __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]