CIT 590 Assignment 4: Balanced Ternary
Fall 2015, David Matuszek

# Purposes of this assignment

• To give you more practice with string manipulation.
• To demonstrate the use of global variables.
• To teach basic use of raising and catching exceptions.

# General idea of the assignment

Your assignment is to write a "calculator" for balanced ternary integers. It will be able to do addition, subtraction, multiplication, and integer division, as well as negation and modulus (remainder). It will also have a one-number "memory,", and it will be able to convert between decimal and balanced ternary.

# Details

In the descriptions below, the word integer will refer to an ordinary integer, such as you have already been using in Python. The term balanced ternary number (BT for short) will mean a string composed of one or more of the characters` '1'`,` '0'`, and` 'N' `(but not` 'n'`)

You will have a single global variable, `memory`, which will hold a single number; it is your choice whether to keep this number as an integer or as a BT string. Most of the operations specified below will change this number.

The user may type in any of the following expressions, where `BT` stands for a balanced ternary number. These are the only kinds of expressions that your calculator needs to handle. There may or may not be a space between the operator and the memory. The user may also type in more than one expression on a line, with optional spaces between expressions, and the computer should do the computations left to right and display only the final answer.

Expression What it means
`+ BT ` Adds the number to memory
`- BT ` Subtracts the number from memory
`* BT ` Multiplies memory by the number
`/ BT ` Divides memory by the number
`% BT ` Sets memory to memory mod the number
`=`` BT` Just puts the number into memory

The user is allowed to enter leading zeros (such as` '00N1'`); however, your calculator should not give results with leading zeros.

Save your program on a file named` bt.py` and your unit tests on a file named `bt_test.py`.

Here are the functions you should have.

## Functions that do computation

Except as noted,

• None of these functions should request input from the user or print anything.
• You should assume that, except for `evaluate`, the functions are all called with legal arguments.
• The parameter `bt` will be a string representing a valid `BT`.
• Except as noted, the functions modify the `memory` variable, and return `None`.
• The `evaluate` function should carefully check its input for errors, and only call the other functions with correct arguments.
`add(bt)`
Adds `bt` to `memory`.
`subtract(bt)`
Subtracts `bt` from `memory`.
`multiply(bt)`
Multiplies `memory` by `bt`.
`divide(bt)`
Divides `memory` by `bt`. Raises an `Exception` if `bt == 0`.
`remainder(bt)`
Sets memory to `memory % bt`. Raises an `Exception` if `bt == 0`. If negative numbers are involved, the results are the same as they would be for integers in Python (in other words, just let Python do whatever it does in this case).
`negate()`
Multiplies `memory` by the decimal number `-1` (or the balanced ternary number `N`).
`store(bt)`
Sets `memory` to `bt`, replacing whatever value had been there previously.
`bt_to_int(bt)`
Returns the integer value represented by the string parameter `bt`. Does not use the global variable `memory`.
`int_to_bt(n)`
Returns a string representing the `BT` value of the integer parameter `n`. Does not use the global variable `memory`.
`memory_as_int()`
Returns the integer value of the number stored in `memory`.
`memory_as_bt()`
Returns a string representing the balanced ternary number stored in `memory`.
`evaluate(string)`
Takes a string that may have been entered by the user (or may have come from our test methods), and
1. Finds the various parts of the string. The input string should consist of one or more expressions optionally separated by whitespace, for example `'=1NN1 + N01*1N'`. If an error is found, return an error message.
2. Evaluate the expressions, left to right. If successful, return the contents of `memory` as a balanced ternary string.
3. If an exception occurs during expression evaluation, catch the exception, and return the error message as a string. The value of `memory` is undefined (but probably what it was just before the exception happened).

You may find it useful to write "helper functions" for some of these steps, otherwise you may end up with a very long function.

## The only function that interacts with the user

`REPL()`
This function implements a basic Read-Evaluate-Print-Loop. It should:
• Read an input from the user,
• If the input is `quit`, return from the `REPL` function (this will end the program).
• Evaluate the input, using the above `evaluate` method,
• Print the result (either a balanced ternary number, or an error message), and
• Loop (do it again). Or, instead of a loop, you could make a recursive call to `REPL`.

This should be the only function that does any input/output. It's also the only function you don't need to unit test.

## Programming hints

• The functions` bt_to_int(bt) `and` int_to_bt(dec) `are fundamental, so do these first. Both are fairly difficult; `bt_to_int(bt) `is somewhat easier than ` int_to_bt(dec).`
• To get the last digit of a decimal number n, use` n % 10`. To remove the last digit of a decimal number n, use` n // 10`.
• You can use `n % 3`, where n is an ordinary integer, to find what the rightmost ternary digit should be. That might give you `2`, with is not a legal balanced ternary digit, but you should be able to figure out what to do with it.
• It's very easy to find the negative of a balanced ternary number; just change `N``1`.
• Inside the program, you can do the arithmetic using integers. Why try to multiply two strings?
• It's better to have many short functions than a few long ones. My `REPL` function is very short (7 lines), because most of the work is done in `evaluate(string)`.
• Here's a rule of thumb: You should be able to see the entire function on the screen, without scrolling.
• Here are some handy string functions you may want:
• `len(s)` -- returns the length of the string
• `s.upper(), s.lower()` -- returns the uppercase/lowercase version of the string
• `s.startswith(t)` -- returns `True` if string `s` starts with string` t`
• `s.replace(t, u)` -- returns a string like s, but with all occurrences of string t replaced by string u. u may be the empty string,` ''`, in which case all occurrences of string t are deleted.
• `s in t` -- returns `True` if string s is a part of string t
• And don't forget string slicing: `s[n:m]`, `s[n:]`, and `s[:m]`.

It's a good idea to end your program with

``````    if __name__ == '__main__':
REPL()``````
(In this program, the "main" method is named `REPL`, not `main`. )

# Due date:

Before 6am Wednesday September 23. Zip your two files and submit them to Canvas. No other form of submission will be accepted.