Lösningsförslag 2022-08-17#
Del A#
Lösning A1
Rätt alternativ: D
Kommentarer: Den officiella dokumentationen säger: ”A module is a file containing Python definitions and statements.” En modul kan alltså innehålla script-kod. Ett paket (package) är en samling av paket och moduler, dvs. inte samma sak som en modul.
Kursen går inte igenom .pym-filer, så ni förväntas inte veta vad det är.
Lösning A2
Rätt alternativ: C
Kommentar: Operatorn + innebär konkatenering (=ihopslagning) för strängar.
Lösning A3
Rätt alternativ: B
Kommentarer: Variabeln pinch_of_salt
definieras i funktionen add_pinch_of_salt
som en lokal variabel. Denna är helt orelaterad till variabeln pinch_of_salt
i det globala scopet.
Lexikonet cake
används i funktionen utan att ha definierats lokalt. Därför används cake
från det globala scopet. Förändringen av cake
sker alltså även i det globala scopet.
Motiveringen är tyvärr inte helt korrekt. Att den globala variabeln pinch_of_salt
är oförändrad efter funktionsanropet beror inte på att floats är oföränderliga (vilket visserligen är sant) utan på att pinch_of_salt
i funktionen är en lokal variabel som inte påverkar den globala variabeln med samma namn.
Lösning A4
Rätt alternativ: C
Lösning A5
Rätt alternativ: D
Lösning A6
Rätt alternativ: C
Lösning A7
Rätt alternativ: B
Lösning A8
Rätt alternativ: D
Lösning A9
Rätt alternativ: B
Lösning A10
Rätt alternativ: C
Del B#
B1#
Lösningsförslag
class Pizza:
def __init__(self, flour, topping, crust):
self.flour = flour
self.topping = topping
self.crust = crust
B2#
Lösningsförslag
class Pizza:
def __init__(self, flour, topping, crust):
self.flour = flour
self.topping = topping
self.crust = crust
available_flour = ['white', 'brown', 'wholegrain']
available_toppings = ['mozzarella', 'cheddar', 'gorgonzola']
available_crusts = ['thin', 'sicilian', 'focaccia']
if flour in available_flour and topping in available_toppings and crust in available_crusts:
self.startBaking() # Only works if the method startBaking is implemented
else:
print('Pizza aborted, one of the input ingredients is out of stock.')
B3#
Lösningsförslag
import time
class Pizza:
def __init__(self, flour, topping, crust):
self.flour = flour
self.topping = topping
self.crust = crust
available_flour = ['white', 'brown', 'wholegrain']
available_toppings = ['mozzarella', 'cheddar', 'gorgonzola']
available_crusts = ['thin', 'sicilian', 'focaccia']
if flour in available_flour and topping in available_toppings and crust in available_crusts:
self.startBaking()
else:
print('Pizza aborted, one of the input ingredients is out of stock.')
def startBaking(self):
self.ready = False # True/False instead of suggested 1 or 0.
self.time_start = time.time()
B4#
Lösningsförslag
def isReady(self):
time_limit = 5*60 # 5 minutes converted to seconds
time_passed = time.time() - self.time_start
if time_passed > time_limit:
self.ready = True
print(f'Pizza with {self.topping} topping, {self.flour} flour dough and {self.crust} crust is ready!')
else:
time_remaining = (time_limit - time_passed)/60
print(f'Pizza with {self.topping} topping, {self.flour} flour dough and {self.crust} crust is still in the oven!')
print(f'Wait for another {time_remaining:.2f} minutes.')
B5 (class Pizzeria)#
Lösningsförslag
import random
class Pizzeria:
def __init__(self, N):
available_flour = ['white', 'brown', 'wholegrain']
available_toppings = ['mozzarella', 'cheddar', 'gorgonzola']
available_crusts = ['thin', 'sicilian', 'focaccia']
# Create N pizzas with random flour, topping, and crust
self.allPizzas = []
for _ in range(N):
flour = available_flour[random.randint(0, len(available_flour)-1)]
topping = available_toppings[random.randint(0, len(available_toppings)-1)]
crust = available_crusts[random.randint(
0, len(available_crusts)-1)]
self.allPizzas.append(Pizza(flour, topping, crust))
def priceOfAllPizzas(self):
number_of_pizzas = len(self.allPizzas)
flour_prices = {'white':10, 'brown':15, 'wholegrain':20}
topping_prices = {'mozzarella': 3, 'cheddar': 6, 'gorgonzola': 9}
crust_prices = {'thin': 2, 'sicilian': 4, 'focaccia': 7}
cost = 0
all_ingredients_available = True
for pizza in self.allPizzas:
if pizza.topping not in topping_prices:
all_ingredients_available = False
if pizza.flour not in flour_prices:
all_ingredients_available = False
if pizza.crust not in crust_prices:
all_ingredients_available = False
cost += topping_prices[pizza.topping]
cost += flour_prices[pizza.flour]
cost += crust_prices[pizza.crust]
if all_ingredients_available:
print(f'The total cost for {number_of_pizzas} pizzas is {cost} units.')
else:
print('One or more ingredients unavailable. Order aborted')
B6 (extra topping)#
Frågan är inte helt tydlig. Här tolkar vi det som att den extra toppingen läggs till som en ytterligare instansvariabel, här med namn extra_topping
.
Lösningsförslag
För att få med den extra toppingen i utskriften av isReady()
ändrar vi i konstruktorn och isReady()
när metoden addExtraTopping()
läggs till.
def __init__(self, flour, topping, crust):
self.flour = flour
self.topping = topping
self.crust = crust
self.extra_topping = ''
available_flour = ['white', 'brown', 'wholegrain']
available_toppings = ['mozzarella', 'cheddar', 'gorgonzola']
available_crusts = ['thin', 'sicilian', 'focaccia']
if flour in available_flour and topping in available_toppings and crust in available_crusts:
self.startBaking()
else:
print('Pizza aborted, one of the input ingredients is out of stock.')
def isReady(self):
time_limit = 5*60 # 5 minutes converted to seconds
time_passed = time.time() - self.time_start
if self.extra_topping == '':
extra_topping_str = ''
else:
extra_topping_str = f'extra {self.extra_topping}, '
if time_passed > time_limit:
self.ready = True # True/False instead of suggested 1 or 0.
print(f'Pizza with {extra_topping_str}{self.topping} topping, {self.flour} flour dough and {self.crust} crust is ready!')
else:
time_remaining = (time_limit - time_passed)/60
print(f'Pizza with {extra_topping_str}{self.topping} topping, {self.flour} flour dough and {self.crust} crust is still in the oven!')
print(f'Wait for another {time_remaining:.2f} minutes.')
def addExtraTopping(self, topping):
allowed = ['prosciutto', 'funghi', 'pineapple']
if not self.ready:
if topping in allowed:
self.extra_topping = topping
else:
print('That topping is not available!')
else:
print("Can't add topping, pizza is already done!")
B1-B6#
Lösningsförslag med enkel testkod.
import time
import random
class Pizza:
def __init__(self, flour, topping, crust):
self.flour = flour
self.topping = topping
self.crust = crust
self.extra_topping = ''
available_flour = ['white', 'brown', 'wholegrain']
available_toppings = ['mozzarella', 'cheddar', 'gorgonzola']
available_crusts = ['thin', 'sicilian', 'focaccia']
if flour in available_flour and topping in available_toppings and crust in available_crusts:
self.startBaking()
else:
print('Pizza aborted, one of the input ingredients is out of stock.')
def startBaking(self):
self.ready = False # True/False instead of suggested 1 or 0.
self.time_start = time.time()
def isReady(self):
time_limit = 5*60 # 5 minutes converted to seconds
time_passed = time.time() - self.time_start
if self.extra_topping == '':
extra_topping_str = ''
else:
extra_topping_str = f'extra {self.extra_topping}, '
if time_passed > time_limit:
self.ready = True # True/False instead of suggested 1 or 0.
print(f'Pizza with {extra_topping_str}{self.topping} topping, {self.flour} flour dough and {self.crust} crust is ready!')
else:
time_remaining = (time_limit - time_passed)/60
print(f'Pizza with {extra_topping_str}{self.topping} topping, {self.flour} flour dough and {self.crust} crust is still in the oven!')
print(f'Wait for another {time_remaining:.2f} minutes.')
def addExtraTopping(self, topping):
allowed = ['prosciutto', 'funghi', 'pineapple']
if not self.ready:
if topping in allowed:
self.extra_topping = topping
else:
print('That topping is not available!')
else:
print("Can't add topping, pizza is already done!")
class Pizzeria:
def __init__(self, N):
available_flour = ['white', 'brown', 'wholegrain']
available_toppings = ['mozzarella', 'cheddar', 'gorgonzola']
available_crusts = ['thin', 'sicilian', 'focaccia']
self.allPizzas = []
for _ in range(N):
flour = available_flour[random.randint(0, len(available_flour)-1)]
topping = available_toppings[random.randint(0, len(available_toppings)-1)]
crust = available_crusts[random.randint(
0, len(available_crusts)-1)]
self.allPizzas.append(Pizza(flour, topping, crust))
def priceOfAllPizzas(self):
number_of_pizzas = len(self.allPizzas)
flour_prices = {'white':10, 'brown':15, 'wholegrain':20}
topping_prices = {'mozzarella': 3, 'cheddar': 6, 'gorgonzola': 9}
crust_prices = {'thin': 2, 'sicilian': 4, 'focaccia': 7}
cost = 0
all_ingredients_available = True
for pizza in self.allPizzas:
if pizza.topping not in topping_prices:
all_ingredients_available = False
if pizza.flour not in flour_prices:
all_ingredients_available = False
if pizza.crust not in crust_prices:
all_ingredients_available = False
cost += topping_prices[pizza.topping]
cost += flour_prices[pizza.flour]
cost += crust_prices[pizza.crust]
if all_ingredients_available:
print(f'The total cost for {number_of_pizzas} pizzas is {cost} units.')
else:
print('One or more ingredients unavailable. Order aborted')
myDeliciousPizza = Pizza('wholegrain', 'cheddar', 'sicilian')
time.sleep(3)
myDeliciousPizza.isReady()
myDeliciousPizza.addExtraTopping('prosciutto')
myDeliciousPizza.isReady()
my_pizzeria = Pizzeria(5)
my_pizzeria.priceOfAllPizzas()
B7 (Equation parsing)#
Lösningsförslag
def is_valid_equation(equation):
numbers = [str(i) for i in range(0, 10)]
admissible_chars = numbers + ['=', '+']
# Check that only admissible characters are in equation
for char in equation:
if char not in admissible_chars:
return False
# Check that there is exactly one =
if equation.count('=') != 1:
return False
# Check for numbers left and right of =
for part in equation.split('='):
for number in part.split('+'):
# Ensure that no element in part.split('+') is empty.
# An empty element implies one of the following:
# 1. part starts or ends with '+'
# 2. part contains '++' (two pluses in a row)
if len(number) == 0:
return False
# All checks passed
return True
Kod som testar funktionen med ekvationerna i uppgiften
valid_equations = [
'1+2=456',
'12+34=40+3+2+01',
'123=143',
'12+3=1+23',
'123=103+20',
'0+00+000+00100=00000+000000'
]
invalid_equations = [
'1+2=3=2+1',
'12=3*4',
'a+1=1+a',
'12++3=15',
'tralala',
'1 + 2 = 3',
'c#',
'1+2+=3',
'='
]
print('--- Valid equations ---')
for eq in valid_equations:
print(f'{eq}: {is_valid_equation(eq)}')
print('--- Invalid equations ---')
for eq in invalid_equations:
print(f'{eq}: {is_valid_equation(eq)}')
B8 (A river of spaces)#
Den här uppgiften är i svåraste laget, även för del B.
Lösningsförslag
def longest_river_of_spaces(list_of_lines):
# The dict "counts" stores the length of the longest river
# that leads to a certain space character in the text, from above.
# As keys in count, we use tuples of the form: (line_index, character_index)
counts = {}
for line_ind, line in enumerate(list_of_lines):
for char_ind, char in enumerate(line):
if char == ' ':
# We found a space! Might be the start of a river.
counts[(line_ind, char_ind)] = 1
# Check if this space is actually part of an existing river.
for shift in range(-1, 2):
if (line_ind-1, char_ind + shift) in counts:
# If this space is part of multiple existing rivers,
# then pick the longest.
counts[(line_ind, char_ind)] = max(
counts[(line_ind, char_ind)], 1 + counts[(line_ind-1, char_ind + shift)])
# Return the length of the longest river (or 0, if no spaces were found)
if counts == {}:
return 0
return max(counts.values())
Kod som testar funktionen med texten i uppgiften
text_block = [
'Two fierce and enormous bears, distinguished',
'by the appellations of Innocence and Mica',
'Aurea, could alone deserve to share the',
'favour of Maximin. The cages of those trusty',
'guards were always placed near the',
'bed-chamber of Valentinian, who frequently',
'amused his eyes with the grateful spectacle',
'of seeing them tear and devour the bleeding',
'limbs of the malefactors who were abandoned',
'to their rage. Their diet and exercises were',
'carefully inspected by the Roman emperor;',
'and, when Innocence had earned her discharge',
'by a long course of meritorious service, the',
'faithful animal was again restored to',
'the freedom of her native woods.'
]
print(longest_river_of_spaces(text_block))