2013-04-21 145 views
1

我是新来的Prolog,我似乎无法自己得到这个答案。只计算数字和字母列表中的数字

我想要的是,Prolog统计列表中的数字,而不是每个元素。因此,例如:

getnumbers([1, 2, c, h, 4], X). 

应该给我:

X=3 

getnumbers([], 0). 
getnumbers([_ | T], N) :- getnumbers(T, N1), N is N1+1. 

是我得到了什么,但它显然给了我在列表中的每个元素。我不知道如何以及在哪里放一个“只计数”。

回答

1

考虑使用内置的谓词(例如,在SWI-Prolog的),并检查它们的实现,如果你有兴趣在如何做到这一点吧:

include(number, List, Ns), length(Ns, N)

+0

啊我看,这工作得非常好。谢谢,但是,如果我想避免使用内置的谓词,你能指出我正确的方向吗?就像在现有代码中实现“只使用数字”一样。从我看到的情况看来,只有在咨询序言的时候,你可以使用数字/ 1,这是真的吗? – Majusbeh 2013-04-21 16:49:11

0
当然

,必须检查要查看它是否满足条件的元素的类型。

number/1这是你正在寻找的谓词。

另请参见if/then/else构造,用于递归子句。

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). 
+0

如果head *是一个数字,第三个子句也匹配。 – mat 2013-04-22 13:43:22

+0

不明白垫子。如果head是一个数字,它将被第二条规则所捕获,所以第三条规则永远不会达到,因为3条款将按1..2..3的顺序执行,或者我错过了什么? – magus 2013-04-22 17:01:54

+0

如果head是一个数字,则适用第二条和第三条规则。由于回溯,两者都将被尝试,并且按照该顺序进行。你是否在'? - getnumbers([1])上试过这个程序。'? – mat 2013-04-23 07:48:06

0

一个共同的序言成语有这种问题是先定义你的断言对于大众消费,并把它调用一个“工人”谓词。通常它会使用某种累加器。对于您的问题,市民的消费谓词是一样的东西:

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

请注意,这是单调的:延迟变量绑定总是l听起来很健康。试想一下:

 
?- 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)). 
+0

理想情况下'number/1'的测试,'atom/1'由一个明确的'nonvar/1' **保护,就好像它们会产生实例化错误一样。 – false 2015-06-16 09:19:51