Uke 5 — Løkker / while / for¶
Vi skal se på noen eksempler på while-loops og for-loops, hvor vi kan repetere instruksjoner flere ganger.
I https://automatetheboringstuff.com/2e/chapter2/ finnes en god oversikt over alle tre muligheter for kontroll av programflyt vi skal bruke:
if
while
for
Denne uken vær sikker på at du har god kontroll over hvordan innrykk fungerer i python. De er viktige for å definere rekkefølgen og strukturen til koden din.
Obs
Når vi bruker løkker er det mulig å lage program som aldri avsluttes.
Om du tror at koden din er i en uendelig loop kan du avslutte
kjøringen ved å taste ctrl-c
i terminalen som kjører koden.
Eksempler¶
Eksempel 1¶
While-løkker (while-loops) brukes i situasjoner når løkka skal utføres så lenge noe er sant.
Her er noen eksempler på while-løkker.
Last ned filen her: eksempel_while.py
. Prøv først å si hva
som kommer til å skje når du kjører koden. Et tips er å selv gå
igjennom de første iterasjonene av hver loop ved hjelp av penn og
papir og se hva som skjer. Så kjøre koden og se om det var riktig.
print('Countdown...')
num = 10 # start
while num > 0: # test
print(num)
num -= 1 # update
# first square less than 1000
n = 1 # start
while n*n < 1000: # test
n += 1 # update
print(n, 'is the first number where n^2 is larger than 1000')
s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" # start
while s != "": # test
print(s)
s = s[1:] # update
I koden ser du at det er merket med ’start’, ’test’ og ’update’. En while-loop er avhengig av et vilkår og kjøres om vilkåret er oppfylt. Vilkåret er linja som er merka med ’test’.
Vilkåret i while-løkker trenger ofte en startverdi som oppdateres mens løkken utføres. Dette er linja merket med ’start’ med ’start’ (startverdi) og ’update’ (oppdateringen) i koden. Litt senere skal vi se hva som skjer om man for eksempel ikke oppdaterer startverdien i løpet av løkken.
Eksempel 2¶
Her er noen eksempler på break
og continue
. Man bruker break
til å avbryte en løkke. Man bruker continue
til å fortsette neste
iterasjon av løkken før man kommer til slutten av en blokk.
Last ned filen her: eksempel_break_continue.py
. Prøv først å si hva som
kommer til å skje når du kjører koden. Kjør så koden og se om det var
riktig.
# use a counting loop to do something N times
n = 0
while n < 7:
print('Hello!')
n += 1
# Read input 5 times:
n = 0
while n < 5:
name = input(f'Name {n+1}? ')
print('Hello,', name)
n += 1
# break
while True:
answer = input('Should we continue? ')
if answer == 'n':
break
print('Great, let\'s go one more time...')
print('Bye!')
# continue
text = "Good morning!"
print(text)
i = 0
while i < len(text):
letter = text[i]
print(letter)
i += 1
continue
print('Never gets here')
print('Done')
###########
print('Good morning again...')
# function to use later. What does it do on its own?
def print_NxN_times(txt, N):
n = 0
while n < N:
print(txt * N)
n += 1
text = "Good morning!"
i = 0
while i < len(text):
letter = text[i]
if letter == 'o':
i += 1
continue
print_NxN_times(letter, 3)
i += 1
########
n = 1
while n < 50:
if n % 7 == 0:
print(f'{n} is divisible by 7. Skipping 3 numbers')
n += 3
continue
print(n, 'is not divisible by 7. Try next number')
n += 1
Se på den siste løkken. Den kan skrives om ved hjelp av if-else sånn at
man ikke må bruke continue
. Finner du ut hvordan man kan gjøre det?
Kan noen av de andre løkkene skrives om sånn at vi får det samme resultatet
uten å bruke continue
? Kan løkken med break
skrives om sånn at
vi får det samme resultatet uten å bruke break
?
Både break
og continue
kan også brukes med for-loops som kommer nedenfor.
Eksempel 3¶
Her er noen eksempler på for-løkker (for-loops).
Last ned filen her: eksempel_for.py
. Prøv først å si hva som
kommer til å skje når du kjører koden. Kjør så koden og se om det var
riktig. Merk spesielt hvilke tall du får fra løkkene med range()
.
Hva er det minste tallet du får? Hva er det største? Hva om du
bruker tre tall som argument til range()
?
Prøv selv med noen ulike tall.
for letter in "Hello":
print(letter)
print('Range 1:')
for n in range(7):
print(n)
print('Range 2:')
for n in range(3, 7):
print(n)
print('Range 3:')
for n in range(2, 17, 3):
print(n)
#########################
# 2 ways to do the same
#########################
print('Afternoon 1:')
result = ""
for letter in "Good afternoon":
if letter == 'o':
result += '0'
else:
result += letter
print(result)
print('Afternoon 2:')
result = ""
for letter in "Good afternoon":
if letter == 'o':
result += '0'
continue
result += letter
print(result)
Sammenligne output fra de siste to løkkene. Hvilken løkke er lettere for deg å forstå?
Eksempel 4¶
Alle for-løkker kan skrives om til while-løkker. Her er to eksempler.
Last ned og kjør filen her: eksempel_for_to_while.py
. Skjønner du hva
som skjer i alle løkkene?
# Every for-loop can be written as a while-loop:
print('For-loop')
for i in range(2,19,3):
print(i)
print('While-loop')
x = 2
while x < 19:
print(x)
x += 3
#################
print('For-loop')
for s in 'Oppvaskmaskin':
print(s)
print('While-loop')
text = 'Oppvaskmaskin'
index = 0
while index < len(text):
s = text[index]
print(s)
index += 1
#################
Kan du skrive om en av for-løkkene fra eksempel 3 til en while-løkke?
Det finnes ofte flere ulike måter til å gjøre det samme ting med programmering. Noen er enklere å bruke enn andre, og det kommer an på konteksten hva som er den beste muligheten.
Når vi vet på forhånd hvor mange iterasjoner vi trenger er det vanlig å bruke
for
. Der unngår vi at vi må håndtere startverdien, test og oppdatering av loop-verdien
selv.
while
-løkker bruker vi når vi ikke vet hvor mange iterasjoner vi trenger for
å finne et resultat. Det kan være at stop-betingelsen er komplisert, eller at vi
må ta input fra brukeren flere ganger frem til den passer.
Eksempel 5¶
Her er et eksempel på problemløsning ved hjelp av en for-loop i Python. Vi skal løse Problem 1 fra projecteuler.net:
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
Så hvordan går vi fra problem til kode? Denne prosessen kan deles opp i to deler.
Finne ut en algoritme som løser problemet.
Implementere algoritmen i valgt programmeringsspråk (i vårt tilfelle, Python).
Algoritme¶
La oss begynne med den første delen. Vi vil finne ut et sett med instrukser som gir summen vi trenger. Om vi ville beregnet summen opp til 10 selve, med papir og penn, ville vi sannsynligvis tenkt/gjort noe slikt:
1 er ikke et multiplum av 3 eller 5, så gjør vi ingen med dette tallet.
2 er ikke et multiplum av 3 eller 5, så gjør vi ingen med dette tallet.
3 er et multiplum av 3, så vi må ta med tallet i summen. Summen vår blir da 3.
4 er ikke et multiplum av 3 eller 5, så gjør vi ingen med dette tallet.
5 er et multiplum av 5, så vi må ta med tallet i summen. Summen vår blir da 3 + 5 = 8.
6 er et multiplum av 3, så vi må ta med tallet i summen. Summen vår blir da 8 + 6 = 14.
7 er ikke et multiplum av 3 eller 5, så gjør vi ingen med dette tallet.
8 er ikke et multiplum av 3 eller 5, så gjør vi ingen med dette tallet.
9 er et multiplum av 5, så vi må ta med tallet i summen. Summen vår blir da 14 + 9 = 23.
Vi prøver å sammenfatte hva vi gjør her. Vi går igjennom tallene fra 1 til 9 og sjekker om tallet er et multiplum av 3 eller 5. Ved sånt tilfelle adderer vi tallet til summen. La oss skrive dette litt klarere, og for et godtykkelig tall \(N\) som øvre grense:
Gå igjennom heltallen fra \(1\) til \(N-1\) (for eksempel 9 om den øvre grensen er 10).
For hvert tall, sjekke om tallet er et multiplum av 3 eller 5.
Om det er det, addere tallet til summen.
Dette er algoritmen vår. Den er ikke avhengig av noe programmeringsspråk. Dette er bare et sett med instrukser som, om man utfører dem, gir summen fra problemet.
Implementasjon¶
Nå er det tid for del 2: å implementere algoritmen i Python. Her må man finne de delene av
programmeringsspråket man skal bruke. I dette tilfelle vil vi gjøre noe for alle tall fra
1 til den øvre grensen (som vi gir navnet max_N
). Dette kan vi for eksempel gjøre med
en for
-loop over range(max_N)
. Denne går fra og med null til og med max_N - 1
:
max_N = 10
for n in range(max_N):
Vi må også definere summen før løkken (den er null fra begynnelsen),
ellers har vi ingen summe å addere det første tallet til. Så vi lager en variabel summe
som har verdien null, før for-løkken:
max_N = 10
summe = 0
for n in range(max_N):
For hver iterasjon av for-løkken skal vi sjekke om det aktuelle tallet n
er et multiplum av 3 eller 5.
Dette kan vi gjøre med et if-statement innen for-løkken. Her sjekker vi om
tallet er deleligt med 3 eller 5 (det er samme som at det er et multiplum av 3 eller 5)
med koden n % 3 == 0 or n % 5 == 0
. Om det er det adderer vi tallet til summen med koden
summe += n
. Ellers skal vi ikke gjøre noe, så det er ingen mer kode innen for-løkken.
Her er koden. Du kan laste ned filen her: eksempel_problem_solving.py
. Kjør koden og endre på
max_N
sånn at du kan svare på problemet. Hva er summen av alle multiplumer av 3 og 5 som er
mindre enn 1000?
# Problemløsning
max_N = 10
summe = 0
for n in range(max_N):
if (n % 3 == 0) or (n % 5 == 0):
summe += n
print(f'The sum of all multiples of 3 or 5 below {max_N} is {summe}')
Hvordan kunne du svare på problemet med while-løkke i stedet av for-løkken?
Eksempel 6¶
Her er noen eksempler på kode som ikke er riktig.
Når vi bruker while-loops er det mulig å lage program som aldri avsluttes om vilkåret i
while-løkken alltid er oppfylt.
Om du tror at koden din er i en uendelig loop kan du avslutte
kjøringen ved å for eksempel taste ctr-c
i terminalen som kjører koden.
Last ned filen her: errors_1.py
. Prøv først om du kan finne feilen i koden. Kjør
siden koden og se hva som skjer. Endre koden slik at den går å kjøre, og ikke blir fast i en
uendelig loop.
# typing CTRL-c in the terminal stops a running program
print('Countdown:')
n = 10
while n > 0:
print(n)
print('Countdown again:')
n = 10
while n > 0:
print(n)
n += 1
print('It\'s a new day!')
text = "Good morning!"
i = 0
while i < len(text):
letter = text[i]
if letter == 'o':
continue
i += 1
print(letter)
i += 1
print('Find the sum of all numbers from 1 to 100')
for n in range(1,101):
sum = 0
sum += n
print(sum)
print('Again, find the sum of all numbers from 1 to 100')
for n in range(1,101):
sum_2 += n
print(sum_2)
Det er mange gode eksempler og oppgaver i Automate the boring stuff, se for eksempel: «Practice Questions» 1. - 13.
Obligatoriske oppgaver¶
Oppgave 1:¶
I oppgave_1.py
skriv en while
-løkke som skriver ut alle partall fra 5 til 25. Husk at med while-løkker trenger du tre ting: (1) start, (2) test, og (3) update.
Eksempelkjøring:
6
8
10
...
24
Oppgave 2:¶
I oppgave_2.py
lag en løkke for å snakke med en dum chatbot, bruk en while True
løkke . Chatboten kan bare si tre ting: Hei! Vil du snakke med meg?
, Så kult!
, eller Ha det bra!
Du må bruke input()
for å svare chatboten. Bruk break
for å avlutte while
-løkken når du får inn Nei
. TIPPS: Hvis du er usikker på denne oppgaven se eksempel 2 eksempel_break_continue
.
Eksempelkjøring:
Hei! Vil du snakke med meg? Ja
Så kult!
Hei! Vil du snakke med meg? Nei
Ha det bra!
Oppgave 3:¶
I oppgave_3.py
lag en for
-løkke som skriver ut tallene i 3-gangen opp til og med 15.
Eksempelkjøring:
3
6
9
12
15
Oppgave 4:¶
I oppgave_4.py
skriv en for
-løkke eller while
-løkke som sjekker alle tallene fra 1 til 10 og skriver ut {x} er partall! hvis partall og {x} er oddetall! hvis oddetall.
Eksempelkjøring:
1 er oddetall!
2 er partall!
3 er oddetall!
...
10 er partall!
Oppgave 5:¶
I oppgave_5.py
skriv en while
-løkke som beregner fakulteten (\(n!\)) til et input int tall fra brukeren.
For eksempel, 5! = 5 * 4 * 3 * 2 * 1 = 120
Eksempelkjøring:
Tall: 5
120
Eksempelkjøring:
Tall: 0
1
Oppgave 6:¶
I oppgave_6.py
skriv en while
-løkke som skriver ut dette mønsteret:
Eksempelkjøring:
*
**
***
****
Husk å oppdatere tellingen på slutten av løkken!
Oppgave 7:¶
I oppgave_7.py
skriv en for
-løkke som skriver ut det samme mønsteret som i oppgave 6.
Oppgave 8:¶
I oppgave_8.py
skriv en for
-løkke som teller ned fra 10 til 1 og så skriver ’LIFTOFF!’
Eksempelkjøring:
10
9
...
2
1
LIFTOFF!
Oppgave 9:¶
I oppgave_9.py
skriv en for
-loop som skriver ut bokstavene i "oppvaskmaskin"
på hver sin linje.
Eksempelkjøring:
o
p
p
v
a
s
k
m
a
s
k
i
n
Oppgave 10: Project Euler nr.9¶
Et pytagoreisk trippel består av tre positive heltall \(a < b < c\), slik at \(a^2 + b^2 = c^2\) (f.eks \(3^2 + 4^2 = 9 + 16 = 25 = 5^2\)).
Det finnes kun et pytagoreisk trippel slik at \(a + b + c = 1000\). Finn produktet \(abc\).
Skriv en funksjon pytag_trippel(sum_abc)
som tar
et argument sum_abc
. Loop over tallene a, b, c
slik at a+b+c == sum_abc
.
Når du finner et trippel a b c
som tilsvarer beskrivelsen ovenfor,
skal funksjonen returnere a*b*c
.
For å svare Project Euler tester vi med pytag_trippel(1000)
.
Tips: etter du velger \(a\) og \(b\), må du bare sjekke én verdi for \(c\). Ikke bruk input() her, det stopper de automatiske testene.