我发现了一个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.
关于计数,首先尝试考虑代码的含义.
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.
... 应该与未绑定的左操作数一起使用.拿这个查询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 = ...
,当您在顶层进行查询时,它会向您报告在此查询的成功校样期间所做的所有新变量绑定.作为最简单的例子:
哪个数字在3到5之间,都包括?
?- between(3, 5, X). X = 3 ; X = 4 ; X = 5.
当然,您不需要X
手工打印出值; 只需输入分号即可获得下一个答案.在最后一个答案之后,您将获得一个完整的停止并返回?-
提示.
关于排序:它对整个列表进行排序,但只显示排序列表的前9个元素.请参阅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|...] .
希望这可以帮助.