(H) Lottopelejä

Tavoite: Opin toteuttamaan funktioita C++-ohjelmaan.

Ohjeita: Luo uusi projekti: student/02/lotto/.

Maailmasta löytyy jos minkälaista lottopeliä. Näille on kaikille tyypillistä se, että tietystä määrästä numeroituja palloja arvotaan sattumanvaraisesti muutama pallo. Riippuen siitä, kuinka monta näistä arvotuista palloista (uhka)pelaaja on arvannut oikein, hän saa jonkinlaisen palkinnon.

Tässä tehtävässä meitä kiinnostavat ne todennäköisyydet, joilla pelaaja voi saada täysosuman, eli arvata kaikki arvotut pallot oikein. Esimerkiksi siis suomalaisessa lotossa: millä todennäköisyydellä pelaaja arvaa oikein kaikki arvotut 7 palloa, jos hän täyttää vain yhden lottokupongin.

Kyseessä on kombinatoriikkaan liittyvä ongelma: kuinka monta erilaista tapaa on valita esimerkiksi 7 palloa 39 pallon joukosta. Oletetaan, että n on lottopelin kaikkien pallojen lukumäärä ja p arvottujen pallojen lukumäärä. Tällöin erilaisia lottorivejä on olemassa

\[\frac{n\,!}{(n - p)\,! * p\,!}\]

kappaletta. Edellä esiintynyttä !-operaatiota käytetään matematiikassa kuvaamaan luvun kertomaa, mikä tarkoittaa tuloa, jossa tulon tekijöinä ovat annettu luku sekä kaikki sitä pienemmät positiiviset kokonaisluvut. Esimerkiksi

\[\begin{split}\begin{align*} 1! &= 1 \\ 2! &= 1 * 2 = 2 \\ 3! &= 1 * 2 * 3 = 6 \\ 4! &= 1 * 2 * 3 * 4 = 24 \\ 5! &= 1 * 2 * 3 * 4 * 5 = 120 \end{align*}\end{split}\]

ja niin edelleen. Lisäksi on määritelty, että luvun nolla kertoma on yksi eli

\[0! = 1.\]

Edellä esitetyn pohjalta voidaan laskea erilaisten lottorivien määrä suomalaisessa lotossa (jossa arvotaan 7 numeroa 39:stä):

\[\frac{39\,!}{(39 - 7)\,! * 7\,!} = 15380937.\]

Mahdollisuus saada 7 oikein -tulos täyttämällä yksi lottokuponki on siis

\[\frac{1}{15380937}\,.\]

Huomautus

Automaattinen arviointi ei testaa ohjelmaa näin suurilla luvuilla. Riittää, kun käytät laskennassa tietotyyppiä unsigned long int.

Toteuta ohjelma, joka kysyy käyttäjältä kaksi syötearvoa:

  • lottopallojen (eli numeroiden) kokonaismäärän
  • niistä arvottavien pallojen (eli numeroiden) määrän.

Tämän jälkeen ohjelma tulostaa, mikä on se todennäköisyys, jolla voi voittaa päävoiton, jos täyttää vain yhden kupongin (siis 1 jaettuna erilaisten lottorivien lukumäärällä).

Toteuta ohjelmaan lisäksi seuraavien virheilmoitusten tulostukset:

  • “The number of balls must be a positive number.”
  • “The maximum number of drawn balls is the total amount of balls.”

Sekä pallojen kokonaismäärä että arvottavien pallojen määrä kysytään ennen virhetarkastelua. Ensin tarkastellaan, ovatko pallojen määrät positiivisia. Mikäli virhe löytyy, tulostetaan virheilmoitus ja lopetetaan ohjelman suoritus välittömästi. Mikäli molemmat syötetyt luvut ovat positiivisia, tutkitaan pallojen määriä. Tällöinkin virheen löytyessä tulostetaan virheilmoitus ja lopetetaan ohjelman suoritus.

Esimerkki ohjelman toiminnasta:

Enter the total number of lottery balls: 20
Enter the number of drawn balls: 4
The probability of guessing all 4 balls correctly is 1/4845

Enter the total number of lottery balls: -3
Enter the number of drawn balls: 4
The number of balls must be a positive number.

Neuvoja tehtävän tekemiseen:

  • Mieti ensimmäisenä, mitkä osat ohjelmasta kannattaa toteuttaa funktioina.

  • Muistathan, että ison ohjelman testaaminen paloissa (funktio kerrallaan) on helpompaa kuin koko ohjelman testaaminen kerralla. Kun olet toteuttanut funktion, testaa sen toiminta heti ensimmäiseksi.

  • Pienten ohjelman osien testaaminen Pythonissa oli helppoa, koska Python on tulkattava kieli. C++:ssa tarvitset aina kokonaisen ohjelman main-funktioineen, että saat koodin käännettyä ja suoritettua.

  • Esimerkiksi jos olisit toteuttanut funktion foo, joka ottaa parametrinaan kokonaisluvun ja palauttaa jonkin toisen kokonaisluvun, voisit kirjoittaa main-funktion alkuun esim. seuraavat testirivit:

    cout << "foo parametrilla 0 saa arvon" << foo(0) << endl;
    cout << "foo parametrilla 1 saa arvon" << foo(1) << endl;
    cout << "foo parametrilla 5 saa arvon" << foo(5) << endl;
    

Pohdittavaa:

  • Muistele, mitä opit edellisellä kierroksella C++:n tietotyyppien rajoitteista. Tämä sama ohjelma tehtiin edellisellä ohjelmointikurssilla Pythonilla, ja tällöin tehtävänannon esimerkkinä oli suomalainen Lotto-peli:

    Enter the total number of lottery balls: 39
    Enter the number of drawn balls: 7
    The probability of guessing all 7 balls correctly is 1/15380937
    
  • Toimiiko C++:lla toteuttamasi ohjelma nyt oikein suomalaisen loton todennäköisyyttä laskettaessa? (Kuten edellä jo huomautettiin: Automaattinen arviointi ei testaa ohjelmaa näin suurilla luvuilla. Riittää, kun käytät laskennassa tietotyyppiä unsigned long int.)

A+ esittää tässä kohdassa tehtävän palautuslomakkeen.