------ art_15548_16168035.1152489133366
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
Hello
First post here, by the way. Greetings to all:) New to ruby, love it, slaps
on backs all round.
While I haven't solved the pangram problem, I did find what appears to be a
bug in Numeric.divmod on large numbers, as can be seen when using
Bignum.modulo:
irb(main):017:0> 1e22 % 1e21
0.0
irb(main):018:0> 1e23 % 1e22
9.99999999999999e+021
whoops!
Also, I had a bit of fun hacking away at the plumbing required for the
quiz. My solution to generating spelt numbers is, while neither fast nor
optimally pretty I'm sure, novel and rather flexible.
I wrote a little RangeMap class which will map a continuous set of variable
ranges to values. Then I used it to map ranges to spelling rules (in the
form of proc objects). The rules can recursively call eachother using
further lookups on the RangeMap. This system allows easy implentation of
exceptions (such as "twelve hundred" etc), and translation into different
languages or variations of english. Also it could be used to solve the
pangrams problem directly by configuring the rules to tally the characters
rather than generate the actual strings.
class RangeMap
def initialize
@values ash.new
@ranges ]
end
#Insert your range by specifying the lower bound.
#RangeMap generates the upper value based on what's
#already in the map. While not ideal, it makes it
#a lot easier to keep the set continuous.
def insert range_first, value
@values[range_first] alue
lowers values.keys.sort
uppers values.keys.sort
lowers.pop
uppers.shift
@ranges ]
for i in 0...lowers.size do
@ranges << (lowers[i]...uppers[i])
end
end
def find n
if n < @ranges.first.first || n > @ranges.last.last
raise "Number outside ranges: #{@ranges.first.first}-#{@
ranges.last.last}"
end
range_first inary_search(n, 0, @ranges.size)
@values[range_first]
end
protected
def binary_search n, a, b
middle a + b) / 2
range ranges[middle]
if n < range.first
binary_search(n, a, middle)
elsif n > ange.last
binary_search(n, middle, b)
else
range.first
end
end
end
class Integer
@@rules angeMap.new
[{ :first 0, :name "zero" }, { :first 1, :name "one" },
{ :first 2, :name "two" }, { :first 3, :name "three" },
{ :first 4, :name "four" }, { :first 5, :name "five" },
{ :first 6, :name "six" }, { :first 7, :name "seven" },
{ :first 8, :name "eight" }, { :first 9, :name "nine" },
{ :first 10, :name "ten" }, { :first 11, :name "eleven" },
{ :first 12, :name "twelve" }, { :first 13, :name "thirteen"
},
{ :first 14, :name "fourteen" }, { :first 15, :name "fifteen"
},
{ :first 16, :name "sixteen" }, { :first 17, :name "seventeen"
},
{ :first 18, :name "eighteen" },
{ :first 19, :name "nineteen" }].each do |single|
name ingle[:name].freeze
@@rules.insert(single[:first], lambda {|n| name})
end
[{ :first 20, :name "twenty" },
{ :first 30, :name "thirty" },
{ :first 40, :name "forty" },
{ :first 50, :name "fifty" },
{ :first 60, :name "sixty" },
{ :first 70, :name "seventy" },
{ :first 80, :name "eighty" },
{ :first 90, :name "ninety" }].each do |ten|
divisor en[:first]
name en[:name].freeze
@@rules.insert(divisor, lambda do |n|
spelt ame.dup
remainder % divisor
spelt << "-" + execute_rule(remainder) if remainder !
spelt
end)
end
[{ :first 1E2.to_i, :name "hundred" },
{ :first 1E3.to_i, :name "thousand" },
{ :first 1E6.to_i, :name "million" },
{ :first 1E9.to_i, :name "billion" },
{ :first 1E12.to_i, :name "trillion" },
{ :first 1E15.to_i, :name "quadrillion" },
{ :first 1E18.to_i, :name "quintillion" },
{ :first 1E21.to_i, :name "sextillion" },
{ :first 1E24.to_i, :name "septillion" },
{ :first 1E27.to_i, :name "octillion" },
{ :first 1E30.to_i, :name "nonillion" },
{ :first 1E33.to_i, :name "decillion" },
{ :first 1E36.to_i, :name "undecillion" },
{ :first 1E39.to_i, :name "duodecillion" },
{ :first 1E42.to_i, :name "tredecillion" },
{ :first 1E45.to_i, :name "quattuordecillion" },
{ :first 1E48.to_i, :name "quindecillion" },
{ :first 1E51.to_i, :name "sexdecillion" },
{ :first 1E54.to_i, :name "septendecillion" },
{ :first 1E57.to_i, :name "octodecillion" },
{ :first 1E60.to_i, :name "novemdecillion" },
{ :first 1E63.to_i, :name "vigintillion" }].each do |big|
divisor ig[:first]
name " + big[:name].freeze
@@rules.insert(divisor, lambda do |n|
spelt xecute_rule(n/divisor) + name
remainder % divisor
if (remainder > 0)
if remainder < 100
spelt << " and "
else
spelt << ", "
end
spelt << execute_rule(remainder)
end
spelt
end)
end
def self.execute_rule n
@@rules.find(n).call(n)
end
def to_english
self.class.execute_rule(self)
end
end
puts 123456789.to_english
On 7/7/06, Ruby Quiz <james / grayproductions.net> 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 Darren Kirby
>
> One thing that interests me are word puzzles and language oddities. One
> such
> example is the self-documenting panagram. If a panagram is a sentence that
> uses
> every letter in the alphabet, then a self-documenting panagram is a
> sentence
> that enumerates its own letter count. Simple enough, but what if we state
> that
> the letter count must be spelled ie: 'twenty-seven' instead of '27'. Now
> we
> have a challenge.
>
> A while back I wrote a script in Python that finds these sentences. Today
> I
> rewrote it in Ruby and it found me this sentence:
>
> Darren's ruby panagram program found this sentence which contains
> exactly
> nine 'a's, two 'b's, five 'c's, four 'd's, thirty-five 'e's, nine
> 'f's,
> three 'g's, nine 'h's, sixteen 'i's, one 'j', one 'k', two 'l's,
> three 'm's,
> twenty-seven 'n's, fourteen 'o's, three 'p's, one 'q', fifteen
> 'r's,
> thirty-four 's's, twenty-two 't's, six 'u's, six 'v's, seven 'w's,
> six 'x's,
> seven 'y's, and one 'z'.
>
> My script does have its problems, and I would love to see what kind of
> code the
> Ruby experts could come up with to find self-documenting panagrams.
>
> There is a lot more info on self-documenting panagrams at this address:
>
> http://www.cs.indiana.edu/~tanaka/GEB/pangram.txt
>
>
------ art_15548_16168035.1152489133366--