Diagnostics are meant for you to check your understanding of the week's material. They are not worth any points and are not counted towards midterm recovery points; instead, diagnostics are solely for your benefit. If you find yourself struggling with the questions in this diagnostic, consider signing up for Tutoring.

## Lists, Sequences, and Dictionaries

### Question 1

Define `if_this_not_that`, which takes a list of integers `i_list`, and an integer `this`, and for each element in `i_list` if the element is larger than `this` then print the element, otherwise print `that`.

``````def if_this_not_that(i_list, this):
"""
>>> original_list = [1, 2, 3, 4, 5]
>>> if_this_not_that(original_list, 3)
that
that
that
4
5
"""
for elem in i_list:
if elem <= this:
print("that")
else:
print(elem)``````

### Question 2: Group

Write a recursive function that divides an input sequence into a list of smaller sequences that each contain 4 or 5 elements from the original sequence. For example, an input sequence of 14 elements should be divided into sequences of 4, 5, and 5 elements. Use as few 5-element sequences as necessary in the result, and all 5-element sequences should be at the end. Finally, preserve the relative ordering of elements from the original sequence.

Hint: You may assume that the input sequence has length at least 12. Think carefully about how many base cases you need, and what they should be.

``````def group(seq):
"""Divide a sequence of at least 12 elements into groups of 4 or
5. Groups of 5 will be at the end. Returns a list of sequences, each
corresponding to a group.

>>> group(range(14))
[range(0, 4), range(4, 9), range(9, 14)]
>>> group(list(range(17)))
[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15, 16]]
"""
num = len(seq)
assert num >= 12
if num == 12 or num == 13:
return [seq[:4], seq[4:8], seq[8:]]
elif num == 14:
return [seq[:4], seq[4:9], seq[9:]]
elif num == 15:
return [seq[:5], seq[5:10], seq[10:]]
return [seq[:4]] + group(seq[4:])``````

### Question 3: Fill in the blanks

Fill in the blanks for the following lines so that each expression evaluates to the expected output:

``````>>> apply_to_all(_______, [1, 3, -1, -4, 2])
[1, 1, -1, -1, 1]
>>> keep_if(______, [1, 7, 14, 21, 28, 35, 42])
[1, 14, 28, 42]
>>> reduce(_______, _______, '')
'olleh'
>>> reduce(______, apply_to_all(______, 'nnnnn'), __) + ' batman!'
'nanananana batman!'``````
• `apply_to_all(lambda x: x // abs(x), [1, 3, -1, -4, 2])`
• `keep_if(lambda x: x // 7 % 2 == 0, [1, 7, 14, 21, 28, 35, 42])`
• `reduce(lambda x, y: y + x, 'hello', '')`
• ```reduce(lambda x, y: x + y, apply_to_all(lambda s: s + 'a', 'nnnnn'), '') + ' batman!'```

### Question 4: Replace All

Given a dictionary `d`, replace all occurences of `x` as a value (not a key) with `y`.

``````def replace_all(d, x, y):
"""
>>> d = {'foo': 2, 'bar': 3, 'garply': 3, 'xyzzy': 99}
>>> replace_all(d, 3, 'poof')

>>> d == {'foo': 2, 'bar': 'poof', 'garply': 'poof', 'xyzzy': 99}
True
"""
for key in d:
if d[key] == x:
d[key] = y``````

### Question 5: Filter

Implement a `filter` function for linked lists. Remember, recursion is your friend!

``````def filter_link(predicate, r):
""" Returns a link only containing elements in r that satisfy
predicate.

>>> new = filter_link(lambda x : x % 2 == 0, r))
>>> first(new)
50
True
"""
if r == empty:
return r
elif predicate(first(r)):
else:

### Question 6

Write iterative and recursive functions that reverse a given linked list, producing a new linked list with the elements in reverse order. Use only the `link` constructor and `first` and `rest` selectors to manipulate linked lists. (You may write and use helper functions.)

``````def reverse_iterative(s):
"""Return a reversed version of a linked list s.

>>> reverse_iterative(primes)
(7, (5, (3, (2, None))))
"""
rev_list = empty
while s != empty:
s = rest(s)
return rev_list
def reverse_recursive(s):
"""Return a reversed version of a linked list s.