あなたの基本的な考えは健全です。実際、必要なのはall_different/1
制約だけです。このパズルの面白いところは、立方体の表現方法です。私は率直なアプローチを採用し、リンク先のページに示されているのとほぼ同じ方法でキューブを表現します。たとえば、2D レイアウトが次の最初の立方体を表します。
b
r r r g
y
地面のプロローグ用語として:
tmb(b,[r,r,r,g],y)
ここtmb
で、立方体の「上、中、下」を表します。
最初に、次の 4 つのキューブが与えられます。
cube(tmb(b,[r,r,r,g],y)).
cube(tmb(r,[g,y,g,b],b)).
cube(tmb(r,[b,g,r,y],y)).
cube(tmb(g,[b,r,y,g],y)).
次の述語は、キューブを対象の側面に関連付けます。
side_cube(top, tmb(Top,_,_), Top).
side_cube(front, tmb(_,[_,Front|_],_), Front).
side_cube(bottom, tmb(_,_,Bottom), Bottom).
side_cube(back, tmb(_,[_,_,_,Back],_), Back).
ここで重要な点は、立方体の回転はどのように見えるかということです。
cube_rotation(Cube0, Cube) :-
cube_flip(Cube0, Cube1),
cube_rotation_(Cube1, Cube).
cube_rotation_(tmb(Top,[A,B,C,D],Bottom), tmb(Top,[E,F,G,H],Bottom)) :-
append(_, [E,F,G,H|_], [A,B,C,D,A,B,C]).
cube_flip(Cube, Cube).
cube_flip(tmb(Top,[A,B,C,D],Bottom), tmb(A,[Bottom,B,Top,D],C)).
cube_flip(tmb(Top,[A,B,C,D],Bottom), tmb(B,[A,Bottom,C,Top],D)).
演習cube_flip/2
:完全な解を得るには、 の 3 つの欠落している節を埋めてください。
CLP(FD) がなくても、ソリューションの記述が簡単になりました。
solution(Cs) :-
findall(C, cube(C), Cs0),
same_length(Cs0, Cs),
maplist(side_different(Cs), [top,front,bottom,back]),
maplist(cube_rotation, Cs0, Cs).
side_different(Cubes, Side) :-
maplist(side_cube(Side), Cubes, Colors),
all_dif(Colors).
all_dif([]).
all_dif([D|Ds]) :- maplist(dif(D), Ds), all_dif(Ds).
上記のコード (前述したように、演習として省略した 3 つの節がありません) を使用しても、既に 2 つの解決策が見つかります。
?- solution(Cubes).
Cubes = [tmb(r,[r,y,r,b],g),tmb(y,[g,b,g,r],b),tmb(b,[y,g,r,y],r),tmb(g,[b,r,y,g],y)] ;
Cubes = [tmb(r,[r,b,r,y],g),tmb(y,[g,r,g,b],b),tmb(b,[r,y,y,g],r),tmb(g,[y,g,b,r],y)] ;
false.
CLP(FD) を使用するには、単純にすべての色を整数にマップし、の代わりにall_different/1
(またはall_distinct/1
、より強力な伝播のために ) を使用しall_dif/1
ます。