BME Villamosmérnöki és Informatikai Kar
Műszaki informatika szak
Nappali tagozat
2007/2008-as tanév, tavaszi félév

Deklaratív programozás

Nagy házi feladat, 1.0 változat

Utolsó módosítás: 2008-04-16
Kiadás: 2008-04-16
Módosított beadási határidő: 2008-05-13 (változott 2008. május 5-én)

Sudoku

A feladvány

A feladvány a közismert Sudoku egy variánsa.

Egy s=n*k sorból és o=m*k oszlopból álló tábla c=n*m cellája egyenként k*k mezőt tartalmazó négyzet, ahol 1k5 és 1n, mk. A kezdetben részben kitöltött táblát úgy kell kitölteni 1 és k*k közötti egészekkel, hogy egy-egy cella összes mezőjében, továbbá a tábla egy-egy sorában, illetve oszlopában különböző számok legyenek.

Egy hagyományos, részben kitöltött Sudoku-táblát és néhány variánsát mutatja az 1. ábra.
    
+++++++++++++++++++      
+  2 3|4 1  |5 8  +
+  7 8|     |  2 1+
+    5|7 2  |  3 9+
+-----------------+
+  8 2|9 6 1|  4  +
+  9  |5   4|  1  +
+  6  |2 7 3|9 5  +
+-----------------+
+7 4  |  9 5|3    +
+2 3  |     |8 9  +
+  5 9|  3 2|1 7  +
+++++++++++++++++++
+++++++++++++      
+  2 3|5 8  +
+  7 8|  2 1+
+    5|  3 9+
+-----------+
+  8 2|  4  +
+  9  |  1  +
+  6  |9 5  +
+-----------+
+7 4  |3    +
+2 3  |8 9  +
+  5 9|1 7  +
+++++++++++++
+++++++++++++++++++      
+  2 3|4 1  |5 8  +
+  7 8|     |  2 1+
+    5|7 2  |  3 9+
+-----------------+
+  8 2|9 6 1|  4  +
+  9  |5   4|  1  +
+  6  |2 7 3|9 5  +
+++++++++++++++++++
+++++++++++++      
+  2 3|4 1  +
+  7 8|     +
+    5|7 2  +
+-----------+
+  8 2|9 6 1+
+  9  |5   4+
+  6  |2 7 3+
+++++++++++++
+++++++++      
+2 3|4  +
+  4|  2+
+-------+
+  2|   +
+   |2 3+
+++++++++
1. ábra     n=3, m=3, k=3,
s=9, o=9, c=9
n=3, m=2, k=3,
s=9, o=6, c=6
n=2, m=3, k=3,
s=6, o=9, c=6
n=2, m=2, k=3,
s=6, o=6, c=4
n=2, m=2, k=2,
s=4, o=4, c=4

A megoldandó feladat

Írjon sudoku néven olyan Prolog-eljárást, ill. SML-függvényt, amely egy feladvány összes megoldását előállítja!

A Prolog-eljárásnak két paramétere van. Első (bemenő) paramétere a feladványt, második (kimenő) paramétere a megoldást írja le. Az eljárásnak a visszalépések során minden megoldást pontosan egyszer kell kiadnia. Ha a feladványnak nincs megoldása, az eljárás hiúsuljon meg.

A Prolog-eljárás bemenő paramétere egy

    s(K,T)

felépítésű struktúra, ahol

A Prolog-eljárás kimenő paramétere ugyancsak egy s(K,T) struktúra.

A bemenő paraméterben a keresett (ismeretlen értékű) mezőket 0 jelöli.

Például az 1. ábra középső, n=2, m=3, k=3, s=6, o=9, c=6 paraméterű feladványát a következő Prolog-struktúrával írjuk le:

   s(3, [[0,2,3,4,1,0,5,8,0], [0,7,8,0,0,0,0,2,1], [0,0,5,7,2,0,0,3,9],
         [0,8,2,9,6,1,0,4,0], [0,9,0,5,0,4,0,1,0], [0,6,0,2,7,3,9,5,0]])

A feladvány egy megoldását a következő struktúra írja le:

   s(3, [[6,2,3,4,1,9,5,8,7], [9,7,8,3,5,6,4,2,1], [1,4,5,7,2,8,6,3,9],
         [5,8,2,9,6,1,7,4,3], [3,9,7,5,8,4,2,1,6], [4,6,1,2,7,3,9,5,8]])

Az SML-függvény egyetlen paramétere a feladványt, az eredménye a megoldásokat írja le. Az eredménylistának a feladvány összes megoldását tartalmaznia kell, mégpedig minden megoldást pontosan egyszer. Ha a feladványnak nincs megoldása, az eredmény az üres lista.

Az SML-függvény paramétere egy (k, t) pár, ahol k és t jelentése azonos a Prolog-eljárás K és T struktúraelemeinek a jelentésével.

Az SML-függvény eredménye egy ugyancsak (k, t) párokból álló lista.

Például az 1. ábra középső, n=2, m=3, k=3, s=6, o=9, c=6 paraméterű feladványát a következő SML-párral írjuk le:

   (3, [[0,2,3,4,1,0,5,8,0], [0,7,8,0,0,0,0,2,1], [0,0,5,7,2,0,0,3,9],
        [0,8,2,9,6,1,0,4,0], [0,9,0,5,0,4,0,1,0], [0,6,0,2,7,3,9,5,0]])

A feladvány megoldásait a következő lista írja le:

   [(3, [[6,2,3,4,1,9,5,8,7], [9,7,8,3,5,6,4,2,1], [1,4,5,7,2,8,6,3,9],
         [5,8,2,9,6,1,7,4,3], [3,9,7,5,8,4,2,1,6], [4,6,1,2,7,3,9,5,8]])
    (...), ...
    (...)
   ]

A megírandó függvény, ill. eljárás specifikációja

A sudoku/2 Prolog-eljárás típusát a következő - megjegyzésként megadott - Prolog-típusdefiníciók írják le.

% :- type sspec ---> s(size, board).
% :- type size  == int.
% :- type field == int.
% :- type board == list list field.

% sudoku(SSpec, SSol):
% SSol az SSpec  specifikációnak megfelelő megoldás.
% :- pred sudoku(sspec::in, sspec::out).

A sudoku SML-függvény típusát a következő SML-típusszinonimák és - itt megjegyzésként megadott - típusspecifikáció írják le.

type size  = int;
type field = int;
type board = field list list;
type sspec  = size * board;
(* sudoku : sspec -> sspec list
*)

Keretprogramok

Programjait keretprogramok segítségével próbálhatja ki. A keretprogramokat a beadáskor használthoz hasonló tesztesetekkel együtt letöltheti később innen. A nagy házi feladatok teszteléséhez és értékeléséhez a keretprogramokkal azonos specifikációjú programokat fogunk használni.

A keretprogram bemenete egy olyan szövegfájl, amelynek első nemüres sora a cella méretét, minden egyes további nemüres sora a Sudoku-tábla egy-egy sorát tartalmazza, ahol az egyes mezők értékét egy vagy több szóköz választja el. Például az 1. ábra bal szélén látható Sudoku-táblát a 2. ábrán látható módon ábrázoljuk a szövegfájlban:

   3
   
   0 2 3  4 1 0  5 8 0
   0 7 8  0 0 0  0 2 1
   0 0 5  7 2 0  0 3 9
   
   0 8 2  9 6 1  0 4 0
   0 9 0  5 0 4  0 1 0
   0 6 0  2 7 3  9 5 0
          	      
   7 4 0  0 9 5  3 0 0
   2 3 0  0 0 0  8 9 0
   0 5 9  0 3 2  1 7 0
      2. ábra

A keretprogram kimenete a 3. ábrán bemutatotthoz hasonló tartalmú szövegfájl.

   -----
   
    6 2 3  4 1 9  5 8 7
    9 7 8  3 5 6  4 2 1
    4 1 5  7 2 8  6 3 9
   
    5 8 2  9 6 1  7 4 3
    3 9 7  5 8 4  2 1 6
    1 6 4  2 7 3  9 5 8
   
    7 4 1  8 9 5  3 6 2
    2 3 6  1 4 7  8 9 5
    8 5 9  6 3 2  1 7 4
   
   -----
   
    9 2 3  4 1 6  5 8 7
    4 7 8  3 5 9  6 2 1
    6 1 5  7 2 8  4 3 9
   
    5 8 2  9 6 1  7 4 3
    3 9 7  5 8 4  2 1 6
    1 6 4  2 7 3  9 5 8
   
    7 4 1  8 9 5  3 6 2
    2 3 6  1 4 7  8 9 5
    8 5 9  6 3 2  1 7 4
   
   -----
   
    9 2 3  4 1 6  5 8 7
    6 7 8  3 5 9  4 2 1
    4 1 5  7 2 8  6 3 9
   
    5 8 2  9 6 1  7 4 3
    3 9 7  5 8 4  2 1 6
    1 6 4  2 7 3  9 5 8
   
    7 4 1  8 9 5  3 6 2
    2 3 6  1 4 7  8 9 5
    8 5 9  6 3 2  1 7 4
   
   -----
      3. ábra

A Prolog-keretprogram

A Prolog-keretprogram a következő négy eljárást exportálja:

sudoku_be(file::in, sspec::out)
A megnevezett szövegfájlból beolvassa a feladványt, és visszaadja a kimenő paraméterben.
sudoku_ki(file::in, sspec::in)
A megnevezett szövegfájlba kiírja a feladvány második paraméterként átadott összes megoldását.
megold(file::in, file::in)
Beolvas egy feladványt az első paraméterrel megnevezett szövegfájlból, és kiírja az összes megoldását a második paraméterrel megnevezett szövegfájlba. Ehhez felhasználja a sudoku/2 eljárást.
stopper(file::in, file::in)
Mint megold/2, de a végén kiírja a feladvány nevét, a megoldások számát és a futási időt is.

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 a sudoku.pl nevű fájlba tegye, különben a ksudoku.pl keretprogram nem találja meg. Ezután futtassa a SICStus interpretert, és töltse be a keretprogramot. Példa:

SICStus 3.12.5 (x86-linux-glibc2.3): Sun Mar 12 09:39:40 CET 2006
Licensed to BUTE-DP-course
| ?- [ksudoku].
% consulting d:/dokumentumok/bme/deklapo/07s/ksudoku.pl...
%  module sudoku_frame imported into user
%  loading e:/programozas/sicstus/library/lists.po...
%  module lists imported into sudoku_frame
%  loaded e:/programozas/sicstus/library/lists.po in module lists, 15 msec 11688 bytes
% consulted d:/dokumentumok/bme/deklapo/07s/ksudoku.pl in module sudoku_keret, 15 msec 29792 bytes
yes
| ?- stopper(..., ...).

A stopper/2, ill. megold/2 eljárások meghívása a sudoku.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.

Az SML-keretprogram

Az SML-keretprogram a következő négy függvényt exportálja:

sudoku_be f
Az f szövegfájlból beolvasott adatokból képzett feladványleíró.
sudoku_ki(m, ms)
Az m szövegfájlba kiírja a feladványnak az ms listával átadott megoldását.
megold(f, m)
Beolvas egy feladványt az f szövegfájlból és kiírja az összes megoldását az m szövegfájlba. Ehhez felhasználja a sudoku függvényt. Eredménye az f nevet és a megoldások számát tartalmazó füzér.
stopper(f, m)
Mint megold, de a végén kiírja a feladvány nevét, a megoldások számát és a futási időt is.

A bemenetet, ill. a kimenetet a terminálra irányíthatjuk Unix alatt a /dev/stdin, ill. a /dev/stdout, MS DOS/Windows alatt mindkét esetben a con fájlnév megadásával.

Használat: olvassa be az interpreterbe a ksudoku.sml programot, és a megfelelő paraméterekre alkalmazza a kívánt függvényt:

Moscow ML version 2.01 (January 2004)
Enter `quit();' to quit.
- use "ksudoku.sml";
> val it = () : unit
- stopper (..., ...);

A keretprogram a use "sudoku.sml" kifejezéssel betölti a keretprogrammal azonos könyvtárban lévő sudoku.sml programot.

Miután a saját sudoku.sml programját módosította, betöltheti a módosított programot, de betöltheti újra a ksudoku.sml programot is, hiszen az betölti a módosított programot is. Sokszor célszerű az SML értelmezőt is újraindítani.

Figyelem: az ETS a beküldött programokat nem az mosml értelmezőprogrammal futtatja, hanem előbb lefordítja és összeszerkeszti az mosmlc fordítóprogrammal, majd az összeszerkesztett programot futtatja. Ezért a beküldött programban olyan függvényeket nem szabad használnia, amelyeket csak az interpreter ismer; ilyen pl. a load vagy a printVal.

Dokumentációs követelmények

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 SML-jegyzetben látható szövegelrendezési szokásokat! 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 HTML, PDF, esetleg ASCII formátumban.

Egyéb követelmények és tudnivalók

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 3.12.x, ill. az MOSML 2.01 rendszerekkel teszteljük.

A programokat és az elektronikus dokumentációt webes felületen lehet 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ízelemű 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 beadása, elfogadása és a tesztesetek 40%-ának sikeres megoldása az aláírás feltétele. A nagy házi feladat elfogadása azt jelenti, hogy a hallgatónak a gyakorlatokon, illetve a feladat beadását követő konzultáción a feladatra vonatkozó kérdések megválaszolásával, illetve módosított részfeladatok megoldásával meg kell győznie a konzulensét arról, hogy a feladatot ő készítette el, és a feladat elkészítéséhez szükséges tudás birtokában van.

A nagy házi feladat megoldását azoknak is javasoljuk, akik korábban szereztek aláírást: ez a deklaratív nyelvek magasszintű elsajátítását nagymértékben segíti.

A programok és az elektronikus dokumentáció módosított beadási határideje 2008. május 13., kedd, 24h.

Az értékeléshez a beadási tesztsorozathoz hasonló nehézségű teszteseteket fogunk használni. Az időkorláton belül helyes eredményt adó tesztesetek mindegyikére 0,5-0,5 pontot adunk. a 10 tesztesetre összesen tehát nyelvenként maximum 5 pontot kaphat. 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 pontot kaphat (ez 15%-a a pluszpontok nélkül elérhető legfeljebb 100 alappontnak).

Azok a programok, amelyek az alapteszt minden feladatát helyesen és az előírt időkorláton belül megoldják, létraversenyben vesznek részt. A leggyorsabban futó SML-, 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.

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 a kódot adó és kapó hallgató sem kaphat pontot. Az algoritmusra vonatkozó ötletek cseréjét viszont nem tiltjuk.


dp@inf.bme.hu