使用Prolog计算字符串中元音的数量

时间:2016-12-13 21:53:38

标签: count prolog

我是prolog的新手,所以我必须向班级老师解释这些代码。 请有人请解释这段代码。感谢

vowel(X):- member(X,[a,e,i,o,u]).
nr_vowel([],0).
nr_vowel([X|T],N):- vowel(X),nr_vowel(T,N1), N is N1+1,!.
nr_vowel([X|T],N):- nr_vowel(T,N).

输出:

1 ?- nr_vowel([a,t,i,k],X).
X = 2.

https://i.stack.imgur.com/dGfU5.jpg

2 个答案:

答案 0 :(得分:1)

解释确实非常合适。

例如,让我们问最简单的问题:

  

有哪些解决方案?

通过发布最常见的查询来尝试,其中所有参数都是新变量

?- nr_vowel(Ls, N).
Ls = [],
N = 0 ;
Ls = [a],
N = 1.

嗯!这可能不是你想描述的!

所以我将您的代码更改为:

nr_vowel([], 0).
nr_vowel([X|T], N):-
        vowel(X),
        nr_vowel(T,N1),
        N #= N1+1.
nr_vowel([X|T], N):-
        nr_vowel(T,N).

然后我们得到:

?- nr_vowel(Ls, N).
Ls = [],
N = 0 ;
Ls = [a],
N = 1 ;
Ls = [a, a],
N = 2 ;
Ls = [a, a, a],
N = 3 ;
etc.

看起来更好!

公平枚举怎么样?我们来看看:

?- length(Ls, _), nr_vowel(Ls, N).
Ls = [],
N = 0 ;
Ls = [a],
N = 1 ;
Ls = [e],
N = 1 ;
Ls = [i],
N = 1 ;
Ls = [o],
N = 1 ;
Ls = [u],
N = 1 ;
Ls = [_2006],
N = 0 ;
Ls = [a, a],
N = 2 ;
Ls = [a, e],
N = 2 .

前几个答案看起来都很有希望,但是Ls = [_2006], N = 0呢?

这显然太笼统

您必须使您的计划更具体,以避免这种过于笼统的答案。

简而言之,这是一个问题:

?- nr_vowel([X], N), X = a.
X = a,
N = 1 ;
X = a,
N = 0.

Whaaat? a 一个元音,为什么N = 0 ??

这是一个较小的概括:

?- nr_vowel([a], 0).
true.

<强> Whaaaaat ...

我将适当的约束添加到谓词中作为练习。

答案 1 :(得分:0)

代码本身就是简单的,它所做的只是计算列表中元音的数量(猜猜这对你很明显)。

我们以您的输入为例,列表为[a,t,i,k]

当您调用 nr_vowel([a,t,i,k],Z)时,prolog会使用第二个nr_vowel子句搜索并统一查询,这是因为它是第一个子句非空列表输入。

现在,元音(a)返回true,因此prolog移动到下一个谓词,该谓词调用 nr_vowel([t,i,k],Z)。然而这一次,当prolog尝试将它与第二个nr_vowel统一时,元音(t)返回false,因此它将它与第三个子句统一起来,并且行为类似,直到列表为空。

一旦列表为空,prolog将Z与0统一并开始递归递归级别并且N = N + 1,具体取决于调用者谓词是否有元音,并且一旦到达顶部在递归链中,Z与N的最终值统一。

简而言之 -

如果列表的头部是元音

,则发生N = N + 1

N = N,即如果列表的头部不是元音则不会发生变化。