% A problem posed by Daniel Ligett (eagle!harpo!decvax!wivax!ligett)
% Dan Ligett   decvax!wivax!ligett   Wang Institute, Tyngsboro MA 01879

% Uebersetzt und bearbeitet von E. Ehses
 
% Wem gehoert das Zebra?
%   
% Es gibt 5 Haeuser, jedes von einer anderen Farbe und von einem Menschen
% einer anderen Nationalitaet mit unterschiedlichem Haustier, Getraenk und
% Zigaretten bewohnt.

% Es gelten die folgenden Ausssagen:

%  1.  Der Englaender lebt im roten Haus.
% 2.  Der Spanier hat einen Hund.
% 3.  Im gruenen Haus trinkt man Kaffee.
% 4.  Der Ukrainer trinkt Tee.
% 5.  Das gruene Haus ist direkt rechts (von dir aus) neben dem
%     elfenbeinfarbenen Haus
% 6.  Der Winstons Raucher haelt einen Papagei
% 7.  Im gelben Haus werden Kools geraucht.
% 8.  Im mittleren Haus wird Milch getrunken
% 9.  Der Norweger lebt in dem ersten Haus links
%10.  Der Chesterfields-Raucher lebt in dem Haus neben dem Mann mit
%     dem Fuchs
%11.  Kools werden neben dem Haus, in dem das Pferd gehalten wird, geraucht.
%12.  Der Lucky Strike Raucher trinkt Orangensaft
%13.  Der Japaner raucht Gauloises
%14.  Der Norweger lebt neben dem blauen Haus

% Die Frage: Wem gehoert das Zebra?  Wer trinkt Wasser?

% Das "Programm"
% ==============

% loesung
%   Ermittlt die Loesung und gibt sie lesbar aus.
loesung:-
    raetsel(X),
    print_alles(X).

% raetsel(Haeuser)
%   Die Loesung sagt, was mit den Haeusern los ist.
raetsel(Haeuser):-
	%  Es gibt fuenf Haeuser mit unbekanntem Inhalt.
        length(Haeuser, 5),
	% Es muessen 16 Regeln erfuellt sein:
	foreach(between(1, 16, Nr), regel(Nr, Haeuser)).

% Die eigentlichen Regeln im Einzelnen
% ====================================

%  Der Englaender lebt im roten Haus.
regel(1, Haeuser):-
        member(H, Haeuser),
        farbe(H, rot),
        nation(H, 'Englaender').

%  Der Spanier hat einen Hund.
regel(2, Haeuser):-
	member(H, Haeuser),
	nation(H, 'Spanier'),
        tier(H, 'Hund').	

%  Im gruenen Haus trinkt man Kaffee.
regel(3, Haeuser):-
	member(H, Haeuser),
	farbe(H, 'gruen'),
	trank(H, 'Kaffee').

%  Der Ukrainer trinkt Tee.
regel(4, Haeuser):-
	member(H, Haeuser),
	nation(H, 'Ukrainer'),
	trank(H, 'Tee').

%  Das gruene Haus ist direkt rechts (von dir aus) neben dem
%  elfenbeinfarbenen Haus
regel(5, Haeuser):-
    links_rechts(Links, Rechts, Haeuser),
	farbe(Links, 'elfenbein'),
	farbe(Rechts, 'gruen').

%  Der Winstons Raucher haelt einen Papagei
regel(6, Haeuser):-
	member(H, Haeuser),
	tier(H, 'Papagei'),
	nikotin(H, 'Winston').

%  Im gelben Haus werden Kools geraucht.
regel(7, Haeuser):-
	member(H, Haeuser),
	farbe(H, 'gelb'),
	nikotin(H, 'Kools').

%  Im mittleren Haus wird Milch getrunken
regel(8, Haeuser):-
	mitte(Mitte, Haeuser),
	trank(Mitte, 'Milch').

%  Der Norweger lebt in dem ersten Haus links
regel(9, [H|_]):-
	nation(H, 'Norweger').

% Der Chesterfields-Raucher lebt in dem Haus neben dem Mann mit
% dem Fuchs
regel(10, Haeuser):-
	neben(H1, H2, Haeuser),
	nikotin(H1, 'Chesterfield'),
	tier(H2, 'Fuchs').

% Kools werden neben dem Haus, in dem das Pferd gehalten wird, geraucht.
regel(11, Haeuser):-
	neben(H1, H2, Haeuser),
	nikotin(H1, 'Kools'),
	tier(H2, 'Pferd').

% Der Lucky Strike Raucher trinkt Orangensaft
regel(12, Haeuser):-
	member(H, Haeuser),
	nikotin(H, 'Lucky Strike'),
	trank(H, 'Orangensaft').

% Der Japaner raucht Gauloises
regel(13, Haeuser):-
	member(H, Haeuser),
	nation(H, 'Japaner'),
	nikotin(H, 'Gauloises').

% Der Norweger lebt neben dem blauen Haus
regel(14, Haeuser):-
	neben(H1, H2, Haeuser),
	nation(H1, 'Norweger'),
	farbe(H2, 'blau').

% Das Haus mit dem Zebra
regel(15, Haeuser):-
	member(H, Haeuser),
	tier(H, 'Zebra').

% Das Haus mit dem Wasser 
regel(16, Haeuser):-
	member(H, Haeuser),
	trank(H, 'Wasser').


% Praedikate zur lesbaren Problembeschreibung
% ===========================================

% Ein Haus und seine Eigenschaften.
%   haus(Farbe, Nation, Tier, Trank, Nikotin)
farbe(haus(Farbe, _, _, _, _), Farbe).
nation(haus(_, Nation, _, _, _), Nation).
tier(haus(_, _, Tier, _, _), Tier).
trank(haus(_, _, _, Trank, _), Trank).
nikotin(haus(_, _, _, _, Nikotin), Nikotin).

% links_rechts(A, B, Haeuser)
%   das Haus A steht in der Reihe der 5 Haeuser links von B
links_rechts(A,B, Haeuser):- append(_, [A,B|_], Haeuser).

% neben(A, B, Haeuser)
%   das Haus A steht in der Reihe der 5 Haeuser neben B
neben(A,B, Haeuser):- links_rechts(A,B, Haeuser).
neben(A,B, Haeuser):- links_rechts(B,A, Haeuser).

% mitte (A, Liste)
%   A steht in der Mitte der Liste.
mitte(A, L):-
    append(Li, [A|Re], L),
    length(Li, N),
    length(Re, N).

% prozedurale Ausgabepraedikate
% =============================

% print_alles(Haeuser)
%    erzeugt eine lesbare Ausgabe aller Ergebnisse
print_alles(Haeuser) :-
    Haeuser = [A,B,C,D,E],
    writef('\nDie Loesung lautet:\n\n'),
    print_haus(1,A), nl,
    print_haus(2,B), nl,
    print_haus(3,C), nl,
    print_haus(4,D), nl,
    print_haus(5,E), nl,

    member(H_Zebra, Haeuser),
    tier(H_Zebra, 'Zebra'),
    nation(H_Zebra, ZebraBesitzer),
    writef('Das Zebra gehoert dem %d ',[ZebraBesitzer]),

    member(H_Wasser, Haeuser),
    trank(H_Wasser, 'Wasser'),
    nation(H_Wasser, WasserTrinker),
    writef('und der %d trinkt Wasser.\n\n', [WasserTrinker]).

% print_haus(N, Haus)
%   die Ausgabe fuer das N-te Haus
print_haus(N, haus(Farbe,Nation,Tier,Getraenk,Rauch)):-
    writef('Das %d. Haus ist %d. Dort lebt ein %d mit seinem %d.\n',
    	 [N,Farbe,Nation,Tier]),
    writef('Der %d trinkt %d und raucht %d.\n', [Nation, Getraenk, Rauch]).
