Uke 10
Innlevering, og Krav for å bestå
- Du kan levere så mange ganger du vil. Siste innlevering teller.
- For å få bestått, må du få 100% riktig av CodeGrade på 3 av de 5 oppgavene. Du kan velge fritt hvilke 3 det blir.
Generelt tips: les alltid gjennom kursnotatene før du begynner på lab’en!
Velg 3 av disse oppgavene:
- Oppgave 1-Pearsons korrelasjonsligning
- Oppgave 2-Football
- Oppgave 3-Måltidsplanlegging
- Oppgave 4-Egyptisk multiplikasjon
- Oppgave 5-Tekstjustering
Oppgave 1
Pearsons korrelasjonsligning er gitt av:
$$r = \frac{\sum_i (x_i - \bar{x})(y_i - \bar{y})}{\sqrt{\sum_i(x_i - \bar{x})^2 \sum(y_i - \bar{y})^2}}$$
\((x, y)\) er tidsserier (hver er en liste med målinger) og \(\bar{x},\bar{y}\) er de tilsvarende gjennomsnittene av hver liste.
I filen uke_10_oppg_1.py implementer Pearsons korrelasjonsligningen som funksjonen pearson_corr(x,y)
som tar som argumenter to lister x og y og returnerer koeffisienten r
hvor \(-1 \leq r \leq 1\).
Fremgangsmåten:
- Ta gjennomsnittet av \(x\) i variablen mean_x og \(y\) i variablen mean_y.
- Lag listene \(dx\) and \(dy\) som inneholder forskjellene \(x_i - \bar{x}\) og \(y_i - \bar{y}\)
- Multipliser hvert sitt element sin forskjell fra gjennomsnittet i x -listen med forskjellen fra gjennomsnittet i y -listen dx[i] * dy[i]. Summer disse multipliserte verdiene og lagre dem i variabelen sum_dxdy*.
TIPS: Du kan bruke
sum()
ogzip()
for å hjelpe med beregningen til produktet av forskjellene for hvert parvis listeelement for å oppsummere disse resultatene.
- Lag nye variabler dx2 og dy2 som summen av de kvadrerte forskjellene: \(dx2 = \sum_i (x_i - \bar{x})^2\) og \(dy2 = \sum_i (y_i - \bar{y})^2\).
- Multipliser dx2 og dy2 og ta kvadratroten til produktet. Lag resultatet i variabelen sqr_dx2dy2.
- Til slutt, beregne korrelasjonskoeffisienten r som divisjon av sum_dxdy med sqr_dx2dy2. Variabelen r er resultatet som funksjonen returnerer.
Testkjøring:
print("Tester pearson_corr... ", end="")
x1_ls = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
y1_ls = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
y2_ls = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]
from math import isclose
assert 1.0 == pearson_corr(x1_ls, y1_ls)
assert isclose(0.77511680258225, pearson_corr(x1_ls, y2_ls))
print("OK")
Oppgave 2
Last ned filen football.py og endre navnet til uke_10_oppg_2.py. Du skal tilpasse kun de markerte delene i filen for å løse de etterfølgende deloppgavene. Denne oppgaven har 2 deler som kan løses hver for seg. Det finnes en exit()
i midten av filen som må fjernes for å kjøre del 2.
Vi skal se på noen resultater fra gruppefasen fra ulike fotball-VM. I hver gruppe finnes det 4 landslag som spiller 6 kamper mot hverandre. Kampresultatene er gitt som en liste av 4-tuples, med 2 strings og 2 int:
[
("Brazil", "Scotland", 2, 1),
("Morocco", "Norway", 2, 2),
("Scotland", "Norway", 1, 1),
("Brazil", "Morocco", 3, 0),
("Brazil", "Norway", 1, 2),
("Scotland", "Morocco", 0, 3),
]
For hvert lag kan vi nå lage en statistikk med 4 tall:
- GF (goals for) - antallet mål som laget har skåret
- GA (goals against) - antallet mål som ble skåret mot laget
- GD (goal difference) - differansen mellom GF og GA, alltid lik GF-GA
- PT (points) - poengsummen: 3 poeng til kampvinneren, 1 poeng til hvert lag om kampen er uavgjort Denne statistikken skal lagres i en datastruktur som er et dict av dicts. Til eksemplet ovenfor ser det sånn ut:
{
'Brazil': {'GF': 6, 'GA': 3, 'GD': 3, 'PT': 6},
'Scotland': {'GF': 2, 'GA': 6, 'GD': -4, 'PT': 1},
'Morocco': {'GF': 5, 'GA': 5, 'GD': 0, 'PT': 4},
'Norway': {'GF': 5, 'GA': 4, 'GD': 1, 'PT': 5},
}
Denne strukturen er ikke sortert ennå, en tilfeldig rekkefølge er greit!
DEL A
Lag en funksjon make_stats(matches)
, der matches er en liste med kampresultater i det formatet vist ovenfor. Funksjonen skal returnere et dict med statistikken i det nevnte dict-formatet. Det finnes et skjelett til make_stats()
allerede i filen, med en liten if-test som sjekker funksjonen din.
Selv om du ikke klarer DEL A, kan du fjerne exit()
på linje 44, og prøve å løse del B.
DEL B
Her skal vi sortere lagene i en tabell for gruppen. Print-funksjoner osv. er allerede klare, det eneste som mangler er en compare
-funksjon som avgjør rekkefølgen til lagene. Avgjørelsen skjer med flere regler, der vi bruker den neste når alle tidligere regler ikke gir en vinner:
- Større poengsum PT
- Større måldifferanse GD
- Flere skårete mål GF
- Vinneren av den direkte kampen mellom de to lagene (vi ignorer en situasjon hvor det er flere enn to lag som er helt like når vi kommer til denne regelen)
- Trekking av lodd
Lag en funksjon compare(matches, data, name_a, name_b)
der matches
er listen til kampresultatene i formatet ovenfor, data
er et ferdig dict med statistikk i formatet ovenfor, og name_a
og name_b
er to strenger med navnene til 2 landslag
Vi tar med data som argument slik at vi kan ignorere funksjonen i DEL A. Vi kan alltid anta at data == make_stats(matches)
Funksjonen skal returnere tallet 1 om lag a ligger høyere i tabellen enn lag b
Funksjonen skal returnere tallet -1 om lag b ligger høyere i tabellen enn lag a
Funksjonen skal printe f"LOTTERY {a} {b}" og returnere tallet 0 om situasjonen er uavgjort mellom a og b
Det finnes et skjelett til compare() allerede i filen, med en rekke tester som sjekker funksjonen din.
Eksempel output
Om alt er bra i begge deler, ser outputtet slik ut (husk å fjerne exit() i linje 44).
make_stats looks good, you can remove the exit() line now!
GF GA GD PT
Brazil 6 3 3 6
Norway 5 4 1 5
Morocco 5 5 0 4
Scotland 2 6 -4 1
--------------------
This looks good!
GF GA GD PT
Nigeria 6 2 4 6
Bulgaria 6 3 3 6
Argentina 6 3 3 6
Greece 0 10 -10 0
--------------------
This looks good!
GF GA GD PT
Mexico 3 3 0 4
Ireland 2 2 0 4
Italy 2 2 0 4
Norway 1 1 0 4
--------------------
This looks good!
LOTTERY Ireland Netherlands
GF GA GD PT
England 2 1 1 5
Ireland 2 2 0 3
Netherlands 2 2 0 3
Egypt 1 2 -1 2
--------------------
This looks good!
Oppgave 3
Måltidsplanlegging for late mennesker:
- Du hadde en lang dag på skolen og du vil ikke dra til matbutikken på veien hjem. Du vet hva som finnes i kjøleskapet ditt og du har fire måltider som du elsker å lage ofte.
- Siden du tar INF100 bestemmer du deg for å lage en algoritme som finner de måltidene som du kan lage med det du har i kjøleskapet ditt. Mat i kjøleskapet og måltider er laget til i en liste, f.eks:
# contents of my fridge, in a list
my_fridge = ["tomato sauce", "mustard", "potatoes", "carrots", "chicken", "frozen fish"]
Måltider er laget til en tuple av tupler:
# meals and corresponding ingredients stored in tuple of tuples
meals = (
# name of dish [0], ingredients [1]
("fish_sticks", ("frozen fish", "potatoes", "mustard")),
("chicken_curry", ("chicken", "curry paste", "carrots", "potatoes", "rice")),
("chicken_veg", ("chicken", "potatoes", "carrots")),
("pasta", ("spaghetti", "tomato sauce")),
)
I filen uke_10_oppg_3.py gjør følgende:
DEL A
Implementer en funksjon som heter meal_list()
som tar som input to argumenter:
- listen av ingredienser i kjøleskapet ditt og
- tuplen av ingredienser til en måltid.
Funksjonen returnerer True
(du har alle ingredienser for å lage måltiden) eller False
(du har IKKE alle ingredienser for å lage måltiden).
Testkjøring:
print("Tester meal_list... ", end="")
assert (meal_list(my_fridge, meals[0][1]))
assert (not meal_list(my_fridge, meals[3][1]))
print("OK")
DEL B
Lag en annen funksjon som heter meal_options()
for å finne måltidene du kan lage med ingrediensene du har i kjøleskapet ditt:
Testkjøring:
print("Tester meal_options... ", end="")
assert ['fish_sticks', 'chicken_veg'] == meal_options(my_fridge, meals)
print("OK")
DEL C
Lag en siste funksjon som heter to_buy()
som returnerer listen over ingredienser du må kjøpe fra butikken for å lage en måltid. Funksjonen tar som input to argumenter:
- listen av ingredienser i kjøleskapet ditt og
- tuplen av ingredienser til en måltid.
TIPPS: Strategien for å løse for DEL C er lik strategien for DEL A, med bare små forskjeller.
Testkjøring:
print("Tester to_buy... ", end="")
assert ['spaghetti'] == to_buy(my_fridge, meals[3][1])
print("OK")
Oppgave 4
I gamle egyptiske tekster finner vi en multiplikasjonsmetode for vilkårlige positive heltall, som fungerer med bare addisjon og dobling.
For å multiplisere for eksempel a = 19
og b = 23
, begynner vi med å skrive 1 og doble det til det nye tallet ville vært større enn a
:
1
2
4
8
16
Vi stopper på 16, siden 32 er større enn a = 19
.
Det finnes nå ett unikt utvalg av disse tallene hvor summen resulterer i a = 19
.
Det er 16 + 2 + 1
. Vi markerer disse tallene med X.
X 1
X 2
4
8
X 16
I den tredje kolonnen starter vi med tallet b = 23
, og fortsetter å doble det.
X 1 23
X 2 46
4 92
8 184
X 16 368
Til slutt tar vi bare de tallene fra den siste kolonnen som er merket med X, og summerer dem:
23 + 46 + 368 = 437
. Dette er vårt resultat: 19 * 23 er 437.
I uke_10_oppg_4.py skriv et program som gjør følgende:
Spør brukeren om to positive heltall med input().
Ved behov, bytt tallene slik at det første tallet er mindre enn det andre.
Regn ut innholdet til den egyptiske multiplikasjonstabellen etter fremgangsmåten som er vist ovenfor.
Skriv ut den ferdige multiplikasjonstabellen med pen formatering og justerte kolonner; slik at den ser ut som eksemplene vist nedenfor.
For formateringen kan du anta at brukeren bare gir deg tall mellom 1 og 99.
Programmet trenger å kjøre bare en gang hver gang det startes, du trenger ikke å be om nye input etter utskriften. Du trenger heller ikke sjekke om input er gyldige tall. Skillelinjene har 25 =
-tegn.
Noen eksempler på programkjøring ser slik ut:
Factor A: 10
Factor B: 13
=========================
1 13
X 2 26
4 52
X 8 104
=========================
2 + 8 = 10
26 + 104 = 130
=========================
10 * 13 = 130
Factor A: 19
Factor B: 23
=========================
X 1 23
X 2 46
4 92
8 184
X 16 368
=========================
1 + 2 + 16 = 19
23 + 46 + 368 = 437
=========================
19 * 23 = 437
Factor A: 17
Factor B: 6
=========================
1 17
X 2 34
X 4 68
=========================
2 + 4 = 6
34 + 68 = 102
=========================
17 * 6 = 102
Oppgave 5
I filen uke_10_oppg_5.py skriv en funksjon justify
som fyller ut en tekst med mellomrom slik at alle rader får samme lengden. Lengden på radene skal være et argument til funksjonen. Den justerede teksten skal returneres av funksjonen som en streng. Funksjonen skal ikke bruke print() eller input(). Her er hele spesifikasjonen:
Input: justify
skal ta to argument, en str (text
) og en int (line_len
).
Output: funksjonen skal returnere samme tekst som i text
men hvor alle rader har lengden line_len
.
Vilkår:
Alle rader må inneholde så mange ord som er mulig innen radlengden.
Funksjonen får bare fylle ut med mellomrom (’ ‘) mellom ordene (ikke tab eller noen annen whitespace).
Mellomrommen i hver rad må være så jevnt fordelt som mulig, i.e. forskjellen mellom størst antall mellomrom og minst antall mellomrom mellom orden i en rad får ikke være mer enn 1. Men du får selv velge hvordan du vil plassere ut mellomrommen så lenge dette er oppfyllt.
Alle rader må begynne med et tegn som ikke er whitespace.
Slutten på alle rader må enten være på formen ‘char\n’ eller ‘char’, hvor ‘char’ er et tegn som ikke er whitespace, i.e. du får ikke begynne eller slutte en rad med mellomrom.
Den siste raden i teksten skal ikke bli fylt ut med mellomrom. I denne raden skal det være eksakt ett mellomrom mellom alle ord.
Du kan anta at ingen ord i
text
er lengre ennline_len
.
Eksempel: om input til funksjonen er følgende tekst:
Alice was beginning to get very tired of sitting by her sister
on the bank, and of having nothing to do: once or twice she had peeped
into the book her sister was reading, but it had no pictures
or conversations in it, 'and what is the use
of a book,' thought Alice 'without pictures or conversation?'
og line_len er 60 skal funksjonen returnere noe slikt:
Alice was beginning to get very tired of sitting by her
sister on the bank, and of having nothing to do: once or
twice she had peeped into the book her sister was reading,
but it had no pictures or conversations in it, 'and what is
the use of a book,' thought Alice 'without pictures or
conversation?'