prolog - 如何在 Prolog 中找到集合的基数?

标签 prolog

我试图在 Prolog 中找到一个集合的基数。众所周知,一个集合不能有重复的元素。我试过了。

cardinal([], 0).
cardinal([_|Tail], N):-
    removeRepeated(Tail, ListWithoutRepeated),
    cardinal(ListWithoutRepeated, N1),
    N is N1 + 1.

----------------------------------------------------
consult:                                            

?- cardinal([1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5], N).
   N = 6

但正确答案是 N = 5。显然,我只计算尾部中的项目,如果头部在尾部重复,则忽略。 所以我尝试了这样的事情。即头尾相加,重复上述过程。

join([], L, [L]).
join([Head|Tail], L, [Head|Tail2]):-
   join(Tail,L, Tail2).

cardinal([], 0).
cardinal([Head|Tail], N):-
    join(Tail,Head, List),
    removeRepeated(List, ListWithoutRepeated),
    cardinal(ListWithoutRepeated, N1),
    N is N1 + 1.

但是当您查询时,会生成一个无限循环。 有人可以帮我解决这个问题吗 任何人都可以帮助我如何为此编写序言语句?

编辑 附上 removeRepeated

removeRepeated([],[]).
removeRepeated([Head|Tail],ListWithoutRepeated):-
    member(Head,Tail),
    !,
    removeRepeated(Tail,ListWithoutRepeated).
removeRepeated([Head|Tail],[Head|ListWithoutRepeated]):-
    removeRepeated(Tail,ListWithoutRepeated).

----------------------------------------------------
consult:                                            

?- removeRepeated([1,1,1,1,2,2,2,3,3,3,4,4,4,8], N).
   N = [1, 2, 3, 4, 8]

最佳答案

编码:

set_cardinality(Xs, N) :-
   list_nub(Xs, Ys),
   length(Ys, N).

使用 list_nub/2 .可以改进此定义的终止,因为它仅在 Xs 的长度固定时终止。但在我们开始讨论之前,让我们先看看你的定义。

关系名称

尝试使用真正反射(reflect)您定义的关系的名称。 cardinal/2removeRepeated/2 都会给人留下这样的印象:前者是红衣主教之间的关系,后者有所作为。但是关系没有任何作用。好吧,他们"is"。或者,它们“相关”。但这些并不是真正的 Action 动词。

现在开始你的第一个定义cardinal/2。实际上,我尝试阅读它。特别是因为它包含了程序员眩晕的第一个原因——这是

递归

是的,这也让我很头晕。幸运的是,您的问题是关于 Prolog 的,在 Prolog 中,我们通常可以隐藏很多东西,但仍然可以获得很多洞察力。这是我首先看到的(我没有看到的东西被划掉)。

cardinal([], 0).
cardinal([_|Tail], N):-
    removeRepeated(Tail, ListWithoutRepeated),
    cardinal(ListWithoutRepeated, N1),
    N is N1 + 1.

The fact, I can handle. Ok, the empty list corresponds to zero. Sounds fine to me. But then, there is the head of this rule: It reads:

N is independent of the first element of the list.

That is: For cardinal([1,2],N) and cardinal([2,2],N) you will get the very same N values. How can this be correct?

removeRepeated/2 (list_nub/2 might be a more relational name) works nicely for queries that have a ground first argument:

?- removeRepeated([1,2], X).
   X = [1,2].
?- removeRepeated([1,2],[1,2]).
   true.

但是,它意外地失败了:

?- removeRepeated([X,2],[1,2]).
   false.    % not relational
?- X = 1, removeRepeated([X,2],[1,2]).
   X = 1.

因此,虽然特化成功,但更一般的查询会失败。这清楚地表明 removeRepeated/2 不是纯关系。有关按预期工作的实现,请参阅 list_nub/2 .

关于prolog - 如何在 Prolog 中找到集合的基数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36906857/

相关文章:

csv - 如何将 csv 文件读入 SWI prolog 中的列表列表,其中内部列表代表 CSV 的每一行?

string - 将输入流转换为 ASCII : explanation of Prolog code

list - DCG 和 Prolog 中列表的反转

list - 如何解决这个列表反转问题?

prolog - 如何从 6 个数字中创建所有可能的 4 位数代码并且不使用重复项?

prolog - 根据列表中的分隔符拆分序言列表?

prolog - gprolog 中的 ANSI 转义字符

prolog - 卡住多个变量

list - 与 2 个示例相关的参数未充分实例化

prolog - 第一个程序,如果列表 1 的元素多于列表 2,则返回 true