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.

## `total` and `test_total`¶

The `total` function inside `hw1.py` and the `test_total` function inside `hw1_test.py` exist only for your examination. 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.

## `count_divisible_digits`¶

📝 Task: Write a function `count_divisible_digits` that takes two integer numbers `n` and `m` as arguments and returns the number of digits in `n` that are divisible by `m`. If `m` is 0, then `count_divisible_digits` should return 0. For this problem, any digit in `n` that is 0 is divisible by any number. You may assume `m` is a single digit (0 ≤ m <10) and that it is not negative.

• `count_divisible_digits(650899, 3)` returns `4` since the digits 0, 6, and 9 are all divisible by 3.

• `count_divisible_digits(-204, 5)` returns `1` since 0 is divisible by 5.

• `count_divisible_digits(24, 5)` returns `0`.

• `count_divisible_digits(1, 0)` returns `0`.

Do not use `str` to solve this problem in any way to solve any part of the problem. Instead, you should solve this problem by manipulating the number itself using integer division.

• `n // 10` evaluates to all but the last digit of `n`.

• `n % 10` evaluates to the last digit of `n`.

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

## `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, a starting location on a grid `x`, and a starting location on a grid `y`. 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 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. 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"`).

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'`). 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"`
• Valid: Date - `"0/200/4"`, Current Format - `"Y/D/M"`, Target Format - `"M/Y"`
• Valid: Date - `"3/2"`, Current Format - `"M/D"`, Target Format - `"D"`
• 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.

📝 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 as well as 2 additional test cases.

## `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 all of the examples 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 integers, an integer `low`, and an integer `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.

• `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], -1, 10)` returns `2.0` since 1, 2, 3 all fall within the specified range and the average of the three numbers is 2.0.

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

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

##### A1 - Primer Initial Submission by Thursday 01/20 at 11:59 pm.