:- dynamic kor/2.

	/*A dynamic-ra csak a "saját" kigyujt illetve kiirat eljárás miatt van
	szükség, a beépített setof, bagof, findall ezt nem igényli!!*/

kor(jani,6).
kor(jozsi,4).
kor(judit,7).
kor(jani,6).
kor(marci,6).
kor(gizi,6).
kor(jeno,3).
kor(mari,5).
kor(jani,6).
kor(gizi,6).
kor(jakab,4).
kor(eva,6).
kor(jani,5).
kor(dezso,3).


	/*  Variációk a bagof-setof-findall beépített predikátumokra*/

/*

FIGYELEM!! Most csak próbálgatásokról van szó - próbálja is ki az egyes 
eljárásokat. "Éles" programban nem szabad ilyen csúnyán kiiratni az eredményt!
*/


proba1 :- bagof(Nev,kor(Nev,6),Hatevesek), writeln(Hatevesek).

proba2 :- setof(Nev,kor(Nev,6),Hatevesek), writeln(Hatevesek).

proba3 :- findall(Nev,kor(Nev,6),Hatevesek), writeln(Hatevesek).

	/*Ezeket vettük gyakorlaton, de nem árt ismét végiggondolni!
	A bagof, findall az összes hatévest kigyűjti a megtalálás sorrendjében,
	a többszörös adatot többször veszi figyelembe.
	A setof minden adatot csak egyszer vesz figyelembe, és az adatokat
	rendezett módon (növekvő sorrendbe) rakja a listába.

	Feladat: próbálja ki a kétéveseket! Figyelje meg a különbségeket!
	(A findall üres listát ad eredményül, a másik kettő "No"-t.)
	*/



	/* Természetesen beépített predikátumok nélkül is megoldható 
	a feladat - ha mi magunk megírjuk az eljárást, pl. így:
	(másképpen is lehetne!)
	Megoldható pusztán listakezeléssel is, de talán egyszerűbb, ha az
	assert-retract predikátumokkal dolgozunk.
	Az assert(tény) beszúr egy tényállítást az adatbázisba (beszúrhat szabályt is,
	de mostani feladatunkhoz erre nincs szükség).
	A retract(tény) pedig kitöröl egy tényállítást az adatbázisból (ez is törölhet szabályt is,
	de most arra sincs szükség).


	Egy lehetséges "saját" ejárás:
	*/

proba4 :- gyujt(6,Hatevesek), writeln(Hatevesek).

gyujt(Ev,Nevek) :- kigyujt(Ev,Nevek), visszair.
	
kigyujt(Ev, [Nev|T]) :- kor(Nev,Ev), retract(kor(Nev,Ev)), 
	assert(temp(Nev,Ev)),kigyujt(Ev,T).
kigyujt(_,[]).

	/* Gondolja végig, miért hibás a

	kigyujt(Ev, [Nev|T]) :- kor(Nev,Ev), kigyujt(Ev,T).
	kigyujt(_,[]).
	
	eljárás!
	(Ha nem tudja végiggondolni, próbálja ki! 
	Meg kell akadályozni, hogy mindig ugyanazt az adatot vegye elő,
	ezért töröljük ki azt az adatot, amelyet már megvizsgáltunk.
	Ha később már nincs szükség ezekre az adatokra, akkor 
	nem kell az assert, ha azonban még később is szükségünk van a 
	"kor" adatokra, akkor a kitörölt "kor" adatot ideiglenesen átrakjuk
	egy másik szerkezetű adatba, majd az eljárás után gondoskodunk róla, 
	hogy visszairjuk az eredeti alakba.
	*/

visszair :- temp(Nev,Ev), retract(temp(Nev,Ev)), 
	assert(kor(Nev,Ev)), fail.
visszair.

	/* A fail azonosan hamis predikátum. "Átrázzuk" vele a Prologot, de 
	sok esetben - pl. itt is - ciklust lehet szervezni a segitségével.
	A visszair pl. a következőképpen működik:
	Vesz egy adatot, kitörli, beszúrja a kor szerkezetű adatok közé, 
	majd a fail miatt hamisan zárulna a szabály, ezért visszalép, 
	vesz egy újabb adatot (mert ez az első - és jelenleg 
	egyetlen - visszalépési pont), azt is átrakja, de a fail miatt ismét
	visszalép egészen addig, amig van újabb adat. 
	Ha már nincs, akkor a szabályfej (visszair) a kovetkező visszalépési 
	pont, ezért rátér a második szabályra.
	Sohase felejtse el lezárni a szabályt!!


	További megjegyzés: Gondolja végig, hogy ez a megoldás melyiknek 
	felel meg, a bagof/3-nak vagy a setof/3-nak?
	Hogyan lehetne megoldani a másikat?
	*/



	/*Ha csak kiiratni akarjuk, de nem akarjuk tárolni a hatévesek névsorát,
	akkor így is megoldhatjuk:
	*/


proba5 :- writeln('Hatévesek:'), kiirat(6).


kiirat(Ev) :- kor(Nev,Ev), writeln(Nev), fail.
kiirat(_).

	/*Vagy még egszerűbben:
		kiirat(Ev) :-  forall(kor(Nev,Ev), writeln(Nev)).
	*/	


	/* További variációk :) */


proba6 :- bagof(Nev,kor(Nev,6),Hatok), sort(Hatok,Hatevesek),
	writeln(Hatevesek).

	/*A setof/3 tulajdonképpen egy bagof/3 és egy sort/2 egymás után.
	Nézze meg a help-ben a sort eljárást! (Egy listából rendezett listát 
	készít, a többszörös előfordulást kihagyva.)

	Természetesen nem csak a bagof-fal együtt lehet használni,
	hanem bármilyen rendezési feladatnál :))

	FONTOS: ez a megoldás egyáltalán nem elegáns, az igazi ez:
	proba6 :- setof(Nev,kor(Nev,6),Hatevesek),writeln(Hatevesek).

	csak szerettem volna, ha meg is tapasztalják a fent leírtakat.
	*/



proba7 :- writeln('Koronkénti kigyűjtés:'), kiirat.

kiirat :- kor(_,Ev), setof(Nev, kor(Nev,Ev), Nevek), 
	  writef('%w évesek:\n',[Ev]),
	  writeln(Nevek), torol(Ev), kiirat.
kiirat :- visszair.

torol(Ev) :- kor(Nev,Ev),  retract(kor(Nev,Ev)),
	assert(temp(Nev,Ev)), torol(Ev).
torol(_).

	/*Veszi az adatbázis első adatát, kikeresi a vele azonos "évű" emberek
	nevét - berakja a Nevek listába, majd kitörli a vizsgált korú embereket.
	Mivel később is szükségünk van a "kor" adatokra, ezért vissza is 
	kell majd iratni.
	Ha később már nem lenne rájuk szükség, akkor egyszerűbb a 
	beépített retractall(kor(_,Ev)) paranccsal törölni.
	Szépséghiba: az életkorok nem nagyság szerint, hanem az 
	adatbázisban elfoglalt helyük szerint következnek egymás után.
	*/

proba7_mas :- writeln('Koronkénti kigyűjtés:'),
	      setof(Nev, kor(Nev,Ev), Nevek), 
	      writef('%w évesek:\n',[Ev]),
	      writeln(Nevek), torol(Ev), fail.
proba7_mas:- visszair.



proba8 :- writeln('Koronkénti kigyűjtés:'), 
	setof((Ev,Nevek),setof(Nev, kor(Nev,Ev),Nevek), Csoportok),
	writeln(Csoportok).

	/*Az eddigiek alapján próbálja meg végiggondolni az egymásba
	ágyazott setof-okat.
	Szépséghiba: Csúnya a Csoportok kiiratása.
	Feladat: 
	1. irassa ki ugyanúgy, mint a proba7.
	2. irassa ki szebben, pl.
	7 évesek:
		jeno
		judit
	6 évesek:
		stb...
	Megjegyzés: mindkét esetben csak a Csoportok kiiratására kell
	külön eljárás.
	*/



proba9 :- writeln('Az adatbázisban szereplő emberek: '), 
	findall(Nev, kor(Nev,_), Nevek),
	writeln(Nevek).



proba10 :- writeln('Az adatbázisban szereplő emberek: '), 
	setof(Nev, kor(Nev,_), Nevek),
	writeln(Nevek).
	
	/* Figyelje meg a proba9-proba10 közötti különbséget!
	A setof most csak a legidősebbeket irja ki!
	(Megjegyzés: most a legidősebbeket írja ki, de nincs garancia 
	arra, hogy milyen sorrendben próbál értéket adni a szabad változónak.
	Csak ennyi mondható: az Év számára vesz egy, az adatbázisban lévő 
	értéket, és az ehhez az értékhez tartozó neveket gyűjti ki.

	Gondolja végig, hogy miért! Ha nem jön rá, nézze meg ismét 
	a proba7, proba8 szabályokat!
	*/


proba11 :- writeln('Az adatbázisban szereplő emberek: '), 
	setof(Nev, Ev^kor(Nev,Ev), Nevek),
	writeln(Nevek).

	/*A ^ jelentése: van olyan. Vagyis az 
	Ev^kor(Nev,Ev) jelentése: 
	van olyan Ev, amelyre kor(Nev,Ev) igaz, azaz
	van olyan Ev, amelyre a kor(Nev,Ev) szerepel az adatbázisban.
	Ez az eljárás tehát kigyűjti a Nevek nevű listába az összes olyan
	Nev-et, aki szerepel az adatbázisban, mégpedig a setof szabályai 
	alapján, azaz növekvő sorrendben és minden adatot csak egyszer.
	Hasonlítsa össze a kapott eredményt a proba9 eredményével!
	*/