Tilbake
3.4

3.4 DRILL — Skriv en funksjon over liste, ordbok eller streng

Full drill på Oppgave 3 (sjanger C/D/E): fra oppgavetekst til kort, eksplisitt funksjon i sensors grunnkonstruksjon-stil, med roterende datainnhold.

80 min
14 oppgaver
DRILLSkriv en funksjon over listeordbok eller streng
Din fremgang i kapitlet
0 / 14 oppgaver
Kapitlets plass i kurset

Forkunnskaper — sist du var her

Hele del 3: kap. 3.1 — Lister,
kap. 3.2 — Ordbøker og
kap. 3.3 — Strenger. Under dem ligger
kap. 2.1 — Funksjoner og
kap. 1.3 — Løkker.

De fire tingene du bruker i hver eneste oppgave her:

- startverdi før løkka, oppdatering inne i den, return etter,
- if k not in d: før du regner på en ordboknøkkel,
- at .split() gir en liste, og at felt fra den alltid er tekster,
- at funksjonen skal returnere, ikke skrive ut.

Kort oppfrisket — de tre datastrukturene, hver med sin startverdi:

ny_liste = []
ny_ordbok = {}
ny_tekst = "" print(ny_liste, ny_ordbok, len(ny_tekst))

Utskrift:

[] {} 0

Legg dem på minnet. Hvilken av de tre du starter med, avgjøres av hva oppgaven ber deg returnere — og det er første steg i oppskriften under.

Løsningsoppskriften — fra oppgavetekst til ferdig funksjon (~10 min)

Alle deloppgavene i Oppgave 3 løses med den samme framgangsmåten. Den har fem steg, og de tre første tar under ett minutt når de sitter.

📜Fem steg fra oppgavetekst til funksjon
Steg 1 — Hva skal returneres? Les siste setning i oppgaveteksten. Er svaret
ett tall eller en sannhetsverdi, trenger du ingen samling. Er svaret en liste, starter du med []. En ordbok gir {}. En tekst gir "".

Steg 2 — Hva løper du gjennom? Det som kommer inn som parameter. En liste
løpes med for e in liste:, en ordbok med for k in ordbok: (og verdien hentes med ordbok[k]), en tekst med for tegn in tekst: — eller for ord in tekst.split(): hvis oppgaven snakker om ord.

Steg 3 — Hvilket mønster? Velg ett av de seks i tabellen under. Signalordene
i oppgaveteksten avgjør, og de er påfallende faste.

Steg 4 — Skriv de tre linjene. Startverdi før løkka, oppdatering inne i den,
return etter. Ikke skriv noe mer før dette skjelettet står.

Steg 5 — Prøv kanttilfellene i hodet. Hva gjør funksjonen med en tom
samling? Og hva gjør den når det ikke finnes noe treff? De to spørsmålene tar ti sekunder og redder feilkode #6 hver gang.

Mønstertabellen

Seks mønstre dekker praktisk talt alle deloppgavene som har vært gitt. Lær signalordene i venstre kolonne — det er dem du leter etter i oppgaveteksten.

Signalord i oppgavenMønsterSkjelett
«hvor mange», «summen av», «gjennomsnittet»teller / akkumulatortotal = 0total = total + xreturn total
«er alle …», «finnes det noen …», «inneholder»flagg + tidlig returfor e in …: if moteksempel: return Falsereturn True
«en ny liste med …», «bare de som …»bygg ny listeny = []ny.append(e)return ny
«tell hvor mange ganger hver …»ordbok som tellerif k not in d: d[k] = 0d[k] = d[k] + 1
«gruppér etter …», «samle alle … per …»grupperingif k not in d: d[k] = []d[k].append(v)
«hvilken … flest», «den største», «den travleste»finn bestebeste = None, beste_antall = 0; oppdater begge
«en ny tekst der …», «fjern alle …»tegn for tegnny = ""ny = ny + tegnreturn ny

De to siste radene brukes ofte sammen: du teller først opp i en ordbok, og finner deretter den beste nøkkelen. Skriv dem som to funksjoner — da rettes de hver for seg, og du får uttelling for den ene selv om den andre skulle bli feil.
✏️Gjennomgått eksamenscase — en full Oppgave 3, med sensors blikk
Oppgave 3 (14 poeng). Et bibliotek registrerer hver utlånt tittel i en liste,
slik at den samme tittelen kan stå der flere ganger.

a) (5 poeng) Skriv tell_utlan(titlene) som returnerer en ordbok fra tittel
til antall utlån.

b) (5 poeng) Skriv mest_utlant(tellingen) som tar imot en slik ordbok og
returnerer tittelen med flest utlån. Er ordboka tom, skal funksjonen returnere
None.

c) (4 poeng) Skriv populaere(tellingen, grense) som returnerer en ny ordbok
med bare de titlene som er lånt ut flere ganger enn grensen.

Steg 1–3 for deloppgave a. Svaret skal være en ordbok, så startverdien er
{}. Du løper gjennom en liste. Signalordene «hvor mange ganger hver» peker rett på ordbok-som-teller.

def tell_utlan(titlene):
    antall = {}
    for tittel in titlene:
        if tittel not in antall:
            antall[tittel] = 0 antall[tittel] = antall[tittel] + 1 return antall

print(tell_utlan(["atlas", "kart", "atlas", "atlas"]))
print(tell_utlan([]))

Utskrift:

{'atlas': 3, 'kart': 1}
{}

Margnotat, deloppgave a (5 p): tom ordbok før løkka (1 p), løkke over lista
(1 p), opprettelse av nøkkelen med 0 (1 p), økningen (1 p), return etter løkka
(1 p). Glemmer du opprettelsen, stopper programmet med KeyError — men de fire andre poengene står. Det er dette som menes med at riktig struktur belønnes selv med en feil i.

— naturlig pausepunkt —

Deloppgave b. Svaret er én tittel, altså ingen ny samling. Signalordet
«flest» peker på finn beste.

def mest_utlant(tellingen):
    beste = None beste_antall = 0 for tittel in tellingen:
        if tellingen[tittel] > beste_antall:
            beste = tittel beste_antall = tellingen[tittel]
    return beste

print(mest_utlant({"atlas": 3, "kart": 1}))
print(mest_utlant({}))

Utskrift:

atlas
None

Margnotat, deloppgave b (5 p): to startverdier (1 p), løkke over nøklene
(1 p), sammenligningen (1 p), oppdatering av begge variablene (1 p), return etter løkka (1 p). Den vanligste feilen er å glemme
beste_antall = tellingen[tittel]. Da sammenlignes alt mot 0, og svaret blir den siste nøkkelen i stedet for den største — én linje, fire poeng igjen.

Legg merke til at b bygger på a, men ikke er avhengig av at du løste a.
Deloppgaven tar imot ordboka som parameter. Fikk du ikke a til, skriver du b likevel — det er nettopp det som menes med at deloppgaver rettes uavhengig.

Deloppgave c. Svaret er en ny ordbok, så startverdien er {} igjen, men nå
uten teller: du kopierer over de parene som oppfyller kravet.

def populaere(tellingen, grense):
    ny = {}
    for tittel in tellingen:
        if tellingen[tittel] > grense:
            ny[tittel] = tellingen[tittel]
    return ny

telling = {"atlas": 3, "kart": 1, "ordliste": 5}
print(populaere(telling, 2))
print(populaere(telling, 100))
print(telling)

Utskrift:

{'atlas': 3, 'ordliste': 5}
{}
{'atlas': 3, 'kart': 1, 'ordliste': 5}

Margnotat, deloppgave c (4 p): tom ordbok (1 p), løkke og betingelse (2 p),
return etter løkka (1 p). Den tomme ordboka som svar på en umulig grense er
riktig, ikke en feil — og den siste linja viser at originalen er urørt, som
den skal være.

Til slutt, om tidsbruk. Hele denne oppgaven er 14 poeng av 100. Bruker du mer
enn tjue minutter på den, tar du dem fra Oppgave 4, som er verdt over tre ganger så mye. Får du ikke en deloppgave til, skriv skjelettet med startverdi, løkke og
return — og gå videre.

Drilløkt 1 — Liste inn, tall eller sannhetsverdi ut (~15 min)

De enkleste deloppgavene, og de som alltid er med. Legg merke til at alle fire løsningene har det samme skjelettet: startverdi, løkke, return etter.

📝Oppgave 1

(Innstegsoppgave, sjanger C — skriv en funksjon over en liste.) Et treningssenter registrerer lengden på hver økt i minutter. Skriv
sum_minutter(oktene) som returnerer summen av alle øktene.

a) Skriv funksjonen med akkumulatormønsteret.

b) Hva returnerer den for den tomme lista?

📝Oppgave 2
Eksamensnivå, sjanger C

En sykkelutleie har en liste over hvor mange sykler som står igjen i hvert stativ. Skriv
alle_tomme(stativene) som returnerer True hvis alle stativene er tomme, og
False ellers.

a) Skriv funksjonen.

b) Hva returnerer alle_tomme([]), og er det rimelig?

📝Oppgave 3
Eksamensnivå, sjanger C

En værstasjon lagrer døgnets målinger. Skriv over_grensen(tallene, grense) som returnerer en
ny liste med bare de målingene som er strengt større enn grensen.

a) Skriv funksjonen.

b) Hva returnerer den når ingen måling er over grensen?

c) Hva ville skjedd hvis du hadde skrevet return tallene til slutt?

📝Oppgave 4
Eksamensnivå, sjanger C

Skriv
snitt(tallene) som returnerer gjennomsnittet av tallene i lista. Er lista tom, skal funksjonen returnere None.

a) Skriv funksjonen.

b) Hva slags type er svaret for [4, 5, 6] — heltall eller desimaltall?

c) Hvorfor er None et bedre svar enn 0 for den tomme lista?

Drilløkt 2 — Ordbok inn eller ut (~16 min)

Sjanger D er den deloppgaven som oftest skiller besvarelsene. Alle fire oppgavene under bruker ett av tre idiomer: teller, gruppering eller finn beste.

📝Oppgave 5
Eksamensnivå, sjanger D

En resirkuleringsstasjon logger hver leveranse som en avfallstype. Skriv
tell_typer(leveranser) som returnerer en ordbok fra avfallstype til antall leveranser.

a) Skriv funksjonen.

b) Hva returnerer tell_typer([])?

📝Oppgave 6
Eksamensnivå, sjanger D

En frivilligsentral har en liste med fornavn. Skriv
grupper_etter_forbokstav(navnene) som returnerer en ordbok fra forbokstav til lista over navn som begynner på den.

a) Skriv funksjonen.

b) Hvorfor er startverdien [] og ikke 0 her?

📝Oppgave 7
Eksamensnivå, sjanger D

Et bibliotek har en ordbok fra tittel til antall utlån. Skriv mest_utlant(utlan) som returnerer tittelen med flest utlån, eller None hvis ordboka er tom.

a) Skriv funksjonen.

b) Hva returnerer funksjonen hvis to titler har like mange utlån?

📝Oppgave 8
Eksamensnivå, sjanger D

Skriv
tell_lengder(ordene) som tar imot en liste med tekster og returnerer en ordbok fra ordlengde til hvor mange ord som har den lengden.

a) Skriv funksjonen.

b) Hvordan skrives nøklene ut, og hvorfor ser de annerledes ut enn i oppgave
5?

Drilløkt 3 — Tekst inn, tekst eller tall ut (~16 min)

Sjanger E er den minst hyppige av de tre (5 av 6 sett), men den er også den mest mekaniske: nesten alle oppgavene er tegn-for-tegn-mønsteret med én betingelse byttet ut.

📝Oppgave 9
Eksamensnivå, sjanger E

Skriv
fjern_vokaler(tekst) som returnerer en ny tekst uten vokalene a, e, i,
o og u. Du kan anta at teksten bare inneholder små bokstaver.

a) Skriv funksjonen.

b) Hva returnerer fjern_vokaler("aeiou"), og hvordan ser det ut i en
utskrift?

📝Oppgave 10
Eksamensnivå, sjanger E

En kantine har dagens meny som én tekst med mellomrom mellom rettene. Skriv
antall_ord_over(setning, n) som returnerer hvor mange ord i setningen som er lengre enn n tegn.

a) Skriv funksjonen.

b) Hva returnerer antall_ord_over("", 3), og hvorfor slipper du å skrive en
egen sjekk for det?

📝Oppgave 11
Eksamensnivå, sjanger E

Skriv
store_forbokstaver(setning) som returnerer setningen med stor forbokstav i hvert ord, og resten uendret. Ordene skal skilles av ett mellomrom.

For "ada marie berg" skal funksjonen gi "Ada Marie Berg".

a) Skriv funksjonen. Du har ikke lov til å bruke ferdige metoder utover
.split() og .upper().

b) Hvorfor må mellomrommet legges til før ordet og ikke etter?

📝Oppgave 12
Eksamensnivå, sjanger D…

En brettspillklubb lagrer oppmøtet som én tekst per kveld, på formen "ada;bo;ada", der hvert navn er skilt med semikolon. Skriv tell_oppmote(linje) som returnerer en ordbok fra navn til antall oppmøter i den linja.

a) Skriv funksjonen. Husk at linja kan ha et linjeskift på slutten.

b) Hva ville gått galt uten .rstrip()?

Drilløkt 4 — De to som skiller (~14 min)

Til slutt to oppgaver på det nivået som avgjør om deloppgaven blir hel eller halv: en som kombinerer to strukturer, og en «finn feilen» der du skal levere et konkret moteksempel.

📝Oppgave 13
Eksamensnivå, sjanger D

En kollektivrute har to lister som hører sammen: stoppene med navn, og passasjerene med antall påstigende på hvert stopp. Det første navnet hører til det første tallet, og så videre.

a) Skriv lag_ordbok(stoppene, passasjerene) som returnerer en ordbok fra
stoppnavn til antall påstigende.

b) Hvorfor må du bruke en indeksløkke her, i stedet for for e in liste:?

c) Hva forutsetter funksjonen om de to listene?

📝Oppgave 14
Eksamensnivå, sjanger I

En student skal finne måneden med flest regndager. Hun leverer:

def travleste(dager):
    beste = None beste_antall = 0 for m in dager:
        if dager[m] > beste_antall:
            beste = m return beste

a) Hva returnerer funksjonen for {"mai": 8, "juni": 14, "juli": 3}?

b) Gi et konkret moteksempel og forklar i én setning hvorfor det går galt.

c) Rett feilen, og vis at den rettede funksjonen virker.

API- og konstruksjonsliste

Begrepsbank

Begrepsbanken er flashcard- og repetisjonsstoff — den gjentar det du nettopp har lest. Hopp trygt over ved førstegangslesing; tidsanslaget for kapitlet gjelder kjernestoffet.

Mønstervalg

Å lese oppgaveteksten som en bestilling av ett bestemt kodemønster.

Framgangsmåten er tre spørsmål i rekkefølge: hva skal returneres (det gir startverdien), hva løper jeg gjennom (det gir løkka), og hvilket signalord står det (det gir oppdateringen).

Klarer du de tre på under ett minutt, er halve deloppgaven løst før du har skrevet en linje. Det er nettopp derfor drillen er verdt tiden: mønstrene skal kjennes igjen, ikke gjenoppfinnes.

Signalord

De faste formuleringene som peker på hvert mønster.

«Hvor mange», «summen av» og «gjennomsnittet» gir teller eller akkumulator.
«Er alle» og «finnes det noen» gir flagg med tidlig retur. «En ny liste med»
og «bare de som» gir bygg ny liste. «Tell hvor mange ganger hver» gir
ordbok som teller, mens «samle alle per» og «gruppér etter» gir
gruppering. «Flest», «størst» og «travleste» gir finn beste. «En ny tekst
der» og «fjern alle» gir tegn for tegn.

Det ene skillet som oftest bommes: «hvor mange» ber om et antall, «hvilke»
ber om innholdet.

Skjelettet

De tre linjene som er felles for alle mønstrene: startverdi før løkka, oppdatering inne i den, return etter.

Skriv dem først, før betingelser og detaljer. Da har du en funksjon som kjører, og du kan fylle inn resten.

På eksamen er skjelettet også det som gir mest uttelling per sekund. En funksjon med riktig skjelett og feil betingelse får det meste; en funksjon med riktig betingelse og return inne i løkka får lite.

Kanttilfellet «tom samling»

Spørsmålet du stiller hver gang: hva gjør funksjonen min med [], {} eller
""?

Løkkemønstrene tåler det av seg selv. Løkka kjører null runder, og
startverdien returneres — 0, en tom liste, en tom ordbok. Det er nesten alltid riktig svar.

Indeksering og divisjon gjør det ikke. liste[0] gir IndexError, og
total / len(tallene) gir ZeroDivisionError. Begge krever en sjekk øverst i funksjonen. Det er feilkode #6.

Kanttilfellet «ikke funnet»

Hva funksjonen skal svare når det ikke finnes noe treff.

Tre svar er i bruk, og valget er ditt. None er det ærligste og brukes når svaret skulle vært et objekt eller en nøkkel. -1 brukes når svaret er en
plass, siden en plass aldri kan være negativ. False brukes når spørsmålet
var et ja eller nei.

Vær forsiktig med -1 når tallet også kan være gyldige data — da kolliderer de to betydningene, og det er feilkode #10.

Delvis riktig gir uttelling

Sensor gir poeng per steg, ikke per fungerende program.

En funksjon med riktig struktur og én indeksfeil får det meste av poengene. En deloppgave rettes uavhengig av de andre, så du kan løse c selv om du ikke fikk til b — og du har lov til å kalle en funksjon oppgaveteksten beskriver, selv om du ikke selv rakk å skrive den.

Det praktiske rådet følger av dette: stå aldri fast. Skriv skjelettet, skriv en kommentar om det du ikke rakk, og gå videre til neste deloppgave.

Å dokumentere en forutsetning

Når oppgaveteksten ikke sier hva som skal skje i et grensetilfelle, velger du selv — og skriver én linje kommentar om valget.

Typiske tilfeller: hva som skjer ved uavgjort i finn beste, om en tom samling gir
True eller en feil, om to parallelle lister forutsettes like lange.

Dette er den ene legitime bruken av kommentarer i en besvarelse. Ellers skal koden stå for seg selv: ingen forklarende kommentar på hver linje, og ikke noe hovedprogram som ikke er bedt om.

Hjelpefunksjon

En liten funksjon som gjør én ting, brukt av en større.

Du har uttrykkelig lov til å legge til dine egne på eksamen, så lenge du kommenterer kort hva de gjør. To grunner til at det lønner seg: hjelpefunksjonen rettes for seg og gir uttelling selv om den store ikke ble ferdig, og koden blir lettere å lese.

Den vanligste delingen i sjanger D er tell først, finn beste etterpå — to korte funksjoner i stedet for én lang.

Teller mot akkumulator

To varianter av samme mønster, og forskjellen er hva du legger til.

Telleren øker med én per treff: antall = antall + 1. Den svarer på «hvor
mange».

Akkumulatoren legger til en verdi fra dataene: total = total + x. Den
svarer på «summen av».

Gjennomsnittet er begge deler: akkumuler summen, del på len(...) til slutt — og husk tomsjekken, ellers deler du på null.

Bygg ny mot endre gammel

Nesten alle oppgaver ber om en ny samling, ikke om at den gamle skal endres.

Det gjelder uansett type: ny = [], ny = {} eller ny = "" før løkka, og
return ny etter. Den samlingen du fikk inn som parameter, leser du bare fra.

Grunnen er at en liste eller ordbok som sendes inn, er den samme som utenfor.
Endrer du den, endrer du kallerens data — og det gir overraskelser som er vanskelige å finne.

Å velge løkkeform

Spørsmålet er alltid: trenger du plassen?

Trenger du bare verdiene, skriver du for e in liste: eller for k in ordbok:.
Det er kortere og kan ikke bomme på grensene.

Trenger du plassen, skriver du for i in range(len(liste)):. De tre tilfellene der du faktisk trenger den, er: å skrive tilbake til lista, å sammenligne naboelementer, og å lese to lister i takt.

Tekst, ord eller felt

Første spørsmål i enhver oppgave i sjanger E: hva er den minste enheten oppgaven snakker om?

Snakker den om tegn, løper du med for tegn in tekst:. Snakker den om
ord, løper du med for ord in setning.split():. Snakker den om felt i en
innlest linje, løper du med for felt in linje.rstrip().split(";"):.

Valget bestemmer resten av funksjonen. Å lese tegn når oppgaven mente ord, er den vanligste bomturen i sjangeren.

Å kontrollere svaret uten maskin

Eksamen er hjelpemiddelfri, så du kan ikke kjøre koden. Tre kontroller tar under et minutt til sammen, og fanger de fleste feilene.

Én: kjør funksjonen i hodet på et eksempel med to eller tre elementer, og
skriv verdiene i margen. To: prøv den tomme samlingen. Tre: tell at
if-blokken oppdaterer like mange variabler som du satte før løkka.

Den siste fanger den vanligste finn-beste-feilen, og den tar fem sekunder.

Tidsbudsjett i Oppgave 3

Oppgave 3 er rundt 28 av 100 poeng, fordelt på tre til fem deloppgaver. Det gir omtrent 45 minutter av de fire timene.

Bruker du mer, tar du tiden fra Oppgave 4, som alene er nesten halve eksamen.
Blir du sittende fast på en deloppgave, skriv skjelettet, skriv en kommentar om hva som mangler, og gå videre.

Poengene er jevnt fordelt, og et halvt svar på hver av fire deloppgaver gir mer enn et perfekt svar på én.

Repetisjon — de sju setningene som må sitte

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.