Chris Pine "Learning Programming" Question

I’m still going through Chris P.'s book on Ruby programming and came
across the following exercise. To put it simply, I just don’t
understand how this code works.

def englishNumber number

We only want numbers from 0-100.

if number < 0
return ‘Please enter a number zero or greater.’
end
if number > 100
return ‘Please enter a number 100 or lesser.’
end

numString = ‘’ # This is the string we will return.

“left” is how much of the number we still have left to write out.

“write” is the part we are writing out right now.

write and left… get it? :slight_smile:

left = number
write = left/100 # How many hundreds left to write out?
left = left - write*100 # Subtract off those hundreds.

if write > 0
return ‘one hundred’
end

QUESTION 1: For example, if I choose 99 as my number, left = number, and
write = left/100, wouldn’t write = 99/100? In that case, why would
write > 0 return ‘one hundred’?

write = left/10 # How many tens left to write out?
left = left - write*10 # Subtract off those tens.

if write > 0
if write == 1 # Uh-oh…
# Since we can’t write “tenty-two” instead of “twelve”,
# we have to make a special exception for these.
if left == 0
numString = numString + ‘ten’
elsif left == 1
numString = numString + ‘eleven’
elsif left == 2
numString = numString + ‘twelve’
elsif left == 3
numString = numString + ‘thirteen’
elsif left == 4
numString = numString + ‘fourteen’
elsif left == 5
numString = numString + ‘fifteen’
elsif left == 6
numString = numString + ‘sixteen’
elsif left == 7
numString = numString + ‘seventeen’
elsif left == 8
numString = numString + ‘eighteen’
elsif left == 9
numString = numString + ‘nineteen’
end
# Since we took care of the digit in the ones place already,
# we have nothing left to write.
left = 0
elsif write == 2
numString = numString + ‘twenty’
elsif write == 3
numString = numString + ‘thirty’
elsif write == 4
numString = numString + ‘forty’
elsif write == 5
numString = numString + ‘fifty’
elsif write == 6
numString = numString + ‘sixty’
elsif write == 7
numString = numString + ‘seventy’
elsif write == 8
numString = numString + ‘eighty’
elsif write == 9
numString = numString + ‘ninety’
end

if left > 0
  numString = numString + '-'
end

end

write = left # How many ones left to write out?
left = 0 # Subtract off those ones.

if write > 0
if write == 1
numString = numString + ‘one’
elsif write == 2
numString = numString + ‘two’
elsif write == 3
numString = numString + ‘three’
elsif write == 4
numString = numString + ‘four’
elsif write == 5
numString = numString + ‘five’
elsif write == 6
numString = numString + ‘six’
elsif write == 7
numString = numString + ‘seven’
elsif write == 8
numString = numString + ‘eight’
elsif write == 9
numString = numString + ‘nine’
end
end

if numString == ‘’
# The only way “numString” could be empty is if
# “number” is 0.
return ‘zero’
end

If we got this far, then we had a number somewhere

in between 0 and 100, so we need to return “numString”.

numString
end

QUESTION 2: The second part of this code is just plain confusing me,
perhaps because I still can’t figure out the first part which it builds
upon.

Any clarification & help would be greatly appreciated.

Am 11.06.2012 17:18, schrieb Michael S.:

QUESTION 1: For example, if I choose 99 as my number, left = number, and
write = left/100, wouldn’t write = 99/100? In that case, why would
write > 0 return ‘one hundred’?

Maybe this helps:

irb(main):001:0> 99/100
=> 0
irb(main):002:0> 250/100
=> 2
irb(main):003:0> 99.0/100
=> 0.99
irb(main):004:0> 250/100.0
=> 2.5

In the first two cases you are dealing with integer division.

For left = 99, write is equal to zero and “one hundred”
is not returned.

Regards,
Marcus

“QUESTION 2: The second part of this code is just plain confusing me,
perhaps because I still can’t figure out the first part which it builds
upon.”

The code example is not very elegant.

Keep this in mind when reading other people’s code - their style may not
be beautiful.

Almost always, when you see lots of if/else, you may be better off using
case/when instead:

if write > 0
if write == 1
numString = numString + ‘one’
elsif write == 2
numString = numString + ‘two’
end
end

Would be like this in case/when:

case write
when 1
numString += ‘one’
when 2
numString += ‘two’
end if write > 0 # though this if condition is not needed. Actually, I
argue that the if write > 0 in the original example is useless too. So
ebst omit the “if write > 0” also here.

Am 11.06.2012 18:16, schrieb Marc H.:

The code example is not very elegant.

Keep this in mind when reading other people’s code - their style may not
be beautiful.

Almost always, when you see lots of if/else, you may be better off using
case/when instead:

The example is from a (very nice) book for programming novices
and case/when has not been introduced at that point…

Very interesting about the print version of this book is that
Chris P. includes solutions for the exercises in two versions:
first a solution that corresponds to the current learning level
of the reader and then a more realistic and more elegant version.

Regards,
Marcus

Hi,

Michael S. wrote in post #1064054:

QUESTION 1: For example, if I choose 99 as my number, left = number, and
write = left/100, wouldn’t write = 99/100? In that case, why would
write > 0 return ‘one hundred’?

When you divide two integers in Ruby, you get an integer division rather
than a “normal” division. You probably remember doing long division in
elementary school. For example, 7 : 3 is 2 with a remainder of 1. This
is exactly how integer division works: 7/3 is 2. And 99/100 is 0 (with a
remainder of 99).

So integer division always yields an integer rather than a float
(fractional number). If you want to do “normal” division, either the
dividend or the divisor has to be a float.

Michael S. wrote in post #1064054:

QUESTION 2: The second part of this code is just plain confusing me,
perhaps because I still can’t figure out the first part which it builds
upon.

The method basically calculates the hundreds, tens and ones of the
number and builds the name from it.

For example, the number 53 consists of 5 tens and 3 ones. The 5 tens
mean that the name begins with “fifty”. And the 3 ones mean that the
name ends with “three”.