E-tenta 2023-12-02
Contents
E-tenta 2023-12-02#
Information#
Tentamen består av två delar, del A och del B.
För betyg 3 krävs 6/10 på del A.
För betyg 4 krävs betyg 3 samt 4/11 på del B.
För betyg 5 krävs betyg 3 samt 8/11 på del B.
Del B rättas enbart om del A är godkänd.
Hjälpmedel#
Via den dator du skriver tentamen på har du åtkomst till:
Kurshemsidor på svenska/engelska.
Fem online-programmeringsmiljöer: myCompiler, Judge0, Programiz, Online Python och GDB Online. Alla dessa innehåller en editor och ett shell-fönster där du kan skriva pythonkod och testa den. Använd den du föredrar.
Länkar till dessa hjälpmedel finns som flikar längst ned i Inspera.
Eftersom du har tillgång till en programmeringsmiljö kan du testa din kod innan du lämnar in den i Inspera. Du kopierar ditt svar från Programiz/Online Python/GDB Online till Inspera. Markera koden med CTRL-A, kopiera med CTRL-C och klistra in i svarsrutan i Inspera med CTRL-V. Ångra med CTRL-Z.
Medan du skriver tentamen sparas dina svar i Inspera var femtonde sekund. Kopiera ofta från online-IDE till Inspera för att inte riskera att förlora kod. Du kan inte öppna tentan igen när du har lämnat in den.
Bedömning#
I del A krävs genomgående att din kod ska fungera enligt anvisning. Kod som inte fungerar ges endast i undantagsfall något annat än 0 poäng.
I del B kan du få delpoäng för icke-fungerande kod som ändå visar att du kommit en bit på vägen.
Kommentering av kod behövs ej för del A. Uppgifterna på del B bör kommenteras på de ställen där en kommentar ökar läsbarheten markant. Svenska kommentarer är ok.
Såvida inget annat anges får du bygga på lösningar till föregående uppgifter även om du inte har löst dessa. Det är tillåtet att införa extra metoder eller funktioner. Uttryck som ”skriv en funktion som” ska alltså inte tolkas så att lösningen inte får struktureras med hjälp av fler funktioner. Alla uppgifter gäller programmeringsspråket Python och all programkod ska skrivas i Python. Koden ska vara läslig, dvs. den ska vara vettigt strukturerad och indenterad. Namn på variabler, funktioner, metoder, klasser etc. ska vara beskrivande men kan ändå hållas ganska korta.
A1#
Nedan är innehållet i en funktion. Den första raden (”funktionshuvudet”) i funktionsdefinitionen har dock försvunnit. Hur bör den se ut?
import math
A = math.pi*r**2
return A*h
Alternativ 1: def volume_of_cylinder(r, h):
Alternativ 2: def volume_of_cylinder(A, h):
Alternativ 3: def volume_of_cylinder(A, r):
Alternativ 4: def dot_product(r, h):
Alternativ 5: def dot_product(A, h):
Alternativ 6: def dot_product(A, r):
Svar
Alternativ 1.
A2#
Nedan finns en klass Circle
definierad.
import math
class Circle:
def __init__(self, center=(0, 0), r=1):
self.center = center
self.r = r
def __str__(self):
return f'Circle centered at {self.center} with radius {self.r}.'
def area(self):
A = math.pi*self.r**2
return A
def move_to(self, new_center):
self.center = new_center
Endast ett av följande påståenden är korrekt. Vilket?
Alternativ 1: Objekt av klassen Circle
har tre instansvariabler: center
, r
och A
.
Alternativ 2: Objekt av klassen Circle
har alltid radie 1.
Alternativ 3: Metoden area
tilldelar en av instansvariablerna ett nytt värde.
Alternativ 4: Metoden move_to
tilldelar en av instansvariablerna ett nytt värde.
Svar
Alternativ 4.
A3#
Nedanstående program simulerar att ett antal tärningar kastas. Om deras värden uppfyller något visst villkor skrivs True ut.
import random
v1 = random.randint(1, 6)
v2 = v1
v3 = random.randint(1, 6)
if v1 + v2 < v3:
print('True')
Vilket av nedanstående alternativ beskriver programmet bäst?
Alternativ 1: Tre olika tärningar kastas. Om summan av de två första blir större än den tredje skrivs True ut.
Alternativ 2: Tre olika tärningar kastas. Om summan av de två första blir mindre än den tredje skrivs True ut.
Alternativ 3: Två olika tärningar kastas. Om den andra blir mer än dubbelt så stor som den första skrivs True ut.
Alternativ 4: Två olika tärningar kastas. Om den andra blir mindre än den första skrivs True ut.
Svar
Alternativ 3.
A4#
Hur många listobjekt skapar nedanstående kod?
a1 = [i for i in range(0, 10)]
a2 = a1.copy()
a3 = [x for x in a1]
a4 = a1
Alternativ 1: Ett listobjekt. a2
, a3
och a4
är referenser till existerande objekt.
Alternativ 2: Två listobjekt. a3
och a4
är referenser till existerande objekt.
Alternativ 3: Tre listobjekt. a4
är en referens till ett existerande objekt.
Alternativ 4: Fyra listobjekt. a1
, a2
, a3
och a4
refererar alla till olika listobjekt.
Svar
Alternativ 3.
A5: Prime numbers#
Skriv en funktion list_of_prime_numbers(limit)
som returnerar en lista med alla primtal som är mindre än eller lika med heltalet limit
. Du får kopiera in och anropa funktionen is_prime
, som ges nedan. Denna funktion tar ett heltal större än eller lika med 2 som parameter och returnerar True
om talet är ett primtal, annars False
.
def is_prime(n):
limit = int(n**0.5)
for i in range(2, limit+1):
if n % i == 0:
return False
return True
Följande kod:
print(list_of_prime_numbers(4))
print(list_of_prime_numbers(11))
ska ge utskriften
[2, 3]
[2, 3, 5, 7, 11]
Lösningsförslag
def list_of_prime_numbers(limit):
lst = []
for i in range(2, limit+1):
if is_prime(i):
lst.append(i)
return lst
A6: Robber language#
När ett ord översätts till det så kallade rövarspråket ersätts alla konsonanter med ”xox”, där x är den ursprungliga konsonanten. Exempel:
b blir till bob
c blir till coc
osv.
Alla vokaler lämnas orörda.
Din uppgift är att skriva en funktion robber_language(word)
som tar en sträng som representerar ett engelskt ord som parameter. Funktionen ska returnera ordet skrivet på rövarspråket. Du kan förutsätta att strängen word endast innehåller bokstäver och att alla bokstäver är gemener (små bokstäver).
Tips: Här är en sträng med de engelska konsonanterna:
consonants = 'bcdfghjklmnpqrstvxz'
Följande kod:
print(robber_language('hello'))
print(robber_language('uppsala'))
ska ge utskriften
hohelollolo
upoppopsosalola
Lösningsförslag
Variant 1:
def robber_language(word):
consonants = 'bcdfghjklmnpqrstvxz'
new_word = ''
for char in word:
if char in consonants:
new_word += char + 'o' + char
else:
new_word += char
return new_word
Variant 2:
def robber_language(word):
consonants = 'bcdfghjklmnpqrstvxz'
for c in consonants:
word = word.replace(c, c + 'o' + c)
return word
A7: Lists of strings#
Skriv en funktion add_lists_of_strings(lst1, lst2)
som tar två listor som parametrar. Listorna förutsätts vara lika långa och innehålla sträng-representationer av tal. Din funktion ska addera listorna elementvis och returnera resultatet. Den lista du returnerar ska också innehålla strängar!
Följande kod:
x = ['1', '2.4', '3.0']
y = ['0.9', '0.1', '0.5']
print(add_lists_of_strings(x, y))
ska ge utskriften
['1.9', '2.5', '3.5']
Lösningsförslag
def add_lists_of_strings(lst1, lst2):
return [str(float(lst1[i]) + float(lst2[i])) for i in range(len(lst1))]
A8: Cheap meals#
I kassasystemet på en restaurang finns menyn sparad som ett lexikon där rätternas namn (strängar) är nycklar och priserna (heltal) är värden. Skriv en funktion list_of_cheap_meals(menu)
som tar ett sådant lexikon som parameter. Funktionen ska returnera en lista med namnen på de rätter som kostar mindre än 100 kr.
Följande kod:
menu = {'burger': 89,
'pizza': 129,
'salad': 99,
'fish': 119}
print(list_of_cheap_meals(menu))
ska ge utskriften
['burger', 'salad']
Lösningsförslag
def list_of_cheap_meals(menu):
cheap_meals = []
for meal, price in menu.items():
if price < 100:
cheap_meals.append(meal)
return cheap_meals
A9: Truncated Maclaurin#
Givet ett tal \(x\) kan talet \(e^x\) approximeras med de \(m\) första termerna i Maclaurin-utvecklingen. Låt approximationen betecknas \(S_m(x)\). Denna ges av:
Skriv en funktion truncated_maclaurin(x, m)
som beräknar och returnerar \(S_m(x)\). Du kan förutsätta att m
är ett positivt heltal (\(m\geq 1\)).
Tips: Använd math.factorial(n)
för att beräkna \(n!\).
Följande kod:
print(round(truncated_maclaurin(1.0, 1), 4))
print(round(truncated_maclaurin(1.0, 3), 4))
print(round(truncated_maclaurin(1.0, 5), 4))
print(round(truncated_maclaurin(0.5, 4), 4))
ska ge utskriften
1.0
2.5
2.7083
1.6458
Lösningsförslag
import math
def truncated_maclaurin(x, m):
result = 0
for i in range(m):
result += x**i/math.factorial(i)
return result
A10: Broken code#
I koden nedan finns en funktion n_most_common_words(text, n)
. Funktionen tar en sträng (text
) och ett positivt heltal (n
) som parametrar. Funktionen ska returnera en lista med de n
vanligaste orden i strängen text
. Tyvärr har det smugit sig in ett antal mindre fel i koden.
Korrigera funktionen n_most_common_words
så att den fungerar som avsett. Det går att få funktionen att fungera genom att korrigera tre av de existerande raderna, men du får göra så många ändringar du vill så länge slutresultatet fungerar korrekt.
OBS! Det kan finnas fel som inte ger några felmeddelanden men som gör att funktionen inte fungerar som avsett. Du måste även korrigera sådana fel.
import re
def part2(element):
return element[1]
def n_most_common_words(text, n=1):
list_of_words = re.findall(r'[a-zA-ZåäöÅÄÖ]+', text)
# Create dict of words and number of occurrences
word_to_count = {}
for word in list_of_words
word = word.lower()
if word in word_to_count:
word_to_count[word] += 1
else:
word_to_count['word'] = 1
# Extract word-count pairs from dict
words_and_counts = list(list_of_words.items())
words_and_counts.sort(key=part2, reverse=True)
# Return a list of the n most common words
return [word for word, count in words_and_counts[:n]]
Lösningsförslag
def n_most_common_words(text, n=1):
list_of_words = re.findall(r'[a-zA-ZåäöÅÄÖ]+', text)
# Create dict of words and number of occurrences
word_to_count = {}
for word in list_of_words: # Saknades :
word = word.lower()
if word in word_to_count:
word_to_count[word] += 1
else:
word_to_count[word] = 1 # Apostroferna skulle bort
# Extract word-count pairs from dict
words_and_counts = list(word_to_count.items()) # list_of_words.items() skulle vara word_to_count.items()
words_and_counts.sort(key=part2, reverse=True)
# Return a list of the n most common words
return [word for word, count in words_and_counts[:n]]
B1-B3: Matriser#
Nedan finns en klass Matrix
definierad. Den innehåller en konstruktor och en __str__
-metod. Dessa metoder är färdiga och du kommer inte behöva ändra dem. Kopiera koden till en editor och läs sedan instruktionerna som kommer efter koden.
import random
class Matrix:
def __init__(self, num_rows, num_cols, values=None):
self.num_rows = num_rows
self.num_cols = num_cols
if values is None:
# Generate random values
self.values = []
for _ in range(num_rows):
row = [random.randint(-10, 10) for _ in range(num_cols)]
self.values.append(row)
else:
# Take user-supplied values
self.values = values
def __str__(self):
output = ''
for i in range(self.num_rows):
for j in range(self.num_cols):
value = self.values[i][j]
output += f'{value:6.1f}'
output += '\n'
return output
Objekt av klassen Matrix
representerar matematiska matriser. En matris har ett antal rader och kolonner och är fylld med tal. Här är ett exempel på en matris \(A\) med 2 rader och 3 kolonner:
Följande är viktig information om klassen Matrix:
Konstruktorn och
__str__
-metoden är färdig och du ska inte ändra dem. Du behöver läsa konstruktorn och förstå hur den fungerar. Du uppmuntras också att använda__str__
-metoden för att kontrollera att du löst uppgifterna korrekt.Klassen
Matrix
har tre instansvariabler. Instansvariabelnvalues
är en lista av listor. Var och en av de inre listorna innehåller tal och svarar mot en rad i matrisen.När ett
Matrix
-objekt skapas kan vi ange hur många rader och kolonner matrisen ska ha, samt vilka värden den ska innehålla. Om värdena utelämnas fylls matrisen med slumpade heltal mellan -10 och 10.
Uppgift B1 (3p)#
Lägg till en metod max
i klassen. Metoden ska returnera det största talet i matrisen. Notera att det inte ska vara det största absolutbeloppet. Här räknas alltså 2 som större än -9, till exempel.
Lösningsförslag
def max(self):
return max([max(row) for row in self.values])
Uppgift B2 (4p)#
Skriv en funktion matrix_add(A, B)
. Funktionen ska ta två objekt av klassen Matrix
som parametrar och returnera ett nytt Matrix
-objekt som motsvarar summan av A
och B
. Kom ihåg att matriser adderas elementvis. Exempel:
Notera att matrix_add
ska vara en funktion, inte en metod i klassen Matrix
. Du kan förutsätta att A
har samma antal rader och samma antal kolonner som B
(annars är matrisadditionen inte matematiskt definierad).
Lösningsförslag
def matrix_add(A, B):
# Assume that A and B have the same dimensions
num_rows = A.num_rows
num_cols = A.num_cols
# Create new values of size (num_cols) x (num_rows),
# temporarily filled with None
values = [[None]*num_cols for _ in range(num_rows)]
for i in range(num_rows):
for j in range(num_cols):
values[i][j] = A.values[i][j] + B.values[i][j]
return Matrix(num_rows, num_cols, values)
Uppgift B3 (4p)#
Lägg till en metod transpose
i klassen Matrix
. Metoden ska förändra Matrix
-objektet så att det istället motsvarar transponatet av den ursprungliga matrisen. Metoden ska alltså inte ha något returvärde.
Kom ihåg att transponatet av en matris innebär att rader och kolonner byter plats. Exempelvis, om
så ges transponatet av \(A\) av
Lösningsförslag
def transpose(self):
# Create new values of size (num_cols) x (num_rows),
# temporarily filled with None
new_values = [[None]*self.num_rows for _ in range(self.num_cols)]
# Fill new_values with transposed values from self.values
for i in range(self.num_rows):
for j in range(self.num_cols):
new_values[j][i] = self.values[i][j]
# Replace attributes
self.values = new_values
num_cols = self.num_cols
self.num_cols = self.num_rows
self.num_rows = num_cols