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:
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:
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)
['banaani', 'apina', 'cembalo']
Funktio choice
puolestaan valitsee satunnaisen alkion tietorakenteesta:
from random import choice
sanat = ["apina", "banaani", "cembalo"]
print(choice(sanat))
'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)
Lottonumerot
/
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)
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.
Salasanan arpoja, osa 1
/
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))
lttehepy olsxttjl cbjncrzo dwxqjdgu gpfdcecs jabyvgar xnbbonbl ktmsjyww ejhprmel rjkoacib
Salasanan arpoja, osa 2
/
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))
2?0n+u31 u=m4nl94 n#=i6r#( da9?zvm? 7h)!)g?! a=59x2n5 (jr6n3b5 9n(4i+2! 32+qba#= n?b0a7ey
Noppasimulaatio
/
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="")
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)
(292, 708, 0) (249, 273, 478)
Satunnaiset sanat
/
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)
cat car carbon
Kirjaudu sisään nähdäksesi tehtävän