我是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.
答案 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 + 1N = N,即如果列表的头部不是元音则不会发生变化。