""" ################################################################################# MIDTERM EXAM ASSIGNMENT RULES ################################################################################# - You are strictly forbidden to share answers with your classmates. - You are not allowed to search for answers on the Internet. You are not allowed to ask for answers in forums or other online communication systems. - Note that, when you find an answer on the web, somebody else will also find it and use it. This means, both of you will submit the exact same answer. This, then, means cheating, regardless of whether you know the other person or not. - If your answers are similar to some other student's answers, you will enter manual cheat check process. We don't care whether you know the other person or not, we don't care whether he/she is your friend or not, we don't care who delivered and who received. Both parties get a discipline penalty if found guilty. - You are not allowed to import any packages. If there are any imports in your submission, we will remove them before grading. - If your file doesn't compile, then you receive 0. Make sure that your indentation and syntax is correct. - Do not change the below function definitions. In other words, DO NOT CHANGE the function names and the parameters of the functions. You are only allowed to write code within the function scope. - Do not print anything on the screen unless you are asked to. Some questions require you to RETURN a value. Printing that value on the screen is not equal to returning the value. - Do not submit any testing code. ################################################################################# DO NOT FORGET TO FILL THE LINES BELOW: My full name : _______________ My student ID : _______________ My department : _______________ """ """ ################################################################################# Question 1: (20 points) Topics: lists, tuples, dictionaries, exceptions ################################################################################# Write a function translate(word_list, dictionary) that will RETURN the list of translated words given as the first argument word_list, based on the dictionary given as the second function argument dictionary. Inputs: 1. word_list - a Python list of strings, e.g., ['blue', 'slim', 'pencil'] 2. dictionary - a Python dictionary such that the key is a string (word in English), and the value is a list of tuples where each tuple (translation, probability) is defined as follows: - translation is a string (word in Turkish) - probability is the probability of translation being the correct translation (and given between 0 and 1). E.g., dictionary = { 'blue': [('mavi', 0.8), ('deniz', 0.10), ('sınav', 0.10)], 'slim': [('ince', 0.6), ('narin', 0.4)], 'pencil': [('kalem', 0.4), ('kurşunkalem', 0.5), ('ibik', 0.1)] } Here, the word 'blue' can have three different translations in Turkish: 'mavi', 'deniz', or 'sinav', but the word 'mavi' is the most likely correct translation with the probability of 0.8. Output: The function should RETURN a list of strings such that each element is the Turkish translation of the original word from the word_list WITH THE HIGHEST PROBABILITY. If any word from the word_list is not in the dictionary, then it should be left in English. Exceptions Rule: You MUST use try-except block(s) to handle the KeyError exception in case the word is not in the dictionary. If-else solutions WILL BE GIVEN PENALTIES! ------------ Sample test case 1 --------------- word_list = ['blue', 'slim', 'pencil'] dictionary = { 'blue': [('mavi', 0.8), ('deniz', 0.10), ('sınav', 0.10)], 'slim': [('ince', 0.6), ('narin', 0.4)], 'pencil': [('kalem', 0.4), ('kurşunkalem', 0.5), ('ibik', 0.1)] } print(translate(word_list, dictionary)) --------------- Expected output --------------- ['mavi', 'ince', 'kurşunkalem'] ------------ Sample test case 2 --------------- word_list = ['blue', 'slim', 'pencil'] dictionary = { 'blue': [('mavi', 0.8), ('deniz', 0.10), ('sınav', 0.10)], 'pencil': [('kalem', 0.4), ('kurşunkalem', 0.5), ('ibik', 0.1)] } print(translate(word_list, dictionary)) --------------- Expected output --------------- ['mavi', 'slim', 'kurşunkalem'] """ def translate(word_list, dictionary): # You must first remove this empty return line to answer this question. # Do not remove it if you will leave this question unanswered. return """ ################################################################################# Question 2: (20 points) Topics: lists, dictionaries, exceptions ################################################################################# Write a function calculate_letter_grades(course_list) that takes a course list as an argument and RETURNs a dictionary with calculated students' grades in a very specific format as described below. Input: course_list - a Python list of lists such that each element list is in the form of ['student_name', 'student_number', 'course_code', [list_of_grades_as_floats]] E.g., course_list = [ ['Ali Velli', '215987523', 'müh101', [70.0, 60.0, 80.0]], ['Veli Ballı', '211487524','müh101', [20.0, 0.0, 40.0]] ] Output: The function should RETURN a dictionary in the following format: The key will be the student_number as a string, the value will be a list with student stats: [student_name, course_name, average_grade, letter_grade] E.g., for the given input list above the returned dictionary should be { '215987523': ['Ali Velli', 'müh101', 70.0, 'C'], '211487524': ['Veli Ballı', 'müh101', 20.0, 'F'] } Calculations: 1. To calculate the average grade you should sum all grades and devide by the total number of grades for each student: average_grade = sum(list_of_grades)/len(list_of_grades) Potential problems (IndexError, ZeroDivisionError, ValueError): a) grades list can be empty (for this exception, the average grade should taken as 0.0), b) some of the grades may not be a valid number (invalid grade entry should be disregarded and left out of the average grade calculations) (See more sample test cases below). 2. After obtaining the average grade, to calculate the letter grade use the following rules: # If 90 <= average_grade <= 100 -> letter_grade = 'A' # If 75 <= average_grade < 90 -> letter_grade = 'B' # If 55 <= average_grade < 75 -> letter_grade = 'C' # If 50 <= average_grade < 55 -> letter_grade = 'D' # If average_grade < 50 -> letter_grade = 'F' Exceptions Rules: You MUST use try-except block(s) to handle all of the possible exceptions discussed above. If-else solutions WILL BE GIVEN PENALTIES! ------------ Sample test case 1 --------------- my_list = [ ['Ali Velli', '215987523', 'müh101', [70.0, 60.0, 80.0]], ['Veli Ballı', '211487524','müh101', [20.0, 0.0, 40.0]] ] print(calculate_letter_grades(my_list)) --------------- Expected output --------------- {'215987523': ['Ali Velli', 'müh101', 70.0, 'C'], '211487524': ['Veli Ballı', 'müh101', 20.0, 'F']} ------------ Sample test case 2 --------------- my_list = [ ['Ali Velli', '215987523', 'müh101', [70.0, 60.0, 80.0]], ['Veli Ballı', '211487524','müh101', [20.0, None, 40.0]] ] print(calculate_letter_grades(my_list)) --------------- Expected output --------------- {'215987523': ['Ali Velli', 'müh101', 70.0, 'C'], '211487524': ['Veli Ballı', 'müh101', 30.0, 'F']} ------------ Sample test case 3 --------------- my_list = [ ['Ali Velli', '215987523', 'müh101', [100.0, 100.0, 70.0]], ['Veli Ballı', '211487524','müh101', [20.0, 'zero', 40.0]] ] print(calculate_letter_grades(my_list)) --------------- Expected output --------------- {'215987523': ['Ali Velli', 'müh101', 90.0, 'A'], '211487524': ['Veli Ballı', 'müh101', 30.0, 'F']} """ def calculate_letter_grades(course_list): # You must first remove this empty return line to answer this question. # Do not remove it if you will leave this question unanswered. return """ ################################################################################# Question 3: (15 points) Topics: dictionaries, tuples ################################################################################# Write a function character_statistics(text) that RETURNs the statistics for each character in the given string text in the form of a dictionary where the key is the character, and the value is a tuple (char_frequency, occurrence_rate). # Write a function that returns the frequency and occurrence rate of # each character in a string. # The results must be returned as a dictionary where key is the character, # and value is a tuple (frequency, rate) Input: text - a string of an arbitrary length. E.g., text = "aaaa bbbb cccc dddd " Output: The function should RETURN a dictionary in the form: { char_1 : (char_1_count, char_1_occurrence_rate_in_text), char_2 : (char_2_count, char_2_occurrence_rate_in_text), ... char_n : (char_n_count, char_n_occurrence_rate_in_text) } E.g., for the given input string "aaaa bbbb cccc dddd " the returned dictionary should be: { 'a': (4, 0.2), ' ': (4, 0.2), 'b': (4, 0.2), 'c': (4, 0.2), 'd': (4, 0.2) } Calculations: 1. To calculate the frequency (count) of a character in text, you need to count the total number of its occurences in the text. E.g., character 'a' is found in 4 places in "aaaa bbbb cccc dddd ", so its frequency is 4. 2. To calculate the occurrence rate of a character in text, you need to divide its frequency with the total length of the text. E.g., the count of the character 'a' is 4 and the total length of the input string is 20, so its occurrence rate is 4/20 = 0.2 ------------ Sample test case 1 --------------- text = "abcdefghij" print(character_statistics(text)) --------------- Expected output --------------- {'a': (1, 0.1), 'b': (1, 0.1), 'c': (1, 0.1), 'd': (1, 0.1), 'e': (1, 0.1), 'f': (1, 0.1), 'g': (1, 0.1), 'h': (1, 0.1), 'i': (1, 0.1), 'j': (1, 0.1)} ------------ Sample test case 2 --------------- text = "aaaaaaaaaaaaaaaaaaaaaaaaaaaa" print(character_statistics(text)) --------------- Expected output --------------- {'a': (28, 1.0)} """ def character_statistics(text): # You must first remove this empty return line to answer this question. # Do not remove it if you will leave this question unanswered. return """ ################################################################################# Question 4: (15 points) Topics: Testing, Debugging ################################################################################# An important step of the merge sort algorithm is merging two lists with respect to the order of the items in the lists. The following code merges two given sorted lists and returns the merged result as a list. You have to add PRINT statements to this code, such that when executed it produces a result like the following: --------------- Sample test case --------------- merge([1,3], [2,6,9]) --------------- Expected PRINTED Output --------------- Entering while -> li3: [] i: 0 j: 0 li1 has item li2 has item appended from li1: 1 li3 after append: [1] Entering while -> li3: [1] i: 1 j: 0 li1 has item li2 has item appended from li2: 2 li3 after append: [1, 2] Entering while -> li3: [1, 2] i: 1 j: 1 li1 has item li2 has item appended from li1: 3 li3 after append: [1, 2, 3] Entering while -> li3: [1, 2, 3] i: 2 j: 1 appended from li2: 6 li3 after append: [1, 2, 3, 6] Entering while -> li3: [1, 2, 3, 6] i: 2 j: 2 appended from li2: 9 li3 after append: [1, 2, 3, 6, 9] """ def merge(li1, li2): i, j = 0, 0 li3 = [] while i < len(li1) or j < len(li2): if i < len(li1): if j < len(li2): if li1[i] <= li2[j]: li3.append(li1[i]) i += 1 else: li3.append(li2[j]) j += 1 else: li3.append(li1[i]) i += 1 else: li3.append(li2[j]) j += 1 return li3 """ ################################################################################# Question 5: (15 points) Topics: Testing, tuples, lists ################################################################################# Write a function tester(arg_list, exp_results) to test an unknown function 'foo'. Your function takes a list of argument tuples and calls the 'foo' function with them. You also receive expected values for each argument set in a seperate list. Your function then RETURNs a list of booleans (True/False) such that each boolean corresponds to a test case and the result is True if the expected result and the actual result from the foo function matches, otherwise it is False. - You don't know the foo function. - You don't know how many arguments foo receives. - Your function must be flexible for any kind of foo function. HINT: Refer to https://note.nkmk.me/en/python-argument-expand/ for an explanation of how to send the items of a tuple as arguments to a function. Example: Assume foo function is declared as below: #################### def foo(a,b,c): return a+b+c #################### --------------- Sample test case --------------- print(tester([(1,2,3), (2,3,4), (3,4,5)], [6,9,12])) --------------- Expected RETURNED Output --------------- [True, True, True] """ def tester(arg_list, exp_results): # You must first remove this empty return line to answer this question. # Do not remove it if you will leave this question unanswered. return """ ################################################################################# Question 6: (15 points) Topics: Lists ################################################################################# Write a function board_check(b, nrow, ncol) that takes a bit string b, an int nrow, and an int ncol as input. The b is a board of nrow rows, and ncol columns. This board is valid if on this board the following rules apply: 1- There are no 2 by 2 squares full of 0s 2- There are no 2 by 2 squares full of 1s If the board is valid, your function must RETURN a tuple as follows: (True, nrow*ncol) where nrow and ncol are the dimensions of the board. Otherwise, it RETURNS a LIST OF TUPLES where each tuple's first two elements represent the cell on the board where one or more of the rules fail, and the remaining elements represent the rules violated. For example, (12, 4, 1) means cell (12,4) violates rule 1. RETURN only the top-left corner of the 2x2 square if there is a violation. The bit string b is provided by row. So the first ncol elements are the first row, the next ncol elements are the second row etc. --------------- Sample test case 1 --------------- # 1010 # 0101 # 1010 # 0101 print(board_check("1010010110100101", 4, 4)) --------------- Expected Output --------------- (True, 16) --------------- Sample test case 2 --------------- # 1110 # 1101 # 1000 # 0100 print(board_check("1110110110000100", 4, 4)) --------------- Expected Output --------------- [(0, 0, 2), (2, 2, 1)] """ def board_check(b, nrow, ncol): # You must first remove this empty return line to answer this question. # Do not remove it if you will leave this question unanswered. return