CIT 590 Assignment 2: Balanced Ternary
Spring 2013, David Matuszek

# Purposes of this assignment

• To get you comfortable with writing functions.
• To learn some string manipulation.
• To emphasize the importance of following specifications exactly.

# 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.

The user will use your program by typing in expressions such as` N0 + 1NN` and will get a balanced ternary number such as` 1N `as a result. Details of what the user may type are given below.

We will do some automated testing of your assignment. That means our program will call functions in your program, and if those functions are missing, or have a different name, or different parameters, or return the wrong kind of values, then they will fail our tests. So be sure to write functions exactly as specified below.

Example (I am using "`Compute:`" as a prompt):

``Compute: N0000 + 1N0N01N0Compute: dec mem-75Compute: bt -75N01N0Compute: mem * N10N10Compute: helloError: I don't understand: helloCompute: quitDone.``

# 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'`)

The user may type in any of the following expressions. These are the only kinds of expressions that your calculator needs to handle.

 `BT + BT ` Adds the two numbers `BT - BT ` Subtracts the second number from the first `BT * BT ` Multiplies the two numbers `BT / BT ` Divides the first number by the second `BT % BT ` Gives the remainder when dividing the first number by the second (see note) `BT` Just puts the number into memory, no other action taken. `-BT ` Computes the negative of the given number `dec BT ` Gives the decimal value of the BT number `bt decimal ` Gives the BT value of the decimal number `quit` Quits the program

Your "calculator" will remember the last number computed (initially zero, when you start the program). In each of the above expressions,

• `BT ` may be a balanced ternary number, written without quotes, or the word `mem`. If it is the word `mem`, then the calculator uses the number stored in its "memory" as that operand.
• The user may (or may not) put spaces before or after numbers, and before or after operators. Your program must handle it either way.
• The user may 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`.

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, with one exception, the functions are all called with legal arguments.
• The parameters `bt`, `bt1`, `bt2` will be strings representing valid `BT` numbers.
• The parameter `dec` will be a decimal integer.
• The `evaluate` function should carefully check its input for errors, and only call the other functions with correct arguments.
• Input parameters and returned results are strings representing valid `BT` numbers.
`add(bt1, bt2)`
Returns the sum of the two parameters as a `BT` number. Also saves the result in memory.
`subtract(bt1, bt2)`
Returns the difference `bt1 - bt2 `as a BT number. Also saves the result in memory.
`multiply(bt1, bt2)`
Returns the product of the two parameters as a `BT` number. Also saves the result in memory.
`divide(bt1, bt2)`
Returns the quotient `bt1 / bt2` as a `BT` number. Does not check to make sure `bt2 != 0`. Also saves the result in memory.
`remainder(bt1, bt2)`
Returns the modulus `bt1 % bt2` as a `BT` number. Does not check to make sure `bt2 != 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). Also saves the result in memory.
`negate(bt)`
Returns the `BT` number which, when added to `bt`, would give zero. Also saves the result in memory.
`bt_to_int(bt)`
Returns the integer value represented by the string parameter `bt`.
`int_to_bt(dec)`
Returns a string representing the `BT` value of the integer parameter `dec`.
`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 (for example, first operand, operator, second operand).
2. Checks for problems (illegal characters, division or mod by zero, etc.). If any problem is found, return an error message. Do not change the contents of memory (`mem`). Do not perform perform the next step.
3. Calls one of the above methods to perform the arithmetic, and return the result as a string.

You may find it useful to write "helper functions" for some of these steps, otherwise you may end up with a very long function.
`store(bt)`
Saves bt in a global variable. This function is called by most of the above functions, and should be the only function that changes this global variable.
`fetch()`
Returns the bt string previously saved in a global variable (or the string` '0'`, if `store` has never been called). This should be the only function that refers to this global variable.

I want to make this as clear as I can: For every legal operation that the user types in, except `quit`, the balanced ternary version of the result is saved in memory. This includes the operations `bt` and `dec`. (Illegal operations should not change memory.)

• To evaluate `bt` and `dec`, you will probably call functions `int_to_bt` and `bt_to_int`, but the functions `int_to_bt` and `bt_to_int` should not themselves change memory, or it will be very difficult to make your program do the right thing.
• To evaluate `dec`, call `bt_to_int` to get an answer, then save the `BT` value; and similarly for the `int_to_bt` operation.

Catch as many errors in the user input as you can. You probably won't be able to catch them all, unless you use features of Python that we haven't talked about yet. We will be testing that your methods work when given correct input.

## 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.

## 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.
• 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.
• `evaluate(string)`does a lot of work--too much for one function. Use additional "helper" functions. For example, one of my helper functions splits the `string` into separate operator and operand strings.
• Remember multiple assignment? Like, `a, b, c = 1, 2, 3` ? You can do the same thing with functions:
```        def powers(n):             return n * n, n * n * n         square, cube = powers(5)```
• 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 Friday January 25. Submit your `.py` file to Canvas. No other form of submission will be accepted.