0

I have to write a rule square(S) in Prolog that tests if a number S is the square of an integer returning false (ex. square(3)) or true (ex. square(4)). I used already a rule that generates all integers between 0 and M:

isInteger(X,M) :- between(0,M,X).

Using this generator I have to write the rule square(S). How can I do it? Thanks

Cœur
  • 37,241
  • 25
  • 195
  • 267
user1336326
  • 71
  • 1
  • 8

2 Answers2

1

This probably will not work as a solution for your homework, but here is one of many ways to do it using constraint logic programming in ECLiPSe CLP Prolog:

:- lib(gfd).
square(S) :-
    sqr(_) #= S.

It means: S is a square if it's an integer and some other value (we don't care what value, so we use "throw-out" variable _) squared equals S.

All modern Prolog systems supports constraint logic programming, and the code will be similar to above.

Sergii Dymchenko
  • 6,890
  • 1
  • 21
  • 46
0

To solve it your way, you just need to check if S is the product of your generated integer multiplied by itself. So you could do it like this:

isInteger(X,M) :- between(0,M,X).

square(N) :-
    isInteger(X, N),
    N is X * X.

I came up with another possible solution, using the sqrt arithmetical function from SWI-Prolog but I think there must be a more elegant one.

I initially expected it would be as simple as X is sqrt(4), integer(X). However, this doesn't work (at least not in SWI-Prolog 7.1.4), because X is unified with the float 2.0 and integer(2.0) is false (since integer is checking the data type, not the value of the number). But this works:

square_of_integer(N) :-
    Int is rationalize(sqrt(N)),
    integer(Int).

It depends on first giving a representation of N as a rational (which, in SWI-Prolog, 'are represented by the compound term rdiv(N,M)'). 2 is rationalize(2.0), i.e., rationalize evaluates to an integer for round numbers.

Shon
  • 3,989
  • 1
  • 22
  • 35