Ekstra oppgave (uke 3)
Dette er en ekstra oppgave for de som føler seg ferdig med stoffet fra uke 3, og har lyst på litt mer utfordring og en liten smakebit på uke 4.
Monty Hall Problem
Monty Hall Problem er et artig problem (gåte?), som går ut på dette:
- Du er deltaker i et spill (game show) der du står foran tre dører:
- Bak en av dørene står en bil du ønsker å vinne, og bak de to andre dørene står det en geit.
- Du velger en dør, og merker at døren er låst.
- Verten i spillet vet hva som er bak dørene, og for å gjøre ting litt enklere, åpner han en annen dør med en geit.
- Du står nå igjen med to dører, den du valgte og en annen. Bak en av dem er det altså en bil, og bak den andre er det en geit.
- Du får nå muligheten til å bytte dør, eller fortsette med den du først valgte.
- Hva bør du gjøre? Hvor stor er sannsynligheten for å få tak i bilen i dette spillet? 50%? Har det noe å si om du bytter dør eller fortsetter med den første du valgte?
Tenk litt over problemet og sjekk at du forstår det før du begynner på oppgavene (men du trenger absolutt ikke å løse det før du begynner på oppgavene).
Løsningsforslag
Det ligger et løsningsforslag her. Merk at det er veldig mange ulike måter å løse denne oppgaven på (spesielt oppgave 2), og at løsningsforslaget er nokså langt. Ved hjelp av konsepter man lærer etter uke 3 kan man løse denne oppgaven enklere og mer elegant.
Her er et annet løsningsforslag på oppgave 2 med kompakt kode, sendt inn av alekshoi.
Oppgave 1: Implementer spillet
Lag en enkel versjon av spillet der en bruker blir bedt om å velge mellom tre dører (ved hjel av input
). Du kan kalle dørene 1, 2 og 3. Spillet skal så gi beskjed om at en av de andre dørene åpnes, og at du nå kan velge mellom de to som er igjen. Brukeren skal få spørsmål om å bli eller bytte, og spillet skal til slutt gi beskjed om han vant en bil eller ikke.
Tips:
- Det kan bli litt tungvint om du representerer innholdet bak hver dør med én variabel for hver dør
- I stedet kan du f. eks representere dørene som en liste:
dorer = ["geit", "bil", "geit"]
- Hvis du vil at innholdet skal være tilfeldig hver gang programmet kjører, kan du bruke shuffle-funksjonen:
- Importer først random i toppen av filen din:
import random
Deretter kan du lage dørene og "shuffle" dem:
dorer = ["geit", "bil", "geit"] random.shuffle(dorer)
Hvis du nå printer dørene vil du se at innholdet stokkes rundt.
- Importer først random i toppen av filen din:
- La gjerne brukeren velge et tall (0, 1 eller 2) slik at du kan hente ut innholdet på den posisjonen i listen.
- Det blir fort en del if-elif-else setninger nå for å sjekke døren og velge en annen dør, men det er greit. Senere i kurset lærer vi bedre måter å løse dette problemet på.
Oppgave 2: Kjør spillet maange ganger
Ved hjelp av for-løkker kan vi utføre kode mange ganger.
Vi er nå interesserte i å finne ut hvor ofte man vinner bilen om man spiller spillet mange ganger og gjør konsekvente valg:
- Hvor ofte vinner man bilen hvis man alltid bytter dør?
- Hvor ofte vinner man bilen hvis man alltid fortsetter med samme dør som man først valgte?
Oppgave 2a:
Putt koden fra oppgave 1 inn i en prosedyre. Kall prosedyren, og sjekk at spillet kjører som før.
def spill():
# putt koden din her ...
# kall prosedyren og sjekk at ting virker
Oppgave 2b:
Vi ønsker nå å kjøre spillet tusenvis av ganger, og orker ikke å skrive inn input hver gang.
Hvis du sørger for å ha tilfeldig plassering av bilen og geitene, bør det ikke ha noe å si hva personen velger i starten, så vi kan droppe å ta input for å få det første valget. Endre i stedet det første valget til å være "hardkodet", bare sett valget til å alltid være f. eks dør 0.
Endre det andre valget til å alltid være at vi fortsetter med samme dør som vi initielt valgte (vi ønsker å se hva som skjer da).
Sørg for at det til slutt i prosedyren alltid printes hvorvidt man vant eller ikke. Unngå at det printes noe annet (vi ønsker ikke så mye output når spillet skal kjøres mange ganger).
Kjør prosedyren og sjekk at det ikke kreves noe user-input, og at spillet kjører med de "hardkodede" valgene.
Oppgave 2c
Som vi skal lære i uke 4, kan man kjøre kode mange ganger ved hjelp av en for løkke. Den enkleste formen for for-løkke ser slik ut:
for i in range(100):
# kode som skal kjøre mange ganger her
Vi skal gå nærmere inn på hvordan denne løkken fungerer i uke 4, men nå trenger du bare å vite at alt som er inne i for-løkken over blir kjørt 100 ganger (merk tallet i 100 i range-funksjonen).
Lag en slik for-løkke, og legg prosedyre-kallet inne i for-løken. Pass på at koden inne i for-løkken er indentert.
Kjør programmet, og sjekk basert på outputen at spillet kjøres mange ganger.
Hvor ofte ser det ut til at man vinner dersom man alltid endrer dør? Endre slik at man alltid beholder samme dør. Hvor ofte ser det ut til at man vinner da?
Oppgave 2d
Basert på det som printes kan vi få litt innsikt i hvor ofte man ser ut til å vinne ved å bytte eller beholde dør, men vi har ikke noe eksakt tall på det.
Vi ønsker nå å telle opp eksakt hvor ofte man vinner.
- Lag en variabel
antall_seiere = 0
over for-løken. Denne ønsker vi å øke med 1 hver gang vi vinner. - I stedet for at prosedyren printer om man vant eller ikke, vil vi at prosedyren skal returnere om vi vant eller ikke.
- Endre prosedyren slik at det helt til slutt returneres enten "vant" eller "vant ikke":
# kode i prosedyren her ... if [sjekk for vurdere om spilleren vant]: return "vant" else: return "vant ikke"
- Endre prosedyren slik at det helt til slutt returneres enten "vant" eller "vant ikke":
Prosedyren vil nå returnere en verdi, som vi kan få tak i der prosedyren kalles. Vi kan deretter øke telleren basert på denne verdien:
antall_seiere = 0
for i in range(100):
returverdi = spill()
if returverdi == "vant":
antall_seiere += 1
print("Antall seiere:", antall_seiere)
Forsøk å implementere dette. Hvor ofte ser man ut til å vinne dersom man alltid bytter dør? Hva om man alltid beholder døren man først valgte? Stemmer dette med intuisjonen din?