2

我发现了一个3 年前的问题,它可以帮助我计算列表中变量的出现次数。这个问题有下面的答案。该代码有效。但我不明白怎么做,有人可以帮我理解这个吗?

这是我找到的代码的答案,用引号括起来是答案的一部分:

count([],X,0). 
count([X|T],X,Y):- count(T,X,Z), Y is 1+Z.
count([X1|T],X,Z):- X1\=X,count(T,X,Z).

'但是请注意,第二个参数 X 应该被实例化。因此,例如 count([2,23,3,45,23,44,-20],23,C) 会将 C 与 2 统一起来。如果您想要使用每个元素的计数'

:- use_module(library(lists)).

count([],X,0).
count([X|T],X,Y):- count(T,X,Z), Y is 1+Z.
count([X1|T],X,Z):- X1\=X,count(T,X,Z)

countall(List,X,C) :-
   sort(List,List1),
   member(X,List1),
   count(List,X,C).

'那么你得到'

 ?- countall([2,23,3,45,23,44,-20],X,Y).
   X = -20,
   Y = 1  ;
   X = 2,
   Y = 1 ;
   X = 3,
   Y = 1  ;
   X = 23,
   Y = 2  ;
   X = 44,
   Y = 1  ;
   X = 45,
   Y = 1  ;
   no

我对Prolog很陌生,我只了解这段代码的一部分,就是这个

sort(List,List1),
member(X,List1),

我将不胜感激整个事情的解释,尤其是 Y 是如何打印的。

4

1 回答 1

6

关于计数,首先尝试思考代码的含义

list_member_occ([], _, 0).       % list is empty, 0 occurrences
list_member_occ([X|Xs], X, N) :- % list has the element at the head
    list_member_occ(Xs, X, N0),  % count number of elements in the tail
    succ(N0, N).                 % the number of occurrences is the
                                 % next natural number
list_member_occ([Y|Xs], X, N) :-
    dif(X, Y),                   % head and the element are different
    list_member_occ(Xs, X, N).   % occurrences in the tail of the list
                                 % is the total number

在这段代码中,succ(N0, N)(可以说)说“N是自然数之后N0”比N is N0 + 1. 一个原因是它succ/2被用于各个方向:

?- succ(2, 3).
true.

?- succ(X, 4).
X = 3.

?- succ(1, X).
X = 2.

... while应该与未绑定的左操作数一起使用。接受这个查询is/2

?- list_member_occ([1,1,2,1], X, 3).

...N作为一个数字而不是自由变量的例子。

使用谓词:

?- list_member_occ([1,2,1], X, N).
X = 1,
N = 2 ;
X = 2,
N = 1 ;
N = 0,
dif(X, 1),
dif(X, 2),
dif(X, 1).

dif/2与 相反,一个有趣的特性\=/2是它X在最后一个解中对变量施加了一个约束:X从现在开始,不能取任何值12

对于使用 获得所有答案的原因dif/2,请考虑:

?- X = Y. % unify X and Y and succeed
X = Y.

?- X \= Y. % succeed if you cannot unify X and Y
false.

?- dif(X, Y). % succeed if X and Y are and will be different
dif(X, Y).

使用时X \= Y,Prolog 会尝试统一其参数,如果统一成功,则失败。这意味着您只能得到所有自由变量彼此统一的解决方案,但您会错过自由变量彼此不同的解决方案。

关于Y = ...,当您在顶层进行查询时,它会向您报告在成功证明此查询期间所做的所有新变量绑定。作为最简单的例子:

哪些数字在 3 和 5 之间,都包括?

?- between(3, 5, X).
X = 3 ;
X = 4 ;
X = 5.

当然,您不需要X手动打印出值;只需键入分号即可获得下一个答案。在最后一个答案之后,您会得到一个句号并返回到?-提示。

关于排序:它对整个列表进行排序,但只显示排序列表的前 9 个元素。请参阅SWI-Prolog 中的此常见问题解答页面。简而言之,最简单的方法是; true在查询后键入,以确保至少有一个选择点,然后使用wandp在显示整个术语和仅显示部分术语之间切换。

?- string_chars("the quick brown fox jumps over the lazy dog", Cs), sort(Cs, S) ; true.
Cs = [t, h, e, ' ', q, u, i, c, k|...],
S = [' ', a, b, c, d, e, f, g, h|...] [write]
Cs = [t, h, e, ' ', q, u, i, c, k, ' ', b, r, o, w, n, ' ', f, o, x, ' ', j, u, m, p, s, ' ', o, v, e, r, ' ', t, h, e, ' ', l, a, z, y, ' ', d, o, g],
S = [' ', a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z] .

?- string_chars("the quick brown fox jumps over the lazy dog", Cs), sort(Cs, S) ; true.
Cs = [t, h, e, ' ', q, u, i, c, k, ' ', b, r, o, w, n, ' ', f, o, x, ' ', j, u, m, p, s, ' ', o, v, e, r, ' ', t, h, e, ' ', l, a, z, y, ' ', d, o, g],
S = [' ', a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z] [print]
Cs = [t, h, e, ' ', q, u, i, c, k|...],
S = [' ', a, b, c, d, e, f, g, h|...] .

希望这可以帮助。

于 2016-01-12T08:41:15.603 回答