2013-10-26 2 views
1

Пока что моя программа может добавить два числа вместе.Реализация вычитания предикатов

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 .. Я был неправ, однако. Кто-нибудь знает, куда пойти с этим?

ответ

2

Каждая цифра может быть представлена ​​только в одном из этих 3-х способов:

  • 0 - нуль;
  • 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))). 
Смежные вопросы