Hetek óta tartó várakozás után te és a barátaid összegyűltök, hogy lejátsszátok a legeslegelső Dungeons & Dragons (D&D) játékotokat. Mivel ez a játék első alkalma, minden játékosnak létre kell hoznia egy karaktert, akivel játszik. A karakter képességeit hatoldalú kockák dobásával határozzák meg, de hol vannak a kockák? Megdöbbenve veszed észre, hogy a barátaid arra várnak, hogy te szerezd be a kockákat; hiszen a te ötleted volt, hogy D&D-t játsszatok! Pánikba esve ráébredsz, hogy elfelejtettél kockát hozni, ami azt jelentené, hogy nem lesz D&D játék. Mivel van némi alapvető programozási ismereted, gyorsan kitalálod a megoldást: írsz egy programot, ami szimulálja a kockadobásokat.
A Dungeons & Dragons játékban minden játékos azzal kezdi, hogy generál egy karaktert, akivel játszhat. Ennek a karakternek többek között hat képessége van: erő, ügyesség, állóképesség, intelligencia, bölcsesség és karizma. Ennek a hat képességnek az értékét véletlenszerűen határozzuk meg. Ehhez négy hatoldalú kockával dobsz, és feljegyzed a három legnagyobb kocka összegét. Ezt hatszor teszed meg, minden képességhez egyszer.
A karaktered kezdeti életerőpontjai 10 + a karaktered állóképesség-módosítója. A karaktered állóképesség-módosítóját úgy kapod meg, hogy a karaktered állóképességéből kivonsz 10-et, elosztod 2-vel, és lefelé kerekíted.
Írj egy véletlenszerű karaktergenerátort, amely követi a fenti szabályokat.
Például a négy kockával végzett hat dobás így nézhet ki:
Mivel az állóképesség 3, az állóképesség-módosító -4, az életerőpontok pedig 6.
A legtöbb programozási nyelv rendelkezik pszeudo-véletlen generátorral, de kevés programozási nyelvet terveztek kockadobásra. Egy ilyen nyelv a Troll.
A funkcionális nyelvekben a legtöbb függvény tiszta. Ez azt jelenti, hogy ugyanarra az argumentumhalmazra mindig ugyanazt az eredményt adják vissza, és semmi mást nem tesznek. Más szóval a tiszta függvények determinisztikusak.
A véletlen érték viszont definíció szerint kiszámíthatatlan és nem determinisztikus. Még az álvéletlenség megvalósítása sem könnyű tiszta környezetben, pedig az nem jelent mást, mint olyan számsorozat visszaadását, amely véletlennek látszik. Ez azért van, mert az álvéletlenszám-generátornak (PRNG) nyomon kell követnie a belső állapotát, hogy visszaadhassa a sorozat következő számát.
A Lean két lehetséges megközelítést kínál erre a problémára:
Használj olyan monádot, amely lehetővé teszi egy álvéletlenszám-generátor belső állapotának megváltoztatását.
Erre pontosan van egy készen elérhető függvény, az IO.rand.
Használj olyan tiszta függvényeket, amelyek argumentumként egy generátort kapnak, és nemcsak az előállított álvéletlen értéket adják vissza, hanem egy frissített generátort is, amely „fel van készítve” a sorozat következő számára.
Ez a feladat a második megközelítést használja. Minden olyan függvény megkapja a generátort, amelynek álvéletlen értéket kell előállítania, és a függvénynek vissza kell adnia mind az értéket, mind a frissített generátort.
Vedd figyelembe, hogy egy adott generátor determinisztikus, azaz mindig ugyanazt az értéket állítja elő. Ahhoz, hogy egy sorozat következő álvéletlen értékét előállítsd, a frissített generátort kell használnod.
Ebben a feladatban a véletlenszerűséget khi-négyzet-próba ellenőrzi p < 0.0001 szignifikanciaszinten.
Ez azt jelenti, hogy ha egy tulajdonságértéket az utasításoknak megfelelően állítanak elő, kevesebb mint 0,01% az esélye annak, hogy egy helyes implementáció véletlen folytán megbukik a teszten.
Vedd figyelembe, hogy az utasítások szerint egy tulajdonságérték egy elfogulatlan d6 (hatoldalú dobókocka) négy dobásából a három legnagyobb eredmény összege.
Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) Lean nyelvet 100 feladat segítségével, valódi emberi mentorálással, mindez ingyen.
Megvizsgáljuk, hogyan generálhatunk (látszólag) véletlenszerű kockadobásokat. Megismerkedsz a seedekkel, az álvéletlen számokkal és néhány gyakori buktatóval. Végül meglátjuk, miért kiváló a tulajdonságalapú tesztelés a véletlenszerű értékeket visszaadó függvények tesztelésére.