CIT 590 Assignment 3: Number Namer
Fall 2015, David Matuszek

# Purpose of this assignment

• To give you more practice with integer arithmetic and string manipulation

# General idea of the assignment

In this assignment you will repeatedly read in a line from the keyboard, change any numbers found into words, and print out the resultant line. For example, if the input is
`Today is Wednesday, September 9, 2015.`
you would print out
`Today is Wednesday, September nine, two thousand fifteen.`

# Details

Write and unit test the following methods, along with any others you may need:
`def name_of_digit(n)`
Takes an integer `n `in the range `0` to `9` and returns a lowercase string representation of that digit.
`def name_of_tens(n)`
Takes an integer `n `in the range `1` to `9` and returns a lowercase string representation of ten times that number. That is, it returns one of the strings `'ten'`, `'twenty'`, ..., `'ninety'`.
`def name_of_teens(n)`
Takes an integer `n `in the range `10` to `19` and returns a lowercase string representation of that number. That is, it returns one of the strings `'ten'`, `'eleven'`, ..., `'nineteen'`.
`def name_of_integer(n)`
Takes an integer `n `in the range `0` to `999999999` and returns a lowercase string representation of that number. That is, it returns one of the strings `'zero'`, `'one'`, ..., ```'nine hundred ninety nine million nine hundred ninety nine thousand nine hundred ninety nine'```. This method should use the preceding methods. The string should neither begin nor end with a blank. The string should not contain the word "and", which is used only when there is both an integer and a fractional part.
`def name_of_fraction(tuple)`
Takes a pair (2-tuple) of integers, where the tuple ```(n, d) ```represents the fraction n/d, and returns a string representation of that fraction. The first integer should be less than the second, and the second should be one of the numbers `10`, `100`, or `1000`, representing `tenths`, `hundredths`, and `thousandths`, respectively. For example, `name_of_fraction((0, 100)) `should return `'zero hundredths'`, and ```name_of_fraction((70, 1000)) ```should return `'seventy thousandths'`.
Special cases:
• `name_of_fraction((1, 10)) `should return ```'one tenth'```.
• `name_of_fraction((1, 100)) `should return ```'one one hundredth'```.
• `name_of_fraction((1, 1000)) `should return ```'one one thousandth'```.
`def name_of_decimal(n, tuple)`
Takes an integer `n`, representing the integral part of a number, and a pair `tuple`, representing the fractional part of a number. It converts these two parts into strings, and conjoins them with the word `and` in between. For example, `name_of_decimal(98, (7, 10))` should return `'ninety eight and seven tenths'`.
Special cases: If either part is zero, omit that part, along with the word `and`. If both parts are zero, just return `'zero'`.
`def name_in_dollars(dollars, cents)`
Takes two integers, `dollars` and `cents`, and produces a string representing that amount, including the word dollars and (possibly) the words `and` and `cents`. The value of `cents` should be less than `100`. For example, `name_in_dollars(12, 7)` should return the string `'twelve dollars and seven cents'`.
Special cases:
• If `dollars` is `0`, return only the cents part. Example: ```name_in_dollars(0, 7)````'seven cents'`.``` ```
• If `dollars` is `1`, use the word `dollar` instead of `dollars`. Example: `name_in_dollars(1, 0)````'one dollar'```.
• If `cents` is `0`, return only the dollars part, not the `and...cents` part.
• If `cents` is `1`, use the word `cent` instead of `cents`.
• If both `dollars` and `cents` are zero, return `'zero dollars'.`
`def name_of_number(str) `
This is the "master" routine, called from `main` to do its magic, and it takes a string as its argument. The string must contain at least one digit, may have a dollar sign as its first character, and may contain a decimal point. This function will examine the string and decide which of the other functions to call to do its work.
`def main()`
Ask the user to type in sentences. For each line that is read in, the function prints out the corresponding sentence with numbers replaced by words. Spacing and punctuation should be preserved. Quits the program (by reaching the end of the `main` method) when the user enters a blank line. This is the only function that does input/output, and is the only function that does not require a unit test.

Hint: The first three of the above methods will be shorter and simpler if you use a dictionary, with integer keys and string values.

Hint: If `n` is a positive integer, then ```n % 10``` is the rightmost digit of that integer, and `n // 10` is all but the rightmost digit.

Follow the above rules, and don't look for other special cases. For example, if you don't do anything special, `'7:30'` will become `'seven:thirty'`, and that's okay.

# Approach

1. Create a file `number_namer.py` and fill it with "stub" functions. That is, all the functions (except `main`) should return the empty string.
2. Create a file `number_namer_test.py`, and import the functions from `number_namer`.
3. Write a test for one of the functions, and run it. It should fail.
4. Write the function you just tested, and test it again. Debug until it passes the test.
5. (Refactor) Clean up the code (improve spacing, remove redundancies, etc.) and make sure the test still passes.
6. If you still have untested functions, go to step 3.

# Expected results

The word `zero` is used for exactly one number--the number zero. It is not used for any other number. For example, the number 2008 is `two thousand eight`, despite all those zeros in it.

Note: The word `zero` may also occur in the result of directly calling ```name_of_fraction((0, d))```, but that method should be called from `name_of_decimal`, which will treat a zero fraction as a special case.

Leading zeros don't change integers. Despite the James Bond movies, `007` is `seven`. (But` .007` is, of course, ```seven thousandths```.)

In this assignment, use the "teens" words only for the last two digits. While `1970` could be "nineteen seventy", the expected (and therefore correct) wording is ```one thousand nine hundred seventy```.

# Coda

At the end of your Python program (after all your function definitions), insert the following lines:

``````if __name__ == "__main__":
main()``````

# Due date

Zip your two Python files and submit them to Canvas by Wednesday, September 16.