0% found this document useful (0 votes)
2 views5 pages

Final 23W Key

The document is the final exam key for CS 211, Winter 2023, detailing the average and median scores of the exam along with specific coding problems related to calculating averages, checking for duplicates in columns, counting good apples, and run-length encoding. It includes sample solutions and assertions for various programming tasks. The document emphasizes the importance of understanding the methods and logic behind the coding challenges presented.

Uploaded by

andyleeper05
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views5 pages

Final 23W Key

The document is the final exam key for CS 211, Winter 2023, detailing the average and median scores of the exam along with specific coding problems related to calculating averages, checking for duplicates in columns, counting good apples, and run-length encoding. It includes sample solutions and assertions for various programming tasks. The document emphasizes the importance of understanding the methods and logic behind the coding challenges presented.

Uploaded by

andyleeper05
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 5

CS 211

Final Exam Key, Winter 2023

Your name: Ichtaca Bansank

Student ID#: 0xc96d3cb

Please do not write your name on other pages.

Average score (arithmetic mean) was 68. Median was 70. There were lots of excellent
scores, and quite a few very low scores.

Histogram
40

35

30

25
Frequency

20
Frequency

15

10

0
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1 More
Bin

Total: of 100 possible


Page 2 of 5

1. [25 points] In a certain class, the average exam score for the term is calculated as the
arithmetic mean of exam scores, but up to two exams at which the student was not present
may be omitted. If the student missed three or more exams, those exams are included in
the average as zeroes. Exams at which the student was present are counted regardless of
score. Finish method average.

class Exam:
"""One exam score"""
def __init__(self, score: int, present: bool):
self.present = present
self.score = score

class TermExams:
"""Exam scores over a term"""
def __init__(self, scores: list[Exam]):
self.scores = scores

def average(self) -> float:


"""Average with up to 2 absences excused"""
count = 0
absences = 0
total = 0
for score in self.scores:
if score.present or absences >= 2:
count += 1
total += score.score
else:
absences += 1
return total/count

pretty_good = TermExams([
Exam(100, True), Exam(100, True),
Exam(0, False), Exam(100, True)])
assert pretty_good.average() == 100.0
pretty_bad = TermExams([
Exam(100, True), Exam(0, False),
Exam(0, False), Exam(0, False)])
assert pretty_bad.average() == 50.0

There were many ways to finish the average method correctly. My sample solution keeps
a separate count of exams to be averaged and total of those exams. Many students instead
kept a count of excused absences and subtracted that from the length of the ‘scores‘ list. I
think there were some other reasonable approaches that I don’t recall at the moment.

CS 211 — Final Exam Key, Winter 2023 (score)


Page 3 of 5

2. [25 points] Finish function no_columns_has_dups. You may write an additional function,
but do not transpose the matrix. It may be useful to remember that set() creates a set,
s.add(x) adds an element x to a set s, and x in s checks whether set s contains element
x.

def no_column_has_dups(grid: list[list[int]]) -> bool:


"""grid is a rectangular matrix.
Return True if NO column in grid contains
contains two elements that are the same.
"""
if len(grid) == 0:
return True
n_cols = len(grid[0])
for col_i in range(n_cols):
col_elements = set()
for row in grid:
if row[col_i] in col_elements:
return False
col_elements.add(row[col_i])
return True

assert no_column_has_dups(
[[1, 2, 2],
[2, 3, 3],
[3, 1, 1]])
assert no_column_has_dups([])
assert no_column_has_dups([[], []])
assert not no_column_has_dups(
[[1, 2, 3],
[8, 3, 1],
[7, 2, 8]])

Again there was more than one way to solve this problem. Note the necessity of testing
whether the grid is empty (len(grid) == 0) before determining the number of columns
(len(grid[0])).
One common approach that I had not anticipated was creating a set of elements in column
and then testing whether the set had the same length as the grid. That is also fine.

CS 211 — Final Exam Key, Winter 2023 (score)


Page 4 of 5

3. [25 points] Finish method count_good in the concrete classes Inner and Apple so that it
counts the number of apples in a tree that meet the quality standard of a Checker object.

class Checker:
"""Abstract base for class that accepts or rejects apples"""
def good(self, fruit: "Apple") -> bool:
raise NotImplementedError("Good method not defined")

class Tree:
"""Abstract base class for nodes of apple tree"""
def count_good(self, checker: Checker) -> int:
"""How many good applies in this tree?"""
raise NotImplementedError("count_good not defined")

class Inner(Tree):
def __init__(self, children: list[Tree]):
self.children = children

def count_good(self, checker: Checker) -> int:


count = 0
for child in self.children:
count += child.count_good(checker)
return count

class Apple(Tree):
"""Leaf nodes of the apple tree"""
def __init__(self, sweetness: int, crispness: int, tartness: int):
self.sweetness = sweetness
self.crispness = crispness
self.tartness = tartness

def count_good(self, checker: Checker) -> int:


if checker.good(self):
return 1
return 0

class GoodForPie(Checker):
def good(self, fruit: "Apple") -> bool:
return fruit.crispness > 5 and fruit.tartness > 5

my_tree = Inner([ Apple(8, 3, 2), Inner([Apple(3, 8, 6), Apple(3, 9, 7)])])


assert my_tree.count_good(GoodForPie()) == 2

An important part of this problem was using a method of the Checker object passed to the
count_good method. Most students got it, but quite a few used GoodForPie directly even
though another Checker object of a different subclass could be passed.

CS 211 — Final Exam Key, Winter 2023 (score)


Page 5 of 5

4. [25 points] A run in a list is a sub-sequence of identical elements. For example, in the
list [“a”, “b”, “b”, “b”, “c”, “b”], there is a run of 3 “b”. It could be run-length encoded as
[(1, “a”), (3, “b”), (1, “c”), (1, “b”)].
Complete the add method of RunLengthEncoding so that as_pairs will return the results
indicated in the test cases below. Try to avoid repetitive code.

class RunLengthEncoding:
"""Instead of x x x y y x x x, encode as (3 x) (2 y) (3 x)"""
def __init__(self):
# Maintain items and repetitions as parallel arrays
self.items: list[str] = []
self.reps: list[int] = []

def add(self, m: str):


"""Might append item or increment reps of last item"""
if len(self.items) == 0:
self.items.append(m)
self.reps.append(1)
return
elif self.items[-1] == m:
self.reps[-1] += 1
else:
self.items.append(m)
self.reps.append(1)

def add_a_bunch(self, l: list[str]):


for e in l:
self.add(e)

def as_pairs(self):
"""Provide as list of pairs"""
return [(self.reps[i], self.items[i]) for i in range(len(self.items))]
# (The 'zip' function also provides a concise way to do this)

rle = RunLengthEncoding()
rle.add_a_bunch(["a", "a", "x", "y", "y", "a", "a"])
assert rle.as_pairs() == [(2, "a"), (1, "x"), (2, "y"), (2, "a")]
rle.add_a_bunch(["a", "b", "b", "b"])
assert rle.as_pairs() == [(2, "a"), (1, "x"), (2, "y"), (3, "a"), (3, "b")]

In addition to list logic, this was a test of maintaining parallel array structures.
I was surprised by the number of students who seemed to mix up add_a_bunch (just a
quick way to call add several times) with add.

CS 211 — Final Exam Key, Winter 2023 (score)

You might also like