% Unsere Datenbasis.
veranstaltung(aaaa, 1).
veranstaltung(bbbb, 1).
veranstaltung(cccc, 1).
veranstaltung(dddd, 2).
veranstaltung(eeee, 3).
veranstaltung(ffff, 4).
veranstaltung(gggg, 5).
veranstaltung(hhhh, 6).
veranstaltung(iiii, 7).
veranstaltung(jjjj, 7).
veranstaltung(kkkk, 8).
veranstaltung(llll, 8).

% Wir definieren eine Ordnung auf den Veranstaltungen, damit wir sagen koennen, dass Permutationen
% wie [bbbb, aaaa] nicht beruecksichtigt werden sollen.
vor(V1, V2) :- veranstaltung(V1, T1), veranstaltung(V2, T2), T1 < T2.
vor(aaaa, bbbb).
vor(aaaa, cccc).
vor(bbbb, cccc).
vor(iiii, jjjj).
vor(kkkk, llll).


% Unser Haupt-Ziel. Jede Loesung dieser Formel ist ein gueltiger Wochenplan.
plan(Plan) :- tage(Plan), alleDrin(Plan), jedeNurEinmal(Plan).


% Idealerweise wollen wir GGGG nicht dienstags oder freitags legen.
optimalerPlan(Plan) :- plan(Plan), gNichtDiOderFr(Plan).


% Eine Woche besteht aus genau 5 Tagen, von denen jeder...
tage([Montag, Dienstag, Mittwoch, Donnerstag, Freitag]) :- tag(Montag), tag(Dienstag), tag(Mittwoch), tag(Donnerstag), tag(Freitag).


% ... eine bis drei Veranstaltungen hat, deren Typen kompatibel sind.
tag([V1]) :- veranstaltung(V1, _).
tag([V1, V2]) :- veranstaltung(V1, T1), veranstaltung(V2, T2), vor(V1, V2), typkompatibel(T1, T2).
tag([V1, V2, V3]) :- veranstaltung(V1, T1), veranstaltung(V2, T2), veranstaltung(V3, T3), vor(V1, V2), vor(V2, V3), typkompatibel(T1, T2), typkompatibel(T2, T3), typkompatibel(T1, T3).


% Typen sind kompatibel, wenn sie ungleich sind. Ausserdem sind 1/2 und 5/6 inkompatibel.
typkompatibel(T1, T2) :- T1 \= T2,  kompatibel(T1, T2), kompatibel(T2, T1).
kompatibel(T1, T2) :- (T1 =:= 1 -> T2 \= 2 ; true), (T1 =:= 5 -> T2 \= 6 ; true).


% Stelle sicher, dass jede Veranstaltung im Plan enthalten ist.
% Ob das wohl schoener geht? Ich hab zu lange kein Prolog mehr geschrieben.
alleDrin(Plan) :- drin(Plan, aaaa), drin(Plan, bbbb), drin(Plan, cccc), drin(Plan, dddd), drin(Plan, eeee), drin(Plan, ffff), drin(Plan, gggg), drin(Plan, hhhh), drin(Plan, iiii), drin(Plan, jjjj), drin(Plan, kkkk), drin(Plan, llll).

drin([Tag|_], Name) :- drin2(Tag, Name), !.
drin([_|Rest], Name) :- drin(Rest, Name).

drin2([Name|_], Name) :- !.
drin2([_|Rest], Name) :- drin2(Rest, Name).


% Stelle auch sicher, dass keine Veranstaltung mehr als einmal drin ist.
jedeNurEinmal([]).
jedeNurEinmal([Tag|Rest]) :- jedeNurEinmal2(Tag, Rest), jedeNurEinmal(Rest).

jedeNurEinmal2([], _).
jedeNurEinmal2([T|Ts], Rest) :- keineTermine(T, Rest), jedeNurEinmal2(Ts, Rest).

keineTermine(_, []).
keineTermine(Name, [Tag|Rest]) :- keinTermin(Name, Tag), keineTermine(Name, Rest).

keinTermin(_, []).
keinTermin(Name, [T|Ts]) :- Name \= T, keinTermin(Name, Ts).


gNichtDiOderFr([_, Dienstag, _, _, Freitag]) :- keineTermine(gggg, [Dienstag, Freitag]).
