| BME Villamosmérnöki és Informatikai Kar
Műszaki informatika szak |
Nappali tagozat
2001/2002-es tanév, tavaszi félév
|
n*n mezőből álló négyzet alakú tábla, amelynek egyes
mezőiben 1 és m közötti számok szerepelnek. A feladat az, hogy
további 1 és m közötti számokat helyezzünk el a táblában úgy,
hogy az alábbi feltételek teljesüljenek:
1..m számok
mindegyike pontosan egyszer szerepel.
1,2,...m,1,2,...,m,... sorrendben követik egymást.
(n-2)*(n-2)
mezőből álló négyzettel.
Az 1. ábra egy feladványt ábrázol, a 2. ábra ennek (egyetlen) megoldását mutatja.
-----------------------\
2 |
/-------------------\ |
| 1 | |
| /-----------\ | |
| | | | |
| | /---\ | | |
| | | | | 1 |
| | \-------/ | |
| | | |
| \---------------/ |
| |
\-----------------------/ |
-----------------------\ 1 - - - 2 3 | /-------------------\ | | - 1 2 3 - | - | | /-----------\ | | | - | 3 1 2 | - | - | | | /---\ | | | | - | 2 | 3 - | - | 1 | | | \-------/ | | | 3 | - - - 1 | 2 | | \---------------/ | | 2 - - 1 3 - | \-----------------------/ |
|
1. ábra. Egy feladvány(n=6, m=3) |
2. ábra. A feladvány megoldása |
buvos_csiga 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
csiga(N, M, As)
felépítésű struktúra, ahol
N a négyzetes tábla mérete, azaz sorainak,
ill. oszlopainak a száma ( N >= 1);
M a csigavonal ciklusa, azaz az egy
sorban/oszlopban levő nem-üres mezők száma; minden sorban és oszlopban
az 1..M számok pontosan egyszer fordulnak elő (1 <= M
<= N)
As az előre kitöltött mezőket leíró lista. A lista egyes
elemei i(Sor,Oszlop,Érték) alakú struktúrák. Egy ilyen elem
azt írja elő, hogy a tábla Sor számú sorának Oszlop
számú oszlopában az Érték szám áll. Az As
lista a (Sor,Oszlop) párok szerint lexikografikusan
rendezett.
Az 1. ábrán bemutatott feladvány esetén például a Prolog-eljárás bemenő paramétere:
csiga(6, 3, [i(1,5,2),i(2,2,1),i(4,6,1)])
A Prolog-eljárás kimenő paramétere a kitöltött tábla. Ezt sorok
listájaként kell előállítani, ahol az egyes sorok egész számokból álló
listák. Ez utóbbi lista minden eleme a tábla egy mezőjét írja le: a 0
számérték jelenti az üres helyet, míg a nem-nulla I érték azt
jelenti, hogy az adott helyen az I szám áll.
A 2. ábrán látható megoldást írja le az alábbi lista:
[[1,0,0,0,2,3],
[0,1,2,3,0,0],
[0,3,1,2,0,0],
[0,2,3,0,0,1],
[3,0,0,0,1,2],
[2,0,0,1,3,0]]
Az SML-függvény paramétere egy (N, M, As)
hármas, ahol N és M jelentése azonos a
Prolog-eljárásnál leírtakkal, míg As egy lista, amelynek
elemei (Sor,Oszlop,Érték) alakú hármasok, amelyek jelentése
szintén azonos a Prolog-eljárásnál leírtakkal.
Az 1. ábrán bemutatott feladvány esetén például az SML-függvény paramétere:
(6, 3, [(1,5,2),(2,2,1),(4,6,1)])
Az SML-függvény eredménye egy olyan lista, amely a feladvány összes
megoldását tartalmazza, mégpedig minden megoldást pontosan
egyszer. Ha a feladatnak nincs megoldása, az eredmény az üres lista. Egy
megoldást a Prologgal azonos módon, listák listájaként kell megadni.
A 2. ábrán látható megoldást írja le például az alábbi (egyelemű) megoldás-lista:
[[[1,0,0,0,2,3],
[0,1,2,3,0,0],
[0,3,1,2,0,0],
[0,2,3,0,0,1],
[3,0,0,0,1,2],
[2,0,0,1,3,0]]
]
A buvos_csiga függvény paraméterének és eredményének
típusát a következő SML-típusdefiníciók írják le.
structure TCsiga =
struct
type meret = int (* 0 < meret *)
type ciklus = int (* 0 < ciklus <= meret *)
type sorszam = int (* 0 < sorszam <= meret *)
type oszlopszam = int (* 0 < oszlopszam <= meret *)
type ertek = int (* 0 < ertek <= ciklus *)
type adott_elem = sorszam * oszlopszam * ertek
type feladvany_leiro = meret * ciklus * adott_elem list
type ertek_vagy_ures = int (* ertek_vagy_ures = 0, ha ures,
egyebkent 0 < ertek_vagy_ures <= ciklus *)
type sor = ertek_vagy_ures list
type csigatabla = sor list
end
signature Csiga =
sig
(* buvos_csiga (N, M, (Sor,Oszlop,Ertek) list) = olyan lista, amelynek az
elemei (tetszőleges sorrendben) az összes olyan N méretű,
egymástól különböző táblák, amelyek mindegyike a felsorolt
(Sor,Oszlop,Ertek) hármasok által meghatározott M ciklusú
csigavonalat ír le
*)
val buvos_csiga : TCsiga.feladvany_leiro -> TCsiga.csigatabla list
end
A Csiga.buvos_csiga függvény feladvany_leiro
típusú paramétere mindenképpen kielégíti az alábbi feltételt:
load "Listsort";
fun helyes_feladvany_leiro(Meret, Ciklus, Adottak) =
let
fun helyes_adott_elem(Sor, Oszlop, Ertek) = 0 < Sor andalso
Sor <= Meret andalso 0 < Oszlop andalso Oszlop <= Meret andalso
0 < Ertek andalso Ertek <= Ciklus;
fun lexikografikusan_hasonlit ((x1,y1,_), (x2,y2,_)) =
if x1 < x2 orelse x1 = x2 andalso y1 < y2 then LESS
else if x1 > x2 orelse x1 = x2 andalso y1 > y2 then GREATER
else EQUAL
fun szomszedok_kulonbozok ((x1,y1,_)::(x2y2s as (x2,y2,_)::xys)) =
(x1 <> x2 orelse y1 <> y2) andalso szomszedok_kulonbozok x2y2s
| szomszedok_kulonbozok _ = true
in
0 < Meret andalso 0 < Ciklus andalso Ciklus <= Meret andalso
(* minden eleme helyes az Adottak listának: *)
(List.all (fn x => x) (map helyes_adott_elem Adottak)) andalso
(* az Adottak lista lexikografikusan rendezett: *)
Listsort.sorted lexikografikusan_hasonlit Adottak andalso
(* Az Adottak lista minden eleme különböző (Sor,Oszlop)
koordinátára vonatkozik (a rendezettség miatt elegendő
ezt a szomszédos elemekre kikötni): *)
szomszedok_kulonbozok Adottak
end
Az SML megoldásában tehát feltételezheti, hogy a bemenő argumentumra
a helyes_feladvany_leiro predikátum igazat ad eredményül (csak
ilyen adattal teszteljük majd a programot).
A buvos_csiga/2 Prolog-eljárás paramétereinek típusát a
következő - megjegyzésként megadott -
Prolog-típusdefiníciók írják le.
% :- type feladvany_leiro ---> csiga(meret, ciklus, list(adott_elem)). % :- type meret == integer. % :- type ciklus == integer. % :- type adott_elem ---> i(sorszam, oszlopszam, ertek). % :- type sorszam == integer. % :- type oszlopszam == integer. % :- type ertek == integer. % :- type csigatabla == list(sor). % :- type sor == list(ertek_vagy_ures). % :- type ertek_vagy_ures == integer. % :- pred buvos_csiga(feladvany_leiro::in, csigatabla::out).A
buvos_csiga/2 eljárás első, feladvany_leiro
típusú paramétere mindenképpen kielégíti az alábbi feltételt:
helyes_feladvany_leiro(csiga(Meret,Ciklus,Adottak)) :-
integer(Meret), integer(Ciklus),
Meret >= 1, Ciklus >= 1,
Ciklus =< Meret.
% nincs nem helyes eleme az Adottak listának:
\+ ( member(Adott, Adottak),
\+ helyes_adott_elem(Meret, Ciklus, Adott)
),
% az Adottak lista lexikografikusan rendezett:
sort(Adottak, Adottak),
% Az Adottak lista minden eleme különböző (Sor,Oszlop)
% koordinátára vonatkozik (a rendezettség miatt elegendő a
% szomszédos elemekre kikötni ezt):
\+ append(_, [i(S,O,_),i(S,O,_)|_], Adottak).
helyes_adott_elem(Meret, Ciklus, i(Sor,Oszlop,Ertek)) :-
integer(Sor), integer(Oszlop), integer(Ertek),
1 =< Sor, Sor =< Meret,
1 =< Oszlop, Oszlop =< Meret,
1 =< Ertek, Ertek =< Ciklus.
A Prolog megoldásában tehát feltételezheti, hogy a bemenő argumentumra a
helyes_feladvany_leiro/1 eljárás sikeresen lefut (csak ilyen adattal
teszteljük majd a programot).
A keretprogram bemenete egy olyan szöveges állomány, amelynek első két sora a feladványtábla mérete és a csigavonal ciklusa. Az ezt követő sorok mindegyikében három szám áll, amelyek az adott elemek sorszámát, oszlopszámát ill. értékét írják le (ld. 3. ábra, vö. 1. ábra).
6 3 1 5 2 2 2 1 4 6 1 |
| 3. ábra. A bemenő állomány tartalma az 1. ábrán látható feladvány esetén |
A keretprogram kimenete a 2. ábrán bemutatotthoz hasonló tartalmú szöveges állomány.
Az SML-keretprogram három függvényt exportál:
signature KCsiga =
sig
val csiga_be : string -> TCsiga.feladvany_leiro
val csiga_ki : string * TCsiga.csigatabla list -> unit
val megold : string * string -> string
end
csiga_be f
f szöveges állományból beolvasott adatokból képzett
feladványleíró.
csiga_ki(m, ms)
ms megoldáslistát olvasható formában kiírja az
m szöveges állományba.
megold(f, m)
f szöveges állományból és
kiírja az összes megoldást az m szöveges állományba.
Ehhez természetesen szüksége van a Csiga.buvos_csiga
függvényre. Eredménye az f nevet, a megoldások
számát és a futási időt mp-ben tartalmazó füzér.
/dev/stdin, ill. a /dev/stdout, MS-DOS alatt
mindkét esetben a con állománynév megadásával.
A Prolog-keretprogram három eljárást exportál:
csiga_be(file::in, feladvany_leiro::out)
csiga_ki(file::in, csigatabla::in)
megold(file::in, file::in)
buvos_csiga/2 eljárásra.
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 irathatunk ki adatokat.
Egyébként a megadott nevű állományba írunk, ill. állományból olvasunk.
A két programhoz közös dokumentációt készítsen - vagy magyarul, vagy angolul. A dokumentáció tartalma legalább a következő legyen:
A dokumentációt elektronikus formában adja be, HTML, esetleg ASCII formátumban.
A programok készülhetnek MS DOS vagy MS Windows alatt is, de Unix (linux)
alatt is működniük kell. A beadott programok tesztelése Unix környezetben a
SICStus Prolog ill. az MOSML rendszerekkel történik.
A programokat és az elektronikus dokumentációt tömörítve, elektronikus
levélben kell elküldeni egy bash szkript segítségével, amely
hamarosan letölthető lesz. Programját
egy 10-tagú tesztsorozattal automatikusan futtatjuk, és erről
válaszlevélben értesítjük. A beadást többször is megismételheti, a
legutolsóként beadott megoldást értékeljük.
A házi feladat beadása nem kötelező, de a DP nyelvek magasszintű elsajátításához nagy segítséget ad. Ezért javasoljuk, hogy a házi feladatot mindkét nyelven készítsék el és adják be. Mindazonáltal elfogadunk csak SML ill. csak Prolog nyelven készült megoldásokat, értelemszerűen felére csökkentett pontszámmal.
A programok és az elektronikus dokumentáció végső beadási határideje 2002. május 6-a, hétfő 24h.
Az értékelés a beadási tesztsorozathoz hasonló nehézségű tesztesetekkel történik. Az időkorláton belül helyes eredményt adó tesztesetek mindegyikére 0,5-0,5 pontot adunk. A 10 futásra ö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. Ha mindkét nyelvből beadja a házi feladatot, akkor tehát maximum 15 pontot kaphat (ez 15%-a a 100 pontos alappontszámnak).
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 pontos alappontszámon felül 15 pluszpontot kap.