Prøveeksamen
| 28. april 2026 |
| 4 timer |
| Lukket digital eksamen (med safe exam browser). |
| Tillatte hjelpemiddel: bøker frå litteraturlista og opp til 6 tosidige A4 ark med eigne notat. |
I tillegg til å være en mulighet for studenter å prøve ut en eksamen-setting, var prøveeksamen dette semesteret også delvis utviklet for forskningsformål. Oppgaveforfatterne har blitt inspirert av tidligere eksamener i emnet og har fått noen inspill fra emneansvarlig før utviklingen av prøven. Noen av oppgavene kommer også fra tidligere eksamener i emnet. Noen av oppgavene i de tre variantene av prøveeksamen var skrevet med ulike bakgrunnshistorier, men løsningene på problemene var i stor grad identisk.
- Kursnotater er tilgjengelige og søkbare under eksamen: pdf
Oppgavetekster, løsningsforslag og sensorveiledning finner du på denne siden.
Fordi eksamen var en lukket digital eksamen uten tilgang til å kjøre koden eller bruke internett, bes sensor ikke gi poengtrekk for forhold som enkelt ville blitt oppdaget og raskt rettet ved kjøring av koden. Dette inkluderer blant annet:
- manglende
import-setninger, - manglende kodeord (som f. eks. manglende
defforan funksjonsdefinisjoner), - feil navn på funksjoner og metoder i standardbiblioteket, i egen kode eller i eksterne moduler (såfremt det fremgår noenlunde av funksjonsnavnet hva kandidaten egentlig mener),
- feil navn på variabler (f. eks. kalle den samme variabelen både
totalogsumi ulike deler av koden), - enkle syntaks-feil (f. eks. manglende kolon etter
if-setninger), - og så videre.
Logiske feil skal det likevel (som hovedregel) bli trukket litt for; selv om man kunne ha oppdaget at noe var feil ved kjøring av koden. Dette inkluderer blant annet:
-
presedensfeil,
-
forveksling av indekser og elementer,
-
off-by-one -feil,
-
feil i algoritmer,
-
og så videre.
1 Automatisk rettet
Finn riktig datatype til hvert uttrykk (eller identifiser Error)
67//76 | |
"smør" in "smørbrødet" | |
[123456789] | |
"1. Januar, 1970"[0] |
Klikk på de grå feltene for å se svaret.
Hva skriver dette programmet ut? (Hvis programmet krasjer, skriv kun Error)
print( (1.2 < 1.19) or (9 > 99) ) | |
print( 'aaa' > 'bbb' ) | |
print( 100 != 100 ) |
def wut(x):
if x[0] == 'a':
if 'c' in x[2]:
if x[1] == 5:
return True
elif x[1] != 10:
y = str(x[1])
return 'y'
else:
if len(x) == 3:
y = x[1] + x[2]
return y
else:
return x[1]
result = wut(['a', '123', 'bc'])
print(result)
Hva skriver dette programmet ut (hvis programmet krasjer, skriv kun Error)?
For å se fasit, klikk «kjør».
def foxtrot(x):
if x >= 10:
return 10
else:
x += 10
if x > 10:
if x % 2 == 0:
x += 1
elif x >= 15:
x -= 1
else:
return 42
return x - 10
result = foxtrot(4)
print(result)
Hva skriver dette programmet ut (hvis programmet krasjer, skriv kun Error)?
For å se fasit, klikk «kjør».
def add(a, b, c):
val = 0
if (a < b) and (a < c):
val = b + c
return val
elif (b < a) and (b < c):
val = a + c
return val
else:
val = a + b
return val
print(val)
result = add(50, 17, 24)
print(result)
Hva skriver dette programmet ut (hvis programmet krasjer, skriv kun Error)?
For å se fasit, klikk «kjør».
def calculate(x):
x = x + x
x = x + x
x = x + x
return x
Hvilken av følgende kan brukes til å erstatte innholdet i funksjonen calculate slik at den modifisere versjonen av calculate returnerer det samme resultatet som den opprinnelige versjonen for alle verdier av x?
- return 4 * x
- return 3 * x
- return 6 * x
- return 8 * x
Svar : return 8 * x
n = 0
ls = [1, 2, 3]
for x in ls:
for y in ls:
if y % 2 == 0:
continue
n = n + 1
print(n)
Hva skriver dette programmet ut (hvis programmet krasjer, skriv kun Error ) ?
For å se fasit, klikk «kjør».
Hvor mange ganger vil dette programmet skrive ut noe (hvis programmet krasjer, skriv kun Error ) ?
n = 12
while n > 0:
print(n)
n = n - 2
Svar: 6
For å se fasit, klikk «kjør».
x = 999
y = {
x: 999,
'y': x,
1: 3
}
y[999] = 'x'
z = [1, x, y, 'z']
Anta at kodesnutten over har blitt kjørt. Hva skrives ut i disse setningene? Dersom programmet ville krasjet på linjen, skriv kun Error .
print(y[1]) | |
print(y['x']) | |
print(z[1]) | |
print(x) | |
print(y[z[0]]) | |
print(y[x]) |
Hva skriver dette programmet ut (hvis programmet krasjer, skriv kun Error ) ?
a = "ba"
b = "ab"
a, b = b, a
print( a + b )
For å se fasit, klikk «kjør».
2 Forklaring
Anta at du har en fil foo.csv som inneholder oversikten over fire venners prestasjoner gjennom dette semesterets strikkeklubb.
name, item, material, days
Lina, gloves, wool, 7
Peter, strip, wool, 20
Pål, sweater, cashmir, 76
Sophie, gloves, wool, 4
Lina, shirt, limum, 55
Sophie, sweater, viscose, 61
Se den vedlagte nedefor. Hva vil innholdet i filen bar.csv være etter at koden som vises nedefor er kjørt? Beskriv filens struktur, dens betydning, og gi anbefalinger om hvordan venner kan forbedre lesbarheten til koden.
from csv import DictReader, DictWriter
from io import StringIO
from pathlib import Path
a = Path('foo.csv').read_text(encoding='utf-8')
b = DictReader(StringIO(a), delimiter=',')
c = {}
for d in b:
e = d['name']
f = int(d['days'])
if e not in c:
c[e] = 0
c[e] += f
g = StringIO()
h = DictWriter(
g,
fieldnames=['n', 't'],
lineterminator='\n'
)
h.writeheader()
h.writerows([
{'n': k, 't': v}
for k, v in c.items()
])
Path('bar.csv').write_text(
g.getvalue(),
encoding='utf-8'
)
Struktur: Filen er en CSV-fil med to kolonner: n (navn) og t (totalt antall dager). Hver rad tilsvarer én person fra foo.csv. Rekkefølgen på radene følger den rekkefølgen personene dukker opp for første gang i foo.csv (Lina, Peter, Pål, Sophie).
Betydning: Filen viser hvor mange dager totalt hver person har brukt på strikkeprojektene sine gjennom semesteret. For eksempel har Lina brukt 7 + 55 = 62 dager (hansker + skjorte), mens Sophie har brukt 4 + 61 = 65 dager.
Anbefalinger for bedre lesbarhet:
Koden bruker gjennomgående enkeltbokstavs-variabelnavn (a, b, c, d, e, f, g, h) som gjør det svært vanskelig å forstå hva koden gjør uten å lese den nøye linje for linje. Følgende endringer anbefales:
- Gi variablene meningsfulle navn, for eksempel
file_contenti stedet fora,readeri stedet forb,totalsi stedet forc,rowi stedet ford,namei stedet fore,daysi stedet forf,outputi stedet forg, ogwriteri stedet forh. - Feltnavnene
'n'og't'ibar.csver lite beskrivende. Å bruke'name'og'total_days'ville gjort filen langt lettere å forstå for en som åpner den uten å kjenne koden. - En kort kommentar øverst i koden som forklarer hva skriptet gjør ville hjulpet leseren å orientere seg raskt.
I treningsprogrammet er en utøver begrenset til fire ukentlige økter med to treningsblokker hver uke. Simulatoren for treningsprogrammet presenteres nedefor.
Simuleringen viser tilfeldigvis at utøveren trene for alltid. Hvordan forhindre dette? Forklar hvor alt gikk galt, og foreslå en løsning og hvordan du kan teste det.
current_block = 2
current_week = 2
while current_week <= 4:
while current_block <= 2:
print(f"Another week of training!")
current_week += 1
current_week = 0
current_block += 1
print(f"Training completed. Good job!")
Koden inneholder feil som fører til at den indre løkken kjører for alltid.
current_week = 0 tilbakestiller uketelleren inne i den indre løkken.
Linjen current_week = 0 er plassert inne i den indre while-løkken. Dette betyr at hver gang en treningsblokk er gjennomført, nullstilles current_week tilbake til 0 — like etter at den ble økt med 1. current_week vil derfor aldri nå verdien 5, og den ytre løkkens betingelse (current_week <= 4) vil aldri bli usann. Linjen current_week = 0 skal fjernes.
Forslag til rettet kode:
current_week = 1
while current_week <= 4:
current_block = 1
while current_block <= 2:
print(f"Week {current_week}, block {current_block}")
current_block += 1
print(f"Another week of training!")
current_week += 1
print(f"Training completed. Good job!")
3 Kodeskriving

Skriv en kodesnutt slik at minnets tilstand blir som vist over. Du vil ikke få trekk i poeng dersom du definerer andre variabler i tilegg.
Klikk på «se steg» -knappen for å verifisere at denne koden gir riktig bilde av minnet.
a = ["a", "b"]
b = ["a", ["a", "b"], a]
test cases:
points = sum([ a == ["a", "b"], b == ["a", ["a", "b"], ["a", "b"]], b[2] is a, (b[1] == a) and (b[1] is not a), (b[1] is not b[2]), ])
En forgasser har som oppgave å blande drivstoff og luft i forbrenningsmotorer. Den fysiske mekanismen er beskrevet av Bernoullis ligning, som sier at følgende størrelse er konstant langs en strømlinje:
$$ \rho v^2 + \rho g h + P = const $$
Der:
- $\rho$ (gresk “rho”) er væsketetthet,
- $v$ er strømningshastighet,
- $h$ er høyden til væskeelementet og
- $P$ er statisk trykk.
Når dysene i forgasseren tettes til, faller strømningshastigheten. Ifølge Bernoullis prinsipp fører dette til at det statiske trykket stiger — summen avviker fra sin forventede konstante verdi, blandingen blir mager og motoren går ustabilt.
Et diagnosesystem registrerer et sett med strømningsmålinger for hver forgasserer under en testkjøring og sammenligner Bernoulli-summen med en kjent optimal verdi. En forgasser flagges for rengjøring dersom avviket overstiger en akseptabel terskel.
Skriv en funksjon check_carburetor() som henter oppslagsverk over forgassersmålinger og returnerer en list med forgassersartikler som krever rengjøring. Forgasseren bør anses som ugyldig hvis
den faktiske verdien er større eller mindre enn forgasseren optimale verdi pluss eller minus en viss terskelverdi på 500. Ta 9.81 som en gravitasjonskonstant.
metrics = {
"KRB-001": {"rho": 750, "v": 2.0, "h": 0.05, "P": 101325, "optimal": 104693},
"KRB-002": {"rho": 750, "v": 1.6, "h": 0.05, "P": 103200, "optimal": 104693},
"KRB-003": {"rho": 750, "v": 2.1, "h": 0.05, "P": 101100, "optimal": 104693},
"KRB-004": {"rho": 750, "v": 1.5, "h": 0.05, "P": 103800, "optimal": 104693},
"KRB-005": {"rho": 750, "v": 1.9, "h": 0.05, "P": 101500, "optimal": 104693}
}
G = 9.81
THRESHOLD = 500
def bernoulli_sum(rho, v, h, P):
return rho * v**2 + rho * G * h + P
def check_carburetor(metrics):
clogged = []
for article, m in metrics.items():
actual = bernoulli_sum(m["rho"], m["v"], m["h"], m["P"])
deviation = abs(actual - m["optimal"])
if deviation > THRESHOLD:
clogged.append(article)
return clogged
print(check_carburetor(metrics))
test cases:
-
check_carburetor({"KRB-001": {"rho": 750, "v": 2.0, "h": 0.05, "P": 101325, "optimal": 104693}})[]
-
check_carburetor({"KRB-002": {"rho": 750, "v": 1.6, "h": 0.05, "P": 103200, "optimal": 104693}})['KRB-004']
-
check_carburetor({"KRB-003": {"rho": 750, "v": 2.1, "h": 0.05, "P": 101100, "optimal": 104693}})[]
-
check_carburetor({"KRB-004": {"rho": 750, "v": 1.5, "h": 0.05, "P": 103800, "optimal": 104693}})['KRB-004']
-
check_carburetor({"KRB-005": {"rho": 750, "v": 1.9, "h": 0.05, "P": 101500, "optimal": 104693}})[]
Enterprenørfirma bruker en standardmetode for å beregne justerert forsendelsesdato for bestillinger. Regelen fungerer slik: ta datoen da bestillingen ble mottatt, legg til 7 dager (behandlingstid), og trekk deretter fra 3 måneder (sesongbasert etterslepsjustering).
Skriv en funksjon calc_dispatch_date() med en parameter dato i “dd.mm” formatet. La funksjonen ta mottaksdatoen for bestillingen og returnere den gyldige justerte forsendelsesdatoen. Alle datoer er av strengtypen.
Sørg for at datoene er gyldige. Du kan anta at året ikke er et skuddår.

# get last month's day
def check_ddmm_correct(month):
if month == 2:
last_m_day = 28
elif month in (1, 3, 5, 7, 8, 10, 12):
last_m_day = 31
else:
last_m_day = 30
return last_m_day
# check that this day is possible for that month
def check_overmonth(day, month):
overflow = day // (check_ddmm_correct(month) + 1) # 1 if overflowed, else 0
day = day % check_ddmm_correct(month) or check_ddmm_correct(month) # keep last day if remainder is 0
month += overflow
month = month % 12 or 12
return day, month
# calculate exp due date
def calc_dispatch_date(dato):
day, month = dato.split(".")
day = int(day)
month = int(month)
day += 7 # step 1
day, month = check_overmonth(day, month)
month = month - 3 # step 2
day, month = check_overmonth(day, month)
return f"{day}.{month}"
test cases:
-
“24.05” - “3.3” (overflow to march)
-
“25.03” - “1.1” (overflow to april)
-
“31.12” - “7.10”
-
“21.05” - “28.02”
-
“22.05” - “1.3”
