1.3 DRILL — Kode → O-notasjon
Systematisk drill i sjanger B: les O-kjøretiden ut av pseudokode med nøstede løkker, halvering og sekvens — de garanterte Del 1-poengene.
Dette kapitlet er ren drill på sjanger B — kjøretid fra kode, altså at du
får en pseudokodesnutt og skal svare med ett -uttrykk. Sjangeren har kommet i
alle sju settene (100 %), ofte med én til to oppgaver per sett, og den ligger
på Del 1, som rettes automatisk.
Det gjør den til den mest forutsigbare poengkilden på hele eksamen: du trenger
ikke kjenne igjen noen algoritme, du trenger ikke huske noen kjøretid, du
trenger bare å telle riktig. Prioritet: høyeste.
To ting fra sensorveiledningene, gjentatt: riktig orden gir poeng selv om
koden har en syntaksfeil, og svaret skal være det strammeste uttrykket —
ett ledd, ingen konstanter.
Slik bruker du kapitlet. Femten oppgaver, ca. fem minutter hver. Du får mest
igjen for å skrive svaret ned på et ark før du åpner fasiten, og for å ta
kontrollen «hva skjer når dobles?» hver eneste gang. Kapitlet tar rundt 80
minutter, og det er helt greit å dele det over to kvelder — det står et
pausepunkt underveis.
Forkunnskaper
- kap. 1.1 — hva betyr, vekstordningen og regelen om
det dominerende leddet.
- kap. 1.2 — de fire løkketellingsreglene. Denne drillen
bruker dem og forklarer dem ikke på nytt.
Sitter selve løkkelesingen løst, kan du varme opp med
Løkker: for, while og range eller
DRILL — Kodesporing: «hva skrives ut?», som trener det
mekaniske blikket på kode.
Fem steg. Følg dem i rekkefølge, hver gang, også når svaret virker åpenbart.
Steg 1 — marker hver løkke, og skriv rekkevidden i margen. For hver løkke,
still nøyaktig ett spørsmål: hvor mange runder går den? Tre svar er mulige:
- grensen inneholder (også n/2, n-1, 2n) gir runder;
- grensen er et fast tall (10, 100, 1000) gir konstant, stryk den;
- tellevariabelen ganges eller deles gir ca. runder.
Steg 2 — gang sammen innenfra og ut. Start med den innerste løkka, gang med
nivået over, og fortsett utover. Skriv ett produkt per blokk.
Steg 3 — legg sammen for sekvens. Blokker som står etter hverandre (samme
innrykk, ikke inni hverandre) legges sammen.
Steg 4 — behold det dominerende leddet og stryk konstantene. Bruk
vekstordningen . Svaret skal
være ett uttrykk.
Steg 5 — kontrollér med doblingstesten, og si hva er. Spør: hva skjer
med antall kjøringer når dobles? Uendret betyr , ett steg til betyr
, dobling betyr , firedobling betyr , åttedobling
betyr . Skriv til slutt én setning om hva teller — det trekkes
eksplisitt for et udefinert .
Fellekatalogen disse fem stegene fanger: konstant indre løkke lest som
(steg 1); oversett dobling eller halvering (steg 1); sekvensielle løkker
ganget i stedet for lagt sammen (steg 3); usimplifisert svar (steg 4).
Oppgi kjøretiden til denne prosedyren. Snutten er skrevet i eksamensformat: etProcedure-hode, en kort beskrivelse, og resten er din jobb.
Procedure Sammenstill(A)
Input: array A med n tall, indeksert fra 0
Output: en telling
n = A.length
c = 0
for i = 0 to n-1:
for j = 0 to 99:
c = c + 1
for i = 0 to n-1:
p = 1
while p < n:
c = c + 1
p = p * 2
for i = 0 to n-1:
for j = i to n-1:
c = c + 1
return cBlokk 1: ytre for i går til n-1, altså runder. Indre for j går til 99
— fast tall, konstant. Sensorkommentar: her sitter det første poenget. En
kandidat som skriver for denne blokken, har lest grensen 99 som om det
sto .
Blokk 2: ytre for i gir runder. Indre while p < n med p = p * 2 er en
doblingsløkke, ca. runder. Sensorkommentar: oppdateringslinja står
nederst, og det er der de fleste tellefeilene oppstår. Les den før du
konkluderer.
Blokk 3: trekantløkke — den indre starter på i og går til n-1, altså
runder.
Steg 2 — gang innenfra og ut.
- Blokk 1: .
- Blokk 2: .
- Blokk 3: .
Steg 3 — sekvens. De tre blokkene står etter hverandre:
Steg 4 — dominerende ledd. Vekstordningen gir
, så trekantsummen dominerer.
Svar: , der er antall elementer i A.
Steg 5 — doblingstesten. For kjører de tre blokkene henholdsvis 800,
24 og 36 ganger. For : 1600, 64 og 136. Totalt går vi fra 860 til 1800
— litt over dobling foreløpig, men blokk 3 firedobler seg og tar over. For
er tallene 12 800, 896 og 8256, og fra da av er det trekanten som
styrer. Det stemmer med .
Sensors poengfordeling, slik mønsteret pleier å se ut på en slik oppgave:
hovedmomentet er riktig orden — det er der de fleste poengene ligger. Deretter
gis det uttelling for at du sier hvorfor den konstante løkka ikke teller, og for
at er definert. Å skrive svaret som
regnes som riktig telling og feil form: det koster som regel ett poeng.
Modellsvaret, slik du bør skrive det på fire linjer:
«Første blokk: ytre løkke runder, indre løkke fast antall (100) — bidrar
. Andre blokk: ytre runder, indre dobler p og gir ca.
runder — bidrar . Tredje blokk: trekantløkke,
runder — bidrar . Blokkene står etter hverandre, så det dominerende
leddet gjelder: , der er antall elementer i arrayet.»
Oppgavene (ca. 5 min hver)
Skriv svaret ned før du åpner fasiten. Sett gjerne opp de fem stegene i margen
de første gangene — etter fem oppgaver går det av seg selv.
Oppgi kjøretiden.
Procedure AnnenHver(A)
Input: array A med n tall, indeksert fra 0
Output: summen av annethvert tall
n = A.length
s = 0
i = 0
while i < n:
s = s + A[i]
i = i + 2
return sOppgi kjøretiden.
Procedure Rammer(A)
Input: array A med n tall, indeksert fra 0
Output: en telling
n = A.length
c = 0
for i = 0 to n-1:
for j = 0 to 999:
c = c + 1
return cOppgi kjøretiden.
Procedure Ramse(n)
Input: et heltall n
Output: en telling
c = 0
i = 0
while i < n * n:
c = c + 1
i = i + 1
return cOppgi kjøretiden.
Procedure Halvveis(A)
Input: array A med n tall, indeksert fra 0
Output: en telling
n = A.length
c = 0
for i = 0 to n-1:
j = 0
while j < n / 2:
c = c + 1
j = j + 1
return cOppgi kjøretiden.
Procedure Nedtelling(n)
Input: et heltall n
Output: en telling
c = 0
i = n
while i > 1:
for j = 0 to 4:
c = c + 1
i = i / 2
return cAlle fem handlet om steg 1 i oppskriften: å lese rekkevidden riktig.
- Oppgave 1: additivt steg større enn 1 endrer ikke ordenen.
- Oppgave 2: en stor konstant er fortsatt en konstant.
- Oppgave 3: grensen kan inneholde selv om det bare er én løkke.
- Oppgave 4: n / 2 er ikke et fast tall.
- Oppgave 5: en halverende ytre løkke gir , ikke .
Bommet du på én av dem, er det verdt å gå tilbake til
kap. 1.2 før du fortsetter — resten av drillen bygger på
at rekkevidden sitter.
— naturlig pausepunkt (du har brukt ca. 35 minutter) —
Resten av oppgavene kombinerer flere nivåer. Framgangsmåten er den samme; det
eneste nye er at du må holde tunga rett i munnen når du ganger sammen.
Oppgi kjøretiden.
Procedure Trekant(A)
Input: array A med n tall, indeksert fra 0
Output: en telling
n = A.length
c = 0
for i = 0 to n-1:
for j = 0 to i-1:
c = c + 1
return cOppgi kjøretiden.
Procedure TreNivaa(A)
Input: array A med n tall, indeksert fra 0
Output: en telling
n = A.length
c = 0
for i = 0 to n-1:
for j = 0 to n-1:
for k = 0 to 7:
c = c + 1
return cOppgi kjøretiden, og svar også på om det gjør noen forskjell at
tellevariabelen ganges med 3 og ikke med 2.
Procedure Tredeling(A)
Input: array A med n tall, indeksert fra 0
Output: en telling
n = A.length
c = 0
for i = 0 to n-1:
j = 1
while j < n:
c = c + 1
j = j * 3
return cOppgi kjøretiden. Her kalles en annen prosedyre inni løkka.
Procedure SjekkAlle(A)
Input: array A med n tall, indeksert fra 0, sortert stigende
Output: antall tall i A som også finnes i A (trivielt n, men tell arbeidet)
n = A.length
c = 0
for i = 0 to n-1:
if BinærSøk(A, A[i]):
c = c + 1
return cAnta at BinærSøk(A, x) er den vanlige varianten som halverer søkeområdet og
svarer true eller false, med kjøretid på et sortert array med
elementer.
Oppgi kjøretiden.
Procedure ToBlokker(A)
Input: array A med n tall, indeksert fra 0
Output: en telling
n = A.length
c = 0
p = 1
while p < n:
c = c + 1
p = p * 2
for i = 0 to n-1:
for j = 0 to n-1:
c = c + 1
return cDe fem siste (ca. 25 min)
Disse er på det nivået de tyngste sjanger B-oppgavene har ligget. Ta dem gjerne
med klokke: fem minutter hver, og skriv begrunnelsen i tre setninger slik
modellsvaret i sensor-casen viste.
Oppgi kjøretiden.
Procedure Femdobbel(n)
Input: et heltall n
Output: en telling
c = 0
for a = 0 to n-1:
for b = 0 to n-1:
for d = 0 to n-1:
for e = 0 to n-1:
for f = 0 to n-1:
c = c + 1
return cOppgi kjøretiden.
Procedure Trippeltrekant(A)
Input: array A med n tall, indeksert fra 0
Output: en telling
n = A.length
c = 0
for i = 0 to n-1:
for j = 0 to i-1:
for k = 0 to j-1:
c = c + 1
return cOppgi kjøretiden.
Procedure Lagvis(A)
Input: array A med n tall, indeksert fra 0
Output: en telling
n = A.length
c = 0
p = 1
while p < n:
for i = 0 to n-1:
for j = i to n-1:
c = c + 1
p = p * 2
return cOppgi kjøretiden, og si hvilken av de to blokkene som
avgjør svaret.
Procedure Todelt(A)
Input: array A med n tall, indeksert fra 0
Output: en telling
n = A.length
c = 0
for i = 0 to n-1:
m = n
while m > 1:
c = c + 1
m = m / 2
for i = 0 to n-1:
for j = 0 to n-1:
c = c + 1
return cOppgi kjøretiden for hver av de to prosedyrene,
og forklar forskjellen med én setning.
a)
Procedure Ned(n)
Input: et heltall n
Output: ingenting; gjør et fast arbeid per kall
if n <= 1:
return
gjør et fast stykke arbeid
Ned(n / 2)b)
Procedure Steg(n)
Input: et heltall n
Output: ingenting; gjør et fast arbeid per kall
if n <= 0:
return
gjør et fast stykke arbeid
Steg(n - 1)Samlet, slik at du kan lese den rett før eksamen.
- Konstant indre løkke lest som . for j = 0 to 999 er 1000 runder,
ikke . Test: står det n i grensen?
- Oversett dobling eller halvering. j = j * 2 og m = m / 2 gir
runder. Oppdateringslinja står ofte nederst i løkka.
- Sekvensielle blokker ganget i stedet for lagt sammen. Se på innrykket:
inni betyr gang, etter betyr legg sammen.
- Antall løkker forvekslet med antall runder. Én løkke til n * n er
; tre nøstede løkker der to er konstante, er .
- En linje som kaller en prosedyre behandlet som . Kallet arver
kjøretiden til det det kaller.
- Usimplifisert svar. er riktig regnet og feil levert. Ett
ledd, ingen konstanter.
- n uten definisjon. Dette er felle #10 i bokas register — å oppgi
kjøretid eller drøfte uten å si hva problemstørrelsen teller. Én setning
holder.
- Å hoppe over oppgaven fordi koden ser rar ut. Riktig orden gir poeng selv
om snutten ikke ville kompilert. Svar alltid.
Begrepsbank
Begrepsbanken under er flashcard- og repetisjonsstoff — den gjentar det du
nettopp har lest. Hopp trygt over den ved førstegangslesing; tidsanslaget for
kapitlet gjelder oppgavene.
Oppgavetypen der du får en pseudokodesnutt og skal svare med ett -uttrykk.
Har kommet i alle sju settene, ofte to ganger per sett, og ligger på den
auto-rettede Del 1.
Krever ingen algoritmekunnskap — bare telling. Riktig orden gir poeng selv om
koden har en syntaksfeil.
1. Marker hver løkke og finn rekkevidden. 2. Gang sammen innenfra og ut.
3. Legg sammen for sekvens. 4. Behold det dominerende leddet og stryk
konstantene. 5. Kontroller med doblingstesten, og si hva er.
Følg den også når svaret virker åpenbart — de fleste tellefeilene oppstår i steg
1, der det går fortest.
Kontrollen som tar fem sekunder: hva skjer med antall kjøringer når dobles?
Uendret gir ; ett steg til gir ; dobling gir ; litt over
dobling gir ; firedobling gir ; åttedobling gir .
Passer ikke svaret ditt med testen, har du telt feil.
En løkkegrense som inneholder problemstørrelsen — n, n-1, n/2, n*n,2n. Da vokser løkka med inputen, og den teller med i -uttrykket.
Motsatt: en grense som er et rent tall (10, 99, 1000) gir en konstant, uansett
hvor stort tallet er.
At tellevariabelen ganges eller deles i hver runde: j = j * 2, j = j * 3,m = m / 2. Løkka går da ca. runder.
Grunntallet spiller ingen rolle for -klassen: og
skiller seg bare med en konstant faktor, og skrives begge .
At tellevariabelen økes med et fast tall: i = i + 1, i = i + 2, i = i + 3.
Løkka går da , eller runder — alle .
Et større steg endrer altså bare konstanten, aldri ordenen. Dette er den
vanligste forvekslingen med multiplikativ oppdatering.
løkke der den indre grensen følger den ytre løkkevariabelen.
Tre nivåer med samme mønster gir , altså :
konstanten krymper, men ordenen følger antall nivåer.
En linje som kaller en annen prosedyre er ikke — den koster det den
kalte prosedyren koster. Et -kall inne i en løkke over gir
, ikke .
Den vanligste kilden til at et ellers riktig svar bommer med en hel faktor.
Svarformen sensor krever: det strammeste -uttrykket, med ett ledd og uten
konstantfaktorer. , ikke og ikke .
Både et usimplifisert og et unødvendig slapt svar koster poeng, selv om begge
er «sanne».
IN2010 analyserer kjøretid — også for rekursive prosedyrer — ved å telle arbeid
og nivåer. Rekurrensligninger, substitusjonsmetoden og de generelle teoremene
for å løse slike ligninger er ikke pensum.
For rekursjon er spørsmålet alltid det samme: hvor mange kall gjør hvert kall,
hvor mange nivåer blir det, og hva koster hvert kall?
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.