Learning objective: Apply control structures and data structures to solve problems involving numbers, text, and files.

• `hw1.py` is the file to put your implementations for each problem. `hw1.py` is not a runnable program, so we don’t use the main-method pattern.

• `hw1_test.py` is the file for you to put your own tests. The Run button executes this program.

• `cse163_utils.py` is a helper file that has code to help you test your code.

## Useful CSE 163 Resources¶

Expectations: In `hw1.py` you should not use any import statements or features in Python we have not yet discussed in class, section, or HW specs. All of these problems should be solved using the fundamental constructs we’ve learned in class so far. For your testing program, you can use imports (especially to use `cse163_utils``assert_equals` function.

## `total` and `test_total`¶

The `total` function inside `hw1.py` and the `test_total` function inside `hw1_test.py` exist only for your reference. You aren’t required to modify either function but should use them as examples for how to structure your functions inside `hw1.py` and `hw1_test.py`, respectively.

Additionally, you should pay attention to how the comment for `total` mentions any special behavior that might not be obvious to someone who’s seeing the code for the first time. Keep this in mind as you document the other functions in this assessment.

## `is_relatively_prime`¶

📝 Task: Write a function `is_relatively_prime` that takes two integer numbers `n` and `m`, returning `True` if `n` and `m` are relatively prime to each other and `False` otherwise. Two numbers are relatively prime if they share no common factors besides 1. (1 is relatively prime with every number.) Assume the value of `n` and `m` are at least 1.

• `is_relatively_prime(12, 13)` returns `True` since the factors of 12 are 1, 2, 3, 4, 6, 12 and the factors of 13 are 1, 13.

• `is_relatively_prime(12, 14)` returns `False` since the factors of 12 are 1, 2, 3, 4, 6, 12 and the factors of 14 are 1, 2, 7, 14.

• `is_relatively_prime(5, 9)` returns `True` since the factors of 5 are 1, 5 and the factors of 9 are 1, 3, 9.

• `is_relatively_prime(8, 9)` returns `True` since the factors of 8 are 1, 2, 4, 8 and the factors of 9 are 1, 3, 9.

• `is_relatively_prime(8, 1)` returns `True` since we define that 1 is relatively prime with every number.

Do not use data structures to store factors during the execution of the algorithm, and use a single loop rather than nested loops.

📝 Task: Write a test that calls the function with some inputs and compares the output of the program with the expected value using `assert_equals`. Include test cases for all of the examples above as well as 2 additional test cases.

## `travel`¶

📝 Task: Write a function `travel` which takes a string of north, east, south, west directions and a `tuple` indicating the starting `x, y` location on a grid. Your function should return a `tuple` that indicates the new position after following the directions starting from the given `x`, `y`. The returned tuple should be in the format `(x_new, y_new)`. The coordinates for each direction will always be `int`s

The directions string will use `'N'` to indicate increasing the y-coordinate, `'E'` to indicate increasing the x-coordinate, `'S'` to indicate decreasing the y-coordinate, and `'W'` to indicate decreasing the x-coordinate. The case of the characters should be ignored. You can assume that `x` and `y` are both of type `int`. Any characters that are not `'N'`, `'E'`, `'W'`, or `'S'` (ignoring letter-casing) should be ignored.

`travel('NW!ewnW', (1, 2))` should return the tuple `(-1, 4)` following this sequence of movements:

1. Start at `(1, 2)`.

2. Move `'N'` to `(1, 3)`.

3. Move `'W'` to `(0, 3)`.

4. Ignore `'!'` since it is not a valid direction.

5. Move `'e'` to `(1, 3)`.

6. Move `'w'` to `(0, 3)`.

7. Move `'n'` to `(0, 4)`.

8. Move `'W'` to `(-1, 4)`.

📝 Task: Write a test that calls the function with some inputs and compares the output of the program with the expected value using `assert_equals`. Include test cases for all of the examples above as well as 2 additional test cases.

## `reformat_date`¶

📝 Task: Write a function `reformat_date` which takes three strings as arguments representing a date, a current date format, and a target date format and returns a new string with the date formatted in the target format.

A date string will be some non-empty string of numbers separated by `/` (e.g, `"3/6/1995"`). Note that the numbers between the `/`‘s can have any number of digits, but you may assume there is at least one digit for each part of the date provided.

The current and target formats will be some non-empty sequence of the characters `'D'`, `'M'`, `'Y'` separated by `/`. You can assume the given date and the current format will match up (i.e., they will have the same number of `/`‘s) and that any date symbol that appears in the target format also appears in the current format (i.e., if the target format contains a `'Y'` the current format will also contain a `'Y'`).

For example, if we made the method call: `reformat_date("12/31/1998", "M/D/Y", "D/M/Y")`, it should return the string `"31/12/1998"`. In this example, the first argument represents a date and the second argument specifies this date is currently in the format Month/Day/Year (abbreviated `"M/D/Y"`). The third argument specifies that the method should return a new date in the format of Day/Month/Year format (abbreviated `"D/M/Y"`).

Below are some valid/invalid examples of current and target formats. You do not need to handle invalid formats. You may assume we will never pass you an example that is invalid.

• Valid: Date - `"1/2/3"`, Current Format - `"M/D/Y"`, Target Format - `"Y/M/D"`. It should return `"3/1/2"`.
• Valid: Date - `"0/200/4"`, Current Format - `"Y/D/M"`, Target Format - `"M/Y"`. It should return `"4/0"`.
• Valid: Date - `"3/2"`, Current Format - `"M/D"`, Target Format - `"D"`. It should return `"2"`.
• Invalid: Date - `"3/2"`, Current Format - `"M/D/Y"`, Target Format - `"Y/M/D"`
• Reason: The date and the current format don’t have the same number of parts.
• Invalid: Date - `"3/2"`, Current Format - `"M/D"`, Target Format - `"Y/M/D"`
• Reason: Target contains a part of a date (`"Y"`) not in the current format (`"M/D"`).
• Invalid: Date - `"1/2/3/4"`, Current Format - `"M/D/Y/S"`, Target Format - `"M/D"`
• Reason: Date format contains a part that is not `'M'`, `'D'`, or `'Y'`.
• Invalid: Date - `""`, Current Format - `""`, Target Format - `""` (an empty string)
• Reason: An empty string.

Again, you may assume we won’t pass you any of these invalid date formats. We wanted to provide this list and rationale for why they are invalid to give you a better sense of what assumptions you can make about your inputs.

Your function should be as general as possible and avoid hard-coding specific orderings of the date parts.

📝 Task: Write a test that calls the function with some inputs and compares the output of the program with the expected value using `assert_equals`. Include test cases for all of the valid examples above (there should be four of them) as well as 2 additional test cases.

Your function should be as general as possible and avoid hard-coding specific orderings of the date parts.

## `longest_word`¶

📝 Task: Write a function `longest_word` that takes a string filename and returns the longest word in the file with which line it appears on. A word here is defined as a sequence of characters separated by whitespace. If there are ties for the longest word, it should return the one that appears first in the file. If the file is empty or there are no words in the file, the function should return `None`. Assume that the file exists. Consider a file `song.txt` with the following contents.

``````Row, row, row your boat
Gently down the stream
Merrily, merrily, merrily, merrily
Life is but a dream!
``````

Then the call `longest_word('/home/song.txt')` should return `'3: Merrily,'`.

📝 Task: Write a test that calls the function with some inputs and compares the output of the program with the expected value using `assert_equals`. Include test cases for the example above as well as 2 additional test cases.

Hint

Create new files in your workspace for each additional test case. When specifying file names, use absolute paths, such as `/home/song.txt`.

## `get_average_in_range`¶

📝 Task: Write a function `get_average_in_range` that takes a list of floats, a float `low`, and a float `high`, and returns the average of all values within the list that lies in the given range from `low` (inclusive) to `high` (exclusive). If there are no values in the given range, returns 0. Assume `low <= high`.

• `get_average_in_range([1, 5, 6, 7, 9], 5, 7)` returns `5.5` since only 5 and 6 fall in the range between 5 (inclusive) and 7 (exclusive), and the average of 5 and 6 is 5.5.

• `get_average_in_range([1, 2, 3.2], -1, 10)` returns `2.0666666` (repeating) since 1, 2, 3.2 all fall within the specified range and the average of the three numbers is 2.067. Note you should not round the output

📝 Task: Write a test that calls the function with some inputs and compares the output of the program with the expected value using `assert_equals`. Include test cases for all of the examples above as well as 2 additional test cases.

## `mode_digit`¶

📝 Task: Write a function `mode_digit` that takes an integer number `n` and returns the digit that appears most frequently in that number. The given number may be positive or negative, but the most frequent digit returned should always be non-negative. If there is a tie for the most frequent digit, the digit with the greatest value should be returned.

• `mode_digit(12121)` returns `1`.

• `mode_digit(0)` returns `0`.

• `mode_digit(-122)` returns `2`.

• `mode_digit(1211232231)` returns `2`.

Hint

Use data structures to count digit occurrences.

• Do not create strings in any way to solve any part of the problem.

• Do not use any nested loops or recursion.

• Do not use an `if`, `elif`, or `else` branch for each digit. You can still use `if/elif/else` in general for other purposes.

``````# Avoid doing this
if digit == 0:
... # do something with 0
elif digit == 1:
... # do something with 1
...
``````

📝 Task: Write a test that calls the function with some inputs and compares the output of the program with the expected value using `assert_equals`. Include test cases for all of the examples above as well as 2 additional test cases.

## Code Quality¶

Assessment submissions should pass these checks: `flake8`, and code quality guidelines. The code quality guidelines are very thorough. For this assessment, the most relevant rules can be found in these sections:

Note

Make sure to provide a descriptive file header in docstring format, not something generic like “implements functions for Primer”.

## Submission¶

Submit your work by pressing the Mark button. Submit as often as you want until the deadline for the initial submission. You can view your past submissions using the “Submissions” button.

Please make sure you are familiar with the resources and policies outlined in the syllabus and the take-home assessments page.

##### THA 1 - Primer

Initial Submission by Thursday 07/06 at 11:59 pm.