Here's my solution (130.50):
#!perl -lp071
s/te|lv/ q/g;s%(.*?)$&\w*%+($+)*1E0$/
%gi,--$/while
b__m__THoHuyzOnwThFofSisEiiqv=~/[(-^]*./g;$_-=eval;s/.(?=(...)+$)/$&,/g
__END__
This is what it does:
Transform the input into a perl expression that evaluates to the
correct number, evaluate it, and commafy the result.
And this is how it does it:
# Set $/ to "9", for later use. Won't have any effect on the input,
# since "9" never appears there.
#!perl -lp071
# Munge input. Makes numbers 10 and 12-19 more uniform.
s/te|lv/ q/g;
# Loop through the data string, setting $& to consecutive tokens in
# the data string. A token is /[A-Z]*./, slightly obfuscated for the
# tiebreaker.
while ("b__m__THoHuyzOnwThFofSisEiiqv"=~/[(-^]*./g) {
# Substitute all instances of the token in the input.
# Basically this accomplishes three different tasks:
# foo (billion|million|thousand|hundred) bar ->
# +(foo)*1E9 (or 1E6, 1E3, 1E2) bar
# barty foo ->
# +(bar)*1E1 foo (for 20,30,40,etc)
# one|two|three|..|eleven
# +()*1E0-[value of the token]
# Note the newline at the end. It's needed to get the precedence
# of the multiplications right.
s%(.*?)$&\w*%+($+)*1E0$/
%gi,
# And finally decrement $/ on each iteration
--$/
}
# Now we have an expression in $_. For example, "one hundred twelve"
# would produce something like this:
# +(+()*1E0-1)*1E02+()*1E0-3+()*1E0-10
# Negate the eval, since the literals in the expression are negative.
$_-=eval;
# And finally, a suboptimal commafy
s/.(?=(...)+$)/$&,/g
# -pl takes care of the rest
__END__
All in all, the code is just too cute for it's own good, and I'm
sort of suprised that it got me a fourth place. Brute force, man,
brute force.
--
Juho Snellman