Sum of random digits in Prolog - prolog

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)
.

Related

prolog list of all divisors of a number

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.
. %

Sum to a number program in Prolog

Can someone explain how this code works. I am new to Prolog and I am having trouble thinking like a Prolog programmer.
When you input a number followed by a comma and any variable name, it gives you the sum up to that number
sum_to(1,1) :- !.
sum_to(N, R) :- N1 is N-1, sum_to(N1,TR), R is TR + N.
So sum_to(4, N) gives N = 10.
Your definition can be equivalently written as
sum_to( N, R) :- N = 1, R = 1, !.
sum_to( N, R) :- N1 is N-1, sum_to( N1, R1), R is R1+N.
This is a recursive definition -- it contains a call to the same predicate as the predicate itself. Under the condition that you're going to always call it with a free variable as the second argument and a concrete (hopefully positive) number as the first argument, it expresses a function which calculates the second argument's value from the given first argument.
Thus what you have is a recursive functional definition.
Now let's work through some examples, from the simplest to the progressively more and more complex:
sum_to( 1, R1) :- 1 = 1, R1 = 1, !.
\______________/
R1 = 1.
sum_to( 2, R2) :- N1 is 2-1, sum_to( N1, R1), R2 is R1+2.
\________/
N1 is 1, sum_to( 1, R1),
\____________/
R1 = 1, R2 is 1+2
\_____________________________________/
R2 = 3.
sum_to( 3, R3) :- N2 is 3-1, sum_to( N2, R2), R3 is R2+3.
\________/
N2 is 2, sum_to( 2, R2),
\____......____/
\__________________/
R2 = 3, R3 is 3+3
\_____________________________________________/
R3 = 6.
Right? As the execution progresses through the goals left to right, our variables take on their concrete values one after the other, thus enabling the execution of the next goal, and the next, which instantiate yet more variables, until the final value becomes known.
Now do sum_to( 4, R4).
This is a very imperative-style program implementing an inductive definition concidentally written in Prolog.
It relates two numbers:
In the first clause 1 is related to 1. The ! indicates that the interpreter should stop looking for further solutions in the sum_to/2 predicate.
If the first clause doesn't match (because any of the arguments in the call was different from 1) then the second clause is examined.
And now we simply:
Compute N1 as N-1
Make a recursive call with N1, and getting a value in TR such that N1 and TR are related via sum_to/2 (i.e. TR should be the sum of all integers up to N1). Once we get that, we compute R as the sum of TR and N.
The sum_to relation is correct for the first argument being 1.
The sum_to relation at N is correct if the sum_to relation is correct for N-1.
Computation will terminate if the recursive call "makes something smaller" on each call and will eventually hit a smallest value. It does indeed make N smaller on each call and will eventually hit 1. (Unless one calls this predicate with a 0 N or smaller. Then: catastrophe!)
Looking good.
(Incidentally, inductive definitions tend to go from a constant x to +oo, i.e. "going upwards"; above I am stating correctness moving from any N down towards 1. Am I justified in doing so?)

Calculating whether number is prime in Prolog

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.

ERROR: Undefined procedure: (+)/2

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.

Prolog: Simple program outputting solutions

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.

Resources