删除列表中的重复项(序言) [英] Remove duplicates in list (Prolog)

查看:103
本文介绍了删除列表中的重复项(序言)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对Prolog完全陌生,并尝试一些练习.其中之一是:

I am completely new to Prolog and trying some exercises. One of them is:

写一个谓词集(InList,OutList) 这将任意输入 列表,并返回一个列表,其中每个 输入列表的元素仅出现 一次.

Write a predicate set(InList,OutList) which takes as input an arbitrary list, and returns a list in which each element of the input list appears only once.

这是我的解决方案:

member(X,[X|_]).
member(X,[_|T]) :- member(X,T).

set([],[]).
set([H|T],[H|Out]) :-
    not(member(H,T)),
    set(T,Out).
set([H|T],Out) :-
    member(H,T),
    set(T,Out).

不允许使用任何内置谓词(即使不使用not/1也会更好).问题在于,set/2提供了多个 same 解决方案.输入列表中的重复次数越多,将产生更多的解决方案.我究竟做错了什么?预先感谢.

I'm not allowed to use any of built-in predicates (It would be better even do not use not/1). The problem is, that set/2 gives multiple same solutions. The more repetitions in the input list, the more solutions will result. What am I doing wrong? Thanks in advance.

推荐答案

由于Prolog的回溯,您将获得多种解决方案.从技术上讲,提供的每个解决方案都是正确的,这就是为什么要生成它.如果只想生成一个解决方案,则必须在某个时候停止回溯.这就是Prolog cut 的用途.您可能会发现,对此进行阅读会帮助您解决此问题.

You are getting multiple solutions due to Prolog's backtracking. Technically, each solution provided is correct, which is why it is being generated. If you want just one solution to be generated, you are going to have to stop backtracking at some point. This is what the Prolog cut is used for. You might find that reading up on that will help you with this problem.

更新:对.如果第一个变量位于第二个变量的多个位置,则您的member()谓词将以几种不同的方式评估为true.

Update: Right. Your member() predicate is evaluating as true in several different ways if the first variable is in multiple positions in the second variable.

我为该谓词使用了名称mymember(),以免与GNU Prolog的内置member()谓词冲突.我的知识库现在看起来像这样:

I've used the name mymember() for this predicate, so as not to conflict with GNU Prolog's builtin member() predicate. My knowledge base now looks like this:

mymember(X,[X|_]).
mymember(X,[_|T]) :- mymember(X,T).

not(A) :- \+ call(A).

set([],[]).
set([H|T],[H|Out]) :-
    not(mymember(H,T)),
    set(T,Out).
set([H|T],Out) :-
    mymember(H,T),
    set(T,Out).

因此,mymember(1, [1, 1, 1]).通过三种不同的方式得出true的值:

So, mymember(1, [1, 1, 1]). evaluates as true in three different ways:

| ?- mymember(1, [1, 1, 1]).

true ? a

true

true

no

如果您只想要一个答案,则必须使用剪切.将mymember()的第一个定义更改为此:

If you want to have only one answer, you're going to have to use a cut. Changing the first definition of mymember() to this:

mymember(X,[X|_]) :- !.

解决您的问题.

此外,如果愿意,可以通过定义自己的notamember()谓词完全避免使用not().选择是您的.

Furthermore, you can avoid not() altogether, if you wish, by defining a notamember() predicate yourself. The choice is yours.

这篇关于删除列表中的重复项(序言)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆