Monty Hall Pythonilla

Luin Dimensiosta Hannu Korhosen kirja-arvion Tapio Lindin Vesimelonin kuivatus ja muita matemaattisia pähkinöitä -kirjasta. En ole vielä ehtinyt lukemaan kirjaa, mutta se pitänee lukea lähiaikoina. Kirjassa yhtenä ongelmana on kuuluisa Monty Hall-probleema. Aihe on kuikertanut mielessäni jo jonkin aikaa. Niinpä päätin tehdä siitä pienen Python ohjelman. Lähinnä itselleni ja samalla myös oppilaitani varten esimerkkinä siitä, miten sanallinen ongelma käännetään tietokoneohjelmaksi.

Ongelma sanallisesti

Wikipediassa Monty Hall -ongelma esitetään seuraavasti: ” Monty Hallin ongelmassa kilpailijalla on edessään kolme ovea. Yhden oven takana on palkintona auto, kahden muun takana vuohi. Kilpailija, joka ei tiedä minkä oven takana mikin palkinto on, saa valita ovista yhden. Valittuaan oven hän ei vielä avaa sitä. Jäljelle jääneistä kahdesta ovesta avataan toinen, ja sen takana on aina vuohi. Tämän jälkeen kilpailija saa valita, vaihtaako ensin valitsemansa oven toiseen jäljellä olevaan suljettuun oveen, vai pitääkö ensin valitsemansa oven.”

Varmaankin kaikki matikan opet tietävät (viimeistään lukemalla ratkaisun Wikipediasta), että kilpailijan kannattaa vaihtaa, sillä pitämällä ensimmäisen valinnan, niin todennäköisyys voittoon on 1/3 ja vaihtamalla 2/3.

Python koodi

Tehdään Pythonilla ohjelma, joka noudattaa edellä esitettyä tilannetta siten, että kilpailija vaihtaa aina valintansa. Koodia kirjoittaessa en käytä järkeä siinä mielessä, että oikaisisin suoraan ratkaisuun. Toteutan tilanteen ikään kuin ohjeen mukaan. Laitan koodiin rivinumerot ja kommentit, joiden avulla yritän kertoa lukijalle mitä koodissa tapahtuu.

Muutama kommentti koodista

Lukijan on hyvä muistaa, että Pythonissa listan ensimmäisen jäsenen järjestysluku on nolla, toisen järjestysluku on 1 jne. Siksi ovien numerot ovat 0, 1, ja 2.

Rivillä 9: shuffle(lista) funktio sekoittaa syötelistansa jäsenet satunnaisesti.

Rivillä 13: randint(a, b) tuottaa satunnaisen kokonaisluvun väliltä [a, b].

Rivillä 17: pop-metodi poistaa olion listasta ja antaa sen tulosteena.  Jos lista  = [13, 42, 666, 42], niin lista.pop(1) antaa tulokseksi luvun 42 ja samalla listasta katoaa jäsen 42, eli nyt lista on [13, 666, 42].

Rivillä 20: remove-metodi poistaa ensimmäisen esiintymän syötteestään. Jos lista  = [13, 42, 666, 42], niin lista.remove(42) muutaa listan listaksi [13, 666, 42].

Rivillä 23: Leikkauksien avulla saadaan valittua listasta jäseniä. Jos lista on lista  = [13, 42, 666, 42], niin lista[1] tulostaa luvun 42.

Alla ohjelman tuottama tulos muutamalla suorituskerralla.

Kun tuota ohjelmaa ja tulosteita katsoo, niin pikku hiljaa (ainakin minulle) selkenee, että tässä pelissä pelaaja voittaa, jos hän on alun perin valinnut vuohen. Vuohi valitaan todennäköisyydellä 2/3.

Tehdään vielä ohjelmaan sellainen muutos, että suoritetaan se vaikkapa 1000 kertaa ja lasketaan voittojen lukumäärä.

Alla ohjelman tulos:

Seuraavassa tarinassani muokkaan ongelmaa/ohjelmaa sellaiseksi, että vuohia onkin vaikkapa 5 ja voittoautoja 2. Ja samalla tietysti pohdin, mikä siinä tilanteessa on voiton todennäköisyys.

Lähteet

https://dimensiolehti.fi/kirjallisuutta-vesimelonin-kuivatus/

https://fi.wikipedia.org/wiki/Monty_Hallin_ongelma