Tilbake
2.2

2.2 Gjenbruk, hjelpefunksjoner og meny/`main`-dispatcher

Bygge kjeder der funksjoner kaller hverandre, bruke hjelpefunksjoner, og skrive en main/meny som binder alt sammen — slik sensor forventer det på de store oppgavene.

45 min
7 oppgaver
Gjenbrukhjelpefunksjonermeny/`main`-dispatcher
Din fremgang i kapitlet
0 / 7 oppgaver
Forkunnskaper. Kapitlet bygger rett på det forrige:

- kap. 2.1def, parametere, return, flere returverdier og skillet mellom lokale og globale navn. Dette er det viktigste.
- kap. 1.3while-løkka og break, som er hele mekanikken i en meny.
- kap. 1.4input(), som alltid gir en streng, og løkka som spør på nytt til svaret er gyldig.
- kap. 1.2if/elif/else, som er det menyen dispatcher med.

Dataene i dette kapitlet er lister med tall, brukt slik Del 1 bruker dem: gjennomløp med for, oppslag med priser[i] og lengde med len(...). Å lese dem inn fra en fil kommer i kap. 4.1, og hele kjeden settes sammen på eksamensnivå i kap. 7.7.

Løkke 1 — Hvorfor gjenbruk gir poeng (~7 min)

Tenk deg at du skal lage en liten strømprisapp. Den skal kunne vise den høyeste prisen i døgnet, den skal kunne vise snittprisen, og den skal kunne si om det er dyrt akkurat nå. Alle tre trenger å gå gjennom den samme lista med 24 priser.

Den utsatte løsningen er å skrive den samme løkka tre ganger, én i hver funksjon. Den virker. Men den er tre ganger så lang å skrive under tidspress, den har tre steder å gjøre den samme feilen, og den gir ikke uttelling for det sensor faktisk ser etter.

Alternativet er å skrive løkka én gang, i en funksjon med et navn — og la de andre funksjonene kalle den.

Gjenbruk: å kalle sin egen funksjon fra en annen

En funksjon du har definert, kan kalles hvor som helst senere i fila — også inne i kroppen til en annen funksjon. Det er ingen ny konstruksjon: det er akkurat det samme kallet som fra toppnivå.

Kravet er bare at funksjonen er definert før kallet kjøres. Siden alle def-ene i et program kjøres før main() kalles, kan funksjonene fritt kalle hverandre uansett rekkefølge i fila.

def snitt(priser):
    total = 0
    for p in priser:
        total = total + p
    return total / len(priser)

def er_dyrt_naa(priser, naa):
    return naa > snitt(priser)

doegn = [0.42, 0.55, 1.20, 0.98]
print(snitt(doegn))
print(er_dyrt_naa(doegn, 1.05))

Utskrift:

0.7875
True

er_dyrt_naa inneholder ingen løkke. Den låner løkka fra snitt — og blir én linje lang.

Hjelpefunksjon

En hjelpefunksjon er en liten funksjon som ikke svarer på selve oppgaven, men som gjør en bit av arbeidet flere andre funksjoner trenger: snitt, finn_indeks, beregn_verdi.

Kjennetegnet er at den er kort, har et beskrivende navn og ikke skriver ut noe. Den returnerer, slik at den som kaller, bestemmer hva som skal skje med svaret.

Å innføre en hjelpefunksjon som oppgaven ikke ba om, er alltid tillatt og trekker aldri ned. Sensor sidestiller flere korrekte løsninger, og en oppdeling som gjør besvarelsen lettere å lese, er en fordel.

Kopiert kode mot kall

Står den samme kodesnutten to steder, er det en kopi. Kopier er dyre av tre grunner: de tar tid å skrive for hånd, de gir to steder å gjøre feil, og de gir ikke uttelling for gjenbruk.

Kjenn igjen kopien ved at du kan gi de to snuttene det samme navnet. Da er navnet funksjonen din, og de to stedene blir to kall.

Regelen i praksis: skriver du en løkke du har skrevet før i samme besvarelse, stopp og gi den et navn i stedet.

✏️Eksempel 1: Tre funksjoner, én løkke

Strømprisappen skal vise snittprisen, si om prisen akkurat nå er over snittet, og telle hvor mange timer i døgnet som lå over snittet. Skriv de tre funksjonene slik at løkka som regner snittet, bare står ett sted.

def snitt(priser):
    if len(priser) == 0:
        return None
    total = 0
    for p in priser:
        total = total + p
    return total / len(priser)

def er_over_snitt(priser, pris):
    return pris > snitt(priser)

def timer_over_snitt(priser):
    grense = snitt(priser)
    antall = 0
    for p in priser:
        if p > grense:
            antall = antall + 1
    return antall

doegn = [0.42, 0.55, 1.20, 0.98, 1.35, 0.61]
print(snitt(doegn))
print(er_over_snitt(doegn, 1.05))
print(timer_over_snitt(doegn))

Utskrift:

0.8516666666666667
True
3

Tre poenger å ta med seg:

- snitt står én gang. Endrer du senere hvordan snittet regnes, endrer du ett sted.
- timer_over_snitt kaller snitt én gang, før løkka, og lagrer svaret i grense. Hadde kallet stått inne i if-testen, ville snittet blitt regnet ut på nytt for hver eneste pris. Det gir riktig svar, men er unødvendig arbeid — og på en stor datamengde merkes det.
- Ingen av de tre skriver ut noe. Utskriften skjer nederst, der resultatene brukes. Det er den formen som lar neste deloppgave gjenbruke funksjonene.

Legg merke til at snittet skrives som 0.8516666666666667. Flyttall er sjelden pene av seg selv; å runde av til to desimaler i utskriften kommer i kap. 3.4.

📝Oppgave 1

(Innstegsoppgave — minimal sporing. Sjanger B — kodesporing, altså «hva skriver programmet ut?».) Tre funksjoner som bygger på hverandre. Hva skriver programmet ut?

def dobbel(x):
    return x * 2

def firedobbel(x):
    return dobbel(dobbel(x))

def sum_firedobler(verdier):
    total = 0
    for v in verdier:
        total = total + firedobbel(v)
    return total

print(firedobbel(3))
print(sum_firedobler([1, 2, 3]))

Løkke 2 — Kjeden: fra rådata til svar (~8 min)

Programmeringsoppgaven på eksamen har alltid den samme formen, uansett om domenet er bussruter, bibliotekutlån eller strømpriser:

les inn data → omform dem → analysér → vis eller lagre svaret.

Deloppgavene a) til f) er nettopp disse leddene, én funksjon per ledd. Og de er en kjede: leddet i c) tar imot det leddet i b) ga fra seg.

📜Gjenbrukskjeden — mønsteret hele programmeringsoppgaven følger
les_inn(...)      ->  rådataene som en liste eller tabell
omform(data)      ->  tallene konvertert, radene delt opp
analyser(data)    ->  det oppgaven spør etter
skriv_ut(svar)    ->  utskriften brukeren ser
main()            ->  kaller de fire, i den rekkefølgen

Blokken over er en mal, ikke kjørbar kode.

Tre regler gjør kjeden til en kjede, og alle tre er poenggivende:

1. Hvert ledd tar imot resultatet fra det forrige som parameter. Ingen funksjon henter data på egen hånd.
2. main gjør ingen regning selv. Den henter dataene én gang, sender dem videre og viser resultatet.
3. Ingen kopiert kode mellom leddene. Trenger to ledd det samme, blir det en hjelpefunksjon.

I denne boka lærer du leddene ett om gangen: innlesing fra fil i kap. 4.1, omforming i kap. 3.3, analysen i kap. 7.4 og hele kjeden på eksamensnivå i kap. 7.7. Her øver du på selve koblingen, med lister du får ferdig.

Kjede: senere funksjoner bygger på tidligere

En kjede er en rekke funksjoner der utverdien fra den ene er innverdien til den neste. Kravet er at hvert ledd returnerer noe — et ledd som bare skriver ut, kan ikke ha et neste ledd.

På eksamen ser du kjeden i selve oppgaveteksten: «c) Skriv funksjonen finn_beste(tabell) som bruker les_inn_data fra deloppgave a)». Der er kjeden ikke et forslag, men et krav.

Klarte du ikke a)? Skriv likevel c) som om a) virket, og kall funksjonen. Sensor gir uttelling for riktig struktur i c) selv om a) mangler eller er feil.

Å sende data videre som parameter

Data som flere funksjoner trenger, sendes inn som parameter — ikke hentes på nytt inne i hver funksjon.

Det høres selvsagt ut, men den vanligste strukturfeilen i besvarelser er nettopp at hver funksjon åpner og leser fila på nytt. Da blir programmet tregt, og du har skrevet den samme innlesingskoden fire ganger.

Regelen, som du skal ha med deg til Del 7: main leser dataene én gang og sender dem videre. Alle analysefunksjonene tar dataene som parameter og returnerer et svar.

✏️Eksempel 2: Fire ledd som kaller hverandre

En treningslogg har lengden på hver økt i minutter. Skriv en liten kjede: en funksjon som gjør minutter om til timer, en som regner totalen, en som lager en rapportlinje, og en main som binder dem sammen.

def til_timer(minutter):
    return minutter / 60

def total_minutter(oekter):
    total = 0
    for m in oekter:
        total = total + m
    return total

def rapport(oekter):
    minutter = total_minutter(oekter)
    timer = til_timer(minutter)
    return 'Trent ' + str(minutter) + ' minutter, altså ' + str(timer) + ' timer'

def main():
    logg = [45, 30, 90, 60]
    print(rapport(logg))

main()

Utskrift:

Trent 225 minutter, altså 3.75 timer

Se hvordan hvert ledd bare gjør sitt:

- til_timer kan ingenting om treningslogger. Den gjør ett tall om til et annet, og kunne like gjerne vært brukt på reisetid.
- total_minutter er den eneste som har en løkke.
- rapport regner ingenting selv. Den kaller de to andre og setter sammen teksten.
- main har dataene, kaller rapport og skriver ut. Ingen regning.

Sensorblikk: legg merke til str(...) rundt tallene i tekstsammensetningen. Uten den stopper programmet med TypeError, fordi + mellom en streng og et tall ikke er definert. Penere utskrift enn dette kommer i kap. 3.4 — her er poenget koblingen mellom funksjonene.

Merk også at kallet er main() helt til slutt, uten noen vaktsetning rundt. Sensor gir ingen uttelling for if __name__-konstruksjonen, og boka bruker den ikke.

📝Oppgave 2
Sjanger E–I

Et bibliotek fører hvor mange dager hver utlånt bok har vært ute. Boka er forfalt når den har vært ute i mer enn 28 dager.

a) Skriv er_forfalt(dager) som returnerer True eller False.

b) Skriv antall_forfalte(utlaan) som teller hvor mange av tallene i lista som er forfalte — og som bruker funksjonen fra a).

c) Skriv gebyr(utlaan) som returnerer 30 kroner per forfalt bok, og som bruker funksjonen fra b).

Løkke 3 — Hvem eier dataene? (~7 min)

Nå kommer det strukturvalget som skiller en besvarelse som henger sammen, fra en som bare nesten gjør det: hvor dataene bor.

Svaret er kort. Dataene bor i main, og sendes ned til funksjonene som parameter. Funksjonene sender svar opp igjen med return. Ingenting går sidelengs.

`main()` — programmets startfunksjon
main er navnet på funksjonen som styrer programmet: den skaffer dataene, kaller de andre funksjonene i riktig rekkefølge og viser resultatet.

Den er ikke noe spesielt for Python — det er bare et navn, og du kaller den selv med main() nederst i fila. Boka bruker aldri vaktsetningen if __name__, fordi den ikke gir uttelling på eksamen.

Kjennetegnet på en god main er at den er kort og lesbar: hvert kall er ett ledd i kjeden, og du ser hele programmets gang på skjermen samtidig.

Delegering — `main` regner ikke selv

En main som inneholder løkker og regnestykker, har overtatt jobben til funksjonene under. Da er den vanskelig å lese, og deloppgavene kan ikke vurderes hver for seg.

Regelen: main delegerer. Den har data, kall og utskrift — ingen for-løkke som regner ut noe, ingen betingelse som avgjør et faglig spørsmål.

def main():
    priser = [0.42, 0.55, 1.20, 0.98]
    print('Høyeste:', hoyeste(priser))
    print('Snitt:', snitt(priser))

Utskrift: ingen — blokken definerer bare main. Kalles den, skriver den to linjer.

Fire linjer, og du ser hele programmet. Det er malen.

📝Oppgave 3
Sjanger B

Her endrer den første funksjonen lista den får inn: linja verdier[i] = verdier[i] + 10 skriver en ny verdi over element nummer i i lista. Resten av listeapparatet kommer i kap. 3.1 — her trenger du bare å vite at elementet blir overskrevet. Hva skriver programmet ut?

def legg_til_ti(verdier):
    for i in range(len(verdier)):
        verdier[i] = verdier[i] + 10
    return verdier

def tell_over(verdier, grense):
    antall = 0
    for v in verdier:
        if v > grense:
            antall = antall + 1
    return antall

tall = [5, 20, 15]
nye = legg_til_ti(tall)
print(tell_over(nye, 20))
print(tell_over(tall, 20))

Løkke 4 — Konstanter (~5 min)

Noen verdier hører til hele programmet, ikke til én funksjon: prisen per forfalte dag, listen over gyldige distrikter, mva-satsen. De kalles konstanter, og fasitene i arkivet håndterer dem på to måter — begge godkjent.

Modulnivå-konstant

En konstant defineres helt til venstre i fila, utenfor alle funksjoner, og skrives med store bokstaver: GEBYR_PER_BOK = 30, MAKS_LAAN = 28.

Store bokstaver er ikke et krav fra Python — det er et signal til leseren om at verdien ikke endres underveis. Konstanten kan leses fritt inne i funksjonene, akkurat som beskrevet i kap. 2.1.

GEBYR_PER_BOK = 30

def gebyr(antall_forfalte):
    return antall_forfalte * GEBYR_PER_BOK

print(gebyr(3))

Utskrift:

90

Konstant som parameter

Den andre formen er å sende konstanten inn som en parameter med standardverdi: def gebyr(antall, sats=30).

Fordelen er at funksjonen blir uavhengig av resten av fila og kan gjenbrukes med en annen sats. Ulempen er én parameter til å holde styr på.

def gebyr(antall_forfalte, sats=30):
    return antall_forfalte * sats

print(gebyr(3))
print(gebyr(3, 45))

Utskrift:

90
135

Begge former gir full pott. Arkivets løsningsforslag bruker begge — noen ganger en global liste over distrikter, andre ganger den samme lista sendt inn som argument. Velg én og vær konsekvent i besvarelsen.

📝Oppgave 4
Sjanger E–I

En kommune tar 240 kroner i årsgebyr per resirkuleringsdunk, men satsen kan bli endret.

a) Skriv funksjonen arsgebyr(antall_dunker) med satsen som en konstant på modulnivå.

b) Skriv den samme funksjonen på nytt, denne gangen med satsen som en parameter med standardverdi, og vis et kall som overstyrer satsen til 260.

Løkke 5 — Menyløkka (~12 min)

Nå setter vi det siste leddet på plass: programmet som spør brukeren hva det skal gjøre, og fortsetter å spørre til brukeren vil avslutte.

Menyoppgaven står i omtrent halvparten av settene (5 av 10), alltid som siste deloppgave, og den er lett å score på — for den er nesten identisk hver gang. Lær mønsteret én gang, og skriv det ned nesten uten å tenke.

📜Meny-/`main`-mønsteret
while True:
    vis valgene
    valg = input('Valg: ')
    if valg == '1':
        kall funksjon 1
    elif valg == '2':
        kall funksjon 2
    elif valg == 'q':
        break
    else:
        si fra at valget er ugyldig

Blokken over er en mal, ikke kjørbar kode.

Fem detaljer avgjør om mønsteret virker, og hver av dem er en felle som er testet på eksamen:

1. while True: — løkka skal gå til brukeren selv sier stopp, ikke et fast antall ganger.
2. break i avslutningsgrenen — det er den eneste veien ut. Uten den går programmet for alltid (felle #8 — en input-løkke som ikke terminerer riktig).
3. Valget er en streng. input() gir alltid tekst, så testen er valg == '1' med fnutter — ikke valg == 1 (felle #1 — glemt konvertering). Sammenligner du mot tallet 1, er ingen gren noen gang sann.
4. else-grenen fanger alt annet, så programmet ikke bare tier ved en skrivefeil.
5. Menyen vises på nytt hver runde, fordi den står inne i løkka.

Menyløkka `while True:` med `break`
while True: er en løkke der betingelsen alltid er sann. Den stopper bare når kroppen kjører et break — og det er nettopp det du vil ha i en meny, der antall runder bestemmes av brukeren.

break avslutter løkka umiddelbart og hopper til første linje etter den. Står break inne i en funksjon, fortsetter funksjonen etter løkka; det er return som avslutter selve funksjonen.

runde = 0
while True:
    runde = runde + 1
    print('Runde', runde)
    if runde == 3:
        break
print('Ferdig etter', runde, 'runder')

Utskrift:

Runde 1
Runde 2
Runde 3
Ferdig etter 3 runder

Her er tellevariabelen der bare for å vise mekanikken. I en ekte meny er det brukerens svar som avgjør når break kjøres.

Menyvalget er en streng
input() returnerer alltid en streng, uansett hva brukeren skriver. Skriver brukeren 1, får du tegnet '1', ikke tallet 1.

Derfor testes menyvalg mot strenger: if valg == '1':. Testen if valg == 1: er ikke en feilmelding — den er noe verre, nemlig en test som alltid er usann, slik at menyen bare svarer «ugyldig valg» uansett hva brukeren gjør.

Vil du likevel ha et tall, konverterer du selv med int(valg) — men da må du først være sikker på at teksten faktisk er et tall, ellers krasjer programmet. Det er tema i kap. 1.4.

Dispatcher: `if/elif` som fordeler jobben

En dispatcher er koden som ser på valget og sender arbeidet videre til riktig funksjon. Det er en helt vanlig if/elif/else, men rollen er verdt et eget navn: dispatcheren skal bare fordele.

Hver gren består derfor av ett kall, eventuelt med en utskrift rundt. Regner grenene selv, har dispatcheren overtatt jobben til funksjonene — samme feil som en main som regner.

Grenene testes ovenfra og ned, og bare den første sanne kjøres. Rekkefølgen spiller derfor ingen rolle så lenge valgene er ulike.

Avslutningsvalget

Menyen trenger ett valg som betyr «ferdig». I dette faget skrives det som 'q' (for quit) eller '0', og det skal stå i menyteksten — brukeren kan ikke gjette.

Verdien som betyr «stopp», kalles en sentinel: en avtalt verdi som ikke er data, men et signal. Den samme ideen brukes når en løkke leser verdier til brukeren skriver tom tekst.

Avslutningsgrenen inneholder break, og gjerne en kort avskjedslinje før den.

`else`-grenen: ugyldig valg

Alt brukeren kan finne på å skrive, som ikke er et av valgene, havner i else. Der skriver du en kort beskjed og lar løkka gå en runde til — du skal ikke avslutte programmet fordi noen bommet på tasten.

Uten else skjer det ingenting synlig ved en skrivefeil: menyen dukker bare opp igjen, og brukeren tror programmet hang seg. Det er en av de tingene sensor ser etter i menyoppgaven, og den koster deg én linje.

✏️Eksempel 3: Menyen for strømprisappen

Sett sammen alt: to analysefunksjoner, en funksjon som viser valgene, og menyløkka som dispatcher. Brukeren skal kunne velge 1 for høyeste pris, 2 for snittpris, og q for å avslutte.

Analysefunksjonene er de samme som før — hoyeste og snitt, begge med tomtest og return. Menyen legges i sin egen funksjon, og selve valglista i en til:

def vis_valg():
    print('1 - høyeste pris i døgnet')
    print('2 - snittpris i døgnet')
    print('q - avslutt')

def hovedmeny(priser):
    while True:
        vis_valg()
        valg = input('Valg: ')
        if valg == '1':
            print('Høyeste:', hoyeste(priser))
        elif valg == '2':
            print('Snitt:', snitt(priser))
        elif valg == 'q':
            print('Ha det.')
            break
        else:
            print('Ugyldig valg, prøv igjen.')

Utskrift: ingen når blokken bare defineres. Under ser du en kjøring, der hoyeste og snitt er de samme funksjonene som tidligere i kapitlet.

Kjøring:

1 - høyeste pris i døgnet
2 - snittpris i døgnet
q - avslutt
Valg: 1        <- skrevet av brukeren
Høyeste: 1.2
1 - høyeste pris i døgnet
2 - snittpris i døgnet
q - avslutt
Valg: x        <- skrevet av brukeren
Ugyldig valg, prøv igjen.
1 - høyeste pris i døgnet
2 - snittpris i døgnet
q - avslutt
Valg: 2        <- skrevet av brukeren
Snitt: 0.7875
1 - høyeste pris i døgnet
2 - snittpris i døgnet
q - avslutt
Valg: q        <- skrevet av brukeren
Ha det.

I kjøringen over skrev brukeren 1, deretter x (en skrivefeil), deretter 2 og til slutt q. Linjene som er merket med en pil, er det brukeren tastet inn; pilen er lagt til her for lesbarhet og står selvsagt ikke på skjermen. Alt annet er programmets egen utskrift.

Fire ting å legge merke til:

- vis_valg er en egen funksjon. Menyløkka blir kortere og lettere å lese, og valglista står ett sted.
- hovedmeny regner ingenting. Den kaller hoyeste og snitt — den er en dispatcher.
- Skrivefeilen x fanges av else og koster ingenting: løkka går en runde til.
- Prisene sendes inn som parameter. hovedmeny vet ikke hvor de kommer fra, og kan derfor brukes uendret når dataene i Del 4 kommer fra en fil.

Sensorblikk: har du fått med while True, break i q-grenen og fnuttene rundt '1', er hovedstrukturen på plass — og strukturen er det som veier tyngst. Mangler else-grenen, er det et lite trekk, ikke et sammenbrudd.

📝Oppgave 5
Sjanger H

Se på menyløkka under.

def meny(verdier):
    vis_valg()
    valg = input('Valg: ')
    if valg == 1:
        print(hoyeste(verdier))
    if valg == 2:
        print(snitt(verdier))

a) Nevn de tre feilene som gjør at menyen ikke virker som en meny.

b) Skriv den rettede versjonen.

Løkke 6 — main binder alt sammen (~6 min)

Til slutt trenger programmet et startpunkt: én funksjon som skaffer dataene og setter menyen i gang. Det er main, og den er kort.

Dette er også formen den siste deloppgaven på eksamen ber om: «Skriv main som leser inn dataene og lar brukeren velge blant funksjonene du har laget.»

`main` som startpunkt
main har tre linjer i ånden, uansett hvor stor oppgaven er:

1. skaff dataene — i Del 4 ved å lese en fil, her ved å ha en ferdig liste,
2. kall menyen eller kjeden, med dataene som argument,
3. la funksjonene gjøre resten.

Nederst i fila står main() alene, uten innrykk. Det er den ene linja som faktisk starter programmet — alt over er definisjoner som venter.

✏️Eksempel 4: Hele appen på plass

Bind sammen alt fra kapitlet: analysefunksjonene, menyen, og en main som eier dataene. Vis også hva som skjer når brukeren avslutter med det samme.

Selve main er nesten pinlig kort — og det er meningen:

def main():
    doegnpriser = [0.42, 0.55, 1.20, 0.98, 1.35, 0.61]
    print('Strømpriser for døgnet, 6 timer registrert.')
    hovedmeny(doegnpriser)

Utskrift: ingen når blokken bare defineres. Under ser du en kjøring der brukeren avslutter med det samme, med hovedmeny, hoyeste og snitt som tidligere i kapitlet.

Kjøring:

Strømpriser for døgnet, 6 timer registrert.
1 - høyeste pris i døgnet
2 - snittpris i døgnet
q - avslutt
Valg: q        <- skrevet av brukeren
Ha det.

Legg merke til hva main ikke gjør: den har ingen løkke, ingen if, ingen regning. Den eier dataene, sier fra hva programmet er, og gir stafettpinnen videre.

Sensorblikk: rekkefølgen i fila er likegyldig for Python — alle def-ene kjøres før main() kalles, så main kan godt stå øverst. Det som ikke er likegyldig, er at kallet main() står helt til venstre, uten innrykk. Er det rykket inn ved et uhell, er det en del av funksjonen over, og programmet gjør ingenting.

📝Oppgave 6
Sjanger B

Programmet under kjøres, og brukeren skriver 2, deretter q.

def vis():
    print('1 - dobbel')
    print('2 - trippel')
    print('q - slutt')

def dobbel(x):
    return x * 2

def trippel(x):
    return x * 3

def meny(tall):
    while True:
        vis()
        valg = input('Valg: ')
        if valg == '1':
            print(dobbel(tall))
        elif valg == '2':
            print(trippel(tall))
        elif valg == 'q':
            break

meny(7)

a) Hvor mange ganger skrives menyteksten ut?

b) Hvilke andre linjer skrives ut, og i hvilken rekkefølge?

📝Oppgave 7
Eksamensnivå, sjanger…

En turnering har lagret poengsummen til hver spiller i lista poeng, og navnene i lista navn, slik at navn[i] hører til poeng[i].

a) Skriv beste(navn, poeng) som returnerer navnet på spilleren med flest poeng.

b) Skriv antall_over(poeng, grense) som returnerer hvor mange spillere som har mer enn grense poeng.

c) Skriv hovedmeny(navn, poeng) som gjentatt viser valgene 1 (vis beste spiller), 2 (vis hvor mange som har over 20 poeng) og q (avslutt), og som kaller funksjonene fra a) og b).

d) Skriv main som har dataene og starter menyen.

API- og konstruksjonsliste

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 Norges teknisk-naturvitenskapelige universitet. Dette er ikke offisielt studiemateriell. Les mer.