3

I'm currently trying to practice some Prolog. I just started and I'm facing a problem I don't quite understand. I want to determine recursively if one Peano number is the double of another one. I tried to solve it like this:

isDouble(0, X,X).
isDouble(s(Peano1), Peano1, Peano2) :-
    isDouble(Peano1, s(Peano1), Peano2).

For some reason it doesn't work. Does anyone know why?

false
  • 10,264
  • 13
  • 101
  • 209
cybel
  • 381
  • 2
  • 6
  • 16
  • I can't see what you input it and so i also can't see what you are expecting! Do you want them to be evaluated and add them up or just equal number of expressions? – Luai Ghunim Nov 21 '17 at 19:23
  • My input is isDouble(s(s(0)), s(s(0)), s(s(s(s(0))))). I would just like to have true or false as an answer. – cybel Nov 21 '17 at 19:28
  • 2
    You are confusing here something. I assume you need: `isDouble(X, Z) :- sum(X, X, Z).` with the [common definition](https://stackoverflow.com/q/27202175/772868) of `sum/3`. – false Nov 21 '17 at 21:04

1 Answers1

5

You don't need three arguments to define such a predicate. Just consider what relation it should describe: a relation between a number and its double. Hence you only need two arguments and two rules describing the two possibilities. Either the number is zero, then its double is zero as well. Otherwise you have a difference of two s/2 for the double in every recursion but only one for the number:

nat_double(0,0).
nat_double(s(X),s(s(Y))) :-
   nat_double(X,Y).

This yields the desired results:

?- nat_double(X,Y).
X = Y, Y = 0 ;                     % X=0, Y=0
X = s(0),                          % X=1
Y = s(s(0)) ;                      % Y=2
X = s(s(0)),                       % X=2
Y = s(s(s(s(0)))) ;                % Y=4
X = s(s(s(0))),                    % X=3
Y = s(s(s(s(s(s(0)))))) ;          % Y=6
X = s(s(s(s(0)))),                 % X=4
Y = s(s(s(s(s(s(s(s(0)))))))) ;    % Y=8
.
.
.

Or if you want to test a pair as suggested in the comments:

?- nat_double(s(s(0)),s(s(s(s(0))))).
true.

EDIT:

If you insist on the interface isDouble/3, as your comment suggests, then you could define it as a calling predicate for nat_double/2 like so:

isDouble(X,X,Y) :-
   nat_double(X,Y).

That yields the desired result for your example:

?- isDouble(s(s(0)),s(s(0)),s(s(s(s(0))))).
true.
tas
  • 8,100
  • 3
  • 14
  • 22
  • 1
    Thank you for your answer, but I actually my input would look like this `isDouble( s(s(0)), s(s(0)), s(s(s(s(0)))))`, so all I need would be an answer with true or false. – cybel Nov 21 '17 at 19:40
  • 1
    @AnneKunstmann: I updated my post to address your comment :-) – tas Nov 21 '17 at 19:49