| BME Villamosmérnöki és Informatikai Kar
Mérnök-informatikus szak |
Nappali tagozat
2018/2019-es tanév, őszi félév
|
A Mastermind játékot színes kód- és tippbábukkal, fekete és fehér válaszpálcikákkal ketten játsszák egy olyan táblán, amelyen több sorban lyukak vannak. A játékosok egyike, a passzív játékos állítja be a titkos kódot, amit az aktív játékos megpróbál kitalálni a passzív játékostól a tippjeire kapott válaszokból. A játék közismert változatában mind a tipp, mind a kód négy színes bábuból áll, a bábuk hatféle színűek lehetnek.
Az 1. ábrán egy Mastermind játszmát mutatunk be. Itt a tippbábukat az 1..6 számokkal, a fekete, illetve fehér válaszpálcikákat a B, illetve W betűkkel jelöltük (jelentésüket lásd a következő szakaszban).
| Kód- és tippbábuk | Válaszpálcikák | |||||||
| Titkos kód: | ? |
? |
? |
? |
||||
| 1. tipp és válasz: | 1 |
2 |
1 |
2 |
W |
|
|
|
| 2. tipp és válasz: | 5 |
1 |
3 |
5 |
W |
|
|
|
| 3. tipp és válasz: | 2 |
3 |
4 |
4 |
B |
B |
|
|
| 4. tipp és válasz: | 2 |
3 |
6 |
6 |
B |
W |
|
|
| 5. tipp és válasz: | 2 |
6 |
4 |
5 |
B |
B |
W |
W |
| 6. tipp és válasz: | 2 |
6 |
5 |
4 |
B |
B |
B |
B |
7. tipp és válasz helye: | |
|
|
|
|
|
|
|
| 8. tipp és válasz helye: | |
|
|
|
|
|
|
|
A játék aktív játékosként kipróbálható például itt (a játékhoz Flash szükséges), vagy itt (angol nyelven, Flash nem szükséges).
A passzív játékos feladata, hogy a színes bábukból tetszőleges variációt állítson össze, melyet titkos kódnak nevezünk (röviden kód). Azonos színű bábukból több is lehet a kódban. A passzív játékos ezt a kódot az aktív játékos által nem látható lyukakba helyezi, majd a valóságnak megfelelően válaszol az aktív játékos tippeire. Azt mondjuk, hogy a tipp egy bábuja és a kód egy bábuja azonos helyen vannak, ha a tábla azonos oszlopában vannak, egyébként azt mondjuk, hogy különböző helyen vannak.
Az aktív játékos feladata a titkos kód kitalálása, mégpedig a lehető legkevesebb lépésben. Minden lépésben tetszőleges variációt állít össze a színes bábukból, melyet tippnek nevezünk, és tippjét a tábla következő üres sorába rakja. A passzív játékos mindegyik tippről közli, hogy milyen közel van a kódhoz: annyi fekete válaszpálcikát rak a táblára, ahány egyforma színű bábu van a tippben és a kódban azonos a helyen, továbbá annyi fehér válaszpálcikát rak a táblára, ahány egyforma színű bábu van a tippben és a kódban különböző helyen. Más szóval, a fekete válaszpálcikák a pontos, a fehér válaszpálcikák a pontatlan találatok számát adják meg.
Mivel a titkos kódban (és így a tippben is) ugyanaz a szín többször is előfordulhat, ezért a fehér válaszpálcika használatát pontosítani kell. Amikor a kódban többször fordul elő egy szín, akkor az adott színű bábuk közül csak annyihoz rendelhető fehér válaszpálcika, ahányszor az adott szín a tippben a nem megfelelő helyen szerepel; ugyanez a megszorítás fordítva is fennáll. A fehér válaszpálcikák számának meghatározása így pl. a következő módon történhet:
A válaszpálcikák elhelyezése a sorban nem hordoz információt, csak a pálcikák darabszáma számít; így nem lehet tudni, hogy pontosan mely bábukra vonatkoznak. A fekete és fehér pálcikák számából alkotott számpárt válasznak nevezzük. A válasz tehát egy titkos kódhoz és egy tipphez rendelt érték, amely a két bábu-variáció távolságát jellemzi (a 4 fekete és 0 fehér pálcika jelenti azt, hogy a tipp azonos a titkos kóddal).
Az alábbi jelöléseket és adatstruktúrákat használjuk a fenti fogalmakhoz Prolog és Erlang nyelven egyaránt:Max a megengedett színek száma
H a kódban szereplő bábuk száma, azaz a
kód hossza (értelemszerűen a tippek hossza is H)
1..Max intervallumba eső, pozitív egész számH elemű bábulista, az elemsorrend megfelel az oszlopsorrendnekH elemű bábulista, az elemsorrend megfelel az oszlopsorrendnek0..H intervallumba esik
Írjon mmind néven olyan Erlang-függvényt, ill.
Prolog-eljárást, amely a tippek és a hozzájuk tartozó válaszok egy
halmazára előállítja a bemeneti adatoknak megfelelő titkos kódokat!
A függvénynek, illetve az eljárásnak két bemenő paramétere van. Az
első a Max paraméter, azaz a kódban megengedett maximális
érték. A második egy nem-üres lista, a súgás-lista, amelynek
elemei a játszma egy-egy lépésének felelnek meg: egy tippet és az arra
adott választ tartalmazzák.
A játék H (hossz) paramétere implicit módon van megadva: a
(nem-üres) súgás-lista elemeiben szereplő tippek mind H hosszú
listák. Nem szükséges ellenőriznie, hogy ezek a listák egyforma
hosszúságúak-e.
Azt mondjuk, hogy egy K titkos
kód megfelel egy SL súgás-listának
és egy Max maximális kódértéknek (színszámnak), ha
K az 1..Max intervallumba eső egész
számokból áll, és
SL súgás-lista minden elemére fennáll, hogy az adott
súgás-elemben megadott tipp és a K titkos kód
együtteséhez a súgás-elemben megadott válasz tartozik.
A feladat megoldásaként az 1..Max értékekből álló összes
olyan kódot kell előállítani amely a bemenetnek a fenti értelemben
megfelel. A kódok előállításának sorrendje tetszőleges, de egy kódot csak
egyszer szabad előállítani.
Az Erlang-függvény kimenete a megoldást alkotó kódok listája. A Prolog-eljárás kimenete egyetlen kód, azonban visszalépések során az összes megfelelő kódot elő kell állítania. Értelemszerűen, ha a súgás-lista ellentmondást tartalmaz, azaz nincs megfelelő kód, akkor az Erlang-függvény az üres listával tér vissza, a Prolog-eljárás pedig meghiúsul.
Természetesen a függvény, ill. az eljárás által előállított kódok hossza
is H kell legyen, azaz meg kell egyezzen a bemenő paraméterben
szereplő tippek hosszával.
Vegyük például a következő befejezetlen játszmát, amelyben négy szín használható:
| Kód- és tippbábuk | Válaszpálcikák | |||||
| Titkos kód: | ? |
? |
? |
|||
| 1. tipp és válasz: | 1 |
1 |
1 |
B |
|
|
| 2. tipp és válasz: | 1 |
2 |
2 |
W |
|
|
| 3. tipp és válasz: | 3 |
1 |
3 |
B |
B |
|
Ennek a játszmának két megoldása van, amely megfelel a bemenetnek:
[3,1,4] és [4,1,3]. A Prolog-eljárásnak ezt a
két megoldást a visszalépések során fel kell sorolnia, míg az
Erlang-függvény eredményének a [[3,1,4],[4,1,3]] két elemű
listának kell lennie. A játszma két megoldásának sorrendje mindkét nyelv
esetén felcserélhető.
Az mmind/3 Prolog-eljárás típusát a következő -
megjegyzésként megadott - Mercury-típusdefiníciók írják le.
% :- type code == list(int). A code típus egy int típusú elemekből álló listát jelent
% :- type blacks == int. A blacks típus azonos az int típussal
% :- type whites == int. A whites típus azonos az int típussal
% :- type answer ---> blacks/whites. Az answer típusú érték egy olyan kétargumentumú struktúra, amelynek
neve '/', első argumentuma blacks típusú, a második pedig whites típusú
% :- type hint ---> code-answer. A hint típusú érték egy olyan kétargumentumú struktúra, amelynek
neve '-', első argumentuma code típusú, a második pedig answer típusú
% :- pred mmind(int::in, list(hint)::in, code::out).
% mmind(Max, Hints, Code): Code egy olyan titkos kód, amely megfelel a
% a Hints súgás-listának és a Max maximális kódértéknek.
Az mmind:mmind/2 Erlang-függvény típusát a következő
típusdefiníciók írják le.
-type code() :: [integer()]. %% A code() típus egy integer() típusú elemekből álló lista típusa
-type blacks() :: integer(). %% A blacks() típus azonos az integer() típussal
-type whites() :: integer(). %% A whitess() típus azonos az integer() típussal
-type answer() :: {blacks(),whites()}. %% Az answer() típusú érték egy olyan pár, amelynek első eleme blacks(), második eleme whites() típusú.
-type hint() :: {code(),answer()}. %% A hint() típusú érték egy olyan pár, amelynek első eleme code(), második eleme answer() típusú.
-spec mmind:mmind(Max::integer(), Hints::[hint()]) -> Codes::[code()].
%% Codes a Hints súgás-listának és a Max maximális kódértéknek
%% megfelelő összes titkos kód tetszőleges sorrendű listája.
A programot tartalmazó modul attribútumai ezek legyenek ('email@unit.org.hu'
helyébe a saját email-címét, 'year-mm-dd' helyébe a beadás napját
írja be, exportálni csak az 'mmind/2' függvényt exportálja, a '-compile(export_all)'
attribútumot kommentezze ki vagy törölje):
-module(mmind).
-author('email@unit.org.hu').
-vsn('year-mm-dd').
-export([mmind/2]).
%-compile(export_all).
A 2. ábrán látható példa az alábbi módon adható meg a Prolog-eljárásnak, illetve az Erlang-függvénynek, és a megoldást is az itt leírt módon várjuk (de nem feltétlenül ebben a sorrendben).
| ?- mmind(4, [[1,1,1]-1/0,
[1,2,2]-0/1,
[3,1,3]-2/0], Code).
Code = [3,1,4] ? ;
Code = [4,1,3] ? ;
no
mmind:mmind(4, [{[1,1,1],{1,0}},
{[1,2,2],{0,1}},
{[3,1,3],{2,0}}]).
[[3,1,4],[4,1,3]]
Programjait keretprogramok segítségével próbálhatja ki. A keretprogramokat a beadáskor használthoz hasonló tesztesetekkel együtt töltheti le:
A keretprogram bemenete egy olyan szövegfájl, amelynek első sora
a Max számot, azaz a kódban felhasználható legnagyobb értéket
tartalmazza, minden egyes további sorában pedig egy tipp és a rá adott
válasz áll. A tipp pozitív egészek egy vagy több szóközzel elválasztott
sorozata. Egy vagy több szóköz után következik a válasz, amely a fekete és
a fehér válaszpálcikák száma, `/' jellel elválasztva.
A 3. ábra a 2. ábrán bemutatott példát leíró bemeneti fájl tartalmát mutatja.
4 1 1 1 1/0 1 2 2 0/1 3 1 3 2/0 |
A keretprogram kimenete a 4. ábrán bemutatotthoz hasonló tartalmú szövegfájl.
[[3,1,4],[4,1,3]]. |
[3,1,4] és
[4,1,3]. (Ezeket a Prolog-eljárásnak fel kell sorolnia, az
Erlang-függvénynek listába gyűjtve vissza kell adnia. A sorrend természetesen
tetszőleges.)
A kmmind.pl Prolog-keretprogram a következő eljárásokat exportálja:
% :- pred mmind_be(file::in, int::out, list(hint)::out).% :- pred mmind_ki(file::in, list(code)::in).% :- pred megold(file::in, file::in).mmind/3 eljárást.% :- pred stopper(file::in, file::in, list(code)::out).megold/2, de kiírja a feladvány nevét, a megoldások számát és
a futási időt, a harmadik paraméterben pedig visszadja a megoldások listáját.% :- pred teljes_teszt(int::in).1
tests mappában levő összes testXXXd.txt
tesztfájlra:
tests mappában lévő testXXXs.txt fájlban megadott
megoldáshalmazt kapta-e eredményül,tests_out_pl mappát,megold/2) kiírja az eredményt a tests_out_pl
mappában létrehozott testXXXt.txt nevű fájba.XXX egy tetszőleges hosszúságú
számjegysorozatot jelöl.
A keretprogram felhasználja a file típust:
% :- type file == atom.
A file típusú paraméterben a user atomot megadva
a terminálról vihetünk be, ill. a terminálra írathatunk ki adatokat.
Egyébként a megadott nevű fájlba írunk, ill. fájlból olvasunk.
Használat: saját programját az
mmind.pl nevű fájlba tegye be, különben a
kmmind.pl keretprogram nem találja meg. Ezután futtassa a
SICStus interpretert, és töltse be a keretprogramot. Példák az eljárások meghívására:
SICStus 4.4.1 (x86_64-linux-glibc2.17): Fri Mar 16 07:52:32 PDT 2018
Licensed to BUTE DP18a Course
| ?- [kmmind].
% compiling ...
% compiled ... in module mmind_keret, 18 msec 29792 bytes
yes
| ?- megold('tests/test00d.txt','test00m.txt').
| ?- stopper('tests/test00d.txt','test00m.txt',Sols).
| ?- stopper('tests/test00d.txt','test00m.txt',_).
| ?- teljes_teszt(10).
A megold/2, stopper/3, ill. teljes_teszt/1 eljárás meghívása
az mmind.pl programot automatikusan betölti, ha szükséges,
ezért ennek módosításakor nem kell sem a SICStus interpretert
újraindítania, sem a keretprogramot újra betöltenie.
A kmmind.erl Erlang-keretprogram a következő függvényeket
exportálja:
-spec mmind_be(FileIn::string()) ->
MMind::{integer(),[hint()]}.MMind a FileIn szövegfájlból beolvasott, a
Mastermind-feladványt leíró kódértékből és súgás-listából álló pár.-spec mmind_ki(FileOut::string(), Codes::[code()]) ->
none().Codes listában átadott Mastermind-megoldásokat kiírja a
FileOut szövegfájlba.-spec megold(FileIn::string(), FileOut::string()) ->
none().FileIn szövegfájlból, és összes
megoldását kiírja a FileOut szövegfájlba. Ehhez felhasználja
az mmind:mmind/2 függvényt.-spec stopper(FileIn::string(), FileOut::string()) ->
none().kmmind:megold/2, de a végén kiírja a
FileIn nevet, a megoldások számát és a futási időt is.-spec stopper(FileIn::string(), FileOut::string(), FileSol::string()) ->
none().kmmind:stopper/2, de ha a FileSol fájlban értelmezhető
megoldás van, ezt összeveti az eredményül kapott mgoldással.-spec teljes_teszt(Timeout::integer()) ->
[done|timeout].2
tests mappában lévő összes testXXXd.txt
tesztfájlra:
Timeout másodperces időkorláttal,tests mappában lévő testXXXs.txt fájlban megadott megoldáshalmazt kapta-e eredményül,tests_out_er mappát,megold/2) kiírja az eredményt a tests_out_er
mappában létrehozott testXXXt.txt nevű fájlba.XXX egy tetszőleges hosszúságú
számjegysorozatot jelöl.
Használat: saját mmind.erl nevű programját
minden változtatás után fordítsa le,
és mmind.beam néven rakja a keretprogrammal
azonos mappába, különben a kmmind.erl keretprogram nem
találja meg. Ezután indítsa el az Erlang értelmezőt, és töltse be a
lefordított keretprogramot. Példák a függvények meghívására:
Eshell V5.7.4 (abort with ^G)
1> l(kmmind).
{module,kmmind}
2> kmmind:megold("tests/test00d.txt","test00m.txt").
3> kmmind:stopper("tests/test00d.txt","test00m.txt").
4> kmmind:stopper("tests/test00d.txt","test00m.txt","test00s.txt").
5> kmmind:teljes_teszt(10).
A keretprogram automatikusan betölti az mmind.beam programot,
feltéve, hogy a keretprogrammal azonos mappában van.
Ha a saját mmind.erl programját módosítja, a lefordítása után
betöltheti az 'l(mmind).' paranccsal, de újra
betöltheti a
kmmind.erl keretprogramot is, ami magával húzza a módosított
programot. Egyes esetekben célszerű újraindítani az Erlang értelmezőt.
Mindkét programot úgy írja meg (választása szerint vagy magyarul, vagy angolul), hogy a szövegük jól olvasható legyen: válasszon értelmes neveket, specifikálja a paraméterek és más azonosítók szerepét és értelmezési tartományát, magyarázza meg az egyes eljárások, ill. függvények feladatát és működését! Kövesse a Prolog-, ill. az Erlang-diákon használt szövegelrendezési konvenciókat! Javasoljuk, hogy ne írjon 72 karakternél hosszabb sorokat. Minden eljáráshoz és függvényhez készítsen fejkommentet!
A két programhoz készítsen közös dokumentációt; vagy magyarul, vagy angolul. A dokumentáció tartalma legalább a következő legyen:
Fogalmazzon világosan és tömören, ügyeljen a helyes nyelvhasználatra és a helyesírási szabályok betartására! Az indokoltan elvárható formai követelmények be nem tartását, a gondatlan kivitelt szankcionáljuk.
A dokumentációt elektronikus alakban adja be PDF formátumban.
A programok készülhetnek MS Windows alatt is, de Linux alatt is működniük kell. A beadott programokat Linux környezetben a SICStus Prolog 4.4 ill. az Erlang R16A rendszerekkel teszteljük.
Megoldásában Prolog nyelven tetszőleges könyvtárakat használhat, kivéve a
clpfd, clpq, clpr, clpb
és chr Prolog-könyvtárakat: az ezeket a
könyvtárakat felhasználó megoldások a létraversenyben nem vehetnek részt,
és így megajánlott jegyet sem kaphatnak.
Erlang nyelven az adatbázist vagy egyéb mellékhatást használó függvények használata tilos (erlang:get, erlang:put, digraph modul, io modul stb.). Néhány megengedett, állapotmentes modul: array, dict, gb_*, lists, math, ord*, queue, sets, string.
A programokat és az elektronikus dokumentációt webes felületen lehet majd külön-külön feltölteni az Elektronikus Tanársegéd HF beadás menüpontjában. A beadást többször is megismételheti, az utoljára beadott megoldást tekintjük érvényesnek.
Programját egy tíz elemű tesztsorozattal automatikusan futtatjuk. A teszteseteket úgy választjuk meg, hogy legalább négy feladványt a kevésbé ötletes programok is meg tudjanak oldani. Az eredményt levélben közöljük és az ETS-ben is megnézhető.
A nagy házi feladat elkészítése nem kötelező, de megoldását mindenkinek javasoljuk: ez a deklaratív nyelvek magas szintű elsajátítását nagy mértékben segíti.
A beadási határidő után értékeljük a programokat (ez az ún. "éles" teszt). Ehhez a beadási tesztsorozathoz hasonló nehézségű teszteseteket használunk. Az időkorláton belül helyes eredményt adó tesztesetek mindegyikére 0,5–0,5 pontot adunk, a 10 tesztesetre tehát nyelvenként összesen maximum 5 pontot. Ezen felül a dokumentációt, a programkód olvashatóságát, kommentezettségét is értékeljük, nyelvenként maximum 2,5 ponttal. A mindkét nyelven beadott nagy házi feladatra tehát maximum 15 pont kapható (ez 15%-a a pluszpontok nélkül elérhető legfeljebb 100 alappontnak).
Azok a programok, amelyek az éles teszt legalább 8 feladatát helyesen és az előírt időkorláton belül megoldják, létraversenyben vesznek részt. A leggyorsabban futó Erlang-, ill. Prolog-programokra - helyezési számuktól függően - külön-külön 7,5 és 0,5 közötti pluszpont kapható. Ha valaki tehát mindkét nyelvből a leggyorsabb programot írja meg, akkor a 100 alapponton felül 15 pluszpontot kap.
Azok a hallgatók, akik mindkét nyelvből bejutnak a létraversenybe - a tantárgyi adatlapon leírt feltételek fennállása esetén - megajánlott jegyet kapnak.
A programot és dokumentációt mindenkinek saját magának kell elkészítenie. A beadott nagy házi feladatokat gépi úton hasonlítjuk össze, másolás esetén fegyelmi eljárást kezdeményezünk. Az algoritmusra vonatkozó ötletek cseréjét viszont nem tiltjuk.
1 Ezt az eljárást Eisenberger András ültette át Prologra. Vissza
2 Ezt a függvényt Eisenberger András egészítette ki a megoldás ellenőrzésével. Vissza
| DP Admin | $LastChangedDate: 2018-10-27 22:48:10 +0200 (Sat, 27 Oct 2018) $ | Vissza az elejére / Back to the top |