Вы можете легко сгенерировать все возможности из 4 цветов, используя member/2
и maplist/2
:
% give me a list of 4 fresh variables
% select a member of [red,blue,green] for each item of L, backtrackably
length(L,4),
maplist([I]>>(member(I,[red,blue,green])),L).
Выше на самом деле то же самое, что и
L=[L0,L1,L2,L3],
member(L0,[red,blue,green]),
member(L1,[red,blue,green]),
member(L2,[red,blue,green]),
member(L3,[red,blue,green]).
Следите за комбинаторный взрыв.
В случае, если предпочтительнее «следующее без сохранения состояния».
Мы хотим получить следующую красно-зелено-голубую комбинацию из существующей!
Давайте использовать CLP (FD) для реализации биективного отображения между списком цветов и числами.
:- use_module(library(clpfd)).
rgbnumber(red,0).
rgbnumber(blue,1).
rgbnumber(green,2).
rgbnumberlist([L0,L1,L2],N) :-
rgbnumber(L0,N0), N0 in 0..2,
rgbnumber(L1,N1), N1 in 0..2,
rgbnumber(L2,N2), N2 in 0..2,
N #= N0+N1*3+N2*3*3.
rgbnext(Current,Next,Wrap) :-
rgbnumberlist(Current,N),
succ(N,Nx),
Nxm is (Nx mod (3*3*3)), % Beware precedence: mod is as strong as *
(Nx > Nxm -> Wrap = true ; Wrap = false),
rgbnumberlist(Next,Nxm).
И, таким образом:
?- rgbnext([red,red,red],A,Wrap).
A = [blue, red, red],
Wrap = false ;
false.
?- rgbnext([blue,red,red],A,Wrap).
A = [green, red, red],
Wrap = false ;
false.
?- rgbnext([green,red,red],A,Wrap).
A = [red, blue, red],
Wrap = false ;
false.
?- rgbnext([green,green,green],A,Wrap).
A = [red, red, red],
Wrap = true ;
false.
Теперь вы можете используйте это, чтобы найти следующее состояние из текущего.