I want to find all the divisors of a natural number.and output a list.
now my code looks like this:
divisors(0,[]).
divisors(N,[N1|P]):-
N1=N,
RES is (N mod N1),
N1 is N-1,
RES==0,
divisors(N,P).
divisors(N,[N1|P]):-
N1=N,
RES is (N mod N1),
N1 is N-1,
RES\=0,!, fail.
but it doesn't work. tell me, what am I doing wrong?
I've seen what can be done via findall, but I want to do it differently.The idea is as follows. Subtract one from the number (whose divisors we are looking for) each time and if the original number is divided by a new number, then write it to the head of the list.
(I just realized..That I don 't remember N anywhere ..since with recursive calls, it will already be different. I'm completely confused..)
(I just realized..That I don 't remember N anywhere ..since with recursive calls, it will already be different. I'm completely confused..)
That's right, there is no concept of nested scope in Prolog. Instead, we pass everything we need further down among the predicate's arguments, possibly using additional arguments.
Minimal edit to fix your code:
divisors(N,L):- divisors(N,N,L).
divisors(N,0,[]):- !.
divisors(N,N1,[N1|P]):- % use N1
%N1=N,
RES is (N mod N1),
N2 is N1-1,
RES==0,
divisors(N,N2,P).
divisors(N,N1,P):- % skip N1
%N1=N,
RES is (N mod N1),
N2 is N1-1,
RES\=0, %!, fail
divisors(N,N2,P). % same P
The result list L is instantiated in the top-down fashion.
Examples:
49 ?- divisors(12,L).
L = [12, 6, 4, 3, 2, 1].
50 ?- divisors(37,L).
L = [37, 1].
The brute force way of finding all the divisors of a natural number would be something like this:
divisors( 0 , [] ) . % zero is a special case
divisors( N , Ds ) :- % otherwise, the general case applies
integer(N), % - N must be an integer, and
N > 0, % - N must be positive (and greater than 0)
divisors(1,N,Ds) % - invoke our helper predicate to try all possible divisors from 1–N inclusive
. % - Easy!
divisors( D , N , [D|Ds] ) :- % case 1: D is a divisor of N
D < N , % - D must be less than N, and
0 =:= N mod D, % - D must be an integer divisor of N,
!, % - eliminate the choice point
D1 is D+1, % - increment D
divisors(D1,N,Ds) % - recurse down, with D prepended to the result list
. %
divisors( D , N , Ds ) :- % case 2: D is not a divisor of N
D < N , % - D must be less than N, and
0 =\= N mod D, % - D must not be an integer divisor of N
!, % - eliminate the choice point
D1 is D+1, % - increment D
divisors(D1,N,Ds) . % - recurse down, discarding the current D
divisors( N , N , [N] ) % case 3: every number is its own divisor.
. %
Related
The scenario is to mimic rolling 3 six-sided die in Prolog while trying to obey the recursive nature of prolog. This is easily done with the Fibonacci series
n_factorial(N, F) :-
N #> 0,
F #= N*F1,
N1 #= N-1,
n_factorial(N1, F1).
I'm having difficulty translating this to the dice paradigm, where we add a random number to the sum.
# N = number of dice, S = number of sides, R = result
roll_dice(N, S, R) :-
N1 #> 0,
R = random_between(1, S, R1),
N1 #= N-1,
roll_dice(N1, S, R1).
throws an error but neglects the sum anyway. I would normally use += in other languages.
A few things not quite right there:
R = random_between(1, S, R1) stores that structure in R, it does not generate random numbers.
R1 is used for "the random number you get for rolling one die" and "the sum of all the random numbers from rolling all the remaining dice" and it is unlikely those will be the same value, and when they isn't the same, that will fail.
There is no code to do the summing. (The equivalent of the Factorial video using F #= N * F1)
No recursive base case (the first line of the factorial from the video is not shown in your question, it is n_factorial(0, 1).). When N dice remaining gets down to 0, there is nothing to handle that case.
Here is one implementation:
:- use_module(library(clpfd)).
roll_dice(0, _, 0).
roll_dice(NDice, Sides, Sum) :-
NDice #> 0,
random_between(1, Sides, Roll),
Sum #= Roll + RunningTotal,
NDiceLeft #= NDice - 1,
roll_dice(NDiceLeft, Sides, RunningTotal).
while trying to obey the recursive nature of Prolog.
I guess that's important to understand; this can be done with less bolierplate and fewer temporary variables to name, e.g.:
roll_dice(NDice, Sides, Sum) :-
length(Rolls, NDice),
maplist(random(1, Sides), Rolls),
sum_list(Rolls, Sum).
which makes a list Rolls the right size to hold all the rolls, fills them in using maplist to apply random on each of them, and sums that list for the answer.
I'd do something along the lines of:
roll(N,S,R) :- positive_int(N), positive_int(S), roller(N,S,0,R) .
positive_int(N) :- integer(N), N > 0 .
roller(0,_,R,R) .
roller(N,S,T,R) :-
T1 is 1+random(S),
N1 is N-1,
roller(N1,S,T1,R)
.
So I'm trying to work out in Prolog how to take an input, and return whether it is a perfect number or not. Currently i'm close but can't figure out why it isn't working the way I want.
I am approaching this through recursion. If X %N == 0, then N and TT(total) is added to TT1. N will decrease by one and the function will be called recursively until it reaches 1, then the total will be compared to the input number X.
My code is:
factors(X,N,TT) :-
( 0 is X mod N -> TT1 is N + TT ),
TT = TT1,
( N > 1 -> N1 is N-1, factors(X, N1, TT1)
; TT1 = X
).
perfect(X) :-
factors(X, X-1, 0).
Currently it is returning that all inputs are false. I hope this isn't majorly incorrect and only needs to be tweaked.
Cheers
Here a solutions, hope it helps
factors(_,N,N,_).
factors(X,N,NT,Sum):-
N < NT,
( 0 is X mod N ->
Sum1 = Sum + N
; Sum1 = Sum),
N1 is N + 1,
factors(X,N1,NT,Sum1).
perfect(X):-
XT is X/2 + 1,
factors(X,1,XT,0).
I am trying to calculate if the input is a prime number but something goes wrong... here's my code:
primeNumber(X):-
prime_prime(A, 1).
prime_prime(A, B):-
R is A mod B,
R =:= 1,
R =:= A.
prime_prime(X, B):-
B < A,
Next is B + 1,
prime_prime(A, Next).
It gives me false every time. Anyone got any clues or idea on what I am doing wrong?
See http://www.swi-prolog.org/pldoc/man?function=mod/2:
+IntExpr1 mod +IntExpr2
Modulo, defined as Result = IntExpr1 - (IntExpr1 div IntExpr2) × IntExpr2, where div is floored division.
So R should be 0. mod has only one result.
A working solution would be:
primeNumber(A) :-
A > 1, % Negative numbers, 0 and 1 are not prime.
prime_prime(A, 2). % Begin iteration:
prime_prime(A, B) :- % Test if A divides by B without remainder
B >= A % The limit was reached?
-> true % Then it's prime.
; 0 is A mod B % B divides A without a remainder?
-> false % Then it's not prime.
; succ(B, C), % Otherwise: C is B + 1
prime_prime(A, C). % Test if C divides A.
By the way, primeNumber/1 (a predicate named primeNumber, with one argument) is a totally separate predicate from primeNumber/2 (same name, two arguments). A "subfunction" that only gets an extra argument for the start value, is usually given the same name. So instead of prime_prime you should just use primeNumber, though in Prolog you normally don't use camelCase.
Using the optimization that Sergei Lodyagin proposed in the comments:
primeNumber(A) :-
A > 1, % Negative numbers, 0 and 1 are not prime.
sqrt(A, L), % A prime factor of A is =< the square root of A.
prime_prime(A, 2, L). % Begin iteration:
prime_prime(A, B, L) :- % Test if A divides by B without remainder
B >= L % The limit was reached?
-> true % Then it's prime.
; 0 is A mod B % B divides A without a remainder?
-> false % Then it's not prime.
; succ(B, C), % Otherwise: C is B + 1
prime_prime(A, C, L). % Test if C divides A.
And if you use the predefined predicate between(+Low, +High, ?Value):
primeNumber(A) :-
L is floor(sqrt(A)),
\+ (between(2, L, X),
0 is A mod X).
And to reduce the number of iterations even further, you only need to test for odd modules:
primeNumber(2).
primeNumber(A) :-
A > 2,
\+ 0 is A mod 2,
L is floor(sqrt(A) / 2),
\+ (between(1, L, X),
0 is A mod (1 + 2*X)).
Kay already provided a working modification of the broken program. I'll provide a simple analysis of what's broken.
When solving a problem in Prolog, it's good to be able to write out logically what it is you want first. In this case, it appears that you want to declare that:
A number, A, is prime if, for each number B < A, the value of A mod B is non-zero.
There are probably a couple of ways to render this directly into Prolog, of which Kay shows one.
However, the way your original rules are written, they say:
A number, A, is prime if:
(Rule 1) The value of A mod B, for a given value of B, is 1 and is also A.
OR (Rule 2) B < A and Rule 1 is satisfied with A and B+1.
As you can see, the rules as defined have a few issues:
The rules don't match the logical definition of prime described in terms of the modulo relationship between the original number and all the numbers less than itself.
The first rule expects an impossible mathematical condition when A is not equal to 1 (remember, the comma [,] in Prolog is a conjunction)
The rules are initiated with starting divisor of 1, which is probably bad since 1 divides everything and is likely to become an exception to any rules that work
EDIT
Getting back to the first definition of a prime using the modulo operator, we can translate that into Prolog as follows:
is_prime(N) :- % N is prime if...
N > 1, % N > 1, and
non_divisible_from(N, 2). % N is non-divisible by everything from 2 to N-1
non_divisible_from(N, D) :- % N is non-divisible by D through N-1 if...
N =< D. % D >= N
% --OR--
non_divisible_from(N, D) :- % N is non-divisible from D to N-1 if...
N > D, % N > D, and
N mod D =\= 0, % N is non-divisible by D, and
D1 is D + 1, % N is non-divisible by D+1 to N-1
non_divisible_from(N, D1).
This logic is basically the same as Kay's except he's using a Prolog if-then-else construct.
I'm new in SWI-Prolog and I want to check prime function in Prolog.
prime(N) :-
N > 1,
M is N - 1,
check(N, M).
check(_, 1).
check(N, M) :-
M > 1,
R is N - M * N / M,
R > 0,
P is M - 1,
check(N, P).
but when I ask 2 + 2 or another operator like (*)/2, (/)/2,... in Prolog it says: undefined procedure: (+)/2.
I think it is for see or tell. I reassign see(user) and tell(user) but this error occurs again.
why?
In SWI prolog 6.0.2 division as you used it returns floating point number. So prime(13) for example will fail, as remainder is 0. Integer division uses operator //. But check prolog SWI functions rem and mod.
Also you would like to have a cut after first definition of check, otherwise prolog will explore the second definition, which will return false. Cut ensures that after it checked all natural numbers smaller than N, it stops with success.
Here is the corrected code which behaves as desired in SWI Prolog 6.0.2.
prime(N) :-
N > 1,
M is N - 1,
check(N, M).
check(_, 1) :- !.
check(N, M) :-
M > 1,
R is N mod M,
R > 0,
P is M - 1,
check(N, P).
About your error, check this out:
?- 2+2.
ERROR: Undefined procedure: (+)/2
?- X is 2+2.
X = 4
You're supposed to use is in Prolog to force the evaluation of arithmetic expressions. Try typing "help(is)." at SWI-Prolog's prompt.
But your algorithm is massively inefficient, on two accounts. First, you check the candidate number for divisibility by all its preceding numbers, while only those not greater than its square root are enough (if a*b=n and a >= sqrt(n) then b =< sqrt(n)).
Then, you test in reversed order. Multiples of smaller factors are much more frequent than of larger ones, so the testing will get cut off much much earlier when done in ascending order, making the overall program run much much faster. Lastly, no need to test by any even number except 2:
prime(2).
prime(N) :- N > 1,
N mod 2 > 0, % is odd
M is floor(sqrt(N+1)), % round-off paranoia
check(N, M, 3).
check(N, M, F) :- F>M.
check(N, M, F) :- F=<M,
N mod F > 0,
F1 is F + 2, % test by odds only
check(N, M, F1).
primesFromTo(F,T,X):-
between(F,T,X), prime(X).
You are mentioning see and tell: These are very old-fashioned built-in predicates. Better avoid them. Use [file] to load a file, and make to reload it.
For a better implementation of testing primes, see this answer.
I've got a predicate taking a single argument. When there is a solution, this single argument should equal some other argument I have (I have a predicate that goes from one argument to three).
I can print the solution easily to see that the algorithm works. However, I just get false/no when the program runs. I think this is something to do with me giving the program a variable and asking it to return the same variable but altered by the program's execution. I've never had this situation before.
Any ideas guys?
If anyone as any suggestions about the code as a whole then I would welcome comments about that too.
Thanks very much and happy new year :).
% Eulers totient function
phi( M ) :-
phi( 0, 0, M ).
phi( Count, Inter, M ) :-
Count = M,
print(Inter),
M is Inter.
phi( Count, Inter, M ) :-
Count \= M,
coprime( Count, M ),
InterNew is Inter + 1,
CountNew is Count + 1,
phi( CountNew, InterNew, M ).
phi( Count, Inter, M ) :-
Count \= M,
\+ coprime( Count, M ),
CountNew is Count + 1,
phi( CountNew, Inter, M ).
UPDATE: This problem is one of the '99 Prolog problems' at : http://sites.google.com/site/prologsite/prolog-problems/2 and it's question 2.09.
UPDATE: coprime/2 predicate was asked for:
% coprime is defined as two integers having a gcd of 1
coprime( X, Y ) :-
gcd( X, Y, 1 ).
which uses gcd predicate:
% calculating the greatest common divisor of two numbers
% recursive version of Euclidian algorithm
gcd( G, 0, G ).
gcd( Lo, Hi, G ) :-
Hi \= 0,
Inter is Lo mod Hi,
gcd( Hi, Inter, G ).
The false/no answer results from the call M is Inter, which tries to establish equality between the totient Inter and the input number M. Since φ(n) is never equal to n except when n = 1, this almost always fails.
You may have intended to assign the value of Inter to M, but this impossible because M is always bound.