Chris K
Chris K

Reputation: 5

Just learned about recursion, can't figure out how to make it work

I've written a program to take in a number, and print the number in english text. This is my second attempt, while trying to make it more condensed and repeat less.

The code works fine as long as the number is < 100 but over that, and I have issues. I tried removing the gets, and having a parameter on the method itself, but that moved the error from the line with the recursion, to line adding it's value to the variable total.

I think I'm at a point that my current skill isn't grasping. recursion still feels like dark magic to me.

def numberWords num
  #num = gets.chomp.to_i

  singles = ['one',     'two',       'three',    'four',     'five',
           'six',     'seven',     'eight',    'nine']
  tens = ['eleventy',     'twenty',    'thirty',   'forty',    'fifty',
           'sixty',   'seventy',   'eighty',   'ninety']
  teens = ['eleven',  'twelve',    'thirteen', 'fourteen', 'fifteen',
           'sixteen', 'seventeen', 'eighteen', 'nineteen']


  total = ""

  if num == 0
    puts "Zero"
  end

  current = num/1000
  if current > 0
    thousands = numberWords current
    total = total + thousands + "Thousands"
  end

  total = total + " "

  current = num / 100
  if current > 0
    hundreds = numberWords current
    total = total + hundreds + "Hundred"
  end

total = total + " "

  #TENS
  current = num/10
  if current > 1
    total = total + tens[current - 1]
  end

  total = total + " "
  #SINGLES

  num = num - (current*10)
  if num > 0
    total = total + singles[num - 1]
  end

    puts total

end

numberWords(2222)

Upvotes: 0

Views: 70

Answers (1)

mvw
mvw

Reputation: 5105

Try this version:

def number_words(num)
  singles = ['one',     'two',       'three',    'four',     'five',
           'six',     'seven',     'eight',    'nine']
  tens = ['eleventy',     'twenty',    'thirty',   'forty',    'fifty',
           'sixty',   'seventy',   'eighty',   'ninety']
  teens = ['eleven',  'twelve',    'thirteen', 'fourteen', 'fifteen',
           'sixteen', 'seventeen', 'eighteen', 'nineteen']

  if num == 0
    return "zero"
  elsif
    num >= 1000
    q, r = num.divmod(1000)
    return number_words(q) + " thousand" + (r > 0 ? " " + number_words(r) : "") 
  elsif num >= 100
    q, r = num.divmod(100)
    return number_words(q) + " hundred" + (r > 0 ? " " + number_words(r) : "")
  elsif num >= 20
    q, r = num.divmod(10)
    return tens[q - 1] + (r > 0 ? "-" + number_words(r) : "")
  elsif num >= 11
    r = num % 10
    return teens[r - 1]
  elsif num == 10
    return "ten"
  end
  return singles[num - 1]
end

I changed it from puts output to building a string.

Important is the ordering, so if you want to handle millions and billions put those clauses in the correct order.

q and r are short for quotient and remainder.

The arithmetical if (condition ? true-statement : false-statement) is used to surpress "Zero" strings, where they should not be.

The basic idea is to handle what one can handle in an if clause and pass the other work recursively to one self.

Here are some outputs:

0: zero
1: one
2: two
3: three
10: ten
11: eleven
12: twelve
13: thirteen
20: twenty
21: twenty-one
22: twenty-two
23: twenty-three
30: thirty
39: thirty-nine
99: ninety-nine
100: one hundred
101: one hundred one
123: one hundred twenty-three
221: two hundred twenty-one
990: nine hundred ninety
999: nine hundred ninety-nine
1000: one thousand
2222: two thousand two hundred twenty-two

Upvotes: 1

Related Questions