List 序言:第一个重复值
我需要在列表中找到第一个重复的值List 序言:第一个重复值,list,prolog,prolog-dif,List,Prolog,Prolog Dif,我需要在列表中找到第一个重复的值 prep(3[1,3,5,3,5])。应为真 prep(5[1,3,5,3,5])。应为false 我想检查是否与当前值和以前的列表成员相等,直到我找到一个重复的,如果它找到一个,它将测试是否与X相等,但我不知道如何在Prolog中做到这一点 谢谢你的帮助!谢谢不确定这是否是家庭作业/允许使用哪些谓词有限制,但这会让prolog为您执行递归 上面写着。。查找所有重复的IE。其中存在一个带有列表索引I1的项目,而另一个则具有I2,使得它们都具有相同的值N,并且索引
prep(3[1,3,5,3,5])。
应为真
prep(5[1,3,5,3,5])。
应为false
我想检查是否与当前值和以前的列表成员相等,直到我找到一个重复的,如果它找到一个,它将测试是否与X相等,但我不知道如何在Prolog中做到这一点
谢谢你的帮助!谢谢不确定这是否是家庭作业/允许使用哪些谓词有限制,但这会让prolog为您执行递归 上面写着。。查找所有重复的IE。其中存在一个带有列表索引I1的项目,而另一个则具有I2,使得它们都具有相同的值N,并且索引不相同。不要将同一个列表项视为重复项。 这些重复项(按照找到它们的顺序,从一开始就非常关键)放在list AllDups中,如果找到的第一个重复项与正在检查的值M一致,则谓词为true 第一次尝试:这很有效,但效率很低,需要建立一个所有重复项的列表
prep(M, List) :-
findall(N,
(nth0(I1, List, N),
nth0(I2, List, N),
not(I1 =:= I2)),
AllDups),
nth1(1, AllDups, M).
?- prep(3,[1,3,5,3,5]).
true.
?- prep(5,[1,3,5,3,5]).
false.
即使不允许您使用findall,它也可能帮助您解决如何“手动”使用findall的问题
第二次尝试:这不起作用/回溯太远,产生误报
您甚至可以在不使用findall的情况下执行此操作-使用nth0查找第一个重复项,然后如果该项与您正在检查的值一致,则返回true,否则返回false
prep(N, List) :-
nth0(I1, List, N),
nth0(I2, List, N),
not(I1 =:= I2).
第三次尝试:此操作有效,并在找到第一个副本后立即返回
prep(M, List) :-
nth0(I1, List, N),
nth0(I2, List, N),
not(I1 =:= I2), !,
M == N.
rep(N,List):-append(L1,[N |,List),append([N |,L1),\+(rep(,L1))。这是一个使用
dif/2的纯版本,它实现了声音不平等dif/2
由B-Prolog、YAP Prolog、SICStus Prolog和SWI Prolog提供
firstdup(E, [E|L]) :-
member(E, L).
firstdup(E, [N|L]) :-
non_member(N, L),
firstdup(E, L).
member(E, [E|_L]).
member(E, [_X|L]) :-
member(E, L).
non_member(_E, []).
non_member(E, [F|Fs]) :-
dif(E, F),
non_member(E, Fs).
在这个答案中,我们改进了中提供的逻辑纯代码。逐步:
我们将两个谓词合并为一个,它使用一个附加参数将列表成员身份具体化为真值(true
或false
)
memberd\u t/3
相当于memberd/2
+非成员/2
,因此我们可以这样定义它:
memberd_t(X,Xs,true) :-
memberd(X,Xs).
memberd_t(X,Xs,false) :-
non_member(X,Xs).
在实践中,我们使用了memberd_t/3
的优化实现—一个具有更好的确定性的实现
让我们看看memberd\u t/3
实际上包括memberd/2
和非成员/2
?- memberd_t(X,[1,2,3],T).
T = true , X=1
; T = true , X=2
; T = true , X=3
; T = false, dif(X,1), dif(X,2), dif(X,3).
让我们将memberd/2
和非成员/2
替换为memberd\u t/3
firstdup(E,[X|Xs]) :-
( memberd_t(X,Xs,true),
E=X
; memberd_t(X,Xs,false),
firstdup(E,Xs)
).
firstdup(E,[X|Xs]) :-
memberd_t(X,Xs,T),
( T=true
-> E=X
; T=false,
firstdup(E,Xs)
).
上面的模式pred\u t(OtherArgs,t),(t=true->Then;t=false,Else)
可以通过使用编写if(pred\u t(OtherArgs),Then,Else)
更简洁地表达
firstdup(E[X | Xs]):-
如果(成员)(X,Xs),,
E=X,
firstdup(E,Xs))。
让我们运行一些查询
?- firstdup(1,[1,2,3,1]).
true. % succeeds deterministically
?- firstdup(X,[1,2,3,1]).
X = 1. % succeeds deterministically
?- firstdup(X,[A,B,C]). % succeeds, leaving behind a choicepoint
A=X , B=X % ... to preserve the full solution set.
; A=X , dif(B,X), C=X
; dif(A,X), B=X , C=X
; false.
?-firstdup(1[1,2,3,1])。
对决定性地成功
?-firstdup(X[1,2,3,1])。
X=1.%决定性地成功
?-firstdup(X[A,B,C])。%成功,留下一个选择点
A=X,B=X%。。。以保留完整的解决方案集。
; A=X,dif(B,X),C=X
; dif(A,X),B=X,C=X
; 错。
我还是一个乞丐,这对我来说有点难以理解。我们没有在课堂上教授序言,我几乎没有时间自己学习,这个练习只是自学的,所以我以后会努力更好地理解它。谢谢你抽出时间!:)不客气。。毫无疑问,这是一种奇怪的语言。它为你做了这么多,而不是你一直告诉它该做什么,因此你需要了解它可以在幕后做些什么来提出最整洁的解决方案。在你最后添加的prep(5、[1,3,5,3,5])。
还返回true
<代码>?-prep(N[1,3,5,3,5])。N=3;N=5;N=3;N=5;否
@false:I1和I2是列表的索引。。ie在列表“list”中找到两个列表项,它们的值“N”相同,但索引不同。@will ness-yep-我想我已经测试过了。我已经把一个固定版本的编辑2以上。我的第一个解决方案效率很低。。首先生成所有重复项的列表。编辑2包含一个剪切,以确保在找到具有不同索引的两个匹配值后,如果输入值与找到的值不匹配,则不会使用另一个nth0值进行回溯。如果最后一行文本的内容为“…和非成员(X,L)
可以定义为映射列表(dif(X,L)
…”,则更好,为X
和L
提供上下文:
firstdup(E,[X|Xs]) :-
( memberd(X,Xs),
E=X
; non_member(X,Xs),
firstdup(E,Xs)
).
firstdup(E,[X|Xs]) :-
( memberd_t(X,Xs,true),
E=X
; memberd_t(X,Xs,false),
firstdup(E,Xs)
).
firstdup(E,[X|Xs]) :-
memberd_t(X,Xs,T),
( T=true
-> E=X
; T=false,
firstdup(E,Xs)
).
firstdup(E,[X|Xs]) :-
if_(memberd_t(X,Xs),
E=X,
firstdup(E,Xs)).
?- firstdup(1,[1,2,3,1]).
true. % succeeds deterministically
?- firstdup(X,[1,2,3,1]).
X = 1. % succeeds deterministically
?- firstdup(X,[A,B,C]). % succeeds, leaving behind a choicepoint
A=X , B=X % ... to preserve the full solution set.
; A=X , dif(B,X), C=X
; dif(A,X), B=X , C=X
; false.