在列表中计数.帮我理解这段代码 [英] Counting within a list. Help me understand this code

查看:44
本文介绍了在列表中计数.帮我理解这段代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I found a 3 year old question that helps me count the number of occurrences of variables within a list. The question had the answer below. The code works. But I can't understand how, can someone help me make sense of this?

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

Here is the answer with the code I found, writing in quotation marks is part of the answer:

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 统一起来.如果你想为每个元素使用计数'

'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).

'然后你得到'

 ?- 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很陌生,我只了解这段代码的一部分,就是这样

I am very new to Prolog, I only understand one part of this code, and it is this

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

我希望能解释整个事情,尤其是 Y 的打印方式.

I would appreciate an explanation of this the whole thing, especially how Y is being printed.

推荐答案

关于计数,先试着想想代码的含义.

About counting, first try to think about the meaning of the code.

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) 是(可以说)更好的表达方式NN0 之后的自然数>" 比 N 是 N0 + 1.原因之一是 succ/2 旨在用于各个方向:

In this code, succ(N0, N) is (arguably) a better way to say "N is the natural number after N0" than N is N0 + 1. One reason is that succ/2 was meant to be used in every direction:

?- succ(2, 3).
true.

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

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

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

... while is/2 should be used with unbound left operand. Take this query

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

... 例如 N 是一个数字而不是一个自由变量.

... for an example of N being a number instead of a free variable.

使用谓词:

?- 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 中的任何值.

One interesting property of dif/2, as opposed to \=/2, is that it imposes a constraint on the variable X in the last solution: X cannot, from now on, take any of the values 1, or 2.

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

For the reason why you get all answers using dif/2, consider:

?- 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 会尝试统一其参数,并且 如果统一成功则失败.这意味着你只会得到所有自由变量都统一的解,但你会错过自由变量彼此不同的解.

When you use X \= Y, Prolog tries to unify its arguments and fails if the unification succeeds. This means that you only get the solution in which all free variables have been unified to each other, but you miss solutions where free variables are different from each other.

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

About the Y = ..., when you make a query at the top level, it reports to you all new variable bindings that were made during successful proofs of this query. As the most simple example:

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

Which numbers are between 3 and 5, both including?

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

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

You don't need, of course, to print out the values of X by hand; just type a semicolon to get the next answer. After the last answer you get a full stop and return to the ?- prompt.

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

About the sorting: it sorts the whole list, but only shows you the first 9 elements of the sorted list. See this FAQ page from SWI-Prolog. In a nutshell, the easiest is to type ; true after your query, to make sure that there is at least one choice point, and use w and p to switch between showing the whole term and only some of it.

?- 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|...] .

希望这会有所帮助.

这篇关于在列表中计数.帮我理解这段代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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