Note: I'm afraid I could not bring myself to code up some random 
ill-defined method of expressing numbers in English, so I did it the way 
I was taught in school, using hypens and absolutely no "ands" or commas. 
  I think I've got Strunk & White on my side.  Regardless, I'll be 
somewhat surprised if my answer comes out very different from others.

Brute force was not a very practical option when looking for the answer, 
so I assumed it would be OK to do a little bit of analysis and simplify 
the problem.  If my analysis was wrong, then I'll probably lose badly on 
this one.  :)  There may also be a much more elegant way to express all 
of this, but I thought I would just give you a short brain dump here.

Every number from 1 to 10**10 can be expressed in English as a 
concatenation of one or more independent phrases.  Each phrase expresses 
the value of a triplet of numerals from the original number.  For 
example, 56_106_021 uses three phrases: "fifty-six million" for the 
millions triplet (56), "one hundred six thousand" for the thousands 
triplet (106), and "twenty-one" for the ones triplet (021).  I don't 
allow "twelve hundred" for 1200, but I think it would only complicate 
the logic slightly to handle this.

I proceed to find the lowest possible phrase for each of the four 
triplets in the range of interest.  It must be possible to express the 
lowest number name using a subset of the lowest possible phrases for 
each triplet.  And since the desired number must be odd, valid subsets 
will all end with the ones triplet phrase.

The ones triplet range has only 500 phrases: the odd numbers from 1 to 
999.  The thousands triplet has 1000 phrases: the multiples of 1000 from 
1000 to 999_999.  Likewise, the millions triplet has 1000 phrases.  The 
billions triplet has only ten phrases because we stop caring after 
10_000_000_000 (instead of going to 999_999_999_999).  Finding the four 
lowest phrases for each triplet requires examining only 2510 numbers. 
There are only eight combinations of the resulting four phrases that 
represent an odd number.

The result: "eight billion eight hundred eight million eight hundred 
eight thousand eight hundred eighty-five".



#!/usr/bin/ruby

class Integer

   Ones = %w[ zero one two three four five six seven eight nine ]
   Teen = %w[ ten eleven twelve thirteen fourteen fifteen
              sixteen seventeen eighteen nineteen ]
   Tens = %w[ zero ten twenty thirty forty fifty
              sixty seventy eighty ninety ]
   Mega = %w[ none thousand million billion ]

   def to_english
     places = to_s.split(//).collect {|s| s.to_i}.reverse
     name = []
     ((places.length + 2) / 3).times do |p|
       strings = Integer.trio(places[p * 3, 3])
       name.push(Mega[p]) if strings.length > 0 and p > 0
       name += strings
     end
     name.push(Ones[0]) unless name.length > 0
     name.reverse.join(" ")
   end

   private

   def Integer.trio(places)
     strings = []
     if places[1] == 1
       strings.push(Teen[places[0]])
     elsif places[1] and places[1] > 0
       strings.push(places[0] == 0 ? Tens[places[1]] :
                    "#{Tens[places[1]]}-#{Ones[places[0]]}")
     elsif places[0] > 0
       strings.push(Ones[places[0]])
     end
     if places[2] and places[2] > 0
       strings.push("hundred", Ones[places[2]])
     end
     strings
   end

end

# If there are command-line args, just print out English names.
if ARGV.length > 0
   ARGV.each {|arg| puts arg.to_i.to_english}
   exit 0
end

# Return the name of the number in the specified range that is the
# lowest lexically.
def minimum_english(start, stop, incr)
   min_name = start.to_english
   start.step(stop, incr) do |i|
     name = i.to_english
     min_name = name if min_name > name
   end
   min_name
end

# Find the lowest phrase for each 3-digit cluster of place-values.
# The lowest overall string must be composed of elements from this list.
components =
   [ minimum_english(10**9, 10**10, 10**9),
     minimum_english(10**6, 10**9 - 1, 10**6),
     minimum_english(10**3, 10**6 - 1, 10**3),
     minimum_english(10**0, 10**3 - 1, 2) ]

$result = components[-1]
def search_combinations(list, selected = [])
   if elem = (list = list.dup).shift
     if list.empty?
       # Always include the final element from list in the selection.
       string = selected.dup.push(elem).join(" ")
       $result = string if $result > string
     else
       search_combinations(list, selected)
       search_combinations(list, selected.dup.push(elem))
     end
   end
   $result
end

puts search_combinations(components)



-- 
Glenn Parker | glenn.parker-AT-comcast.net | <http://www.tetrafoil.com/>