在给定后裔程度的情况下,如何知道人X是人Y的后代?
我已经尝试过了:
descendant(X, Y, 1) :- son(X, Y).
descendant(X, Y, Degree) :- son(X, Z) , descendant(Z, Y, Degree-1).
如果X是Y的儿子,则son(X, Y)
返回yes
的位置。如果Degree == 1
返回正确的答案,但是对于descendant(X, Y, 2)
,应返回{{1} },如果X是Y的孙子,但返回yes
。
答案 0 :(得分:5)
1)命名:son(X,Y)
的意思是“ X
是Y
的儿子”吗?反之亦然?
son_of(X,Y)
更好。
2)利用successor-arithmetics::我们在这里不需要做一般的算术……我们只需要计数。
所以我们开始in the beginning ...
child_of(abel, adam). % from source child_of(abel, eve). child_of(cain, adam). child_of(cain, eve). child_of(enoch, cain). child_of(irad, enoch). child_of(mehujael, irad). child_of(methushael, mehujael). child_of(lamech, methushael). child_of(jabal, lamech). child_of(jabal, adah). child_of(jubal, lamech). child_of(jubal, adah). child_of(tubal_cain, lamech). child_of(tubal_cain, zillah). child_of(naamah, lamech). child_of(naamah, zillah). child_of(seth, adam). child_of(seth, eve). child_of(enos, seth). child_of(kenan, enos). child_of(mahalalel, kenan). child_of(jared, mahalalel). child_of(enoch, jared). child_of(methuselah, enoch). child_of(lamech, methuselah). child_of(noah, lamech). child_of(shem, noah). child_of(ham, noah). child_of(japheth, noah).
基于child_of/2
,我们首先定义ancestor_of/2
-这对您来说并不新鲜!
ancestor_of(Y, Z) :- child_of(Z, Y). % If Z is a child of Y ... % then Y is an ancestor of Z. ancestor_of(X, Z) :- child_of(Z, Y), % If Z is a child of Y ... ancestor_of(X, Y). % and X is an ancestor of Y ... % then X is an ancestor of Z.
接下来,我们添加一个指示距离的附加参数。
我们使用s/1
项来表示自然数,并向ancestor_of/2
添加新参数:
ancestor_of_dist(Y, Z, s(0)) :- child_of(Z, Y). % If Z is a child of Y ... % then Y is an ancestor of Z with distance = 1." ancestor_of_dist(X, Z, s(N)) :- child_of(Z, Y), % If Z is a child of Y ... ancestor_of_dist(X, Y, N). % and X is an ancestor of Y with distance N ... % then X is an ancestor of Z with distance N+1.
那...谁是谁的祖父母?
?- ancestor_of_dist(X, Z, s(s(0))). X = adam, Z = enoch ; X = eve, Z = enoch ; X = cain, Z = irad ; X = jared, Z = irad ; X = enoch, Z = mehujael ; ... ; X = lamech, Z = japheth ; false.
答案 1 :(得分:3)
Prolog不是一种功能语言。因此,Degree-1
项不会被解释为表达式。对于Prolog,Degree-1
只是一个带有两个参数的复合术语。使用标准write_canonical/1
谓词就可以清楚地看出这一点,该谓词无需使用运算符就可以写出一个术语:
?- write_canonical(Degree-1).
-(_,1)
true.
改为:
descendant(X, Y, 1) :-
son(X, Y).
descendant(X, Y, Degree) :-
son(X, Z) ,
descendant(Z, Y, Degree0),
Degree is Degree0 + 1.
is/2
标准内置谓词将左参数与右参数中的算术表达式的值统一起来。
P.S。请注意,我建议的替代descendant/3
谓词定义将解决您所描述的问题,但它不是有效的定义,因为它不是 tail-recursive 定义。即第二个子句中的递归调用不是子句主体中的最后一个调用。但是,使用累加器即可轻松解决此问题。