Basic primality test predicate in Prolog - prolog

I am trying to create a predicate isPrime/1 that checks if a given number is prime or not. I have come up with the following code:
primeRec(_, 2).
primeRec(X, Y) :- Y > 2, X mod Y-1 > 0, primeRec(X, Y-1).
isPrime(2).
isPrime(X) :- X > 1, X mod 2 > 0, primeRec(X, X).
but it does not seem to work, and I have no idea why. I've found my code to follow the same idea as this one here, except that mine always returns false. for any ?- isPrime(X). with X bigger than 2, which obviously should not happen.

The problem is that you need to define another variable, say Y1, and unify it with the evaluation of Y-1, i.e., Y1 is Y - 1 and use Y1 instead of Y-1 in the second rule for primeRec/1. This because if you want to evaluate an arithmetic expression you need to use is.
primeRec(X, Y) :- Y > 2, Y1 is Y - 1, X mod Y1 > 0, primeRec(X, Y1).

Related

define predicate prolog by requirements

I have to define a predicate p(X, Y), where Y = f(X) where
How could I define the predicate, according to this requirements?
Almost the same way it's written there, three cases for Y's value given different X conditions:
f(X, Y) :- X < 4, Y is X ^ 2 - 1.
f(X, Y) :- X >= 4, X =< 6, Y is sqrt(X) + 1.
f(X, Y) :- X > 6, Y is 9 - X.
or the middle case
f(X, Y) :- between(4, 6, X), Y is sqrt(X) + 1.
which I had originally and find more readable, but changes the behaviour for that case, which is a tradeoff.
Then:
:- f(3, Y).
Y = 8
( zcompare/3 hints at a way to get rid of the choice points without using cut !, but only if you restrict to integers ).
Another way that doesn't leave choice points behind...
f(X,Y) :- X < 4 -> Y is X^2 - 1 ;
X =< 6 -> Y is sqrt(X) + 1 ;
Y is 9 - X .

Prolog - print the sum of the EVEN numbers from 1 to 10

I am trying to print all the even numbers from 1 to 10 using Prolog, and here is what I have tried:
printn(10,0):- write(10),!.
printn(X,Sum):-
( X mod 2 =:= 0 -> Sum is X+Sum, Next is X+1, nl, printn(Next);
Next is X+1, printn(Next) ).
but it returns false.
You don't need to create the list with the numbers from the beginning, it is better to examine numbers once:
print(X,Y):-print_even(X,Y,0).
print_even(X, X, Sum):-
( X mod 2 =:= 0 -> Sum1 is X+Sum;
Sum1 = Sum
), print(Sum1).
print_even(X, Y, Sum):-
X<Y, Next is X+1,
( X mod 2 =:= 0 -> Sum1 is X+Sum, print_even(Next, Y, Sum1);
print_even(Next, Y, Sum)
).
Keep in mind that in Prolog Sum is Sum+1 always fails you need to use a new variable e.g Sum1.
Example:
?- print(1,10).
30
true ;
false.
The most useful way of obtaining Prolog output is to capture the solution in a variable, either individually through backtracking, or in a list. The idea of "printing", which carries over from using other languages allows for formatting, etc, but is not considered the best way to express a solution.
In Prolog, you want to express your problem as a relation. For example, we might say, even_with_max(X, Max) is true (or succeeds) if X is an even number less than or equal to Max. In Prolog, when reasoning with integers, the CLP(FD) library is what you want to use.
:- use_module(library(clpfd)).
even_up_to(X, Max) :-
X in 1..Max,
X mod 2 #= 0, % EDIT: as suggested by Taku
label([X]).
This will yield:
3 ?- even_up_to(X, 10).
X = 2 ;
X = 4 ;
X = 6 ;
X = 8 ;
X = 10.
If you then want to collect into a list, you can use: findall(X, even_up_to(X), Evens).
What error do you have? Here is my solution:
Create list [1...10]
Filter it, excluding odd numbers
Sum elements of the list
Code:
sumList([], 0).
sumList([Head|Tail], Sum) :-
sumList(Tail, Rest),
Sum is Head + Rest.
isOdd(X) :-
not((X mod 2) =:= 0).
sumOfEvenNums(A, B, Out) :-
numlist(A, B, Numbers),
exclude(isOdd, Numbers, Even_numbers),
sumList(Even_numbers, Out).
Now you can call sumOfEvenNums(1, 10, N)
In ECLiPSe, you can write with iterator:
sum_even(Sum):-
( for(I,1,10),fromto(0,In,Out,Sum)
do
(I mod 2 =:= 0 -> Out is In + I;Out is In)
)
With library(aggregate):
evens_upto(Sum) :-
aggregate(sum(E), (between(1, 10, E), E mod 2 =:= 0), Sum).
Thanks to #CapelliC for the inspiration.

How to print all the facts in prolog

I am a beginner and I am using SWI Prolog to write a rule to print all the facts about addition of two numbers.The following is the code:
addition(X,Y,Z) :- Z is X+Y.
add(X,Y):-
between(X,Y,A),
addition(X,A,Z),
writeln(addition(X,A,Z)),
X1 is X+1,
add(X1,Y).
And the following is the output:
1 ?- add(1,2).
addition(1,1,2)
addition(2,2,4)
addition(1,2,3)
addition(2,2,4)
false.
As you can see the output addition(2,2,4) is repeating and addition(2,1,3) is missing. What am I doing wrong here??
addition/3 is a "rule", or a "predicate", not a fact. Anyway, you have defined it as:
% addition(X, Y, Z)
% Z is the sum of the integers X and Y
Now you want to apply this predicate to (and I am guessing here) each pair X and Y such that X is between A and B and Y is between A and B:
% add(A, B, Addition)
% Add all numbers X and Y that are between A and B
add(A, B, addition(X, Y, Z)) :-
between(A, B, X),
between(A, B, Y),
addition(X, Y, Z).
You will notice that you don't need recursion (or iteration): you can use the fact that between/3 is non-deterministic and will create choice points that will be evaluated on backtracking.
You can now call it like this:
?- add(1, 2, A).
A = addition(1, 1, 2) ;
A = addition(1, 2, 3) ;
A = addition(2, 1, 3) ;
A = addition(2, 2, 4).
You can press the ; or space to backtrack and evaluate the next solution.
The third argument to add/3 is unified with the term addition/3 in the head of add/3. It happens to have the same name as the predicate addition/3, but it could have been called anything.
If you insist on printing it out from a single call, you could use forall/2:
?- forall(add(1, 2, A), format('~q', [A])).

Prime factorization in prolog

I'm new to Prolog. I read this code which finds prime factors of an integer:
factors(1,[1]) :-
true, !.
factors(X,[Factor1|T]) :-
X > 0,
between(2,X,Factor1),
NewX is X // Factor1, (X mod Factor1) =:= 0,
factors(NewX,T), !.
And changed it to this one:
factors(1,[[1,1]]) :-
true, !.
factors(X,[Factor1|T]) :-
X > 0,
( is_list(Factor1),
length(Factor1, 2),
Factor1 = [Base|A],
A = [Pow],
between(2,X,Base),
between(1,100,Pow),
NewX is X / (Base ** Pow),
(X mod Base) =:= 0,
(NewX mod Base) =\= 0
),
factors(NewX,T), !.
Well the first one works perfect, but the latter doesn't respond to queries. i.e. when I enter:
factors(2,[[2,1],[1,1]]).
I get 'true', but when I enter:
factors(2,X).
I get 'false'.
Because Base and Pow aren't bound to anything yet (they are parts of the X that you pass), you can't compute NewX (and the betweens might not work, either).
When you enter factors(2,X), Factor1 is not bound and is_list(Factor1) fails.
I think your code
is_list(Factor1),
length(Factor1, 2),
Factor1 = [Base|A],
A = [Pow]
can be abbreviated to Factor1 = [Base,Pow]. Since Factor1 is not used anywhere else, you can move [Base,Pow] into the head of the clause.
You can omit true, it has no effect here. The parenthesis haven't any effect, neither. So your code could be written as:
factors(1,[[1,1]]) :- !.
factors(X,[[Base,Pow]|T]) :-
X > 0,
between(2,X,Base),
between(1,100,Pow),
NewX is X / (Base ** Pow),
(X mod Base) =:= 0,
(NewX mod Base) =\= 0,
factors(NewX,T), !.
On my system (using SICStus), one must use
NewX is X // floor(Base ** Pow)
to prevent that NewX becomes a float which leads to an error when passed to mod as argument.
Edit: I originally wrote that the last cut had no effect. That is not true because between/2 creates choice points. I removed that part of my answer and put the cut back into the code.

print even number using prolog:

How can I print just even numbers in Prolog? This is my code to print numbers from 3 to 1: And how using mult without (*) in anthor example:
predicates
count(integer).
clauses
count(1) :- write(1), nl, !.
count(X) :- X > 1, write(X), nl, X1 = X-1, count(X1), !.
How can I print just even numbers in Prolog
?- between(1, 3, X), X mod 2 =:= 0.
X = 2.
ДМИТРИЙ МАЛИКОВ did a nice, concise method. The one below just builds on the approach that was started:
predicates
count(integer).
clauses
count(X) :-
X /\ 1 =:= 1, !, % Using bitwise AND (/\) to check for odd
X1 is X - 1,
count(X1).
count(X) :-
X > 1,
write(X), nl,
X1 is X - 2,
count(X1).
| ?- count_even(7).
6
4
2
I used bitwise AND (/\) to check the parity of the number just to illustrate a different method. The mod operator works just as well.
Note that for arithmetic expression assignment in prolog, you need is, not =. is will calculate the expression on the right and unify the result to the uninstantiated variable on the left. = will not evaluate the expression.

Resources