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 mainmethod 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.
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)
returns4
since the digits 0, 6, and 9 are all divisible by 3. 
count_divisible_digits(204, 5)
returns1
since 0 is divisible by 5. 
count_divisible_digits(24, 5)
returns0
. 
count_divisible_digits(1, 0)
returns0
.
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 ofn
. 
n % 10
evaluates to the last digit ofn
.
📝 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)
returnsTrue
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)
returnsFalse
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)
returnsTrue
since the factors of 5 are 1, 5 and the factors of 9 are 1, 3, 9. 
is_relatively_prime(8, 9)
returnsTrue
since the factors of 8 are 1, 2, 4, 8 and the factors of 9 are 1, 3, 9. 
is_relatively_prime(8, 1)
returnsTrue
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 ycoordinate, 'E'
to indicate increasing the xcoordinate, 'S'
to indicate decreasing the ycoordinate, and 'W'
to indicate decreasing the xcoordinate. 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 lettercasing) should be ignored.
travel('NW!ewnW', 1, 2)
should return the tuple (1, 4)
following this sequence of movements:

Start at
(1, 2)
. 
Move
'N'
to(1, 3)
. 
Move
'W'
to(0, 3)
. 
Ignore
'!'
since it is not a valid direction. 
Move
'e'
to(1, 3)
. 
Move
'w'
to(0, 3)
. 
Move
'n'
to(0, 4)
. 
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 nonempty 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 nonempty 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"
).
 Reason: Target contains a part of a date (
 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'
.
 Reason: Date format contains a part that is not
 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 (there should be four of them) as well as 2 additional test cases.
Your function should be as general as possible and avoid hardcoding 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 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)
returns5.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)
returns2.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 nonnegative. If there is a tie for the most frequent digit, the digit with the greatest value should be returned.

mode_digit(12121)
returns1
. 
mode_digit(0)
returns0
. 
mode_digit(122)
returns2
. 
mode_digit(1211232231)
returns2
.
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
, orelse
branch for each digit. You can still useif/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:


Boolean Zen

Loop Zen

Factoring

Unnecessary Cases

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 takehome assessments page.
THA 1  Primer
Initial Submission by Thursday 07/07 at 11:59 pm.
Submit on Ed