· 4 years ago · Jan 04, 2021, 03:26 PM
1"""Exam 1 (2021-01-04)."""
2
3
4def sum_of_multiples(limit: int, multiplier: int):
5 """
6 Given a limit, find the sum of all the multiples of multiplier up to but not including that number.
7
8 #1
9
10 Limit and multiplier are both natural numbers.
11 If limit is smaller or equal than multiplier it should return 0.
12
13 sum_of_multiples(20, 5) -> 30
14 sum_of_multiples(10, 1) -> 45
15 sum_of_multiples(5, 5) -> 0
16 """
17 pass
18
19
20def mix_string(s1: str, s2: str) -> str:
21 """
22 Given two strings s1 and s2, create a mixed string by alternating between str1 and str2 chars.
23
24 #2
25
26 mix_string("AAA", "bbb") -> AbAbAb
27 mix_string("AA", "") -> AA
28 mix_string("mxdsrn", "ie tig") -> mixed string
29 """
30 pass
31
32
33def bingo(matrix: list, numbers: list) -> tuple:
34 """
35 Whether the matrix has winning combinations with the given numbers.
36
37 #3
38
39 Check if player got any winning combinations:
40 1. Corners - all 4 corners contain winning numbers
41 2. Diagonals - all diagonals contain winning numbers
42 3. Full game - all numbers in the matrix/ticket are in the winning numbers
43 Example matrix:
44 [
45 [ 5, 7, 11, 15, 21],
46 [22, 25, 26, 27, 9],
47 [34, 2, 48, 54, 58],
48 [59, 61, 33, 81, 24],
49 [90, 37, 3, 6, 32],
50 ]
51
52 :param matrix: 5 x 5 bingo ticket of numbers
53 :param numbers: list of winning numbers (size always at least 4)
54 :return: tuple of booleans (corners, diagonals, full_game)
55 """
56 pass
57
58
59def can_reach(arr: list, start: int) -> bool:
60 """
61 Given an array of non-negative integers arr, you are initially positioned at start index of the array.
62
63 #4
64
65 When you are at index i, you can jump to i + arr[i] or i - arr[i], check if you can reach to any index with value 0.
66
67 Notice that you can not jump outside of the array at any time.
68
69 Solution has to be recursive!
70
71 Example 1:
72 Input: arr = [4,2,3,0,3,1,2], start = 5
73 Output: True
74 Explanation:
75 All possible ways to reach at index 3 with value 0 are:
76 index 5 -> index 4 -> index 1 -> index 3
77 index 5 -> index 6 -> index 4 -> index 1 -> index 3
78
79 Example 2:
80 Input: arr = [4,2,3,0,3,1,2], start = 0
81 Output: True
82 Explanation:
83 One possible way to reach at index 3 with value 0 is:
84 index 0 -> index 4 -> index 1 -> index 3
85
86 Example 3:
87 Input: arr = [1, 2, 0], start = 0
88 Output: False
89 From index 0, we can move to index 1, but then nowhere else.
90
91 :return boolean whether a possible route exists or not
92 """
93 pass
94
95
96def prime_factorization(number: int) -> int:
97 """
98 Given a natural number greater than 1, return it's prime factorization.
99
100 #5
101
102 Return the prime factorization of number.
103
104 Return dict, where the key is a prime factor and the value is count of this factor.
105
106 12 = 2 * 2 * 3 => {2: 2, 3: 1}
107 1960 = 2 * 2 * 2 * 5 * 7 * 7 => {2: 3, 5: 1, 7: 2}
108 79 = 79 * 1 => {79: 1}
109
110 Prime number is a number which is divisible only by 1 and the number itself.
111 For example 2, 3, 5, 7, 11, 13, 17, 19, 23 are prime numbers.
112
113 Examples:
114 2 => { 2: 1 }
115 12 => { 2: 2, 3: 1 }
116 1960 => { 2: 3, 5: 1, 7: 2 }
117 1024 => { 2: 10 }
118 79 => { 79: 1 }
119 121 => { 11: 2 }
120
121 :param number: a number greater than 1
122 :return: dict of prime factors and their counts.
123 """
124 pass
125
126
127class Candy:
128 """Candy #6."""
129
130 def __init__(self, name: str, filling: str):
131 """
132 Candy class constructor.
133
134 :param name: candy name
135 :param filling: candy filling
136 """
137 self.name = name
138 self.filling = filling
139
140
141class CandyShop:
142 """Candy shop #6."""
143
144 def __init__(self):
145 """CandyShop class constructor."""
146 pass
147
148 def add_candies(self, candies: list):
149 """
150 Add list of fresh candies to already existing ones.
151
152 :param candies: list of candies to add
153 :return:
154 """
155 pass
156
157 def get_candies(self) -> list:
158 """
159 Return list of all candies existing in the shop.
160
161 :return: list of all candies
162 """
163 pass
164
165 def get_candies_by_filling(self, filling: str) -> list:
166 """
167 Get list of candies that have the same filling as given in parameter value.
168
169 :return: list
170 """
171 pass
172
173 def sort_candies_by_filling(self) -> list:
174 """
175 Method should return list of candies sorted by filling in alphabetical order.
176
177 If filling is the same, then sort
178 by name in alphabetical order.
179
180 :return: sorted list of candies
181 """
182 pass
183
184 def get_most_popular_candy_name_and_filling(self) -> dict:
185 """
186 Find the most popular candy name and filling.
187
188 Method should return dict with name and filling of the most popular candy in the shop (type of candy which name
189 and filling is present the most in the shop). NB! You should consider the most popular combination of name and filling.
190 {name: most_pop_candy_name, filling: most_pop_candy_filling}
191
192 If there are several suitable candidates, return any of those (doesn't matter which one).
193
194 :return: dict with name and filling of most pop candy
195 """
196 pass
197
198 def get_least_popular_candy_name_and_filling(self) -> dict:
199 """
200 Find the least popular candy name and filling.
201
202 Method should return dict with name and filling of the least popular candy in the shop (type of candy which name
203 and filling is present the least in the shop). NB! You should consider the least popular combination of name and filling.
204 {name: least_pop_candy_name, filling: least_pop_candy_filling}
205
206 If there are several suitable candidates, return any of those (doesn't matter which one).
207
208 :return: dict with name and filling of least pop candy
209 """
210 pass
211
212 def collect_candies_by_filling(self) -> dict:
213 """
214 Group candies by filling.
215
216 Method should return dict with candies divided by filling, where dict key is filling and dict value is list
217 of candies with this filling.
218 {candy_filling: [candy1, candy2]}
219
220 :return: dict of candies divided by filling
221 """
222 pass
223
224
225class Grade:
226 """Grade #7."""
227
228 def __init__(self, grade, weight: int, assignment: str, date: str):
229 """Constructor."""
230 self.assignment = assignment
231 self.value = grade
232 self.weight = weight
233 self.date = date
234 self.previous_grades = {}
235
236 def change_grade(self, new_grade: int, date: str):
237 """
238 Change a previous grade.
239
240 This function should save the previous grade in a dictionary previous_grades, where key is the date and value
241 is the value of the grade. Value and date should be updated.
242 """
243 pass
244
245
246class Student:
247 """Student #7."""
248
249 def __init__(self, name: str):
250 """Constructor."""
251 self.name = name
252 self.grades = {}
253
254 def grade(self, grade: Grade):
255 """
256 Add a grade for an assignment that a students has done.
257
258 Grades are kept in a dictionary where assignment name is the key and Grade object is the value (All previous
259 grades for the same assignment are kept in the Grade object previous grades dictionary).
260 Note that this function is only used when a student does an assignment for the first time.
261 """
262 pass
263
264 def redo_assignment(self, new_grade: int, assignment: str, date: str):
265 """
266 Update the grade for given assignment.
267
268 This function is only used when an assignment has been attempted at least once before. Keep in mind that you
269 need to also keep the history of grades, not create a new grade!
270 """
271 pass
272
273 def calculate_weighted_average(self):
274 """
275 Calculate the weighted average of grades.
276
277 You should take into account the weights. There are three weights: 1, 2 and 3, where 3 means that one grade of
278 weight 3 is the same as three grades of weight 1.
279
280 For example:
281 if there are grades 4 with weight 3 and 3 with weight 1, then the resulting value will be
282 (4 * 3 + 3 * 1) / (3 + 1) = 15 / 4 = 3.75
283 which will be rounded to 4.
284
285 Also make sure not to miss out when a grade is noted as "!". If there is no attempt to redo this, then "!"
286 should be equivalent to grade "1".
287 """
288 pass
289
290
291class Class:
292 """Class #7."""
293
294 def __init__(self, teacher: str, students: list):
295 """Constructor."""
296 self.teacher = teacher
297 self.students = students
298
299 def add_student(self, student: Student):
300 """Add student to the class."""
301 pass
302
303 def add_students(self, students: list):
304 """Add several students to the class."""
305 pass
306
307 def remove_student(self, student: Student):
308 """Remove student from the class."""
309 pass
310
311 def get_grade_sheet(self):
312 """
313 Return grade sheet as a table.
314
315 Grade sheet includes information of all the students in the class and their final grades.
316 All edges should be either "|" or "-".
317 First column is student's name and the second column is the final grade (weighted average).
318 First, second and third row should look something like this (notice the capital letters):
319 ----------------------
320 | Name | Final grade |
321 ----------------------
322
323 Make sure that all the columns are correctly aligned after the longest element.
324 For example, consider following rows:
325 | Ago | 5 |
326 | Some really long name | 3 |
327
328 Rules are following:
329 Each row (except for "-----" rows) starts with "|" and a space " " and ends with a space " " and "|".
330 Text in "Name" column needs to be aligned to left
331 Grades in "Final grade" column need to be centered
332
333 Students in the table should follow the order which they were added to the class.
334
335 The whole table would look something like this:
336 ---------------------------------------
337 | Name | Final grade |
338 ---------------------------------------
339 | Ago | 5 |
340 | Johannes | 4 |
341 | Mari | 5 |
342 | Some really long name | 3 |
343 ---------------------------------------
344
345 """
346 pass
347
348
349if __name__ == '__main__':
350 assert sum_of_multiples(20, 5) == 30
351
352 assert mix_string("AAA", "bbb") == "AbAbAb"
353
354 assert bingo([
355 [5, 7, 11, 15, 21],
356 [22, 25, 26, 27, 9],
357 [34, 2, 48, 54, 58],
358 [59, 61, 33, 81, 24],
359 [90, 37, 3, 6, 32],
360 ], [5, 21, 90, 32]) == (True, False, False)
361
362 assert bingo([
363 [5, 7, 11, 15, 21],
364 [22, 25, 26, 27, 9],
365 [34, 2, 48, 54, 58],
366 [59, 61, 33, 81, 24],
367 [90, 37, 3, 6, 32],
368 ], [5, 21, 90, 32, 25, 48, 81, 27, 61, 91]) == (True, True, False)
369
370 assert can_reach([4, 2, 3, 0, 3, 1, 2], 5) is True
371
372 assert prime_factorization(1960) == {2: 3, 5: 1, 7: 2}
373
374 candy_shop = CandyShop()
375 candy1 = Candy('candy1', 'chocolate')
376 candy2 = Candy('candy2', 'caramel')
377 candy3 = Candy('candy3', 'nut')
378 candy4 = Candy('candy1', 'chocolate')
379 candy5 = Candy('candy2', 'vanilla')
380 candy6 = Candy('candy2', 'vanilla')
381 candy7 = Candy('candy3', 'nut')
382 candy8 = Candy('candy1', 'chocolate')
383
384 candies = [candy1, candy2, candy3, candy4, candy5, candy6, candy7, candy8]
385
386 candy_shop.add_candies(candies)
387
388 # NB! there are candy variable names in comments, not instance name parameter values!!!
389
390 print(candy_shop.get_candies_by_filling('chocolate')) # [candy1, candy4, candy8]
391 print(candy_shop.get_least_popular_candy_name_and_filling()) # {name: candy2, filling: caramel}
392 print(candy_shop.get_most_popular_candy_name_and_filling()) # {name: candy1, filling: chocolate}
393 print(candy_shop.sort_candies_by_filling()) # [candy2, candy1, candy4, candy8, candy7, candy3, candy6, candy5]
394 print(candy_shop.collect_candies_by_filling()) # {chocolate: [candy1, candy4, candy8],
395 # caramel: [candy2],
396 # nut: [candy3, candy7],
397 # vanilla: [candy5, candy6]}
398
399 # Teacher, grade, student
400 mari = Student("Mari Maa")
401 jyri = Student("Jyri Jogi")
402 teele = Student("Teele Tee")
403 cl = Class("Anna", [mari, jyri, teele])
404 mari.grade(Grade(5, 3, "KT", "01/09/2020"))
405 gr = Grade("!", 3, "KT", "01/09/2020")
406 jyri.grade(gr)
407 teele.grade(Grade(4, 3, "KT", "01/09/2020"))
408
409 print(f"Jyri keskmine hinne on {jyri.calculate_weighted_average()}.") # 1
410
411 jyri.redo_assignment(3, "KT", "14/09/2020")
412 print(len(gr.previous_grades)) # 1
413
414 print(f"Jyri keskmine hinne on nyyd {jyri.calculate_weighted_average()}.") # 3
415 print()
416
417 mari.grade(Grade(5, 1, "TK", "30/11/2020"))
418 jyri.grade(Grade(4, 1, "TK", "30/11/2020"))
419 teele.grade(Grade(3, 1, "TK", "30/11/2020"))
420
421 print(f"Teele keskmine hinne on {teele.calculate_weighted_average()}.") # 4
422 print(cl.get_grade_sheet())
423 print()
424
425 tuuli = Student("Tuuli Karu")
426 cl.add_student(tuuli)
427 print(len(cl.students)) # 4
428