在列表中计数。帮助我理解这段代码
Counting within a list. Help me understand this code
我找到了 3 year old question that helps me count the number of occurrences of variables within a list。这个问题有下面的答案。该代码有效。但是我不明白怎么回事,有人可以帮我理解这个吗?
这是我找到的答案,引号是答案的一部分:
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).
'However note that the second argument X is supposed to be instantiated. So e.g. count([2,23,3,45,23,44,-20],23,C) will unify C with 2. If you want the count for every element use'
:- 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).
'Then you get'
?- 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 是如何打印的,我将不胜感激。
关于计数,先试着想一下代码的意思。
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 is N0 + 1
更好的表达“N
是 N0
之后的自然数”的方式。一个原因是 succ/2
用于各个方向:
?- succ(2, 3).
true.
?- succ(X, 4).
X = 3.
?- succ(1, X).
X = 2.
... 而 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
从现在开始不能取任何值 1
或 2
.
为什么您使用 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 = ...
,当您在顶层进行查询时,它会向您报告在该查询的成功证明期间进行的所有新变量绑定。举个最简单的例子:
Which numbers are between 3 and 5, both including?
?- between(3, 5, X).
X = 3 ;
X = 4 ;
X = 5.
当然,您不需要手动打印出 X
的值;只需键入一个分号即可获得下一个答案。在最后一个答案之后,你会得到一个句号并 return 到 ?-
提示符。
关于排序:它对整个列表进行排序,但只显示排序列表的前 9 个元素。参见 this FAQ page from SWI-Prolog。简而言之,最简单的方法是在查询后键入 ; true
,以确保至少有一个选择点,并使用 w
和 p
在显示整个术语之间切换而且只有一部分。
?- 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|...] .
希望对您有所帮助。
我找到了 3 year old question that helps me count the number of occurrences of variables within a list。这个问题有下面的答案。该代码有效。但是我不明白怎么回事,有人可以帮我理解这个吗?
这是我找到的答案,引号是答案的一部分:
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).
'However note that the second argument X is supposed to be instantiated. So e.g. count([2,23,3,45,23,44,-20],23,C) will unify C with 2. If you want the count for every element use'
:- 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).
'Then you get'
?- 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 是如何打印的,我将不胜感激。
关于计数,先试着想一下代码的意思。
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 is N0 + 1
更好的表达“N
是 N0
之后的自然数”的方式。一个原因是 succ/2
用于各个方向:
?- succ(2, 3).
true.
?- succ(X, 4).
X = 3.
?- succ(1, X).
X = 2.
... 而 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
从现在开始不能取任何值 1
或 2
.
为什么您使用 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 = ...
,当您在顶层进行查询时,它会向您报告在该查询的成功证明期间进行的所有新变量绑定。举个最简单的例子:
Which numbers are between 3 and 5, both including?
?- between(3, 5, X).
X = 3 ;
X = 4 ;
X = 5.
当然,您不需要手动打印出 X
的值;只需键入一个分号即可获得下一个答案。在最后一个答案之后,你会得到一个句号并 return 到 ?-
提示符。
关于排序:它对整个列表进行排序,但只显示排序列表的前 9 个元素。参见 this FAQ page from SWI-Prolog。简而言之,最简单的方法是在查询后键入 ; true
,以确保至少有一个选择点,并使用 w
和 p
在显示整个术语之间切换而且只有一部分。
?- 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|...] .
希望对您有所帮助。