作为初学者,我正在尝试从列表中删除所有重复项。
我确实得到一个令人满意的答案,但这应该是唯一的答案。反而,
Prolog继续提供其他答案。
我尝试使下面的代码与示例查询 compress([[a,a,b,c],s)。
唯一的答案应该是s = [a,b,c],
我没有获得免费变量的无限解决方案:
S = [a, b, c|_1422]
S = [a, b, _1420, c|_1428]
S = [a, b, _1420, _1426, c|_1434]
S = [a, b, _1420, _1426, _1432, c|_1440].
如下面的代码中所示, 我尝试了剪切。这不是家庭作业问题,我真的只是尝试得到它。特别是,我想知道如何使此特定的代码工作而不是查找某人代码(我知道应该有更多稀疏的解决方案)。先感谢您!!!
compress([],[]).
compress([],_):-!.
% I tried out a first cut here, but it doesn´t affect the amount of solutions
compress([Head|Tail],Set):-
unique2(Head,Tail,Set),
compress(Tail,Set).
unique2(X,[],[_List]):-!.
% I tried out a second cut here, but again there is an endless amount of answers
unique2(X,List,List):-
member(X,List).
unique2(X,List,List2):-
member(X,List2).
unique2(X,List,NewList):-
not(member(X,NewList)),
addelem(X,List,NewList).
addelem(X,List,[X|List]).
Being a beginner to prolog, I am trying to remove all duplicates from a list.
I do get a satisfying answer but this should be the only answer. Instead,
prolog keeps on providing other answers.
I try to make the code below working with the example query compress([a,a,b,c],S).
The only answer should be S = [a, b, c],
instead of getting an infinite amount of solutions with free variables:
S = [a, b, c|_1422]
S = [a, b, _1420, c|_1428]
S = [a, b, _1420, _1426, c|_1434]
S = [a, b, _1420, _1426, _1432, c|_1440].
I tried cuts, as illustrated in the code below. It is not a homework problem, I just really try to get it. Especially, I would like to know how I can get this specific code working instead of looking up someone elses code (I am aware that there should be way more sparse solutions). Thank you in advance!!!
compress([],[]).
compress([],_):-!.
% I tried out a first cut here, but it doesn´t affect the amount of solutions
compress([Head|Tail],Set):-
unique2(Head,Tail,Set),
compress(Tail,Set).
unique2(X,[],[_List]):-!.
% I tried out a second cut here, but again there is an endless amount of answers
unique2(X,List,List):-
member(X,List).
unique2(X,List,List2):-
member(X,List2).
unique2(X,List,NewList):-
not(member(X,NewList)),
addelem(X,List,NewList).
addelem(X,List,[X|List]).
发布评论
评论(4)
编辑要注意:
从您的评论中:
我认为您正在考虑您的
unique2
谓词。您的
unique2
只需要这样做:compress/2
需要处理终止案例(空列表)。一旦这样做,就已经得到了: .org/p/sypssqlo.pl[现在,返回原始答案]
这将丢弃所有重复项的最后一个:
https://swish.swim.swi-prolog.org/p/mghqgthb.pl
保持第一个并不复杂。我们将只使用累加器的辅助谓词。由于它以相反的顺序构建结果集,因此我们需要逆转它。这给了我们这一点:
Edited to note:
From your comment:
I think that you're overthinking youro
unique2
predicate.Your
unique2
just need do something like this:And your
compress/2
needs to handle the terminating case (the empty list). Once you do that, you've got this: https://swish.swi-prolog.org/p/sypssqLO.pl[and now, back to the original answer]
This will discard all but the last of any duplicates:
https://swish.swi-prolog.org/p/MghqGThB.pl
To keep the first isn't much more complicated. We'll just use a helper predicate with an accumulator. Since it builds the result set in reverse order, we need to reverse it. That gives us this:
https://swish.swi-prolog.org/p/PHQgypMu.pl
这是一种无需
反向
的方法,它似乎比dedupe
(均使用MemberChk
进行性能,这是在SWI-Prolog中进行了优化的) :SWI-Promog中的性能比较:
Here is a method without needing
reverse
which seems a little faster thandedupe
(both usingmemberchk
for performance, which is optimized in swi-prolog):Performance comparison in swi-prolog:
我想到了:
...但是它比
dedupe
:使用
memberchk
而不是成员
indedupe
,在Swi-Prolog中的性能加倍:I came up with:
... but it is slower than
dedupe
:Using
memberchk
instead ofmember
indedupe
, doubles the performance in swi-prolog:实现这一目标的一种有趣的方法
A fun way to achieve this is with