#!/usr/bin/ruby # ## http://rosettacode.org/wiki/Names_to_numbers # func names_to_number(str) { static nums = Hash.new( zero => 0, one => 1, two => 2, three => 3, four => 4, five => 5, six => 6, seven => 7, eight => 8, nine => 9, ten => 10, eleven => 11, twelve => 12, thirteen => 13, fourteen => 14, fifteen => 15, sixteen => 16, seventeen => 17, eighteen => 18, nineteen => 19, twenty => 20, thirty => 30, forty => 40, fifty => 50, sixty => 60, seventy => 70, eighty => 80, ninety => 90, hundred => 1e2, thousand => 1e3, million => 1e6, billion => 1e9, trillion => 1e12, quadrillion => 1e15, quintillion => 1e18, ); # Groupings for thousands, millions, ..., quintillions static groups = /\d{4}|\d{7}|\d{10}|\d{13}|\d{16}|\d{19}/; # Numeral static num = /\d+/; str.trim!; # remove leading and trailing whitespace str.gsub!('-', ' '); # convert hyphens to spaces str.words!.join!(' '); # remove duplicate whitespace, convert ws to space str.lc!; # convert to lower case # tokenize sentence boundaries str.gsub!(/([.?!]) /, {|a| ' ' + a + "\n"}); str.gsub!(/([.?!])$/, {|a| ' ' + a + "\n"}); # tokenize other punctuation and symbols str.gsub!(/\$(.)/, {|a| "$ #{a}" }); # prefix str.gsub!(/(.)([;:%'',])/, {|a,b| "#{a} #{b}"}); # suffix nums.each { |key, value| str.gsub!(Regex.new('\b' + key + '\b'), value) }; str.gsub!(/(\d) , (\d)/, {|a,b| a + ' ' + b}); str.gsub!(/(\d) and (\d)/, {|a,b| a + ' ' + b}); static regex = [ Regex.new('\b(\d) 100 (\d\d) (\d) (' + groups + ')\b'), Regex.new('\b(\d) 100 (\d\d) (' + groups + ')\b'), Regex.new('\b(\d) 100 (\d) (' + groups + ')\b'), Regex.new('\b(\d) 100 (' + groups + ')\b'), Regex.new('\b100 (\d\d) (\d) (' + groups + ')\b'), Regex.new('\b100 (\d\d) (' + groups + ')\b'), Regex.new('\b100 (\d) (' + groups + ')\b'), Regex.new('\b100 (' + groups + ')\b'), Regex.new('\b(\d\d) (\d) (' + groups + ')\b'), Regex.new('\b(\d{1,2}) (' + groups + ')\b'), Regex.new('((?:' + num + ' )*' + num + ')'), ]; str.gsub!(regex[0], {|a,b,c,d| (a.to_i*100 + b.to_i + c.to_i) * d.to_i }); str.gsub!(regex[1], {|a,b,c| (a.to_i*100 + b.to_i) * c.to_i }); str.gsub!(regex[2], {|a,b,c| (a.to_i*100 + b.to_i) * c.to_i }); str.gsub!(regex[3], {|a,b| (a.to_i * b.to_i * 100) }); str.gsub!(regex[4], {|a,b,c| (100 + a.to_i + b.to_i) * c.to_i }); str.gsub!(regex[5], {|a,b| (100 + a.to_i) * b.to_i }); str.gsub!(regex[6], {|a,b| (100 + a.to_i) * b.to_i }); str.gsub!(regex[7], {|a| (a.to_i * 100) }); str.gsub!(regex[8], {|a,b,c| (a.to_i + b.to_i) * c.to_i }); str.gsub!(regex[9], {|a,b| (a.to_i * b.to_i) }); str.gsub!(/\b(\d\d) (\d) 100\b/, {|a,b| (a.to_i + b.to_i) * 100}); str.gsub!(/\b(\d{1,2}) 100\b/, {|a| (a.to_i * 100) }); str.gsub!(/\b(\d{2}) (\d{2})\b/, {|a,b| (a.to_i * 100) + b.to_i}); str.gsub!(regex[10], {|a| a.split(' ').map{.to_i}.sum }); } var tests = Hash.new( "Seventy-two dollars" => "72 dollars", "Seventy two dollars" => "72 dollars", "One Hundred and One Dalmatians" => "101 dalmatians", "A Hundred and One Dalmatians" => "a 101 dalmatians" "One Hundred One Dalmatians" => "101 dalmatians", "Hundred and One Dalmatians" => "101 dalmatians" "One Thousand and One Nights" => "1001 nights", "Two Thousand and One: A Space Odyssey" => "2001 : a space odyssey", "Twenty Thirteen" => "2013", "Nineteen Eighty-Four" => "1984", "four billion, two hundred ninety-four million, nine hundred sixty-seven thousand, two hundred ninety five" => "4294967295", "Nine quadrillion, seven trillion, one hundred ninety-nine billion, two hundred fifty-four million, seven hundred forty thousand, nine hundred ninety two" => "9007199254740992", "Nine Hundred Ninety-Nine" => "999", "One Thousand One Hundred Eleven" => "1111", "Eleven Hundred Eleven" => "1111", "Eight Thousand Eight Hundred Eighty-Eight" => "8888", "Eighty-Eight Hundred Eighty-Eight" => "8888", "Seven Million Seven Hundred Seventy-Seven Thousand Seven Hundred Seventy-Seven" => "7777777", "Ninety-Nine Trillion Nine Hundred Ninety-Nine Billion Nine Hundred Ninety-Nine Million Nine Hundred Ninety-Nine Thousand Nine Hundred Ninety-Nine" => "99999999999999", "ninety-nine" => "99", "three hundred" => "300", "three hundred and ten" => "310", "one thousand, five hundred and one" => "1501", "twelve thousand, six hundred and nine" => "12609", "five hundred and twelve thousand, six hundred and nine" => "512609", "forty-three million, one hundred and twelve thousand, six hundred and nine" => "43112609", "two billion, one hundred" => "2000000100", "zero" => "0", "eight" => "8", "one hundred" => "100", "one hundred twenty three" => "123", "one thousand one" => "1001", "ninety nine thousand nine hundred ninety nine" => "99999", "one hundred thousand" => "100000", "nine billion one hundred twenty three million four hundred fifty six thousand seven hundred eighty nine" => "9123456789", "one hundred eleven billion one hundred eleven" => "111000000111", ); tests.each { |k,v| var conv = names_to_number(k); conv == v || die "#{conv.dump} != #{v.dump} (from: #{k.dump})\n"; } say "** Test passed!";