A
Adam Shelly
Over on rec.puzzles, Eric A. proposed a variant in which the letters of a
sentence are grouped, then "counted aloud", omitting the "s"s for the plural
form. Thus, seeding the sequence with "LOOK AND SAY", we get:
0. LOOK AND SAY
1. TWO A ONE D ONE K ONE L ONE N TWO O ONE S ONE Y
2. ONE A ONE D SIX E ONE K ONE L SEVEN N NINE O ONE S TWO T TWO W ONE Y
3. ONE A ONE D TEN E TWO I ONE K ONE L TEN N NINE O THREE S THREE T ONE V
THREE W ONE X ONE Y
and so on. (Note the difference between this and the L&S sequence--the letters
are counted rather than read in order). Eric wants to know when the sequence
enters a cycle, and how long that cycle is. Well?
My solution follows. I rolled my own integer to word routine. The
shortest cycle I found starts with letter 'Y':
C:\code\quiz>looksay2.rb y
Y
After 50 iterations, repeated pattern 48:
SIXTEEN E SIX F TWO G THREE H FIVE I TWO L NINE N NINE O SIX R FOUR S
FOUR T FIVE U FIVE V TWO W TWO X ONE Y
Loop length = 2
-Adam
---looksay2.rb---
class Integer
GROUPS =%W{ THOUSAND MILLION BILLION TRILLION QUADRILLION
QUINTILLION SEXILLION SEPTILLION OCTILLION NONILLION}.unshift nil
DIGITS = %W{ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE}.unshift nil
TEENS = %W{TEN ELEVEN TWELVE THIRTEEN FOURTEEN FIFTEEN SIXTEEN
SEVENTEEN EIGHTEEN NINETEEN}
TENS = %W{TEN TWENTY THIRTY FOURTY FIFTY SIXTY SEVENTY EIGHTY
NINETY}.unshift nil
def to_w
return @word if @word
p "making word for #{self}" if $DEBUG
digits = to_s.split('').reverse.map{|c|c.to_i}
return @word = "DECILLIONS" if digits.size > 33
phrase,group = [],0
until digits.empty?
phrase << GROUPS[group]
d = digits.slice!(0,3)
d[1]||=0
if d[1] == 1
phrase << TEENS[d[0]]
else
phrase << DIGITS[d[0]] << TENS[d[1]]
end
phrase << "HUNDRED" << DIGITS[d[2]] if (d[2] and d[2]!=0)
phrase.pop if (phrase.compact! and phrase[-1] == GROUPS[group])
group+=1
end
@word = phrase.reverse.join ' '
end
end
if __FILE__ == $0
phrase = ARGV[0]||"LOOK AND SAY"
print = ARGV[1] == 'p'
results=[];
h=Hash.new(0)
i=0
str = phrase.upcase
puts str
until (m = results.index str)
print "#{i}: ", str, "\n" if print
results<< str
str.split('').each{|c| h[c]+=1}
h.delete(' ')
str = h.to_a.sort.map{|c,n| [n.to_w,c] }.join " "
h.clear
i+=1
end
puts "\nAfter #{i} iterations, repeated pattern #{m}: "
puts str
puts "Loop length = #{i-m}"
end