好的,这是交易:
以下是代码:
mix([],[],_).
mix(P1,P2, Pile):-
takeshirt(P1,1,Taken1,Rem1), takeshirt(P2,1,Taken2,Rem2), #Take one
append(Pile,Taken1,New), append(New,Taken2,NewPile), #Put both of them
mix(Remain1,Remain2,NewPile).
这就是结果:
1 ?- mix([a,b],[c,d],NewPile).
NewPile = [] .
我希望它看起来像:
1 ?- mix([a,b],[c,d],NewPile).
NewPile = [b, d, a, c] .
或者无论结果如何。我通过图形化调试器进行了检查,发现当最后一次调用 mix 时,绑定是:
P1 = Taken1 = [b]
P2 = Taken2 = [c]
Pile = [a, d]
Rem1 = Rem2 = []
New = [a, d, b]
NewPile = [a, d, b, c] #<--- Interresting
所以当最终调用时,所需的值在NewPile中:
mix([],[],_).
发生。在此之后,它像一个纸牌屋一样崩溃。
所以问题是:
mix([],[],_).
我想从基本情况返回_值,此规则 mix 实际上是从更高的实例中使用,我发送两个堆并获得新的堆。
更新
为了澄清关于 takehirt 规则的一些评论,这里是:
takeshirt(_,0,[],_).
takeshirt(List,Number,[Element|Taken],Remain) :- N > 0,
length(List,Len),
Index is random(Len) + 1,
removeshirt_at(Element,List,Index,Remain),
Number1 is Number - 1,
takeshirt(Remain,Number1,Taken,Remain).
答案 0 :(得分:2)
请考虑对您的代码进行以下修改:
mix([], [], []) :- !.
mix(P1, P2, Pile) :-
takeshirt(P1, 1, Taken1, Rem1),
takeshirt(P2, 1, Taken2, Rem2),
append(Taken1, Taken2, Pile0),
mix(Rem1, Rem2, Pile1),
append(Pile0, Pile1, Pile).
似乎你需要累积'衬衫'(作为列表原子)。在这里,我们递归地将它们附加到mix/3
(Pile
)的第三个参数上,直到两个输入列表都是空列表时命中基本情况(第一个子句)(注意切割{{这里需要1}},因为第二个子句的绑定模式与第一个匹配,所以我们要排除它)。第二个子句的行为,每个步骤从每个输入列表中取一件衬衫,要求它们的长度必须相等。
为了测试这一点,我使用了!
的以下定义:
takeshirt/4
请注意,此处的第二个参数未使用,因为takeshirt(Ps, _, [P], Rem) :-
select(P, Ps, Rem).
用于从列表中获取单个元素(衬衫),并返回余数。 select/3
之后没有剪切(!
)允许此谓词在从列表中选择所有其他元素(衬衫)时回溯。如果我们现在使用此定义执行您的示例查询,我们可以得到:
select
......我们可以看到1 ?- mix([a,b],[c,d],NewPile).
NewPile = [a, c, b, d] ;
NewPile = [a, d, b, c] ;
NewPile = [b, c, a, d] ;
NewPile = [b, d, a, c] ;
false.
通过从第一堆(第一个输入列表)中取出一件衬衫,然后从第二堆(第二个输入列表)中取出一件衬衫,列举所有可能的“回合”。依此类推,直到两个输入列表都为空。如果您mix/3
的定义没有留下选择点,(非回溯),那么您只能获得一个解决方案(如果有的话)。