List Prolog只从列表中获取相同的元素

List Prolog只从列表中获取相同的元素,list,prolog,List,Prolog,我是Prolog编程的初学者。我有一个从列表中删除相同元素的程序?但我只需要列表中相同的元素 具有预期答案的示例查询: ?- set([1,2,3,4,2,3], Xs). Xs = [2,3]. 序言代码: ismember(X, SET) :- member(X, SET). set([], []). set([H|T], [H|Out]) :- not(ismember(H,T)), set(T, Out). set([H|T], Out) :- isme

我是Prolog编程的初学者。我有一个从列表中删除相同元素的程序?但我只需要列表中相同的元素

具有预期答案的示例查询:

?- set([1,2,3,4,2,3], Xs).
Xs = [2,3].
序言代码:

ismember(X, SET) :-
   member(X, SET).

set([], []).
set([H|T], [H|Out]) :-
    not(ismember(H,T)),
    set(T, Out).
set([H|T], Out) :-
    ismember(H, T),
    set(T, Out).
谢谢大家!

又快又脏

?- S=[1,2,3,4,2,3], setof(C, R^(select(C,S,R),memberchk(C,R)), L).
S = [1, 2, 3, 4, 2, 3],
L = [2, 3].
是“生成和测试”模式的专门化

表演怎么样

'slow quick and dirty'(S0, S) :-
    setof(C, R^(select(C,S0,R),member(C,R)), S).

'better quick and dirty'(S0, S) :-
    setof(C, R^(select(C,S0,R),memberchk(C,R)), S).

'still better quick and dirty'(S0, S) :-
    setof(H, Done^H^R^(append(Done,[H|R],S0),memberchk(H,R)), S).

test(N) :-
    findall(R, (between(1,N,_), random_between(10,100,R)), S),
    time('slow quick and dirty'(S, Sa)),
    time('better quick and dirty'(S, Sb)),
    time('still better quick and dirty'(S, Sc)),
    Sa = Sb, Sb = Sc,
    time(remove_uniq(S, Sd)),
    maplist(length, [Sa, Sb, Sc, Sd], Ls),
    writeln(Ls).

25 ?- so:test(100).
% 10,225 inferences, 0.003 CPU in 0.003 seconds (100% CPU, 3506071 Lips)
% 282 inferences, 0.001 CPU in 0.001 seconds (99% CPU, 226231 Lips)
% 254 inferences, 0.001 CPU in 0.001 seconds (100% CPU, 347891 Lips)
% 22,697 inferences, 0.018 CPU in 0.028 seconds (65% CPU, 1272020 Lips)
[28,28,28,28]
true.

26 ?- so:test(1000).
% 1,011,929 inferences, 0.275 CPU in 0.276 seconds (100% CPU, 3674049 Lips)
% 3,015 inferences, 0.013 CPU in 0.013 seconds (98% CPU, 239535 Lips)
% 2,924 inferences, 0.013 CPU in 0.016 seconds (82% CPU, 216598 Lips)
% 351,724 inferences, 0.262 CPU in 0.272 seconds (96% CPU, 1343870 Lips)
[91,91,91,91]
true.
出于好奇,我已经包括了remove_uniq/2,但是,考虑到不同的语义,我认为它不具有严格的可比性

使用member/2,我们有一个二次复杂度。 memberchk(在C中实现为内置)的运行时效率只是挤出了过滤器延迟:效率几乎成了线性


append/3而不是select/3允许进一步的小改进。

以下是从相关问题“”派生出来的

配合使用 并且,我们将
remove\u uniq/2
定义如下:

remove_uniq([], []). remove_uniq([E|Es], Xs0) :- tpartition(=(E), Es, Ts, Fs), if_(Ts = [], Xs0 = Xs, Xs0 = [E|Xs]), remove_uniq(Fs, Xs).
怎么样
[1,2,3,4,3,2]
?你想得到什么结果<代码>[2,3](保留最左边的引用)或
[3,2]
(保留最右边的引用)或“任何一个都可以”?ismember(X,SET):-member(X,SET)的目的是什么?你有没有尝试过修改现有的代码来解决你的问题?这个比较是伪造的。考虑<代码> -NoMLIST(11000000,XS),时间(成员CHECK(0,Xs))。< /代码>我得到<代码> 3推论,0.029秒内0.029个CPU(100%个CPU,102个嘴唇)< /代码>和<代码> false <代码>。我觉得有两条信息混淆了:首先,
setof(append&memberchk)
setof(select&member)
快。第二,当使用
memberchk/2
时,推断计数低得离谱。(这就是我想用我的评论指出的。)如果我们比较
test(100)
test(1000)
,我们也需要考虑PRNG
remove_uniq/2
基于memberd,而不是member。因此,对于10到100之间的1000个整数,肯定有很多重复!s(X)用于进行有趣的实验@重复:谢谢!请看这个。我已经更改了随机基的密度(请参见test/1),但是remove\u uniq不能很好地处理它。我得到了
?-测试(10000)。。。129561295推论
:- remove_uniq([1,2,3,4,2,3], [2,3]).
%                 ^ ^          ^ ^
%                 |-+--------- take leftmost occurrence
%                 v v          v v 
:- remove_uniq([1,2,3,4,3,2], [2,3]).
%                 ^ ^          ^ ^
%                 |-+--------- preserve the original order
%                 v v              v v
:- remove_uniq([5,3,2,1,2,3,2,3], [3,2]).