List 使用prolog再添加两个引用
我有一个列表List 使用prolog再添加两个引用,list,prolog,prolog-dif,logical-purity,prolog-toplevel,List,Prolog,Prolog Dif,Logical Purity,Prolog Toplevel,我有一个列表[a,b,a,a,a,c,c] 我需要为每个元素再添加两个引用 最终结果应如下所示: [a, a, a, b, b, b, a, a, a, a, a, c, c, c, c] % Case 1 dbl([],[]). % Case 2 dbl([X],[X,X,X]). % Case 3 dbl([X,X|Xs], [X|Ys]) :- % [...] recursion skipping the leading X % Case 4 dbl([X,Y|Xs], [X,X,
[a,b,a,a,a,c,c]
我需要为每个元素再添加两个引用
最终结果应如下所示:
[a, a, a, b, b, b, a, a, a, a, a, c, c, c, c]
% Case 1
dbl([],[]).
% Case 2
dbl([X],[X,X,X]).
% Case 3
dbl([X,X|Xs], [X|Ys]) :-
% [...] recursion skipping the leading X
% Case 4
dbl([X,Y|Xs], [X,X,X|Ys]) :-
dif(X,Y),
% [...] we inserted the copies, so recursion on [Y|Xs] and Ys
如果列表中有一个项目与下一个项目相同,那么它会一直运行,直到有一个新项目,当它找到新项目时,它会添加上一个项目的两个匹配项,然后继续
这是到目前为止我的代码,但我不知道如何添加两个
dbl([], []).
dbl([X], [X,X]).
dbl([H|T], [H,H|T], [H,H|R]) :- dbl(T, R).
您的代码看起来有点奇怪,因为最后一条规则包含三个参数。您只调用二进制版本,因此任何递归都不会尝试派生它 您已经有了一个好主意,可以查看列表中元素发生变化的部分。因此有4种情况: 1) 你的名单是空的。 2) 你只有一个元素。 3) 您的列表以两个相等的元素开始。 4) 您的列表以两个不同的元素开始 案例1未指定,因此您可能需要为此找到一个合理的选择。案例2在某种程度上类似于案例4,因为列表的结尾可以被视为元素中的一个更改,您需要附加两个副本,但之后就完成了。案例3非常简单,我们可以只保留元素并在其余元素上递归。案例4是您需要再次插入两份副本的情况 这意味着您的代码将如下所示:
[a, a, a, b, b, b, a, a, a, a, a, c, c, c, c]
% Case 1
dbl([],[]).
% Case 2
dbl([X],[X,X,X]).
% Case 3
dbl([X,X|Xs], [X|Ys]) :-
% [...] recursion skipping the leading X
% Case 4
dbl([X,Y|Xs], [X,X,X|Ys]) :-
dif(X,Y),
% [...] we inserted the copies, so recursion on [Y|Xs] and Ys
案例3应该很容易完成,我们只需从两个列表中删除第一个X,然后在dbl上递归([X | Xs],Ys)。请注意,我们通过两次写入同一变量隐式地使前两个元素相等(即,我们统一了它们)
如果你看案例4的开头,你可以直接模仿你描述的模式:假设列表以X开始,然后Y,它们是不同的(dif(X,Y)),X被重复3次而不是仅仅复制,然后我们继续从Y:dbl([Y | Xs],Ys]开始的递归
那么让我们试试谓词:
?- dbl([a,b,a,a,a,c,c],[a,a,a,b,b,b,a,a,a,a,a,c,c,c,c]).
true ;
false.
我们的测试用例被接受(true),并且我们没有找到多个解决方案(false)。
让我们看看是否找到了错误的解决方案:
?- dif(Xs,[a,a,a,b,b,b,a,a,a,a,a,c,c,c,c]), dbl([a,b,a,a,a,c,c],Xs).
false.
?- dbl(X,[a,a,a,b,b]).
false.
不,那也很好。如果列表中有变量,会发生什么
?- dbl([a,X,a],Ys).
X = a,
Ys = [a, a, a, a, a] ;
Ys = [a, a, a, X, X, X, a, a, a],
dif(X, a),
dif(X, a) ;
false.
X=a,则Ys为5 as的单次运行;或者X不等于a,那么我们需要在所有三次运行中追加副本。看起来也不错。(*)
现在让我们看看,如果我们只指定解决方案会发生什么:
?- dif(Xs,[a,a,a,b,b,b,a,a,a,a,a,c,c,c,c]), dbl([a,b,a,a,a,c,c],Xs).
false.
?- dbl(X,[a,a,a,b,b]).
false.
对,一个只运行两个bs的列表不可能是我们规范的结果。因此,让我们尝试添加一个:
?- dbl(X,[a,a,a,b,b,b]).
X = [a, b] ;
false.
万岁,成功了!作为最后一个测试,让我们看看如果我们用两个变量调用谓词会发生什么:
?- dbl(Xs,Ys).
Xs = Ys, Ys = [] ;
Xs = [_G15],
Ys = [_G15, _G15, _G15] ;
Xs = [_G15, _G15],
Ys = [_G15, _G15, _G15, _G15] ;
Xs = [_G15, _G15, _G15],
Ys = [_G15, _G15, _G15, _G15, _G15] ;
Xs = [_G15, _G15, _G15, _G15],
Ys = [_G15, _G15, _G15, _G15, _G15, _G15] ;
[...]
看起来我们得到了正确的答案,但我们只看到了一次运行的案例。这是prolog搜索策略的结果(我在这里不解释)。但是,如果我们在生成较长的列表之前先查看较短的列表,我们可以看到所有的解决方案:
?- length(Xs,_), dbl(Xs,Ys).
Xs = Ys, Ys = [] ;
Xs = [_G16],
Ys = [_G16, _G16, _G16] ;
Xs = [_G16, _G16],
Ys = [_G16, _G16, _G16, _G16] ;
Xs = [_G86, _G89],
Ys = [_G86, _G86, _G86, _G89, _G89, _G89],
dif(_G86, _G89) ;
Xs = [_G16, _G16, _G16],
Ys = [_G16, _G16, _G16, _G16, _G16] ;
Xs = [_G188, _G188, _G194],
Ys = [_G188, _G188, _G188, _G188, _G194, _G194, _G194],
dif(_G188, _G194) ;
[...]
因此,我们似乎有一个工作谓词(**),假设您填写了文本中缺少的目标:)
(*)这里有一句话:这个案例之所以有效,是因为我们使用的是dif。通常遇到的第一个相等谓词是=、==及其各自的否定\=和\==。=表示可统一性(替换参数s.t中的变量。变量变为相等),而==表示语法相等(术语完全相等)。例如:
这意味着,如果我们用a代替X,我们可以使f(X)等于f(a)。这意味着,如果我们问它们是否不能相等(\=),我们会得到错误的答案。另一方面,这两个项不相等,因此==返回false,其否定\==返回true
这也意味着X\==Y始终为真,因此我们不能在代码中使用\==。与此相反,dif等待直到它能够决定其参数是否相等。如果在找到答案后仍未决定,则打印“dif(X,a)”语句
(**)最后一句话:这里还有一个if-then-else构造(test->goals\u if\u true;goals\u if\u false)的解决方案,它合并了案例3和案例4。由于我更喜欢这个解决方案,您可能需要自己研究另一个版本
dbl([X,Y|T], [X,X,X|R]) :- X \= Y, !, dbl([Y|T], R).
dbl([H|T], R) :-
T = []
-> R = [H,H,H]
; R = [H|Q], dbl(T, Q).
第一个子句处理基本需求,添加了两个关于顺序更改的元素。
第二个将列表终止处理为序列更改,否则将执行纯拷贝。TL;DR:
从陈述的角度来看,这是完美的。
它的确定性可以在不牺牲的情况下得到改善
代码变体#0:@lambda.xy.x的代码 下面是我们要改进的代码: dbl0([], []). dbl0([X], [X,X,X]). dbl0([X,X|Xs], [X|Ys]) :- dbl0([X|Xs], Ys). dbl0([X,Y|Xs], [X,X,X|Ys]) :- dif(X, Y), dbl0([Y|Xs], Ys). 更好?有点,但确定性可能更好 代码变体#2:索引 为了让Prolog看到
dbl1\u3
的两个递归子句是互斥的(在某些情况下),我们具体化了
术语相等,然后根据该值编制索引:
这就是发挥作用的原因:
dbl2([], []).
dbl2([E|Es], Xs) :-
dbl2_(Es, Xs, E).
dbl2_([], [E,E,E], E).
dbl2_([E|Es], Xs, E0) :-
=(E0, E, T),
t_dbl2_(T, Xs, E0, E, Es).
t_dbl2_(true, [E|Xs], _, E, Es) :-
dbl2_(Es, Xs, E).
t_dbl2_(false, [E0,E0,E0|Xs], E0, E, Es) :-
dbl2_(Es, Xs, E).
dbl2([],[])。
dbl2([E|Es],Xs):-
dbl2(Es,Xs,E)。
dbl2_([],[E,E,E],E)。
dbl2|([E|Es],Xs,E0):-
(E0,E,T),
t_dbl2_(t,Xs,E0,E,Es)。
t_dbl2_(真,[E | Xs],_,E,Es):-
dbl2(Es,Xs,E)。
t_dbl2_(假[E0,E0,E0 | Xs],E0,E,Es):-
dbl2(Es,Xs,E)。
使用SWI Prolog的示例查询:
?- dbl0([a],Xs).
Xs = [a, a, a] ;
false.
?- dbl1([a],Xs).
Xs = [a, a, a].
?- dbl2([a],Xs).
Xs = [a, a, a].
?- dbl0([a,b,b],Xs).
Xs = [a, a, a, b, b, b, b] ;
false.
?- dbl1([a,b,b],Xs).
Xs = [a, a, a, b, b, b, b] ;
false.
?- dbl2([a,b,b],Xs).
Xs = [a, a, a, b, b, b, b].
?-dbl0([a],Xs)。
Xs=[a,a,a];
错。
?-dbl1([a],Xs)。
Xs=[a,a,a]。
?-dbl2([a],Xs)。
Xs=[a,a,a]。
?-dbl0([a,b,b],Xs)。
Xs=[a,a,a,b,b,b,b];
错。
?-dbl1([a,b,b],Xs)。
Xs=[a,a,a,b,b,b,b];
错。
?-dbl2([a,b,b],Xs)。
Xs=[a,a,a,b,b,b,b]。
要使上述代码更紧凑,请使用控件构造。我正准备将此版本与@repeat合并使用时,我看到@repeat已经建议了它。因此,这本质上是@repeat所概述的更紧凑的版本:
list_dbl([],[]).
list_dbl([X],[X,X,X]).
list_dbl([A,B|Xs],DBL) :-
if_(A=B,DBL=[A,B|Ys],DBL=[A,A,A,B|Ys]),
list_dbl([B|Xs],[B|Ys]).
?- list_dbl([a],DBL).
DBL = [a,a,a]
?- list_dbl([a,b,b],DBL).
DBL = [a,a,a,b,b,b,b]
它通过@repeat产生与dbl2/2相同的结果:
list_dbl([],[]).
list_dbl([X],[X,X,X]).
list_dbl([A,B|Xs],DBL) :-
if_(A=B,DBL=[A,B|Ys],DBL=[A,A,A,B|Ys]),
list_dbl([B|Xs],[B|Ys]).
?- list_dbl([a],DBL).
DBL = [a,a,a]
?- list_dbl([a,b,b],DBL).
DBL = [a,a,a,b,b,b,b]
OP的示例查询按预期工作:
?- list_dbl([a,b,a,a,a,c,c],DBL).
DBL = [a,a,a,b,b,b,a,a,a,a,a,c,c,c,c]
此外,这里还有@lambda.xy.x提供的一些示例查询。它们产生的结果与@repeat的dbl/2和@lambda.xy.x的dbl/2相同:
?- dif(Xs,[a,a,a,b,b,b,a,a,a,a,a,c,c,c,c]), list_dbl([a,b,a,a,a,c,c],Xs).
no
?- list_dbl(X,[a,a,a,b,b]).
no
?- list_dbl(L,[a,a,a,b,b,b]).
L = [a,b] ? ;
no
?- list_dbl(L,DBL).
DBL = L = [] ? ;
DBL = [_A,_A,_A],
L = [_A] ? ;
DBL = [_A,_A,_A,_A],
L = [_A,_A] ? ;
DBL = [_A,_A,_A,_A,_A],
L = [_A,_A,_A] ? ;
...
?- list_dbl([a,X,a],DBL).
DBL = [a,a,a,a,a],
X = a ? ;
DBL = [a,a,a,X,X,X,a,a,a],
dif(X,a),
dif(a,X)
?- length(L,_), list_dbl(L,DBL).
DBL = L = [] ? ;
DBL = [_A,_A,_A],
L = [_A] ? ;
DBL = [_A,_A,_A,_A],
L = [_A,_A] ? ;
DBL = [_A,_A,_A,_B,_B,_B],
L = [_A,_B],
dif(_A,_B) ? ;
DBL = [_A,_A,_A,_A,_A],
L = [_A,_A,_A] ?
嗯,这个列表应该是一个普通的序言列表,t