Получение всех комбинаций цветов в списке? - PullRequest
1 голос
/ 30 апреля 2020

У меня есть три возможных цвета: красный, зеленый, синий.

У меня есть начальный список: [синий, синий, синий, синий].

Мне по сути нужно создать поиск алгоритм, который находит заданный список Find (который также является списком, содержащим четыре цвета). Вот как выглядит скелет алгоритма поиска:

look(Find):- search([red, red, red, red], Find).

search([A,B,C,D], [A,B,C,D]):- do-something(A,B,C,D).

search(Node, Find):-
  successor(Node, Next),
  search(Next, Find).

Моя проблема с определением successor. Как я могу найти преемника, которого, я уверен, я не посещал раньше, пока не найду тот, который равен списку Find - особенно когда я не использую домен ({красный, синий, зеленый}) в предикате , Любая помощь приветствуется. Спасибо!

1 Ответ

1 голос
/ 30 апреля 2020

Вы можете легко сгенерировать все возможности из 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.

Теперь вы можете используйте это, чтобы найти следующее состояние из текущего.

...