BME Villamosmérnöki és Informatikai Kar
Mérnök-informatikus alapszak |
Nappali tagozat
2009/2010-es tanév, tavaszi félév
|
A megoldandó feladat a közismert Sudoku egy variánsa (n-away sudoku).
A Sudoku-feladvány egy m=k*k
sorból és m
oszlopból álló négyzetes tábla, amely m
darab k*k
méretű négyzetes cellára bomlik, ahol 1 ≤ k ≤ 5
.
Emellett a feladvány részét képezi egy n
távolságkonstans,
amely az ún. távolságinfók értelmezéséhez szükséges, ahol 1 ≤ n
≤ m-1
.
A Sudoku-tábla egyes mezői segítő információkat (röviden infókat)
tartalmazhatnak. A feladvány megfejtése, azaz a Sudoku-megoldás a
bemenettel azonos méretű olyan négyzetes tábla, amelynek minden
mezője 1
és
m
közötti egészekkel van kitöltve úgy, 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 vannak. Emellett a Sudoku-megoldásnak az infók által
leírt feltételeknek is meg kell felelnie.
Az infó legegyszerűbb esete a száminfó, amely egy 1
és m
közötti egész érték. Ebben az esetben a
Sudoku-megoldásban az adott mezőbe a megadott számértéknek kell kerülnie.
Az infók másik fajtája a távolságinfó, amely kétféle lehet: s
és w
. Az előbbi azt írja le, hogy az adott mező
értéke n
távolságra van az alatta - azaz tőle délre (south) -
levő mező értékétől, míg az utóbbi ugyanezt állítja az adott mező bal
oldali - azaz tőle nyugatra (west) levő - szomszédjáról. Két érték
távolságán különbségük abszolút értékét értjük.
A feladvány az összes lehetséges távolságinfót tartalmazza. Tehát ha a
Sudoku-feladvány egy mezője nem tartalmazza az s
(w
) infót, akkor biztos, hogy az adott mező és a déli
(nyugati) szomszédja közötti távolság n
. Másszóval egy
Sudoku-megoldás nem megfelelő, ha egy olyan oldalszomszédos mezőpárt
tartalmaz, amelyek távolsága n
, és ugyanakkor a pár északi
(keleti) mezője a feladványban nem tartalmazza az s
(w
) távolságinfót.
Egy mezőben egyfajta infóból legfeljebb egy lehet, tehát egy mezőre 0, 1, 2 vagy 3 infó vonatkozhat.
Három Sudoku-feladványt mutatunk az 1. ábrán, amelyek paraméterei
rendre k = 3, n = 2
; k = 2, n = 1
; és k = 3, n = 3
.
Az 1. ábrán látható három feladvány megoldását a 2. ábra mutatja. Mindhárom feladványnak ez az egyetlen megoldása. Általános esetben természetesen egy feladvány megoldásainak száma lehet 0, 1, vagy több.
Írjon sudoku
néven olyan Prolog-eljárást, ill.
Erlang-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(N,T)
felépítésű struktúra, ahol
N
a távolságkonstans,T
a sorok listájaként megadott négyzetes tábla, ahol
egy sor a benne levő mezők listája.T
lista hossza M
, és minden elemének a hossza
is M
. Itt M
egy négyzetszám, azaz M =
K*K
, ahol K
a Sudoku-cella mérete.
A feladvány egyes mezőiben infók esetleg üres listája áll. Egy infó az
s
vagy a w
atom, illetve az 1 ≤ I ≤
M
szám lehet. Az infók listájában az elemek sorrendje tetszőleges.
A Prolog-eljárás kimenő paramétere a feladvány egy megoldása, amely számokat tartalmazó listák listájaként van ábrázolva.
Például az 1. ábra középső feladványát a következő Prolog-struktúrával írjuk le:
s(1, [[ [s], [], [], [s]], [ [], [], [], []], [ [], [s], [s,w], []], [ [4], [], [w], []]])
A feladvány egyetlen megoldását a következő lista írja le:
[[ 2, 4, 1, 3], [ 3, 1, 4, 2], [ 1, 3, 2, 4], [ 4, 2, 3, 1]]
Az Erlang-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 Erlang-függvény paramétere egy {N,T}
pár, ahol N
és T
jelentése azonos a Prolog-eljárás N
és
T
struktúraelemeinek a jelentésével. Jelölje M
most is a K*K
értéket.
A feladvány egyes mezőiben infók esetleg üres listája áll. Egy infó
az s
vagy w
atom, illetve az 1 ≤ I ≤
M
szám lehet. Az infók listájában az elemek sorrendje itt is
tetszőleges.
Az Erlang-függvény eredménye a feladvány összes megoldásának listája, ahol mindegyik megoldás számokat tartalmazó listák listájaként van ábrázolva.
Például az 1. ábra középső feladványát a következő Erlang-párral írjuk le:
{1, [[ [s], [], [], [s]], [ [], [], [], []], [ [], [s], [s,w], []], [ [4], [], [w], []]]}
A feladvány összes megoldását tartalmazó egyelemű lista a következő:
[[[ 2, 4, 1, 3], [ 3, 1, 4, 2], [ 1, 3, 2, 4], [ 4, 2, 3, 1]]]
| ?- sudoku(s(1, [[[s], [], [],[s]], [ [], [], [], []], [ [],[s], [s,w], []], [ [], [], [w], []] ] ), Table). Table = [[3,1,4,2], [2,4,1,3], [4,2,3,1], [1,3,2,4]] ? ; Table = [[2,4,1,3], [3,1,4,2], [1,3,2,4], [4,2,3,1]] ? ; no | ?- sudoku(s(1, [[[s], [], [],[s]], [ [], [], [], []], [ [],[s], [s,w], []], [[4], [], [], []] ] ), Table). no
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(dist, board).
% :- type dist == int.
% :- type field == list(info).
% :- type info ---> s; w; int.
% :- type board == list(list(field)).
% :- type ssol == list(list(int)).
% sudoku(SSpec, SSol):
% SSol az SSpec feladványt kielégítő megoldás.
% :- pred sudoku(sspec::in, ssol::out).
A sudoku:sudoku/1
Erlang-függvény típusát a következő -
megjegyzésként megadott - Erlang-típusdefiníciók írják le.
%% @type sspec() = {dist(), board()}.
%% @type dist() = integer().
%% @type field() = [info()].
%% @type info() = s | w | integer().
%% @type board() = [[field()]].
%% @type ssol() = [[integer()]].
%% @spec sudoku:sudoku(SSpec::sspec()) -> SSols::[ssol()].
%% @doc SSols az SSpec feladványt kielégítő megoldások listája.
A programot tartalmazó modul attribútumai ezek legyenek:
-module(sudoku). -author(email@unit.org.hu). -vsn('year-mm-dd'). -export([sudoku/1]).
Programjait keretprogramok segítségével próbálhatja ki. A keretprogramokat a beadáskor használthoz hasonló tesztesetekkel együtt innen töltheti le. 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
Sudoku-feladvány távolságkonstansát, minden egyes további nem üres sora a
Sudoku-feladvány egy-egy sorát tartalmazza, ahol az egyes mezők értékét egy
vagy több szóköz választja el. A -
karakter jelzi, ha egy
mező nem tartalmaz infót. Ha tartalmaz, az infókat tetszőleges sorrendben
adhatjuk meg; a mezőhöz tartozó infók között nem lehet szóköz.
Például az 1. ábra közepső Sudoku-feladványát a 3. ábrán látható módon ábrázolhatjuk a bemeneti szövegfájlban:
1 s - - s - - - - - s sw - 4 - w -3. ábra
A keretprogram kimenete a 4. ábrán bemutatotthoz hasonló tartalmú szövegfájl.
----- 2 4 1 3 3 1 4 2 1 3 2 4 4 2 3 1 -----4. ábra
A ksudoku.pl
Prolog-keretprogram a következő négy eljárást
exportálja:
sudoku_be(file::in, sspec::out)
sudoku_ki(file::in, ssol::in)
megold(file::in, file::in)
sudoku/2
eljárást.stopper(file::in, file::in)
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/10s/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/10s/ksudoku.pl in module sudoku_keret, 15 msec 29792 bytes yes | ?- stopper('teszt0.txt','teszt0.sol').
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.
A ksudoku.erl
Erlang-keretprogram a következő négy függvényt
exportálja:
@spec ksudoku:sudoku_be(FileIn::string()) -> SSpec::sspec()
SSpec
a FileIn
szövegfájlból beolvasott
Sudoku-feladvány.@spec ksudoku:sudoku_ki(FileOut::string(), SSols::[ssol()]) -> void()
SSols
listában átadott Sudoku-megoldásokat kiírja a
FileOut
szövegfájlba.@spec ksudoku:megold(FileIn::string(), FileOut::string()) -> void()
FileIn
szövegfájlból és összes
megoldását kiírja a FileOut
szövegfájlba. Ehhez felhasználja
a sudoku:sudoku/1
függvényt.@spec ksudoku:stopper(FileIn::string(), FileOut::string()) -> void()
ksudoku:megold/2
, de a végén kiírja a
FileIn
nevét, a megoldások számát és a futási időt is.
Használat: saját sudoku.erl
nevű programját
minden változtatás után fordítsa le,
és sudoku.beam
néven rakja a keretprogrammal
azonos mappába, különben a ksudoku.erl
keretprogram nem
találja meg. Ezután indítsa el az Erlang interpretert, és töltse be a
lefordított keretprogramot. Példa:
Eshell V5.6.3 (abort with ^G) 1> l(ksudoku). {module,ksudoku} 2> ksudoku:stopper("teszt0.txt","teszt0.sol").
A keretprogram automatikusan betölti a sudoku.beam
programot,
feltéve, hogy a keretprogrammal azonos mappában van.
Ha a saját sudoku.erl
programját módosítja, a lefordítása után
betöltheti az l(sudoku). paranccsal, de újra betöltheti a
ksudoku.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. 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.
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 Erlang/OTP R12B 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.
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ó 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.
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.