# Midterm Test—Sample Solutions

Question 1.October 16 2019, 6:10pm — Duration:[6 marks]

This question has six parts. For each question on the left-hand side, circle the letter(s) in front of the corresponding answer(s) on the right-hand side.

Solution:

1. B 2. A, C, E 3. F                4. B, C                            5. A, D                 6. B, C

Question 2. [3 marks] Part (a) [2 marks]

Consider the problem of writing function is_same_letter that has the following docstring description:

Return True if and only if s1, s2, and s3 are the same letter ignoring letter case.

For example, ‘a’, ‘A’, ‘a’ are, but ‘a’, ‘b’, ‘c’, and ‘a’, ‘a’, ‘B’ are not.”””

Several solution attempts are given below. Some are correct and some are incorrect.

Circle the letter in front of each solution attempt that correctly implements the function.

• def is_same_letter(s1: str, s2: str, s3: str) -> bool:

if s1.lower() != s2.lower():

if s2.lower() != s3.lower():

return False else:

return True

• def is_same_letter(s1: str, s2: str, s3: str) -> bool:

if s1.lower() != s2.lower(): return False

elif s2.upper() != s3.upper():

return False

else:

return True

• def is_same_letter(s1: str, s2: str, s3: str) -> bool:

if s1.upper() == s2.upper():

if s2.upper() == s3.upper():

return True

return False

• def is_same_letter(s1: str, s2: str, s3: str) -> bool:

if s1.lower() == s2.lower(): return True

elif s2.lower() == s3.lower():

return True

else:

return False

Solution: B and C.

# Part (b) [1 mark]

Fill in the box below to correctly implement function is_same_letter using a single return statement. Sample solution:

def is_same_letter(s1: str, s2: str, s3: str) -> bool:

 s1.lower() == s2.lower() and s2.upper() == s3.upper() # Another solution: s1.upper() == s2.upper() and s2.upper() == s3.upper()

return

# Question 3. [4 marks]

Complete the following function according to its docstring. You must use the constant VOWELS in your solution. VOWELS = ‘AEIOU’

def omit_uppercase_vowels(s: str) -> str:

“””Return a new string with all the characters in s except those that are also in VOWELS, or an empty string if s is empty or contains only uppercase vowels.

>>> omit_uppercase_vowels(‘Happy Anniversary!’)

‘Happy nniversary!’

>>> omit_uppercase_vowels(‘HELLO THERE!’)

‘HLL THR!’

>>> omit_uppercase_vowels(‘AAA’)

‘’

“””

Sample solutions:

# Possible solution: no_vowels = ‘’

for ch in s:

if ch not in VOWELS: no_vowels = no_vowels + ch # Alternative: no_vowels += ch

return no_vowels

# Another possible solution: no_vowels = ‘’

for i in range(len(s)): if s[i] not in VOWELS: no_vowels = no_vowels + s[i]               # Alternative: no_vowels += s[i]

return no_vowels

# Question 4. [4 marks]

Fill in the boxes below to correctly complete the body of function get_different_matches according to its docstring. Do not change the code outside of the boxes.

def get_different_matches(lst: List[int]) -> List[int]:

“””Return a new list that contains each item in lst that is not equal to the item immediately before it and not equal to the item immediately after it in lst. The first and last items of lst must not be included because they do not have items on both sides.

Precondition: len(lst) >= 3

>>> get_different_matches([1, 2, 3, 3, 4, 2])

[2, 4]

>>> get_different_matches([2, 2, -1, 1, 6])

[-1, 1]

>>> get_different_matches([7, 7, 5, 5])

[]

“””

Sample solutions:

# Possible solution matches = [] for i in range(1, len(lst) – 1):       # don’t loop over first and last indexes if lst[i – 1] != lst[i] and lst[i + 1] != lst[i]:

matches.append(lst[i])                     # matches.extend([lst[i]])

# matches = matches + [lst[i]]

return matches

# Another possible solution matches = [] for i in range(len(lst)): # loop over all indexes, and # now check if i middle (not first/last) index if 1 <= i <= len(lst) – 1 and lst[i – 1] != lst[i] and lst[i + 1] != lst[i]:

matches.append(lst[i])

return matches

# Question 5. [4 marks]

Part (a) [2 marks]

Fill in the box with the while loop condition required for the function to work as described in the docstring. Do not change the code outside of the box.

def find_index_of_last_upper(s: str) -> int:

“””Return the index of the last occurrence of an uppercase letter in s or –

1 if s contains no uppercase letters.

>>> find_index_of_last_upper(‘CSC108’)

2

>>> find_index_of_last_upper(‘801CSC’)

5

>>> find_index_of_last_upper(‘cs’)

-1

“””

i = len(s) – 1

 i >= 0 and not s[i].isupper() # s[i] in ’ABC…’

while:

i = i – 1 return i

Part (b) [2 marks]

Fill in the two boxes below to correctly implement the following function. Do not change the code outside of the boxes. Your code must call find_index_of_last_upper from Part (a).

def find_index_of_first_upper(s: str) -> int:

“””Return the index of the first occurrence of an uppercase letter in s or len(s) if s contains no uppercase letters.

>>> find_index_of_first_upper(‘CSC108’)

0

>>> find_index_of_first_upper(‘801CSC’)

3

>>> find_index_of_first_upper(‘cs’)

2 “””

 s[::-1] *OR* s[-1::-1] *OR* s[:len(s)-1:-1] *OR* s[len(s)::-1]

reversed_s =

 len(s) – 1 – find_index_of_last_upper(reversed_s)

return

# Question 6. [4 marks]

Complete the following function according to its docstring. You must use the constant HASHTAG_SYMBOL in your solution.

HASHTAG_SYMBOL = ‘#’

def is_valid_hashtag(s: str) -> bool:

“””Return True if and only if s is a valid hashtag. A valid hashtag begins with a HASHTAG_SYMBOL and is followed by a valid tweet word. A valid tweet word contains only alphanumeric characters and underscores. Also, a valid tweet words contains at least one alphanumeric character.

Precondition: len(s) >= 1

>>> is_valid_hashtag(“#WeTheNorth”)

True

>>> is_valid_hashtag(“hello#world1”)

False

>>> is_valid_hashtag(“#Raptors!!!”)

False

>>> is_valid_hashtag(“#_”)

False

“””

Sample solution:

if s[0] != HASHTAG_SYMBOL:

return False

alnum_count = 0 # need to make sure there is at least one alphanumeric char in s

# Start looping from after the # symbol.

for char in s[1:]:

if char.isalnum(): alnum_count = alnum_count + 1

elif char != “_”:

# Valid tweet words can only contain _ or alphanumeric characters. return False

return alnum_count > 0

Use the space on this “blank” page for scratch work, or for any solution that did not fit elsewhere.

Clearly label each such solution with the appropriate question and part number.

Total Marks = 25