[SOLUTION] English Numerals (#25)

This is my first submitted solution, and I hope I've figured the time
zones right and it's actually been 48 hours. Also, I haven't been
coding Ruby (or at all) for all that long, so I hope my code is
decent.
It was a fun quiz. I had to choose some rules that don't quite match
up with natural speech in my dialect, since I was unable to pin down
systematically what the rules for my dialect are. (I say "nine hundred
one", but "two hundred and one", for instance. It's just odd.)
Anyway, without further ado:

class Integer

  def teen
    case self
    when 0: "ten"
    when 1: "eleven"
    when 2: "twelve"
    else in_compound + "teen"
    end
  end

  def ten
    case self
    when 1: "ten"
    when 2: "twenty"
    else in_compound + "ty"
    end
  end

  def in_compound
    case self
    when 3: "thir"
    when 5: "fif"
    when 8: "eigh"
    else to_en
    end
  end

  def to_en(ands=true)
    small_nums = [""] + %w[one two three four five six seven eight nine]
    if self < 10: small_nums[self]
    elsif self < 20: (self % 10).teen
    elsif self < 100:
      result = (self/10).ten
      result += "-" if (self % 10) != 0
      result += (self % 10).to_en
      return result
    elsif self < 1000
      if self%100 != 0 and ands
        (self/100).to_en(ands)+" hundred and "+(self%100).to_en(ands)
      else ((self/100).to_en(ands)+
        " hundred "+(self%100).to_en(ands)).chomp(" ")
      end
    else
      front,back = case (self.to_s.length) % 3
        when 0: [0..2,3..-1].map{|i| self.to_s[i]}.map{|i| i.to_i}
        when 2: [0..1,2..-1].map{|i| self.to_s[i]}.map{|i| i.to_i}
        when 1: [0..0,1..-1].map{|i| self.to_s[i]}.map{|i| i.to_i}
        end
      degree = [""] + %w[thousand million billion trillion quadrillion
      quintillion sextillion septillion octillion nonillion decillion
      undecillion duodecillion tredecillion quattuordecillion
      quindecillion sexdecillion septdecillion novemdecillion
      vigintillion unvigintillion duovigintillion trevigintillion
      quattuorvigintillion quinvigintillion sexvigintillion
      septvigintillion octovigintillion novemvigintillion trigintillion
      untregintillion duotrigintillion googol]
      result = front.to_en(false) + " " + degree[(self.to_s.length-1)/3]
      result += if back > 99: ", "
                elsif back > 0: ands ? " and " : " "
                else ""
                end
      result += back.to_en(ands)
      return result.chomp(" ")
    end
  end

end

# I'm not really happy about re-defining degree, but I couldn't figure
# out where to put it so it would be available both places I use it.
degree = [""] + %w[thousand million billion trillion quadrillion
quintillion sextillion septillion octillion nonillion decillion
undecillion duodecillion tredecillion quattuordecillion
quindecillion sexdecillion septdecillion novemdecillion
vigintillion unvigintillion duovigintillion trevigintillion
quattuorvigintillion quinvigintillion sexvigintillion
septvigintillion octovigintillion novemvigintillion trigintillion
untregintillion duotrigintillion googol]
medium_nums = (1..999).map{|i| i.to_en}
print "The alphabetically first number (1-999) is: "
puts first = medium_nums.min.dup
first_degree = degree[1..-1].min
first << " " + first_degree
puts "The first non-empty degree word (10**3-10**100) is: "+first_degree
next_first = (["and"] + medium_nums).min
first << " " + next_first
puts "The next first word (numbers 1-999 + 'and') is: "+next_first
if next_first == "and"
  puts "Since the last word was 'and', we need an odd number in 1..99."
  odd_nums = []
  (0..98).step(2){|i| odd_nums << medium_nums[i]}
  first_odd = odd_nums.min
  puts "The first one is: "+first_odd
  first << " " + first_odd
else # This will never happen; I can't bring myself to write it.
end
puts "Our first odd number, then, is #{first}."

This is my first submitted solution, and I hope I've figured the time
zones right and it's actually been 48 hours.

Thanks for taking the time to submit. Welcome. (And yes, you were on time)

# I'm not really happy about re-defining degree, but I couldn't figure
# out where to put it so it would be available both places I use it.

You can just move the definition up to towards the top of the file, so it appears before the method that uses it. It when then be available in both places.

Hope that helps.

James Edward Gray II

···

On Mar 27, 2005, at 7:01 PM, Eliah Hecht wrote:

"James Edward Gray II" <james@grayproductions.net> suggested:

# I'm not really happy about re-defining degree, but I couldn't figure
# out where to put it so it would be available both places I use it.

You can just move the definition up to towards the top of the file, so it
appears before the method that uses it. It when then be available in both
places.

That won't work for the method Integer#to_en. You could make it a constant
(starting with a capital letter, either in Object implicitly or in Integer)
or a global (with a $ in front, these are not usually recommended).

class Integer

  DEGREE = [""] + %w[thousand million billion trillion quadrillion
    quintillion sextillion septillion octillion nonillion decillion
    undecillion duodecillion tredecillion quattuordecillion
    quindecillion sexdecillion septdecillion novemdecillion
    vigintillion unvigintillion duovigintillion trevigintillion
    quattuorvigintillion quinvigintillion sexvigintillion
    septvigintillion octovigintillion novemvigintillion trigintillion
    untregintillion duotrigintillion googol]

  def teen
....
      result = front.to_en(false) + " " + DEGREE[(self.to_s.length-1)/3]
....
first_degree = Integer::DEGREE[1..-1].min
....

Cheers,
Dave

···

On Mar 27, 2005, at 7:01 PM, Eliah Hecht wrote:

Dave Burt wrote:

"James Edward Gray II" <james@grayproductions.net> suggested:

# I'm not really happy about re-defining degree, but I couldn't figure
# out where to put it so it would be available both places I use it.
     

You can just move the definition up to towards the top of the file, so it appears before the method that uses it. It when then be available in both places.
   
That won't work for the method Integer#to_en. You could make it a constant (starting with a capital letter, either in Object implicitly or in Integer) or a global (with a $ in front, these are not usually recommended).

class Integer

DEGREE = [""] + %w[thousand million billion trillion quadrillion
   quintillion sextillion septillion octillion nonillion decillion
   undecillion duodecillion tredecillion quattuordecillion
   quindecillion sexdecillion septdecillion novemdecillion
   vigintillion unvigintillion duovigintillion trevigintillion
   quattuorvigintillion quinvigintillion sexvigintillion
   septvigintillion octovigintillion novemvigintillion trigintillion
   untregintillion duotrigintillion googol]

def teen
....
     result = front.to_en(false) + " " + DEGREE[(self.to_s.length-1)/3]
....
first_degree = Integer::DEGREE[1..-1].min
....

Cheers,
Dave

what about octodecillion ?

···

On Mar 27, 2005, at 7:01 PM, Eliah Hecht wrote:

--
David N. Springer Phone: (715) 830-1200 Ext. 126
Silicon Logic Engineering, Inc. FAX: (715) 830-1887
7 South Dewey Street, Suite 1 Mailto:springer@siliconlogic.com
Eau Claire, WI 54701 Web: http://www.siliconlogic.com

Guess I must have missed that one. Doesn't change the
which-odd-number-comes-first result, though.

···

On Tue, 29 Mar 2005 01:23:49 +0900, David N. Springer <springer@siliconlogic.com> wrote:

what about octodecillion ?