4.1 DRILL — Kodesporing: «hva skrives ut?»
Systematisk drill i å kjøre kode mekanisk i hodet og angi utskriften **eksakt** — Oppgave 1, den billigste og mest forutsigbare poengkilden.
Dette kapitlet driller Oppgave 1, som står i 6 av 6 moderne eksamenssett
(100 %) og er verdt rundt 8 poeng. Sjangeren heter A — kodeforståelse, altså
«hva skriver dette programmet ut?», og består av fem til sju korte deloppgaver.
Oppgave 1 er den billigste poengkilden på hele settet. Den krever ingen kreativitet, ingen struktur og ingen god idé — bare at du kan kjøre koden mekanisk i hodet og skrive resultatet nøyaktig. Til gjengjeld er den nådeløs:
i de nyere settene rettes den automatisk, så 5 og 5.0 er ikke det samme svaret, og et manglende mellomrom er null poeng.
Dette må sitte — bokas høyeste av tre nivåer. Regn med å bruke rundt 20 av de
240 minuttene her, og regn med å få alle poengene.
Tidsbudsjett: kapitlet er på 90 minutter. Sporingsmetoden og det gjennomgåtte
eksempelet tar rundt 25 minutter; de seksten oppgavene er fire økter à ca. 16 minutter. Ta pause der markørene står.
Forkunnskaper — sist du var her
Hele del 1 til 3: kap. 1.1 — Variabler og datatyper,
kap. 1.2 — Betingelser,
kap. 1.3 — Løkker,
kap. 2.1 — Funksjoner,
kap. 3.1 — Lister,
kap. 3.2 — Ordbøker og
kap. 3.3 — Strenger.
Dette kapitlet lærer deg ingen ny konstruksjon. Det lærer deg å lese dem du allerede kan, uten å ta feil.
Tre ting du bruker på hver eneste oppgave, kort oppfrisket:
print(3, "a")
print(9 / 3, 9 // 3)
print([1, 2], {"a": 1})Utskrift:
3 a
3.0 3
[1, 2] {'a': 1}Merk ett mellomrom mellom komma-argumenter, at / alltid gir desimaltall, og at lister og ordbøker skrives med sine parenteser og med enkle anførselstegn rundt tekster. Disse tre detaljene avgjør flere poeng i Oppgave 1 enn all algoritmisk forståelse til sammen.
Sporingsmetoden — fem steg (~10 min)
Å spore kode er et håndverk med en fast oppskrift. Den er kjedelig, og det er hele poenget: du skal ikke gjette hva programmet gjør, du skal regne det ut.
endrer seg, og én kolonne til høyre som heter «Utskrift så langt». Én rad per linje eller per runde i løkka. Dette er ikke pynt: uten tavle husker du feil.
Steg 2 — Tell rundene i løkka først. range(3) gir 0, 1, 2 — tre runder.range(1, 4) gir 1, 2, 3 — også tre. range(len(liste)) gir nøyaktig de lovlige indeksene. Skriv opp verdiene før du begynner å regne, så slipper du å telle mens du sporer.
Steg 3 — Les hver print bokstavelig. Komma gir ett mellomrom. En liste
skrives med hakeparenteser, en ordbok med krøllparenteser, og tekster inne i
dem får enkle anførselstegn. En tekst skrevet ut alene får ingen.
Steg 4 — Hold styr på typen. Er verdien et heltall eller et desimaltall? En
tekst eller et tall? / gir alltid float; // og % gir heltall når begge sidene er heltall; + på to tekster skjøter dem.
Steg 5 — Skriv svaret eksakt, uten pynt. Ikke 5.0 for heltallet 5, ikke'tekst' med anførselstegn i svarfeltet, ingen ekstra mellomrom. I et auto-rettet felt er formen en del av svaret.
Fellekatalogen — de sju fellene som går igjen
Oppgave 1 er ikke tilfeldig satt sammen. De samme sju fellene roterer, og hver deloppgave tester som regel nøyaktig én av dem.
| Nr. | Fellen | Kjennetegn i koden |
|---|---|---|
| 1 | Tekst forvekslet med tall (#3) | anførselstegn rundt sifre, eller + mellom to verdier som «ser ut som tall» |
| 2 | Glemt konvertering (#4) | int(...) står ett sted og ikke et annet |
| 3 | Muteringsrekkefølge | to variabler oppdateres i samme runde, og den andre bruker den nye verdien |
| 4 | Nøstet akkumulering | en løkke inne i en løkke, ofte med en if og en teller |
| 5 | while med flere variabler | betingelsen avhenger av noe som endres midt i kroppen |
| 6 | Indeks og av-med-én (#5, #6) | liste[i], liste[-1], range(1, len(...)) |
| 7 | Ordbok som endrer seg selv | d[k] = d[k] + 1 inne i en løkke |
De seksten oppgavene i dette kapitlet roterer alle sju, med fire økter etter tema. Kjenner du igjen fellen på synet, vet du også hvor du skal være ekstra nøye.
mellomrom og linjeskift slik terminalen viser den.
a) (2 p)
a = "12" b = "3" print(a + b, int(a) + int(b))b) (2 p)
x = 3 y = 2 for i in range(2):
x = x + y y = x - y print(x, y)c) (2 p)
tall = [4, 8, 15]
print(tall[-1] - tall[0], len(tall))d) (2 p)
d = {}
for bokstav in "banan":
if bokstav not in d:
d[bokstav] = 0 d[bokstav] = d[bokstav] + 1 print(d)| Uttrykk | Type på sidene | Resultat |
|---|---|---|
a + b | tekst + tekst | "123" — skjøtet |
int(a) + int(b) | tall + tall | 15 — lagt sammen |
a = "12" b = "3" print(a + b, int(a) + int(b))Utskrift:123 15Margnotat (2 p): ett poeng per riktig verdi. Skriver du 15 15, har du
oversett anførselstegnene; skriver du 123 123, har du oversett int(...).
Fellen er #3 — heltall forvekslet med tekst.
— naturlig pausepunkt —
Deloppgave b — felle 3. To variabler oppdateres i samme runde, og den andre
linja bruker den nye verdien av x.
| Runde | x etter linje 1 | y etter linje 2 |
|---|---|---|
| start | 3 | 2 |
i = 0 | 3 + 2 = 5 | 5 - 2 = 3 |
i = 1 | 5 + 3 = 8 | 8 - 3 = 5 |
x = 3 y = 2 for i in range(2):
x = x + y y = x - y print(x, y)Utskrift:8 5Margnotat (2 p): her er tavla hele forskjellen. Bruker du den gamleverdien av
x på linje to, får du 8 3 — riktig metode, feil rekkefølge, og på et auto-rettet felt null poeng. Fyll ut én rad om gangen, ovenfra og ned.Deloppgave c — felle 6. Negativ indeks og lengde.
| Uttrykk | Verdi |
|---|---|
tall[-1] | 15 — siste element |
tall[0] | 4 — første element |
len(tall) | 3 — antall elementer |
tall = [4, 8, 15]
print(tall[-1] - tall[0], len(tall))Utskrift:
11 3Margnotat (2 p): merk at ingen av de to verdiene har hakeparenteser. Det er
enkeltverdier hentet ut av lista, ikke lista selv. Fellen er #5 — å lese -1 som nest siste, eller lengden som største indeks.
Deloppgave d — felle 7. En ordbok som endrer seg selv.
| Bokstav | Ny nøkkel? | Ordboka etter runden |
|---|---|---|
b | ja | {'b': 1} |
a | ja | {'b': 1, 'a': 1} |
n | ja | {'b': 1, 'a': 1, 'n': 1} |
a | nei | {'b': 1, 'a': 2, 'n': 1} |
n | nei | {'b': 1, 'a': 2, 'n': 2} |
d = {}
for bokstav in "banan":
if bokstav not in d:
d[bokstav] = 0 d[bokstav] = d[bokstav] + 1 print(d)Utskrift:{'b': 1, 'a': 2, 'n': 2}Margnotat (2 p): to ting må stemme samtidig — tallene og rekkefølgen.Nøklene står i den rekkefølgen de ble opprettet i, ikke alfabetisk og ikke etter størrelse. Og tekstnøklene skrives med enkle anførselstegn.
Om tidsbruk: hele denne oppgaven er 8 poeng av 100, og bør ta rundt 20
minutter med tavle. Det er de billigste poengene på settet — men bare hvis du skriver formen riktig.
Drilløkt 1 — Typer, uttrykk og forgrening (~16 min)
Fire oppgaver som tester felle 1, 2 og utskriftsformen. Før tavle på alle fire, selv om de ser enkle ut — det er nettopp de enkle som taper poeng på formen.
(Innstegsoppgave, sjanger A — kodesporing.) Hva skriver programmet ut? Skriv utskriften nøyaktig, med mellomrom og linjeskift slik terminalen viser den.
a = "7" b = "3" print(a + b)
print(int(a) + int(b))
print(int(a) // int(b), int(a) % int(b))(Innstegsoppgave, sjanger A — kodesporing.) Hva skriver programmet ut? Skriv utskriften nøyaktig, med mellomrom og linjeskift slik terminalen viser den.
print(9 / 3)
print(9 // 3, 9 % 3)
print(2 ** 3, 7 / 2)Hva skriver programmet ut? Skriv utskriften nøyaktig, med mellomrom og linjeskift slik terminalen viser den.
poeng = 60 if poeng > 60:
print("bestatt")
elif poeng > 40:
print("nesten")
else:
print("ikke bestatt")
print("ferdig")Hva skriver programmet ut? Skriv utskriften nøyaktig, med mellomrom og linjeskift slik terminalen viser den.
print("a", "b")
print("a" + "b")
print(1, 2.0, True)
print("2" * 3)| Oppgave | Felle | Det som avgjør |
|---|---|---|
| 1 | tekst mot tall (#3) | anførselstegnene |
| 2 | typen på resultatet | / gir alltid desimaltall |
| 3 | forgrening og kantverdi | > mot >=, og innrykket |
| 4 | utskriftsform | komma gir mellomrom, pluss gir ikke |
Ingen av dem krevde en tavle med mange rader — men alle fire krevde at du leste
formen like nøye som verdien. Det er halve Oppgave 1.
— naturlig pausepunkt —
Drilløkt 2 — Løkker og oppdateringsrekkefølge (~18 min)
Her kommer fellene som faktisk krever tavle. Fyll ut én rad per runde, ovenfra og ned, og ikke hopp over en linje fordi du «ser» hva den gjør.
Hva skriver programmet ut? Skriv utskriften nøyaktig, med mellomrom og linjeskift slik terminalen viser den.
a = 2 b = 1 for i in range(3):
a = 2 * a + b b = a - b print(a, b)Hva skriver programmet ut? Skriv utskriften nøyaktig, med mellomrom og linjeskift slik terminalen viser den.
total = 0 for i in range(4):
for j in range(i):
if j % 2 == 0:
total = total + 1 print(total)Hva skriver programmet ut? Skriv utskriften nøyaktig, med mellomrom og linjeskift slik terminalen viser den.
n = 20 s = 0 runder = 0 while n > 1:
s = s + n n = n // 2 runder = runder + 1 print(s, n, runder)Hva skriver programmet ut? Skriv utskriften nøyaktig, med mellomrom og linjeskift slik terminalen viser den.
antall = 0 sum_verdi = 0 for i in range(10, 0, -3):
antall = antall + 1 sum_verdi = sum_verdi + i print(i, antall, sum_verdi)| Oppgave | Felle | Kontrollen som fanger den |
|---|---|---|
| 5 | muteringsrekkefølge | fyll ut tavla linje for linje, aldri parallelt |
| 6 | nøstet akkumulering | skriv opp hvilke verdier hver indre løkke gir |
| 7 | while med flere variabler | noter sluttverdien til betingelsesvariabelen |
| 8 | negativt steg, løkkevariabel etter løkka | skriv opp range-verdiene først |
Alle fire har det samme botemiddelet: tell rundene før du regner. Det tar femten sekunder og fjerner den vanligste kilden til feil svar.
— naturlig pausepunkt —
Drilløkt 3 — Lister og indekser (~16 min)
Nå kommer felle 6 for fullt. Skriv alltid indeksene over elementene før du begynner — det tar fem sekunder og fjerner halvparten av feilene.
Hva skriver programmet ut? Skriv utskriften nøyaktig, med mellomrom og linjeskift slik terminalen viser den.
maalinger = [3, 9, 12, 5]
print(maalinger[1], maalinger[-2])
print(maalinger[0] + maalinger[3])
print(len(maalinger), maalinger)Hva skriver programmet ut? Skriv utskriften nøyaktig, med mellomrom og linjeskift slik terminalen viser den.
tall = [2, 5, 8]
ny = []
for t in tall:
ny.append(t * 2)
tall[0] = 99 print(tall)
print(ny)
print(tall + ny)Hva skriver programmet ut? Skriv utskriften nøyaktig, med mellomrom og linjeskift slik terminalen viser den.
verdier = [6, 2, 9, 4]
resultat = []
for i in range(1, len(verdier)):
resultat.append(verdier[i] - verdier[i - 1])
print(resultat)
print(len(resultat), verdier[-1] - verdier[0])Hva skriver programmet ut? Skriv utskriften nøyaktig, med mellomrom og linjeskift slik terminalen viser den.
tall = [5, 3, 8, 1, 7]
valgt = []
i = 0 while i < len(tall):
if tall[i] > tall[0]:
valgt.append(tall[i])
i = i + 2 print(valgt, len(valgt))
print(i, tall[-1])| Oppgave | Felle | Kontrollen som fanger den |
|---|---|---|
| 9 | positiv og negativ indeks | skriv indeksene over elementene |
| 10 | ferdig bygget liste påvirkes ikke | fyll ut begge listene før du leser videre |
| 11 | grenser i naboløkke | tell hvor mange runder range(1, n) gir |
| 12 | steg, kantverdi og sluttverdi | noter verdien til i etter løkka |
Alle fire krever samme forarbeid: skriv opp indeksene og rundene før du regner. Det er sekundene som avgjør Oppgave 1.
— naturlig pausepunkt —
Drilløkt 4 — Ordbøker, tekst og funksjoner (~18 min)
Den siste økta er den tyngste. Her kommer felle 7, og de sammensatte oppgavene der du må spore et funksjonskall inne i en løkke.
Hva skriver programmet ut? Skriv utskriften nøyaktig, med mellomrom og linjeskift slik terminalen viser den.
d = {"a": 2}
d["b"] = 5 d["a"] = d["a"] + 3 print(d)
print(len(d), d["a"], "c" in d)Hva skriver programmet ut? Skriv utskriften nøyaktig, med mellomrom og linjeskift slik terminalen viser den.
d = {}
for tall in [4, 1, 4, 2, 4, 1]:
if tall not in d:
d[tall] = 0 d[tall] = d[tall] + 1 print(d)
print(len(d), d[4], d[1] + d[2])Hva skriver programmet ut? Skriv utskriften nøyaktig, med mellomrom og linjeskift slik terminalen viser den.
linje = "31;Grorud;Fornebu" felt = linje.split(";")
ny = "" for tegn in felt[0]:
ny = tegn + ny print(felt)
print(len(felt), felt[-1])
print(ny, int(ny) + 1)Hva skriver programmet ut? Skriv utskriften nøyaktig, med mellomrom og linjeskift slik terminalen viser den.
def juster(x, grense):
if x > grense:
return x - grense return 0
sum_verdi = 0 tallene = [12, 7, 20]
for tall in tallene:
sum_verdi = sum_verdi + juster(tall, 10)
print(sum_verdi)
print(juster(10, 10), juster(3, 10), juster(25, 10))Fem feil koster nesten alle poengene som mistes i Oppgave 1:
- #3 — tekst forvekslet med tall. Anførselstegn rundt sifre gjør + til
skjøting og * til gjentakelse. Se etter dem før du regner.
- Feil type i svaret. / gir alltid desimaltall. Skriver du 3 der
terminalen viser 3.0, er svaret galt i et auto-rettet felt.
- Muteringsrekkefølge. En linje ser verdiene slik de er akkurat da. Fyll ut
tavla ovenfra og ned, aldri parallelt.
- #5 — av-med-én. range(1, len(...)) gir én runde færre.
liste[len(liste)] finnes ikke. Skriv indeksene over elementene først.
- Feil utskriftsform. Komma gir ett mellomrom, pluss gir ingenting. Lister
og ordbøker får sine parenteser og enkle anførselstegn rundt tekster;
enkeltverdier får ingen av delene.
Og én ting som ikke er en feil, men en vane: skriv aldri svaret uten å ha ført tavle. Oppgavene i Oppgave 1 er valgt nettopp fordi de ser opplagte ut.
Begrepsbank
Begrepsbanken er flashcard- og repetisjonsstoff — den gjentar det du nettopp har lest. Hopp trygt over ved førstegangslesing; tidsanslaget for kapitlet gjelder kjernestoffet.
En tabell med én kolonne per variabel som endrer seg, én rad per linje eller runde, og en siste kolonne «Utskrift så langt».
Den er ikke pynt, og den er ikke for sensor — den er for deg. Uten tavle holder du to eller tre verdier i hodet samtidig, og nettopp det er det oppgaven er konstruert for å gjøre vanskelig.
Regn med et halvt minutt per deloppgave. Det er billig, mot 8 poeng.
Det første du skriver opp, før du regner på noe.
range(3) gir 0, 1, 2. range(1, 4) gir 1, 2, 3. range(10, 0, -3) gir 10, 7,
4, 1. range(0) gir ingen runder. Stoppverdien er alltid eksklusiv, uansett retning.
Antall runder er stopp - start når steget er 1. Med et annet steg må du skrive verdiene ut — det er raskere enn å regne, og du bommer ikke.
At en linje ser variablenes verdier slik de er akkurat da, ikke slik de var ved rundens start.
Står det
a = 2 b = 1 a = a + b b = a + b print(a, b)Utskrift:
3 4bruker den siste linja den nye a (3), ikke den gamle (2). Å fylle ut tavla parallelt i stedet for ovenfra og ned er den vanligste kilden til feil svar i løkkeoppgaver.
Verdien som ligger nøyaktig på grensen i en betingelse.
60 > 60 er usann; 60 >= 60 er sann. Oppgave 1 velger nesten alltid data som ligger på kanten, fordi det er der forskjellen mellom > og >= vises.
Vanen som lønner seg: hver gang du ser en sammenligning, sjekk om verdien er akkurat like stor. Er den det, er det sannsynligvis hele poenget med deloppgaven.
Med faste grenser ganges antallet: for i in range(3) medfor j in range(2) inni gir 3 ganger 2, altså 6 runder.
Med en indre grense som avhenger av den ytre må du telle: for j in range(i) gir 0, 1, 2 … runder etter tur. Den første runden gjør da ingenting, fordirange(0) er tom.
Skriv opp j-verdiene per i i en egen kolonne. Det er raskere enn å prøve å holde dem i hodet.
En løkkevariabel forsvinner ikke når løkka er ferdig. Den beholder den siste verdien den fikk, og kan leses på linja etter.
For for i in range(10, 0, -3): er i lik 1 etterpå — den siste verdienrange ga, ikke stoppverdien.
For en while gjelder det samme, men med en vri: variabelen har den verdien som gjorde betingelsen usann. Etter while i < 5: med i = i + 2 fra 0, er i lik 6, ikke 5.
Komma mellom argumentene gir ett mellomrom mellom dem i utskriften, ogprint avslutter alltid med linjeskift.
Pluss gjør noe annet: print("a" + "b") er ett argument, og gir ab uten mellomrom.
Skillet er verdt et poeng i nesten hver eneste Oppgave 1. Les hvert print bokstavelig: hvor mange argumenter er det, og hva står mellom dem?
print(liste) viser hakeparenteser, komma og ett mellomrom etter hvert komma — og tekster inne i lista får enkle anførselstegn.print(liste[0]) viser ingen av delene: det er én verdi, ikke en liste.
Begge formene dukker gjerne opp i samme deloppgave, nettopp for å teste om du ser forskjellen. Skriv svaret slik terminalen ville vist det, tegn for tegn.
print(ordbok) viser krøllparenteser, kolon og komma: {'a': 1, 'b': 2}.Tekstnøkler får enkle anførselstegn, heltallsnøkler får ikke. En telling over
tall gir {4: 3, 1: 2}, mens en telling over ord gir {'buss': 3}.
Rekkefølgen er den nøklene ble opprettet i. Å overskrive en verdi flytter ikke nøkkelen bakerst, og ordboka sorterer aldri.
/ gir alltid desimaltall, også når regnestykket går opp: 9 / 3 er 3.0.// og % gir heltall når begge sidene er heltall.I et auto-rettet svarfelt er 3 og 3.0 to ulike svar, og bare det ene er riktig. Det samme gjelder 18 mot 18.0.
Vanen som lønner seg: skriv typen i margen ved siden av hver verdi mens du sporer. Da ser du selv når en divisjon har gjort et heltall om til et desimaltall.
Anførselstegn er det første du leter etter, før du regner på noe.
"1" + "2" er "12"; 1 + 2 er 3. "ab" * 3 gjentar; 2 * 3 ganger."12" == 12 er usann. Og alt som kommer fra input(), en fil eller .split() er tekst, uansett hvor mye det ser ut som et tall.
Dette er feilkode #3 og #4, og de to er tilsammen den hyppigste fellen i
Oppgave 1.
I de nyere settene rettes Oppgave 1 maskinelt: du skriver svaret i et lite felt, og en maskin sammenligner det med fasiten.
Det betyr at formen er en del av svaret. Skriv 18, ikke 18.0. Skrivtekst, ikke 'tekst' med anførselstegn. Ikke legg til mellomrom du ikke ser i terminalen, og ikke fjern noen heller.
Er du i tvil om formen, skriv den slik print ville vist den — det er alltid fasiten.
I en if-elif-else-kjede kjøres nøyaktig én gren: den første som er sann. Resten prøves ikke engang.
To selvstendige if-er er noe helt annet — der er begge spørsmål, og begge kan slå til. Forskjellen er ett ord i koden, og den snur svaret.
Se også etter linjer uten innrykk under kjeden. De står utenfor og kjøres uansett hvilken gren som slo til.
Når en løkke kaller en funksjon, sporer du funksjonen for seg først.
Lag en liten tavle med én rad per kall: argumentene inn, betingelsene inne i funksjonen, og verdien ut. Deretter setter du returverdiene inn i den ytre tavla.
Husk at en funksjon uten return gir None, og at return avslutter umiddelbart — linjer under blir aldri kjørt.
Skriv ordboka på nytt, i sin helhet, etter hver runde. Ikke prøv å holde endringene i hodet.
To spørsmål per runde: ble nøkkelen opprettet nå, eller fantes den fra før?
Og hva ble den nye verdien?
Rekkefølgen i utskriften følger opprettelsen. Derfor må du notere når hver nøkkel dukket opp første gang — det er ikke noe du kan rekonstruere til slutt.
Oppgave 1 er rundt 8 av 100 poeng, fordelt på fem til sju deloppgaver. Det gir omtrent 20 av de 240 minuttene.
Bruk dem. Dette er den eneste oppgaven der du kan være sikker på å få alle poengene, fordi svaret er mekanisk og fasiten entydig.
Men ikke bruk mer. Blir du sittende fast på én deloppgave, skriv ditt beste forsøk og gå videre — deloppgavene rettes hver for seg, og Oppgave 4 venter med nesten halve eksamen.
Dette kapitlet er skrevet av Anthropics toppmodeller (Claude Opus og Claude Fable) og er foreløpig ikke manuelt gjennomgått — kvalitetskontrollen gjøres av uavhengige KI-agenter, og innmeldte feil rettes fortløpende. Funnet en feil? Meld fra, så retter vi den. Les mer om hvordan innholdet lages.
Skolesaga er en uavhengig læringsressurs og er ikke tilknyttet eller godkjent av Universitetet i Oslo. Dette er ikke offisielt studiemateriell. Les mer.