Del A
Contents
Del A#
För betyg 3 på tentan krävs minst 5/8 godkända uppgifter på del A. För betyg 4 respektive 5 krävs dessutom ett visst antal poäng på del B.
A1#
import math
class Fyrkant:
def __init__(self, sida):
pi = math.pi
self.hojd = 2 * sida
self.bredd = 3 * sida
self.area = self.hojd * self.bredd
self.vinklar = [pi/2, pi/2, pi/2, pi/2]
self.diag1, self.diag2 = 2 * [math.sqrt(self.hojd ** 2
+ self.bredd ** 2)]
def parallellogram(self, ang):
self.vinklar = [ang, pi - ang, ang, pi - ang]
self.diag1 = math.sqrt(self.hojd ** 2 + self.bredd ** 2
+ 2 * self.hojd * self.bredd * math.cos(ang))
self.diag2 = math.sqrt(self.hojd ** 2 + self.bredd ** 2
- 2 * self.hojd * self.bredd * math.cos(ang))
def __str__(self):
return f'Area = {self.area}'
Betrakta koden ovan. Vilket alternativ använder korrekt terminologi för de olika komponenterna i koden?
Alternativ 1:
moduler: math, self
klasser: Fyrkant
funktioner: sqrt, cos
metoder: __init__(), __str__(), diag1, diag2, vinklar
attribut: hojd, bredd, area
Alternativ 2:
moduler: math
klasser: Fyrkant
funktioner: sqrt, cos, area, parallellogram()
metoder: __init__(), parallellogram(), __str__()
attribut: hojd, bredd, area, vinklar, diag1, diag2
Alternativ 3:
moduler: math
klasser: Fyrkant
funktioner: sqrt, cos
metoder: __init__(), parallellogram(), __str__()
attribut: hojd, bredd, area, vinklar, diag1, diag2
Alternativ 4:
moduler: math
klasser: Fyrkant
funktioner: sqrt, cos, parallellogram()
metoder: __init__(), __str__()
attribut: hojd, bredd, area, vinklar, diag1, diag2, self
Svar
Svar: Alternativ 3
A2#
import random as rd
import matplotlib.pyplot as plt
from math import sqrt
from turtle import Turtle
Betrakta koden ovanför. För varje påstående nedanför, ange om det är sant eller falskt. För att få 1 poäng på den här uppgiften krävs 4 av 4 rätta svar.
1. sqrt
och Turtle
är en funktion respektive en klass från modulerna math
respektive turtle
. Sant eller falskt?
Svar
Sant
2. sqrt
och Turtle
är funktioner från modulerna math
respektive turtle
.
Sant eller falskt?
Svar
Falskt
3. rd
och plt
är funktioner från modulerna random
respektive matplotlib.pyplot
. Sant eller falskt?
Svar
Falskt
4. rd
och plt
är import-alias till modulerna random
och matplotlib.pyplot
. Sant eller falskt?
Svar
Sant
A3#
Skriv en funktion summa_av_slumptal(limit)
som summerar en serie slumpmässiga heltal mellan 0 och 10 och returnerar summan av slumptalen. Summan ska returneras när nästa term i serien hade gjort att summan blivit större än en angiven gräns limit
.
Förutom summan ska även antalet termer i summan returneras.
Ledning: Importera modulen random
med satsen import random
.
Funktionen random.randint(a, b)
ger slumpmässiga heltal mellan a
och b
.
Exempel: Följande kod
summa, antal = summa_av_slumptal(21)
print(f'Summan av {antal} slumptal blev {summa}.')
ska till exempel kunna ge utskriften:
Summan av 5 slumptal blev 19.
Utskriften kommer att variera då det är en summa av slumptal.
Lösningsförslag
import random
def summa_av_slumptal(limit):
previous_sum = 0 # Variable for sum without last random number
current_sum = 0 # Variable for sum including last random number
count = 0 # Number of terms in sum
while current_sum <= limit:
previous_sum = current_sum
number = random.randint(0, 10)
current_sum = previous_sum + number
count += 1
count -= 1 # Subtract 1 to get number of terms in previous_sum
return previous_sum, count
A4#
Kast med en tärning modelleras med klassen Dice
:
import random
class Dice:
def __init__(self, sides):
self.sides = sides
self.num_rolls = 0
self.sum = 0
def __str__(self):
return f'Sidor: {self.sides:2d}, summa: {self.sum:2d} efter {self.num_rolls} kast'
def roll(self):
value = random.randint(1, self.sides)
self.sum += value
self.num_rolls += 1
Varje tärningsobjekt har ett antal sidor (instansvariabeln sides
) och håller koll på hur många gånger tärningen har kastats hittills (instansvariabeln num_rolls
) samt summan av alla kast hittills (instansvariabeln sum
).
Uppdatera metoden roll
så att den tar en parameter number
och kastar tärningen number
gånger. Metoden ska även uppdatera instansvariablerna num_rolls
och sum
på lämpligt sätt.
Om man anger ett värde på number
som är mindre än 1 skall metoden använda number = 1
.
Följande kod
d = Dice(6)
d.roll(5)
print(d)
d.roll(2)
print(d)
d.roll(-2)
print(d)
ska till exempel kunna ge utskriften
Sidor: 6, summa: 17 efter 5 kast
Sidor: 6, summa: 27 efter 7 kast
Sidor: 6, summa: 28 efter 8 kast
Notera att du endast får uppdatera metoden roll
i klassen. Du får INTE göra några andra ändringar i koden.
Lösningsförslag
def roll(self, number):
if number < 1:
number = 1
for _ in range(number):
value = random.randint(1, self.sides)
self.sum += value
self.num_rolls += 1
A5#
Skriv en funktion word_count(text)
som tar en sträng text
som parameter. Funktionen ska ta reda på vilka ord som förekommer i texten samt hur många gånger varje ord förekommer. Denna information ska returneras i form av en lista där varje element är en tupel med ordet som första element och antal förekomster som andra element. Listan ska vara sorterad i bokstavsordning och orden ska vara skrivna med enbart gemener (små bokstäver).
Ledning 1: Använd ett lexikon.
Ledning 2: Du kan plocka ut en lista med alla ord i en text med hjälp av följande kod
import re
list_of_words = re.findall(r'[a-zA-ZåäöÅÄÖ]+', text)
Körexempel: Följande kod
text = 'O jerum, jerum, jerum, O quae mutatio rerum'
word_list = word_count(text)
for element in word_list:
print(f'{element[0]}:{element[1]}',end = ', ')
ska resultera i utskriften
jerum:3, mutatio:1, o:2, quae:1, rerum:1,
Lösningsförslag
import re
def word_count(text):
list_of_words = re.findall(r'[a-zA-ZåäöÅÄÖ]+', text)
word2count = {} # Dict of words and number of occurrences
for word in list_of_words:
word = word.lower()
if word in word2count:
word2count[word] += 1
else:
word2count[word] = 1
return (sorted(word2count.items()))
A6#
En text är skriven på ett tangentbord som saknar de svenska bokstäverna å, ä, ö, Å, Ä samt Ö. Istället har man använt följande ”översättningstabell”:
{
förå
}
förä
|
förö
[
förÅ
]
förÄ
_
förÖ
Skriv en funktion svenska_tecken(text)
som tar en sträng text
som parameter och returnerar en motsvarande sträng där {
, }
, |
, [
, ]
och _
har ersatts med å, ä, ö, Å, Ä och Ö.
Exempel (från en dikt av Gustav Fröding)
Följande kod
text = """D’} e {, vett ja”, skrek ja, f|r ja ble rasen, ”{ i {a } e |, h|rer han lite, d’} e {, { i {a } e |."""
print(svenska_tecken(text))
ska resultera i utskriften
D’ä e å, vett ja”, skrek ja, för ja ble rasen, ”å i åa ä e ö, hörer han lite, d’ä e å, å i åa ä e ö.
Lösningsförslag 1
def svenska_tecken(text):
text = text.replace('{','å')
text = text.replace('}','ä')
text = text.replace('|','ö')
text = text.replace('[','Å')
text = text.replace(']','Ä')
text = text.replace('_','Ö')
return text
Lösningsförslag 2
def svenska_tecken(text):
text_ut = text
translation_dict = {'{': 'å', '}': 'ä', '|': 'ö', '[': 'Å', ']': 'Ä', '_': 'Ö'}
for old, new in translation_dict.items():
text_ut = text_ut.replace(old, new)
return text_ut
A7#
Skriv en funktion statistik(lst)
som beräknar medelvärde och median för en lista lst
med n
tal. Funktionen behöver kunna hantera listor med både jämna och udda antal värden.
OBS! Du får inte använda modulen statistics
.
Ledning 1: För beräkning av medianen är det smidigt om listan är sorterad i storleksordning. Medianen är då det mittersta värdet i fallet när n
är udda. Om n
är jämnt är medianen medelvärdet av de två mittersta värdena.
Körexempel: Koden
lst = [10, 1, 3, 4, 2]
medelvarde, median = statistik(lst)
print(f'Medianen är {median} och medelvärdet är {medelvarde}.')
ska resultera i utskriften
Medianen är 3 och medelvärdet är 4.0.
Lösningsförslag
def statistik(lst):
lst = sorted(lst)
n = len(lst)
medelvarde = sum(lst)/n
if n%2 != 0:
median = lst[n//2]
else:
median = (lst[n//2 - 1] + lst[n//2])/2
return medelvarde, median
A8#
Du har gjort ett experiment tillsammans med en kursare där ni, var för sig, varje hel timme mätt temperaturen T
i ett prov. Ni har sparat mätningarna i varsitt lexikon med klockslaget som nyckel och temperaturen (i grader Celsius) som värde. I labbrapporten ska ni redovisa medelvärdena av era temperaturmätningar. Det visar sig dock att ni sparat data på två olika sätt.
Du har sparat lexikonet
data_1 = {'12':1.1,'13':2.8,'14':3.4}
Din kursare har sparat lexikonet
data_2 = {'14:00':'3.5','13:00':'2.9','12:00':'1.4'}
Skriv en funktion merge_data(data_1, data_2)
som tar de två olika lexikonen som parametrar och returnerar ett lexikon med klockslagen som nycklar och medelvärdena av era mätningar som värden. Funktionen ska fungera även för andra lexikon med samma format (men exempelvis fler mätpunkter).
Ledning: Du kan utgå från att data läses in i ordningen data_1
, data_2
. Du kan också anta att de båda lexikonen innehåller samma klockslag (hela timmar), bara skrivna med eller utan :00
.
Körexempel: Koden
data_1 = {'12': 1.1, '13': 2.8, '14': 3.4}
data_2 = {'14:00': '3.5', '13:00': '2.9', '12:00': '1.4'}
merged_data = merge_data(data_1, data_2)
for time in merged_data:
print(f' Kl {time} var temperaturen {merged_data[time]:.2f} grader Celsius.')
ska ge utskriften
Kl 12 var temperaturen 1.25 grader Celsius.
Kl 13 var temperaturen 2.85 grader Celsius.
Kl 14 var temperaturen 3.45 grader Celsius.
Lösningsförslag
def merge_data(data_1, data_2):
merged_data = {}
for time_1 in data_1:
temp_1 = data_1[time_1]
time_2 = time_1 + ':00'
temp_2 = float(data_2[time_2])
merged_time = time_1
merged_temp = (temp_1 + temp_2) / 2
merged_data[merged_time] = merged_temp
return merged_data
Del B#
För betyg 4 resp. 5 krävs godkänd del A samt 8 resp. 12 poäng av 16 möjliga på del B.
På midsommarafton på landet brukar somliga arrangera ett ”potatisrace”. Racet går till så att man placerar en potatis på en sked, sätter skeden i munnen, och sedan försöker gå en sträcka och balansera potatisen. Följande regler gäller:
Först i mål vinner.
Tappar man potatisen måste man gå tillbaka till start och börja om från början.
Om två personer kommer i mål samtidigt vinner den som är yngst.
Din uppgift är att simulera ett potatisrace. Till din hjälp har du klassen Participant
, vars konstruktor är given nedan. De tre instansvariablerna har följande betydelser:
age
: heltal, deltagarens ålderposition
: heltal, deltagarens position på banan.0
motsvarar startpositionen ochlength - 1
motsvarar mållinjen på en bana av längdlength
.direction:
deltagarens nuvarande riktning, antingen1
(framåt) eller-1
(bakåt).
class Participant:
def __init__(self, age, position=0, direction=1):
self.age = age
self.position = position
self.direction = direction
B1 (2 poäng)#
Skapa en klass Potatisrace
. Skriv en konstruktor __init__(self, length, num_participants)
som tar parametrarna length
(heltal, längden på banan) och num_participants
(heltal, antal deltagare).
Klassen Potatisrace
ska ha följande två instansvariabler:
length
: banans längdparticipants
: en lista mednum_participants
element. Dessa ska vara objekt av klassenParticipant
och representerar deltagarna i racet. Initialt ska alla deltagare stå på startlinjen och titta framåt. Deltagarnas åldrar ska vara slumpmässiga heltal mellan 10 och 80.
Ledning: Importera modulen random
och använd funktionen random.randint(min, max)
för att slumpa fram åldrarna.
Lösningsförslag
import random
class Potatisrace:
def __init__(self, length, num_participants):
self.length = length
self.participants = []
position = 0
direction = 1
for _ in range(num_participants):
age = random.randint(10, 80)
self.participants.append(Participant(age, position, direction))
B2 (3 poäng)#
I klassen Potatisrace
, lägg till en __str__()
-metod som illustrerar loppet vid ett givet ögonblick. Positionen för varje deltagare markeras med bokstaven P. Nedan visas hur utskriften ska se ut för ett exempel med tre deltagare och banlängd 5.
Initialt, när alla deltagare står på startlinjen ska utskriften vara:
[P ]
[P ]
[P ]
Senare in i loppet, då deltagarnas positioner ändrats, ska utskriften till exempel kunna bli:
[ P ]
[ P]
[ P ]
Här ser vi att deltagaren på bana 2 precis gått i mål och vunnit racet.
Lösningsförslag
def __str__(self) :
res = '\n'
for p in self.participants:
# Create a list of n blank spaces
list_of_chars = [' ']*self.length
# Put a 'P' where the particiant is
list_of_chars[p.position] = 'P'
row_str = ''.join(list_of_chars)
res += '[' + row_str + ']\n'
return res
B3 (3 poäng)#
Lägg till en metod step()
i klassen Participant
. Metoden ska ta en parameter drop_prob
som motsvarar sannolikheten att deltagaren tappar potatisen i samband med ett steg (drop_prob=0.2
motsvarar 20% risk att tappa potatisen, t.ex.). Metoden ska, i tur och ordning, utföra följande:
Gå ett steg (av längdenhet 1) i deltagarens nuvarande riktning, dvs. antingen ett steg framåt eller ett steg bakåt.
Generera ett slumptal som avgör huruvida deltagaren tappar sin potatis i samband med detta steg. Om potatisen tappas ska deltagaren vända sig bakåt, dvs. riktningen ska sättas till
-1
.Om deltagaren nu står på startlinjen, sätt dess riktning till
1
.
Ledning: Anropet random.random()
returnerar ett slumpmässigt decimaltal mellan 0 och 1.
Lösningsförslag
def step(self, drop_prob):
"""Complete one step. drop_prob is the probability of dropping the potato"""
# Take a step in the current direction
self.position += self.direction
# If the potato was dropped, set direction to -1
r = random.random()
if r < drop_prob:
self.direction = -1
# If the participant is at the starting position, set direction to 1
# (regardless of whether the potato was dropped in this step)
if self.position == 0:
self.direction = 1
B4 (2 poäng)#
Lägg till en metod step_all()
i klassen Potatisrace
som tar ett steg med alla deltagare. Metoden ska ta en parameter drop_prob
som används för alla deltagare.
Lösningsförslag
def step_all(self, drop_prob=0.2):
"""Step all race participants"""
for p in self.participants:
p.step(drop_prob)
B5 (2 poäng)#
I klassen Potatisrace
, skriv en metod is_finished
som returnerar True
om minst en deltagare nått målet, annars False
. Om en deltagare står på position length - 1
, där length
är banans längd, räknas det som att hen nått målet.
Lösningsförslag
def is_finished(self):
"""Return True if at least one participant reached the finish line, otherwise False"""
for p in self.participants:
if p.position == self.length-1:
return True
return False
B6 (4 poäng)#
I klassen Potatisrace
, lägg till och färdigställ metoden determine_winner()
:
def determine_winner(self):
"""Return the index of the winning participant. If multiple participants have reached
the finish line, the youngest one wins. This method assumes that there is at least one
winner so that is_finished() returns True."""
Metoden ska returnera det index i listan participants
som svarar mot den vinnande deltagaren. Kom ihåg att om flera deltagare nått målet i samma steg så vinner den yngsta!
När du löst denna uppgift ska du kunna simulera ett potatisrace med nedanstående main
-funktion.
def main():
drop_prob = 0.2
race = Potatisrace(5, 3)
print(race)
while not race.is_finished():
race.step_all(drop_prob)
print(race)
winning_index = race.determine_winner()
winning_age = race.participants[winning_index].age
print(' ')
print(f'Racet klart! Vinnare är bana {winning_index+1} med en deltagare som är {winning_age} år gammal')
if __name__ == '__main__':
main()
Den avslutande utskriften ska till exempel kunna bli som nedan.
Racet klart! Vinnare är bana 1 med en deltagare som är 47 år gammal
[ P ]
[ P ]
[ P ]
Lösningsförslag
def determine_winner(self):
"""Return the index of the winning participant. If multiple particpants have reached
the finish line, the youngest one wins. This method assumes that there is at least one
winner so that is_finished() returns True."""
winners_age = 1000 # Set winning age to some large number
for index, p in enumerate(self.participants):
if p.position == self.length - 1 and p.age < winners_age:
winners_age = p.age
winners_index = index
return winners_index
Lösningsförslag B1-B6
import random
class Participant:
def __init__(self, age, position=0, direction=1):
self.age = age
self.position = position
self.direction = direction
def step(self, drop_prob):
"""Complete one step. drop_prob is the probability of dropping the potato"""
# Take a step in the current direction
self.position += self.direction
# If the potato was dropped, set direction to -1
r = random.random()
if r < drop_prob:
self.direction = -1
# If the participant is at the starting position, set direction to 1
# (regardless of whether the potato was dropped in this step)
if self.position == 0:
self.direction = 1
class Potatisrace:
def __init__(self, length, num_participants):
self.length = length
self.participants = []
position = 0
direction = 1
for _ in range(num_participants):
age = random.randint(10, 80)
self.participants.append(Participant(age, position, direction))
def __str__(self) :
res = '\n'
for p in self.participants:
# Create a list of n blank spaces
list_of_chars = [' ']*self.length
# Put a 'P' where the particiant is
list_of_chars[p.position] = 'P'
row_str = ''.join(list_of_chars)
res += '[' + row_str + ']\n'
return res
def step_all(self, drop_prob=0.2):
"""Step all race participants"""
for p in self.participants:
p.step(drop_prob)
def is_finished(self):
"""Return True if at least one participant reached the finish line, otherwise False"""
for p in self.participants:
if p.position == self.length-1:
return True
return False
def determine_winner(self):
"""Return the index of the winning participant. If multiple participants have reached
the finish line, the youngest one wins. This method assumes that there is at least one
winner so that is_finished() returns True."""
winners_age = 1000 # Set winning age to some large number
for index, p in enumerate(self.participants):
if p.position == self.length - 1 and p.age < winners_age:
winners_age = p.age
winners_index = index
return winners_index