到目前为止,我的程序可以将两个数字加在一起。
s(0)
代表1
,s(s(0))
代表2
,依此类推
p(0)
代表-1
,p(p(0))
代表-2
等。
我希望能够调用一个程序
add2(s(s(0)), p(0), Z).
返回
Z = s(0).
我的代码如下:
numeral(0).
numeral(s(X)) :- numeral(X).
add(0,X,X).
add(s(X),Y,s(Z)) :- add(X,Y,Z).
numeral(X+Y) :- numeral(X), numeral(Y).
add2(X,Y,Z):-add(X,Y,Z).
add2(X+Y, Z,A) :-add(X,Y,R),add2(R,Z,A).
add2(Z,X+Y,A) :-add(X,Y,R),add2(Z,R,A).
numeral(p(X)) :- numeral(X).
add2(p(X),Y,p(Z)) :- add2(X,Y,Z).
p(s(X)) =:= 0.
s(p(X)) =:= 0.
我的逻辑是,如果列表中有p(s(0))
,它只会将其等同于0
。但是我错了。有人知道该去哪儿吗?
答案 0 :(得分:2)
每个数字只能用以下三种方式之一表示:
0
- null; s(X)
- 接下来,其中X
是数字; p(X)
- 之前,其中X
是数字; add2/3
应该取2个数字并返回它们的总和。可以为每个可能的参数手动定义:
add2(0, 0, 0).
add2(0, s(X), Y) :- Y = s(X).
add2(0, p(X), Y) :- Y = p(X).
add2(s(X), 0, Y) :- Y = s(X).
add2(s(X), s(Y), Z) :- add2(X, Y, s(s(Z))).
add2(s(X), p(Y), Z) :- add2(X, Y, Z).
add2(p(X), 0, Y) :- Y = p(X).
add2(p(X), s(Y), Z) :- add2(X, Y, Z).
add2(p(X), p(Y), Z) :- add2(X, Y, p(p(Z))).
效果很好:
?- add2(s(s(0)), p(0), Z).
Z = s(0) .
值得注意的是,add2/3
规则的许多案例实际上是重叠的,可以消除:
add2(0, X, X).
add2(X, 0, X).
add2(s(X), s(Y), Z) :- add2(X, Y, s(s(Z))).
add2(s(X), p(Y), Z) :- add2(X, Y, Z).
add2(p(X), s(Y), Z) :- add2(X, Y, Z).
add2(p(X), p(Y), Z) :- add2(X, Y, p(p(Z))).