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.