【问题标题】:Getting all the combinations of colors in a list?获取列表中的所有颜色组合?
【发布时间】:2020-04-30 14:48:17
【问题描述】:

我有三种可能的颜色:红色、绿色、蓝色。

我有一个初始列表:[blue, blue, blue, blue]。

我基本上需要创建一个搜索算法来查找给定列表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 的继任者 - 特别是当我没有在谓词中使用域({red, blue, green})时.任何帮助表示赞赏。谢谢!

【问题讨论】:

    标签: search prolog logic


    【解决方案1】:

    您可以使用member/2maplist/2 轻松生成4 种颜色的所有可能性:

    % 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.
    

    现在您可以使用它从当前状态中查找下一个状态。

    【讨论】:

    • 感谢您的回复。这是一个很酷的技巧。我还有两个额外的问题:首先,有没有不使用 maplist 的简单方法?其次(更重要的是),我如何在我的后继谓词中暗示这一点,以使已检查的颜色组合不会再次被检查?谢谢。
    • 是的,您可以不使用maplist/2 来实现,但这可以通过硬编码L 的长度来完成,如上所示,或者通过滚动您自己的maplist/2 版本来完成,它会向下递归@987654330 @ 并通过调用member/2 将每个列表位置限制为一个值。这里没有什么可赢的。
    • 现在你有一个所有组合的“生成器”,你不需要递归调用 successor。您只需调用一个地图列表,然后验证颜色是否是您想要的。如果没有,验证失败,Prolog 回溯到地图列表并生成下一个颜色列表,然后再次验证,等等:search(X) :- generate_with_maplist(X), verify(X), format("Found solution ~q",[X]).
    • 不幸的是,我的意思是保持算法的骨架相同,并且只相应地定义后继者。这是一个简单的谓词,但我看不出它是如何简单地完成的。如果您对如何做到这一点有任何想法,我会很高兴听到他们的声音。尽管如此,你给我的解决方案很有趣,即使我不能使用它。再次感谢!
    • 添加了“下一个”谓词。这不是低效的,而是有效的。它还使用 CLP(FD)。在模计算中遇到了一些障碍,快疯了......
    猜你喜欢
    • 1970-01-01
    • 2013-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多