, , , , ,

[SOLVED] CSC110Y1F Final Examination 2022 Python

$25

File Name: CSC110Y1F_Final_Examination_2022_Python.zip
File Size: 367.38 KB

5/5 - (1 vote)

CSC110Y1F (All Sections)

Final Examination

Date: December 2022 Examination Period

1. [15 marks] Short answer.

(a) [3 marks] Each of the following interactions in the Python console ends with an expression and blank space. For each one, write the value that would be displayed.  If evaluating the code would cause an error,

write  “ERROR” and briefly  explain why the  error would occur.

>>>  len(‘CSC110’)  +  len({‘abc’})

>>>  {‘hi’:  2,  ‘bye’:  3}[2]

>>>  sum([x  *  2  for  x  in  [1,  3,  5]  if  x  >  2])

>>>  words  =  [‘chocolate’,  ‘orange’,  ‘is’,  ‘tasty’]

>>>  words[1][0]  +  words[0][1]  +  words[3][0]

>>> my_stack  =  Stack1()   #  Assume  this  is  a  valid  Stack  implementation

>>> my_stack.push(1)

>>> my_stack.push(2)

>>> my_stack.pop()

>>>  numbers  =  [10,  1,  3]

>>>  numbers  =  list.sort(numbers)

>>>  numbers[0]

(b) [5 marks] Answer each of the following questions.  You only need 1-3 sentences per response.

(i)  David says, “The Python interpreter allows us to access private instance attributes of a class, so it’s useless to mark instance attributes as private.” Explain why David is incorrect.

(ii)  Tom says, “The Diffie-Hellman algorithm is an example of a symmetric-key cryptosystem.” Explain why Tom is incorrect.

(iii)  Define the term abstract method.

(iv) In our Python files, we typically write testing code like doctest.testmod() inside an if statement, if name ==  ‘ main ’ . Explain why we do this.

(v) In our run simulation function, we used a priority queue (events) to store the simulation’s events. For your reference, here is the main simulation loop code:

while  not  events .is_empty():

event  =  events.dequeue()

new_events  =  event.handle_event(system)

for  new_event  in  new_events:

events.enqueue(new_event)

Explain why we used a priority queue instead of a queue.

(c) [3 marks] Consider the following code:

@dataclass

class  Person:

“””A  person .

Instance  Attributes:

–  name:  The  name  of  this  person .

–  pet:  A  pet  dog  that  this  person  owns,  or  None  if  this  person  does  not own  a  pet  dog .

“””

name:  str

pet:  Optional[Dog]  =  None

@dataclass

class  Dog:

“””A  pet  dog .

Instance  Attributes:

–  name:  The  name  of  this  dog .

–  owner:  The  person  who  owns  this  dog .

“””

name:  str

owner:  Person

(i) What does the type annotation Optional[Dog] (for pet) mean?

(ii)  Translate the following Person representation invariant into valid Python code:  “If this person (self) owns a pet dog, then that dog’s owner is the same object as self.”

(d) [4 marks] Consider the following function definition, which uses the defintions from the previous part.

def  get_dog(person:  Person,  dog_name:  str)  ->  Dog:

“””Modify  the  given  person  to  become  the  owner  of  a  new  dog  named  dog_name . Return  the  new  dog .

Preconditions:

–  person.pet  is  None

“””

#  MARKER  A

new_dog  =  Dog(name=dog_name,  owner=person) person.pet  =  new_dog

#  MARKER  B

return  new_dog

Suppose we run this function in the Python console and execute the following code:

>>>  tom  =  Person(name=’Tom’) >>>  get_dog(tom,  ‘Fluffy’)

The object-based memory model diagram below shows the state of memory at MARKER  A, when get dog is first called.

Modify the diagram to show the the state of memory at MARKER  B, immediately before get dog returns. You may need to add additional boxes for new objects, and/or modify existing parts of the diagram.

2. [9 marks] Programming.

(a) [4 marks] Implement the following function, according to its docstring.  You must use comprehension expressions in your solution, and may not use loops.

You may, but are not required to, define a helper function in your solution.  Any helper functions you define must include type annotations but do not need to include a docstring.

def  len_special_lists(lists_of_numbers:  list[list[int]])  ->  list[int]: “””Return  the  lengths  of  the  given  lists  of  numbers  that  contain

at  least  one  even  integer .

>>>  lists1  =  [[1,  3],  [110],  [1,  2,  3,  4]]

>>>  len_special_lists(lists1)   #  [110]  and  [1,  2,  3,  4]  have  at  least  one  even  integer [1,  4]

>>>  lists2  =  [[],  [1],  [1,  3,  5,  7]]

>>>  len_special_lists(lists2)   #  No  list  has  at  least  one  even  integer []

“””

#  TODO:  write  your  function  body  here

(b) [5 marks] This part considers a function nutrient totals with two parameters:

•  foods:    set[str]. A set of foods in a meal, for example: {‘twinkie’,  ‘fries’}

•  food to nutrients:   dict[str,  dict[str,  int]]. A nested dict that stores the number of grams of  ‘carbs’ , ‘protein’, and ‘fat’ in different food items. For example:

{‘twinkie’:       {‘carbs’:  47,  ‘protein’:  2,   ‘fat’:  9  }, ‘fries’:             {‘carbs’:  40,  ‘protein’:  3,   ‘fat’:  17}, ‘protein  bar’:  {‘carbs’:  21,  ‘protein’:  20,  ‘fat’:  5  }}

nutrient totals returns a new dict containing the total number of grams of ‘carbs’ , ‘protein’, and ‘fat’ across all of the given foods.

Complete function nutrient totals by implementing the function body. You may  not  define any helper functions.

def  nutrient_totals(foods:  set[str],

food_to_nutrients:  dict[str,  dict[str,  int]])  ->  dict[str,  int]: “””See  description  above .

Preconditions:

–  all(food  in  food_to_nutrients  for  food  in  foods)

–  food_to_nutrients  is  in  the  format  described  above

>>>  f_to_n  =  {‘twinkie’:       {‘carbs’:  47,  ‘protein’:  2,    ‘fat’:  9  }, . . .                      ‘fries’:             {‘carbs’:  40,  ‘protein’:  3,   ‘fat’:  17}, . . .                      ‘protein  bar’:  {‘carbs’:  21,  ‘protein’:  20,  ‘fat’:  5  }} >>>  actual  =  nutrient_totals({‘twinkie’,  ‘fries’},  f_to_n)

>>>  expected  =  {‘carbs’:  47  +  40,  ‘protein’:  2  +  3,  ‘fat’:  9  +  17} >>>  actual  ==  expected

True “””

#  Accumulate  the  result  in  the  following  provided  dict   nutrients_so_far  =  {‘carbs’:  0,  ‘protein’:  0,  ‘fat’:  0}

#  TODO:  complete  the  body  of  the  function

return  nutrients_so_far

3. [5 marks] Debugging and testing.

Consider the following function definition.

def  space_counts(strings:  list[str])  ->  list[int]:

“””Return  the  number  of  space  characters  in  each  given  string .

>>>  space_counts([‘Tom’,  ‘David  is  cool’]) [0,  2]

“””

spaces_so_far  =  0   counts_so_far  =  []

for  string  in  strings:   for  char  in  string:

if  char  ==  ‘   ‘:                 #  Check  whether  char  is  a  space spaces_so_far  +=  1

list.append(counts_so_far,  spaces_so_far) return  counts_so_far

This implementation of space counts does pass the doctest example, but actually has a subtle error, and so is not correct on all possible inputs to the function.

(a) [2 marks] Complete the unit test below to show an example valid input to space counts that will cause the test to fail because this implementation returns an incorrect value.

def  test_space_counts_error()  ->  None:

“””A  test  case  for  space_counts  that  reveals  an  error  in  the  given  implementation .

If  we  ran  this  test  with  pytest  and  the  current  implementation,  we  would  expect this  test  to  *fail*  because  of  the  error  in  the  function  body .

“””

actual  =  space_counts(                                                                                    )  #  FILL  THIS  IN

expected  =                                                                                                              #  FILL  THIS  IN

assert  actual  ==  expected

(b) [1 mark] Explain what is the error in the given implementation.  Do not explain how to fix the error here.

(c) [1 mark] Explain how to fix the error.

(d) [1 mark] Explain why the doctest example passes for the given implementation of  space counts, even though that implementation has an error. For your reference, here is the doctest example:

>>>  space_counts([‘Tom’,  ‘David  is  cool’]) [0,  2]

4. [6 marks] Number theory. Consider the following statement:

“For all integers a, b, and c, IF gcd(a,b) = 1 and a divides bc, THEN a divides c.”

(a) [1 mark] Translate the above statement into symbolic logic. You may use the gcd function and divisibility symbol | in your translation; do not expand the definition of divisibility.

(b) [5 marks] Prove the above statement.

Your proof may use any definitions and theorems provided on the Reference Sheets, but no other theo- rems/properties of divisibility or modular equivalence. We have left space for rough work here and on the next page, but please write your formal proof in the box below.

Hint: use the GCD Characterization Theorem and multiply an equation by c.

5. [9 marks] Object-Oriented Modelling.

In this question, you will write Python code to model students and courses at a university.

(a) [5 marks] First you’ll create a data class to represent a student, based on the following description:

A student has a user name (e.g., ‘liudavid’) and a mapping to keep track of courses they have passed, where each key of the mapping is a course code (e.g.,  ‘CSC110’) and the associated value is the integer grade they received in that course (e.g., 85).

Each student must satisfy the following properties:

1.  The student’s user name is non-empty.

2.  Every grade associated with a passed course is between 50 and 100, inclusive.

In the space below, complete the data class by writing instance attribute names and type annotations in the class body and appropriate representation invariants in the docstring.

NOTE: You may not use the dict .values method in this question.

@dataclass

class  Student:

“””A  class  representing  a  university  student .

NOTE:  you  do  not  need  to  write  English  descriptions  of  the  instance  attributes . Just make  sure  to  pick meaningful  attribute  names  in  the  class  body .

Representation  Invariants:    (TODO:  write  appropriate  representation  invariants  here)

“””

#  TODO:  write  appropriate  instance  attribute  names  and  type  annotations  here

(b) [4 marks] In the space below, we’ve begun a class Course to represent a university course.

class  Course:

“””A  class  representing  a  university  course .

Instance  Attributes:

–  code:  This  course’s  course  code,  e.g .  ‘CSC110’

–  students:  A  list  of  students  currently  enrolled  in  this  course

Representation  Invariants:

–  every  student  in  self .students  has  a  unique  user  name

“””

code:  str

students:  list[Student]

Complete the following method for the Course class. You may not define any helper functions.

class  Course:

. . .  #  continued  from  above

def  enrol(self,  student:  Student)  ->  bool:

“””Enrol  the  given  student  in  this  course  and  return  whether the  student  was  successfully  enrolled .

Do  NOT  enrol  the  student  if  either:

1 .  The  student  has  already  passed  this  course  (i .e . ,  this  course’s  code  is in  the  student’s  “passed  courses” mapping) .

2 .  There  is  a  student  with  the  same  user  name  already  enrolled  in  this  course .

(In  those  two  cases,  False  should  be  returned.)

“””

6. [6 marks] Runningtime analysis.

Analyse the running time of the following function, in terms of n, the length of its input list, and/or the input value m. To simplify your analysis, you may ignore the running time of Line 4.

def loopy(numbers: list[int], m: int) -> None:

# Line

1

“””Precondition: m >= 0″””

# Line

2

for number  in numbers:

# Line

3 (Loop

1)

i = 1

# Line

4

while i < m:

# Loop

5 (Loop

2)

i = i * 3

# Loop

6

print(i + number)

# Loop

7

print(sum(numbers))

# Loop

8

Note: for all lists x, sum(x) takes len(x) steps.

7. [7 marks] Worst-case running-time analysis. You are given the following function:

def  f(numbers:  list[int], m:  int)  ->  None: “””Precondition: m  >=  0″””

for  i  in  range(0, m): if  i  in  numbers:

print(‘Found’) else:

print(‘Not  found’)

(a) [5 marks] Perform. a lower bound analysis of the worst-case running time of this function, in terms of n, the length of numbers, and/or the input value m.  The Omega expression that you conclude should be tight, meaning that the worst-case running time should be Theta of this expression, but you are not required to show that.

(b) [2  marks] Suppose we modify f so that the numbers parameter is a set[int] instead of a list[int]. How would the running time of this function change?  Briefly explain your answer, but do not  perform a formal running-time analysis.

8. [3 marks]  Stacks/Queues/Priority Queues ADTs.

Warning: this is meant to be a challenging question, and is deliberately weighted less than other questions. We strongly recommend completing the rest of this  exam  before  attempting  this question.

Implement the following function, according to its docstring. You may not define any helper functions.

def  pop_biggest(stacks:  list[Stack])  ->  int:

“””Remove  and  return  the maximum  item  that  is  on  the  top  of  one  of  the  given  stacks . Return  0  if  all  given  stacks  are  empty .

Preconditions:

–  the  top  element  of  each  stack  is  an  int  and  is  >  0

–  the  top  element  of  each  stack  is  unique  (so  don’t  worry  about  ties)

“””

#  TODO:  write  your  function  body  here

Reviews

There are no reviews yet.

Only logged in customers who have purchased this product may leave a review.

Shopping Cart
[SOLVED] CSC110Y1F Final Examination 2022 Python
$25