Osa 7

Satunnaisuus

Tässä luvussa tutustutaan standardikirjaston moduuliin random, joka tarjoaa välineistöä satunnaislukujen generointiin ja muuhun satunnaiseen toiminnallisuuteen.

Tässä ja seuraavissa luvuissa esiteltävien funktioiden yhteyteen on lisäilty linkkejä standardikirjaston dokumentaatioon. Linkkejä kannattaa klikkailla ja pikkuhiljaa totutella siihen, miltä dokumentaatio näyttää.

Luvun arpominen

Funktio randint(a, b) antaa satunnaisen kokonaisluvun väliltä a...b. Esimerkiksi seuraava ohjelma simuloi nopan heittämistä:

from random import randint

print("Noppa antaa:", randint(1, 6))

Ohjelman tulos voisi olla vaikkapa:

Esimerkkitulostus

Noppa antaa: 4

Seuraava ohjelma puolestaan heittää noppaa kymmenen kertaa:

from random import randint

for i in range(10):
    print("Noppa antaa:", randint(1, 6))

Ohjelman tulos voisi olla seuraava:

Esimerkkitulostus

Noppa antaa: 5 Noppa antaa: 4 Noppa antaa: 3 Noppa antaa: 2 Noppa antaa: 3 Noppa antaa: 4 Noppa antaa: 6 Noppa antaa: 4 Noppa antaa: 4 Noppa antaa: 3

Huomaa, että funktio randint toimii eri logiikalla kuin aiemmin käyttämämme funktio range, joka luo lukuvälin. Kun kutsumme funktiota randint(1, 6), lukuväli on 1...6, mutta kun kutsumme funktiota range(1, 6), lukuväli on 1...5.

Lisää funktioita

Funktio shuffle sekoittaa sille annetun tietorakenteen. Esimerkiksi seuraava ohjelma sekoittaa listalla olevat sanat:

from random import shuffle

sanat = ["apina", "banaani", "cembalo"]
shuffle(sanat)
print(sanat)
Esimerkkitulostus

['banaani', 'apina', 'cembalo']

Funktio choice puolestaan valitsee satunnaisen alkion tietorakenteesta:

from random import choice

sanat = ["apina", "banaani", "cembalo"]
print(choice(sanat))
Esimerkkitulostus

'cembalo'

Lottorivin arvonta

Tarkastellaan esimerkkinä tilannetta, jossa haluamme arpoa lottorivin. Lotossa on yhteensä 40 numeroa, joista arvotaan 7 numeroa riviin.

Yksinkertainen tapa koettaa arpoa lottorivi on seuraava:

from random import randint

for i in range(7):
    print(randint(1, 40))

Tämä ei ole kuitenkaan toimiva tapa, koska sama numero saattaa tulla useita kertoja riviin. Tarvitsemme jonkin menetelmän, joka varmistaa, että jokainen numero on eri numero.

Yksi mahdollisuus on tallentaa arvotut numerot listaan ja lisätä uusi numero listaan vain, jos sitä ei vielä ole siellä. Voimme jatkaa tätä, kunnes listassa on 7 numeroa:

from random import randint

rivi = []
while len(rivi) < 7:
    uusi = randint(1, 40)
    if uusi not in rivi:
        rivi.append(uusi)

print(rivi)

Voimme kuitenkin toteuttaa arvonnan myös lyhyemmin funktion shuffle avulla:

from random import shuffle

kaikki = list(range(1, 41))
shuffle(kaikki)
rivi = kaikki[0:7]
print(rivi)

Tässä ideana on, että luomme ensin listan, jossa on kaikki numerot väliltä 1–40. Tämän jälkeen sekoitamme listan ja valitsemme sitten 7 ensimmäistä numeroa riviin. Tämän ansiosta meidän ei tarvitse tehdä silmukkaa.

Itse asiassa voimme toteuttaa arvonnan vielä helpommin, koska Pythonin standardikirjastossa on myös funktio sample, joka valitsee annetusta tietorakenteesta halutun määrän alkioita:

from random import sample

kaikki_luvut = list(range(1, 41))
rivi = sample(kaikki_luvut, 7)
print(rivi)
Ohjelmointitehtävä:

Lottonumerot

Pisteitä:
Loading...

/

Loading...

Tee funktio lottonumerot(maara: int, alaraja: int, ylaraja: int), joka arpoo annetun määrän satunnaislukuja väliltä alaraja...ylaraja, tallentaa ne listaan ja palauttaa listan. Lukujen tulee olla palautetussa listassa suuruusjärjestyksessä.

Koska kyseessä ovat lottonumerot, sama numero ei saa esiintyä listassa kahta kertaa.

Esimerkki:

for numero in lottonumerot(7, 1, 40):
    print(numero)
Esimerkkitulostus

4 7 11 16 22 29 38

Mistä satunnaisluvut tulevat?

Moduulin random toiminta perustuu algoritmiin, joka tuottaa satunnaislukuja tietyn lähtöarvon ja matemaattisten operaatioiden avulla. Lähtöarvoa kutsutaan myös nimellä siemenarvo (engl. seed value).

Voimme halutessamme antaa siemenarvon itse funktiolla seed:

from random import randint, seed

seed(1337)
# tästä tulee aina sama satunnaisluku
print(randint(1, 100))

Kun annamme siemenarvon itse, satunnaisuutta käyttävät funktiot antavat samat tulokset ohjelman jokaisella suorituskerralla. Tulokset voivat kuitenkin riippua käytetystä Pythonin versiosta.

Ohjelmointitehtävä:

Salasanan arpoja, osa 1

Pisteitä:
Loading...

/

Loading...

Tee funktio, jonka avulla on mahdollista luoda halutun pituisia satunnaisista pienistä kirjaimista (väliltä a-z) muodostettuja salasanoja.

Esimerkki:

for i in range(10):
    print(luo_salasana(8))
Esimerkkitulostus

lttehepy olsxttjl cbjncrzo dwxqjdgu gpfdcecs jabyvgar xnbbonbl ktmsjyww ejhprmel rjkoacib

Ohjelmointitehtävä:

Salasanan arpoja, osa 2

Pisteitä:
Loading...

/

Loading...

Tee paranneltu versio edellisen tehtävän funktiosta. Funktio saa nyt kolme parametria:

  • jos toinen parametri on True, salasanassa on myös (yksi tai useampi) numero
  • jos kolmas parametri on True, salasanassa on myös (yksi tai useampi) erikoismerkki joukosta !?=+-()#

Salasanassa täytyy olla parametreista riippumatta aina vähintään yksi kirjain. Voit olettaa, että funktiota kutsutaan aina parametreilla, joilla on mahdollista tuottaa halutunlaisia salasanoja.

Esimerkki:

for i in range(10):
    print(luo_hyva_salasana(8, True, True))
Esimerkkitulostus

2?0n+u31 u=m4nl94 n#=i6r#( da9?zvm? 7h)!)g?! a=59x2n5 (jr6n3b5 9n(4i+2! 32+qba#= n?b0a7ey

Ohjelmointitehtävä:

Noppasimulaatio

Pisteitä:
Loading...

/

Loading...

Tehdään tässä tehtävässä muutamia funktioita, joita on mahdollista käyttää nopanheittoon liittyvissä peleissä.

Normaalin nopan sijaan tehtävässä käytetään ns. epätransitiivisia noppia, joista on lisää tietoa esim. tässä artikkelissa tai tässä videossa.

Käytössä on kolme noppaa:

  • Nopassa A on numerot 3, 3, 3, 3, 3, 6
  • Nopassa B on numerot 2, 2, 2, 5, 5, 5
  • Nopassa C on numerot 1, 4, 4, 4, 4, 4

Tee funktio heita(noppa: str), joka heittää parametrinsa kertomaa noppaa. Esimerkki:

for i in range(20):
    print(heita("A"), " ", end="")
print()
for i in range(20):
    print(heita("B"), " ", end="")
print()
for i in range(20):
    print(heita("C"), " ", end="")
Esimerkkitulostus

3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 6 3 6 3 2 2 5 2 2 5 5 2 2 5 2 5 5 5 2 5 2 2 2 2 4 4 4 4 4 1 1 4 4 4 1 4 4 4 4 4 4 4 4 4

Tee vielä funktio pelaa(noppa1: str, noppa2: str, kertaa: int) joka heittää kokonaisluvun kertoman määrän parametreina olevia noppia. Funktio palauttaa tuplen, joka kertoo nopan 1 voittojen lukumäärän, nopan 2 voittojen lukumäärän ja tasapelien lukumäärän.

tulos = pelaa("A", "C", 1000)
print(tulos)
tulos = pelaa("B", "B", 1000)
print(tulos)
Esimerkkitulostus

(292, 708, 0) (249, 273, 478)

Ohjelmointitehtävä:

Satunnaiset sanat

Pisteitä:
Loading...

/

Loading...

Tehtäväpohjassa on annettu tiedosto sanat.txt, joka sisältää englannin kielen sanoja, yksi sana joka rivillä.

Kirjoita funktio sanat(n: int, alku: str), joka palauttaa listassa n kappaletta satunnaisia sanoja tiedostosta. Kaikkien palautettujen sanojen tulee alkaa annetulla merkkijonolla.

Jos funktiota esim. kutsuttaisiin parametreilla sanat(3, "ca"), se voisi palauttaa listassa esim. sanat "cat", "car" ja "carbon". Sama sana ei saa esiintyä listassa kahdesti.

Jos annetulla merkkijonolla alkavia sanoja ei löydy tarpeeksi annetun kokoisen ryhmän muodostamiseen, funktio tuottaa poikkeuksen ValueError.

Esimerkki:

lista = sanat(3, "ca")
for sana in lista:
    print(sana)
Esimerkkitulostus

cat car carbon

Kysely:
Loading...
Pisteitä:
Loading...

Kirjaudu sisään nähdäksesi tehtävän

Seuraava osa: