我是Prolog的新手,我似乎无法自己解决这个问题。
我想要的是,Prolog在列表中计算所有数字,而不是每个元素。例如:
getnumbers([1, 2, c, h, 4], X).
应该给我:
X=3
getnumbers([], 0).
getnumbers([_ | T], N) :- getnumbers(T, N1), N is N1+1.
我有什么,但它显然给了我列表中的每个元素。我不知道如何以及在何处放置“仅计数”。
答案 0 :(得分:2)
像往常一样,当您使用列表(和SWI-Prolog)时,您可以使用在那里找到的模块lambda.pl:http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl
:- use_module(library(lambda)).
getnumbers(L, N) :-
foldl(\X^Y^Z^(number(X)
-> Z is Y+1
; Z = Y),
L, 0, N).
答案 1 :(得分:1)
考虑使用内置谓词(例如在SWI-Prolog中),并检查它们的实现,如果您对如何自己做这件事感兴趣:
include(number, List, Ns), length(Ns, N)
答案 2 :(得分:1)
保持逻辑纯粹,很简单:使用元谓词
tcount/3
与改进的类型测试谓词number_t/2
(number_truth/2
的缩写)相配合:
number_t(X,Truth) :- number(X), !, Truth = true.
number_t(X,Truth) :- nonvar(X), !, Truth = false.
number_t(X,true) :- freeze(X, number(X)).
number_t(X,false) :- freeze(X,\+number(X)).
让我们运行OP建议的查询:
?- tcount(number_t,[1,2,c,h,4],N). N = 3. % succeeds deterministically
请注意,这是单调的:延迟变量绑定始终是逻辑上合理的。考虑:
?- tcount(number_t,[A,B,C,D,E],N), A=1, B=2, C=c, D=h, E=4. N = 3, A = 1, B = 2, C = c, D = h, E = 4 ; % succeeds, but leaves choice point false.
最后,让我们看一下以下相当普遍的查询的一些答案:
?- tcount(number_t,[A,B,C],N).
N = 3, freeze(A, number(A)), freeze(B, number(B)), freeze(C, number(C)) ;
N = 2, freeze(A, number(A)), freeze(B, number(B)), freeze(C,\+number(C)) ;
N = 2, freeze(A, number(A)), freeze(B,\+number(B)), freeze(C, number(C)) ;
N = 1, freeze(A, number(A)), freeze(B,\+number(B)), freeze(C,\+number(C)) ;
N = 2, freeze(A,\+number(A)), freeze(B, number(B)), freeze(C, number(C)) ;
N = 1, freeze(A,\+number(A)), freeze(B, number(B)), freeze(C,\+number(C)) ;
N = 1, freeze(A,\+number(A)), freeze(B,\+number(B)), freeze(C, number(C)) ;
N = 0, freeze(A,\+number(A)), freeze(B,\+number(B)), freeze(C,\+number(C)).
答案 3 :(得分:0)
答案 4 :(得分:0)
这使用Prolog的自然模式与数字/ 1匹配,以及附加条款(下面的3)来处理非数字的情况。
% 1 - base recursion
getnumbers([], 0).
% 2 - will pass ONLY if H is a number
getnumbers([H | T], N) :-
number(H),
getnumbers(T, N1),
N is N1+1.
% 3 - if got here, H CANNOT be a number, ignore head, N is unchanged, recurse tail
getnumbers([_ | T], N) :-
getnumbers(T, N).
答案 5 :(得分:0)
这类问题的常见原因是首先为公共消费定义谓词,并让它调用'worker'谓词。通常它会使用某种累加器。对于您的问题,公共消费谓词类似于:
count_numbers( Xs , N ) :-
count_numbers_in_list( Xs , 0 , N ) .
count_numbers_in_list( [] , N , N ) .
count_numbers_in_list( [X|Xs] , T , N ) :-
number(X) ,
T1 is T+1 ,
count_numbers_in_list( Xs , T1 , N )
.
您还需要构造递归位,以便它也是尾递归,这意味着递归调用除了参数列表中的数据之外什么都不依赖。这允许编译器在每次调用时重用现有的堆栈帧,因此谓词实际上变为迭代而不是递归。正确的尾递归谓词可以处理无限长度的列表;一个不会在每次递归时分配一个新的堆栈帧并最终炸掉它的堆栈。上面的count_numbers_in_list/3
是尾递归的。这不是:
getnumbers([H | T], N) :-
number(H),
getnumbers(T, N1),
N is N1+1.