[Prolog]論理パズル/条件から住人と部屋の位置を推定する問題

【論理パズル4】http://twitter.com/puzzlegiver_bot/status/274468300510089216
ベタ書き。部屋は行列にした方が「右側」などを綺麗に実装できる。

【論理パズル4】http://twitter.com/puzzlegiver_bot/status/274468300510089216
ベタ書き。部屋は行列にした方が「右側」などを綺麗に実装できる。

:- op(700, xfx, ∈).
∈(X, Y) :- contains(Y, X).

contains([Val|_], Val).
contains([_|Tail], Val) :- contains(Tail, Val).

部分集合([], _).
部分集合([E|L], R) :- E ∈ R, 部分集合(L, R).
集合同値(L, R) :- 部分集合(L, R), 部分集合(R, L).

階層(Room, 0) :- Room ∈ [g, h, i].
階層(Room, 1) :- Room ∈ [d, e, f].
階層(Room, 2) :- Room ∈ [a, b, c].
右隣(a, b). 右隣(b, c).
右隣(d, e). 右隣(e, f).
右隣(g, h). 右隣(h, i).
左隣(L, R) :- 右隣(R, L).
隣(X, Y) :- 右隣(X, Y) ; 左隣(X, Y).
右側(X, Y) :- X ∈ [a, d, g], Y ∈ [b, c, e, f, h, i].
右側(X, Y) :- X ∈ [b, e, h], Y ∈ [c, f, i].
左側(X, Y) :- 右側(Y, X).
真下(a, d). 真下(b, e). 真下(c, f).
真下(d, g). 真下(e, h). 真下(f, i).
真上(D, U) :- 真下(U, D).
上階(X, Y) :- 階層(X, XRank), 階層(Y, YRank), XRank > YRank.

?-	A = [Akamatsu, Aoki, Kihara, Shirasawa, Kuroi, Haitani, Kaneco, Nobody0, Nobody1],
	右側(Haitani, Kuroi),
	上階(Kihara, Aoki),
	左隣(Akamatsu, _), 右隣(Akamatsu, _),
	左側(Kaneco, Aoki),
	隣(Kihara, Shirasawa),
	階層(Haitani, 2),
	隣(Kuroi, X1),
	隣(Akamatsu, X2),
	真上(Kaneco, X3),
	集合同値([X1, X2, X3], [Nobody0, Nobody1]),
	\+(真上(Aoki, Shirasawa)),
	\+(真下(Kihara, Akamatsu)),
	\+(隣(Kaneco, Shirasawa)),
	\+(隣(Haitani, Shirasawa)),
	集合同値(A, [a, b, c, d, e, f, g, h, i]). 
/*

A:
[h,d,b,c,e,a,i, g,f]
[h,d,b,c,e,a,i, f,g]
[h,d,b,c,e,a,i, g,f]
[h,d,b,c,e,a,i, f,g]

すなわち
A: ハイタニ, B: キハラ,   C: シラサワ,
D: アオキ,   E: クロイ,   F: (空),
G: (空),     H: アカマツ, I: カネコ,
*/