> by Martin DeMello
I decided not to miss all the fun, and implemented my own spelling not
lookong in prior quuiz solutions. BTW, the full-fledged spelling is not
necessary, as the biggest number to spell for this quiz I found was 37
(bigger input texts will require more), but - fun is fun. Interesting facts
(hope I did not make any typos, they would screw up all statistics):
Worst (or one of) word in unix dictionary is 'SYMPATHIZED' - 303 hops before
entering loop of 885 iterations;
Best - surprise! - 'ERROR' - only 7+5
################## spelling part ##########################
TOTEENS=[nil, 'one two three four five six seven eight nine ten eleven
twelve thirteen fourteen fifteen sixteen seventeen eighteen
nineteen'.split].flatten
TENS=[nil, nil, 'twenty thirty forty fifty sixty seventy eighty
ninety'.split].flatten
EXPS_US=[nil,'thousand million billion trillion quadrillion quintillion
sextillion septillion octillion nonillion decillion undecillion duodecillion
tredecillion quattuordecillion quindecillion sexdecillion septendecillion
octodecillion novemdecillion vigintillion'.split].flatten
EXPS_NON_US=[nil,'million billion trillion quadrillion quintillion
sextillion septillion octillion nonillion decillion'.split].flatten
class Integer
def spell(us=true)
return 'zero' if self==0
self<0 ? 'minus '+(-self).spell_unsign(us) : self.spell_unsign(us)
end
def spell_unsign(us=true)
size=us ? 3 : 6
res=[]
self.to_s.reverse.scan(%r"\d{1,#{size}}").each_with_index {|s, i|
n=s.reverse.to_i
if n>0
sp=us ? n.spell_small : n.spell(true)
sp.gsub!('thousand','milliard') if i==1 && !us
sc=us ? EXPS_US[i] : EXPS_NON_US[i]
res << sc if sc
res << sp
end
}
res.compact.reverse.join(' ')
end
def spell_small
res=[]
hundred=TOTEENS[self/100]
res << hundred << 'hundred' if hundred
res << TENS[self%100/10] << (self<20 ? TOTEENS[self%100] :
TOTEENS[self%10])
res.compact.join(' ')
end
end
################## actial quiz part ##########################
def count_and_say str
h=str.split(//).inject(Hash.new(0)){|h,c|h[c]+=1; h}
h.delete(' ')
res=''
h.keys.sort.each {|k|
res << ' ' unless res.empty?
res << h[k].spell << ' ' << k
}
res
end
it=start=0
hres={(orig=last=ARGV[0].downcase.delete("^a-z"))=>it}
while true
puts now=count_and_say(last)
it+=1
key=now.delete(' ') # slight optimization, gives ~10% on 'sympathized'
break if start=hres[key]
hres[key],last=it,key
end
puts "#{start} + #{it-start}"