#!/usr/bin/ruby
#
#
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!";