Homework 3
Due by 11:59pm on Wednesday, 7/5
Instructions
Download hw03.zip.
Submission: When you are done, submit with
python3 ok --submit
.
You may submit more than once before the deadline; only the final submission
will be scored. Check that you have successfully submitted your code on
okpy.org.
See Lab 0
for more instructions on submitting assignments.
Using OK: If you have any questions about using OK, please refer to this guide.
Readings: You might find the following references useful:
Homework questions
Recursion and Tree Recursion
Question 1: G function
A mathematical function G
on positive integers is defined by two
cases:
G(n) = n, if n <= 3
G(n) = G(n - 1) + 2 * G(n - 2) + 3 * G(n - 3), if n > 3
Write a recursive function g
that computes G(n)
. Then, write an
iterative function g_iter
that also computes G(n)
:
def g(n):
"""Return the value of G(n), computed recursively.
>>> g(1)
1
>>> g(2)
2
>>> g(3)
3
>>> g(4)
10
>>> g(5)
22
>>> from construct_check import check
>>> check(HW_SOURCE_FILE, 'g', ['While', 'For'])
True
"""
"*** YOUR CODE HERE ***"
def g_iter(n):
"""Return the value of G(n), computed iteratively.
>>> g_iter(1)
1
>>> g_iter(2)
2
>>> g_iter(3)
3
>>> g_iter(4)
10
>>> g_iter(5)
22
>>> from construct_check import check
>>> check(HW_SOURCE_FILE, 'g_iter', ['Recursion'])
True
"""
"*** YOUR CODE HERE ***"
Use OK to test your code:
python3 ok -q g
python3 ok -q g_iter
Question 2: Ping pong
The ping-pong sequence counts up starting from 1 and is always either counting
up or counting down. At element k
, the direction switches if k
is a
multiple of 7 or contains the digit 7. The first 30 elements of the ping-pong
sequence are listed below, with direction swaps marked using brackets at the
7th, 14th, 17th, 21st, 27th, and 28th elements:
1 2 3 4 5 6 [7] 6 5 4 3 2 1 [0] 1 2 [3] 2 1 0 [-1] 0 1 2 3 4 [5] [4] 5 6
Implement a function pingpong
that returns the nth element of the
ping-pong sequence. Do not use any assignment statements; however, you
may use def
statements.
Hint: If you're stuck, try implementing
pingpong
first using assignment and awhile
statement. Any name that changes value will become an argument to a function in the recursive definition.
def pingpong(n):
"""Return the nth element of the ping-pong sequence.
>>> pingpong(7)
7
>>> pingpong(8)
6
>>> pingpong(15)
1
>>> pingpong(21)
-1
>>> pingpong(22)
0
>>> pingpong(30)
6
>>> pingpong(68)
2
>>> pingpong(69)
1
>>> pingpong(70)
0
>>> pingpong(71)
1
>>> pingpong(72)
0
>>> pingpong(100)
2
>>> from construct_check import check
>>> check(HW_SOURCE_FILE, 'pingpong', ['Assign', 'AugAssign'])
True
"""
"*** YOUR CODE HERE ***"
You may use the function has_seven
, which returns True if a number k
contains the digit 7 at least once.
Use OK to test your code:
python3 ok -q pingpong
Question 3: Count change
Once the machines take over, the denomination of every coin will be a power of two: 1-cent, 2-cent, 4-cent, 8-cent, 16-cent, etc. There will be no limit to how much a coin can be worth.
A set of coins makes change for n
if the sum of the values of the
coins is n
. For example, the following sets make change for 7
:
- 7 1-cent coins
- 5 1-cent, 1 2-cent coins
- 3 1-cent, 2 2-cent coins
- 3 1-cent, 1 4-cent coins
- 1 1-cent, 3 2-cent coins
- 1 1-cent, 1 2-cent, 1 4-cent coins
Thus, there are 6 ways to make change for 7
. Write a function
count_change
that takes a positive integer n
and returns the number
of ways to make change for n
using these coins of the future:
def count_change(amount):
"""Return the number of ways to make change for amount.
>>> count_change(7)
6
>>> count_change(10)
14
>>> count_change(20)
60
>>> count_change(100)
9828
"""
"*** YOUR CODE HERE ***"
Hint: you may find it helpful to refer to the implementation of
count_partitions
.
Use OK to test your code:
python3 ok -q count_change
Question 4: Towers of Hanoi
A classic puzzle called the Towers of Hanoi is a game that consists of three
rods, and a number of disks of different sizes which can slide onto any rod.
The puzzle starts with n
disks in a neat stack in ascending order of size on
a start
rod, the smallest at the top, forming a conical shape.
The objective of the puzzle is to move the entire stack to an end
rod,
obeying the following rules:
- Only one disk may be moved at a time.
- Each move consists of taking the top (smallest) disk from one of the rods and sliding it onto another rod, on top of the other disks that may already be present on that rod.
- No disk may be placed on top of a smaller disk.
Complete the definition of move_stack
, which prints out the steps required to
move n
disks from the start
rod to the end
rod without violating the
rules.
def print_move(origin, destination):
"""Print instructions to move a disk."""
print("Move the top disk from rod", origin, "to rod", destination)
def move_stack(n, start, end):
"""Print the moves required to move n disks on the start pole to the end
pole without violating the rules of Towers of Hanoi.
n -- number of disks
start -- a pole position, either 1, 2, or 3
end -- a pole position, either 1, 2, or 3
There are exactly three poles, and start and end must be different. Assume
that the start pole has at least n disks of increasing size, and the end
pole is either empty or has a top disk larger than the top n start disks.
>>> move_stack(1, 1, 3)
Move the top disk from rod 1 to rod 3
>>> move_stack(2, 1, 3)
Move the top disk from rod 1 to rod 2
Move the top disk from rod 1 to rod 3
Move the top disk from rod 2 to rod 3
>>> move_stack(3, 1, 3)
Move the top disk from rod 1 to rod 3
Move the top disk from rod 1 to rod 2
Move the top disk from rod 3 to rod 2
Move the top disk from rod 1 to rod 3
Move the top disk from rod 2 to rod 1
Move the top disk from rod 2 to rod 3
Move the top disk from rod 1 to rod 3
"""
assert 1 <= start <= 3 and 1 <= end <= 3 and start != end, "Bad start/end"
"*** YOUR CODE HERE ***"
Use OK to test your code:
python3 ok -q move_stack
Question 5: Flatten
Write a function flatten
that takes a (possibly deep) list and "flattens" it.
For example:
>>> lst = [1, [[2], 3], 4, [5, 6]]
>>> flatten(lst)
[1, 2, 3, 4, 5, 6]
Hint: you can check if something is a list by using the built-in
type
function. For example,
>>> type(3) == list
False
>>> type([1, 2, 3]) == list
True
def flatten(lst):
"""Returns a flattened version of lst.
>>> flatten([1, 2, 3]) # normal list
[1, 2, 3]
>>> x = [1, [2, 3], 4] # deep list
>>> flatten(x)
[1, 2, 3, 4]
>>> x = [[1, [1, 1]], 1, [1, 1]] # deep list
>>> flatten(x)
[1, 1, 1, 1, 1, 1]
"""
"*** YOUR CODE HERE ***"
Use OK to test your code:
python3 ok -q flatten
Question 6: Merge
Write a function merge
that takes 2 sorted lists lst1
and lst2
,
and returns a new list that contains all the elements in the two lists
in sorted order.
def merge(lst1, lst2):
"""Merges two sorted lists.
>>> merge([1, 3, 5], [2, 4, 6])
[1, 2, 3, 4, 5, 6]
>>> merge([], [2, 4, 6])
[2, 4, 6]
>>> merge([1, 2, 3], [])
[1, 2, 3]
>>> merge([5, 7], [2, 4, 6])
[2, 4, 5, 6, 7]
"""
"*** YOUR CODE HERE ***"
Use OK to test your code:
python3 ok -q merge
Question 7: Mergesort
Mergesort is a type of sorting algorithm. It follows a naturally recursive procedure:
- Break the input list into equally-sized halves
- Recursively sort both halves
- Merge the sorted halves.
Using your merge
function from the previous question, implement
mergesort
.
Challenge: Implement mergesort itself iteratively, without using recursion.
def mergesort(seq):
"""Mergesort algorithm.
>>> mergesort([4, 2, 5, 2, 1])
[1, 2, 2, 4, 5]
>>> mergesort([]) # sorting an empty list
[]
>>> mergesort([1]) # sorting a one-element list
[1]
"""
"*** YOUR CODE HERE ***"
Use OK to test your code:
python3 ok -q mergesort