help please I need to find ((2n-1)!!) \ (2n)!! but I only know how to write factorial not double.
factorial(0,1).
factorial(N,F) :-
N>0,
N1 is N-1,
factorial(N1,F1),
F is N * F1.
If you look up the Wikipedia entry on double factorial you can easily spot the two candidates for base cases: 0!! = 1 and 1!! = 1. Depending on the number n being odd or even you'll arrive at one of those base cases when calculating n!! recursively because, in the recursive rule, n is decreased by 2 instead of 1 (compared to n!). You can express that in Prolog like so:
doublefactorial(0,1).
doublefactorial(1,1).
doublefactorial(N,F) :-
N > 1,
N2 is N-2,
doublefactorial(N2,F1),
F is N * F1.
If you query this predicate you'll get the desired result:
?- doublefactorial(0,F).
F = 1 ;
false.
?- doublefactorial(1,F).
F = 1 ;
false.
?- doublefactorial(2,F).
F = 2 ;
false.
?- doublefactorial(3,F).
F = 3 ;
false.
?- doublefactorial(4,F).
F = 8 ;
false.
?- doublefactorial(5,F).
F = 15 ;
false.
.
.
.
However, due to the use of >/2 and is/2, this predicate can only be used in one direction:
?- doublefactorial(N,10395).
ERROR: >/2: Arguments are not sufficiently instantiated
?- doublefactorial(N,F).
N = 0,
F = 1 ;
N = F, F = 1 ;
ERROR: >/2: Arguments are not sufficiently instantiated
If you'd like to use the predicate in all directions you could opt to use CLP(FD):
:- use_module(library(clpfd)).
doublefactorial2(0,1).
doublefactorial2(1,1).
doublefactorial2(N,F) :-
N #> 1,
N2 #= N-2,
F #= N * F1,
doublefactorial2(N2,F1).
?- doublefactorial2(N,10395).
N = 11 ;
false.
?- doublefactorial2(N,46080).
N = 12 ;
false.
?- doublefactorial2(N,F).
N = 0,
F = 1 ;
N = F, F = 1 ;
N = F, F = 2 ;
N = F, F = 3 ;
N = 4,
F = 8 ;
N = 5,
F = 15 ;
N = 6,
F = 48 ;
N = 7,
F = 105 ;
N = 8,
F = 384 ;
N = 9,
F = 945 ;
.
.
.
Note how the goal F #= N * F1 can now be put in front of the recursive goal, thus making the predicate tail-recursive, because that equation is now propagated as a constraint. For more information see the SWI-Prolog documentation on CLP(FD).
To calculate (2n)!!/(2n-1)!! or (2n-1)!!/(2n)!! for a particular n you can query the the predicate like this:
?- N=5, X #= 2*N, doublefactorial2(X,F1), Y #= 2*N-1, doublefactorial2(Y,F2), RESULT is F1/F2.
N = 5,
X = 10,
F1 = 3840,
Y = 9,
F2 = 945,
RESULT = 4.063492063492063 ;
false.
?- N=5, X #= 2*N, doublefactorial2(X,F1), Y #= 2*N-1, doublefactorial2(Y,F2), RESULT is F2/F1.
N = 5,
X = 10,
F1 = 3840,
Y = 9,
F2 = 945,
RESULT = 0.24609375 ;
false.
Note that the result is actually calculated using is/2. This is because, in general, the result is not an integer but a rational number, hence you can use CLP(Q) to get the result as a fraction:
?- use_module(library(clpq)).
% library(clpq) compiled into clpq 0.08 sec, 1,189 clauses
true.
?- N=5, X #= 2*N, doublefactorial2(X,F1), Y #= 2*N-1, doublefactorial2(Y,F2), {RESULT = F1/F2}.
N = 5,
X = 10,
F1 = 3840,
Y = 9,
F2 = 945,
RESULT = 256 rdiv 63 ;
false.
?- N=5, X #= 2*N, doublefactorial2(X,F1), Y #= 2*N-1, doublefactorial2(Y,F2), {RESULT = F2/F1}.
N = 5,
X = 10,
F1 = 3840,
Y = 9,
F2 = 945,
RESULT = 63 rdiv 256 ;
false.
For more details see the SWI-Prolog documentation on CLP(Q). Due to the use of CLP(FD) you can also query for a range of n, say 1 to 5:
?- N in 1..5, X #= 2*N, doublefactorial2(X,F1), Y #= 2*N-1, doublefactorial2(Y,F2), {RESULT = F1/F2}.
N = Y, Y = F2, F2 = 1,
X = F1, F1 = RESULT, RESULT = 2 ;
N = 2,
X = 4,
F1 = 8,
Y = F2, F2 = 3,
RESULT = 8 rdiv 3 ;
N = 3,
X = 6,
F1 = 48,
Y = 5,
F2 = 15,
RESULT = 16 rdiv 5 ;
N = 4,
X = 8,
F1 = 384,
Y = 7,
F2 = 105,
RESULT = 128 rdiv 35 ;
N = 5,
X = 10,
F1 = 3840,
Y = 9,
F2 = 945,
RESULT = 256 rdiv 63 ;
false.
Related
I'm trying to implement n_factors/2 predicate that works in all directions.
:- use_module(library(clpz)).
n_factors(N, Fs) :-
integer(N),
N > 1,
primes(Ps),
n_factors0(N, Fs, Ps),
!.
n_factors(N, Fs) :-
var(N),
primes(Ps),
N #> 1,
above(2, N),
n_factors0(N, Fs, Ps).
above(I, I).
above(I, N) :- I1 is I + 1, above(I1, N).
n_factors0(N, [F|Fs], [P|Ps]) :-
N #> 1,
F #=< N,
P #=< N,
( P * P #> N ->
F = N, Fs = []
; ( N #= N1 * P ->
F #= P, n_factors0(N1, Fs, [P|Ps])
; F #> P, n_factors0(N, [F|Fs], Ps)
)
).
When I am issuing the following query I get:
?- C #> 6, C #< 12, n_factors(A, [B,C]).
C = 7, A = 14, B = 2
; C = 7, A = 21, B = 3
; C = 11, A = 22, B = 2
; C = 11, A = 33, B = 3
; C = 7, A = 35, B = 5
; C = 7, A = 49, B = 7
; C = 11, A = 55, B = 5
; C = 11, A = 77, B = 7
; C = 11, A = 121, B = 11
;
before the program moves on to exploring the realm of rather large numbers. So the question I've go is the following: knowing for certain that the mathematical problem is constraint enough to terminate, how do I find the missing constraint in my program? What I am doing right now is staring at the screen before trying to add "invariant" conditions here and there and see if they help.
primes(Ps) is a "frozen" infinite list with all prime numbers. I don't think the implementation thereof is important for this question but just in case
primes(Ps) :-
Ps = [2,3|T],
primes0(5, Ps, Ps, T),
!.
primes0(C, [D|Ds], Ps, T) :-
( D * D > C ->
T = [C|T1], C1 is C + 2, freeze(T1, primes0(C1, Ps, Ps, T1))
; ( C mod D =:= 0 ->
C1 is C + 2, primes0(C1, Ps, Ps, T)
; primes0(C, Ds, Ps, T)
)
).
I'm quite new to prolog and I am trying to write a predicate which gives the value of nth prime number and it looks like nth_prime(N, Prime) .
I have already done the function that counts if the number is prime or not
div(X, Y):- 0 is X mod Y.
div(X, Y):- X>Y+1, Y1 is Y+1, div(X, Y1).
prime(2):- true.
prime(X):- X<2, false.
prime(X):- not(div(X, 2)).
I don't understand what is my next step, and how I should count which prime belong to N.
Your code is a bit unusual for prolog but (with the exception of prime(1)) it works.
Here is a solution for your predicate:
nextprime(N,N):-
prime(N),
!.
nextprime(P, Prime):-
PP is P+1,
nextprime(PP,Prime).
nthprime(1, 2).
nthprime(N, Prime):-
N>1,
NN is N-1,
nthprime(NN, PrevPrime),
PP is PrevPrime+1,
nextprime(PP, Prime).
?- nthprime(1,P).
P = 2 ;
false.
?- nthprime(2,P).
P = 3 ;
false.
?- nthprime(3,P).
P = 5 ;
false.
It works as follows: It is known that the first prime number is 2 (nthprime(1, 2).). For every other number N larger than 1, get the previous prime number (nthprime(NN, PrevPrime)), add 1 until you hit a prime number. The add 1 part is done through a help predicate nextprime/2: for a given number P it will check if this number is a prime. If yes, it returns this number, otherwise it will call itself for the next higher number (nextprime(PP,Prime)) and forwards the output. The bang ! is called a cut which cuts the other choice branches. So if you once hit a prime, you can not go back and try the other path.
To test it you can ask ?- nthprime(N,P). for a given N. Or to check multiple answers at once, let's introdice a helperpredicate nthprimeList/2 which calls nthprime/2 for every item in the firstlist and puts the "output" into a list:
nthprimeList([],[]).
nthprimeList([N|TN],[P|TP]):-
nthprime(N,P),
nthprimeList(TN,TP).
?- nthprimeList([1,2,3,4,5,6,7,8,9],[P1,P2,P3,P4,P5,P6,P7,P8,P9]).
P1 = 2,
P2 = 3,
P3 = 5,
P4 = 7,
P5 = 11,
P6 = 13,
P7 = 17,
P8 = 19,
P9 = 23;
false.
Using your definitions, we define the following to count up and test all numbers from 2 and up, one after another:
nth_prime(N, Prime):-
nth_prime(N, Prime, 1, 2). % 2 is the candidate for 1st prime
nth_prime(N, P, I, Q):- % Q is I-th prime candidate
prime(Q)
-> ( I = N, P = Q
; I1 is I+1, Q1 is Q+1, nth_prime(N, P, I1, Q1)
)
; Q1 is Q+1, nth_prime(N, P, I, Q1).
Testing:
30 ?- nth_prime(N,P).
N = 1,
P = 2 ;
N = 2,
P = 3 ;
N = 3,
P = 5 ;
N = 4,
P = 7 ;
N = 5,
P = 11 .
31 ?- nth_prime(N,P), N>24.
N = 25,
P = 97 ;
N = 26,
P = 101 ;
N = 27,
P = 103 .
32 ?- nth_prime(N,P), N>99.
N = 100,
P = 541 ;
N = 101,
P = 547 ;
N = 102,
P = 557 .
I want to create a predicate divisors(X,[Y]) which is true if
X>1 and Y is the list of all divisors of X starting with X and going down to 1.
What my code right now looks like:
divisors(1,[1]).
divisors(X,[Y,Z|Ys]) :-
X>0,
Y is X,
Y>Z,
divides(X,[Z|Ys]).
divides(X,[Y,Z|Ys]) :-
Y>Z,
0 is X mod Y,
divides(X,[Z|Ys]).
divides(X,[1]).
But there are several problems with it:
prolog returns an error if asked for the list (e.g. ?-divisors(10,X).)
?- divisors(X,[Y]). Where [Y] is an incomplete list of divisors is true...
Edit by Guy Coder
This answer is by the OP and was posted in a comment below.
Moving here so others can see it.
divisors(X,R) :-
X > 1,
divisors(X,1,[],R).
divisors(X,D,R,R):-
D>X.
divisors(N,D0,R0,R) :-
divisors_0(N,D0,R0,R1),
D is D0 + 1,
divisors(N,D,R1,R).
divisors_0(N,D,R0,[D|R0]) :-
divides(N,D).
divisors_0(N,D,R0,R0).
divides(N,D) :-
0 is N mod D.
Op also noted some errors in this version:
It doesn't terminate if I ask a wrong statement like (10,[1,2,3]).
It throws an error if I ask a statement like (X, [10,5,2,1]). (-> Arguments are not sufficiently initialized.)
While the answer by William is nice and probably faster here is answer closer to what you were writing.
divides(N,D) :-
0 is N mod D.
divisors_0(N,D,R0,[D|R0]) :-
divides(N,D).
divisors_0(N,D,R0,R0) :-
\+ divides(N,D).
divisors(_,0,R,R).
divisors(N,D0,R0,R) :-
divisors_0(N,D0,R0,R1),
D is D0 - 1,
divisors(N,D,R1,R).
divisors(X,R) :-
X > 1,
divisors(X,X,[],R), !.
Example:
?- between(1,15,N), divisors(N,Rs).
N = 2,
Rs = [1, 2] ;
N = 3,
Rs = [1, 3] ;
N = 4,
Rs = [1, 2, 4] ;
N = 5,
Rs = [1, 5] ;
N = 6,
Rs = [1, 2, 3, 6] ;
N = 7,
Rs = [1, 7] ;
N = 8,
Rs = [1, 2, 4, 8] ;
N = 9,
Rs = [1, 3, 9] ;
N = 10,
Rs = [1, 2, 5, 10] ;
N = 11,
Rs = [1, 11] ;
N = 12,
Rs = [1, 2, 3, 4, 6, 12] ;
N = 13,
Rs = [1, 13] ;
N = 14,
Rs = [1, 2, 7, 14] ;
N = 15,
Rs = [1, 3, 5, 15].
Edit
OP modified their code, see update in question and had some errors.
This version resolves those errors.
divisors(X,R) :-
(
var(X)
->
false
;
(
var(R)
->
X > 1,
divisors(X,1,[],R)
;
divisors_2(X,R), !
)
).
divisors_2(_,[]).
divisors_2(X,[H|T]) :-
divides(X,H),
divisors_2(X,T).
divisors(X,D,R,R):-
D>X.
divisors(N,D0,R0,R) :-
divisors_0(N,D0,R0,R1),
D is D0 + 1,
divisors(N,D,R1,R).
divisors_0(N,D,R0,[D|R0]) :-
divides(N,D).
divisors_0(_,_,R0,R0).
divides(N,D) :-
0 is N mod D.
The first error: It doesn't terminate if I ask a wrong statement like divisors(10,[1,2,3]).
is fixed by adding to divisors/2
(
var(R)
->
X > 1,
divisors(X,1,[],R)
;
divisors_2(X,R), !
)
and
divisors_2(_,[]).
divisors_2(X,[H|T]) :-
divides(X,H),
divisors_2(X,T).
which just processes the list of denominators instead of generating a list.
The second error: It throws an error if I ask a statement like divisors(X, [10,5,2,1]). (-> Arguments are not sufficiently initialized.)
is resolved by further adding to divisor/2
divisors(X,R) :-
(
var(X)
->
false
;
(
var(R)
->
X > 1,
divisors(X,1,[],R)
;
divisors_2(X,R), !
)
).
which checks if the first parameter X is a variable and if so just returns false. The other option would be to generate an infinite list of answers. While possible it wasn't requested.
In Prolog, it is quite common to use backtracking and propose multiple solutions to the same query. Instead of constructing a list of dividers, we thus can construct a predicate that unifies the second parameter with all divisors. For example:
divisor(N, D) :-
between(1, N, D),
0 is N mod D.
This then yields:
?- divisor(12, N).
N = 1 ;
N = 2 ;
N = 3 ;
N = 4 ;
N = 6 ;
N = 12.
The above algorithm is an O(n) algorithm: we scan for divisors linear with the value of the item for which we want to obtain the divisors. We can easily improve this to O(√n) by scanning up to √n, and each time yield both the divisor (of course in case it is a divisor), and the co-divisor, like:
emitco(D, _, D).
emitco(D, C, C) :-
dif(D, C).
divisor(N, R) :-
UB is floor(sqrt(N)),
between(1, UB, D),
0 is N mod D,
C is N / D,
emitco(D, C, R).
This still yield the correct answers, but the order is like a convergent alternating sequence:
?- divisor(12, N).
N = 1 ;
N = 12 ;
N = 2 ;
N = 6 ;
N = 3 ;
N = 4.
?- divisor(16, N).
N = 1 ;
N = 16 ;
N = 2 ;
N = 8 ;
N = 4 ;
false.
We can obtain a list of the divisors by using a findall/3 [swi-doc] or setof/3 [swi-doc]. The setof/3 will even sort the divisors, so we can implement divisors/2 in terms of divisor/2:
divisors(N, Ds) :-
setof(D, divisor(N, D), Ds).
For example:
?- divisors(2, N).
N = [1, 2].
?- divisors(3, N).
N = [1, 3].
?- divisors(5, N).
N = [1, 5].
?- divisors(12, N).
N = [1, 2, 3, 4, 6, 12].
?- divisors(15, N).
N = [1, 3, 5, 15].
We can use reverse/2 to reverse that result.
I have the following prolog program:
square([H|T], X) :-
squareCompare(T, H, X).
squareCompare([], X, X * X ).
squareCompare([H|T], V, Result) :-
(V * V) < (H * H),
squareCompare(T, V, Result);
(V * V) > (H * H),
squareCompare(T, H, Result).
When I enter:
square([7, 5, 2], Result).
I get Result = 2 * 2, what I want is Result = 4.
This program searches for the smallest square of the element in the list.
Besides the lack of arithmetic evaluation (is/2) as pointed out in the comments there's also an issue with using </2 and >/2: your predicate doesn't work for list with consecutive repetitions, e.g.:
?- square([7,7],X).
false.
where the expected result would be 49. You can remedy that by replacing </2 by =</2 or >/2 by >=/2 in your recursive rule of squareCompare/3:
squareCompare([], X, Y) :-
Y is X*X.
squareCompare([H|T], V, Result) :-
(V * V) < (H * H),
squareCompare(T, V, Result);
(V * V) >= (H * H),
squareCompare(T, H, Result).
Now the predicate yields the desired result:
?- square([7,7],X).
X = 49.
Following another suggestion in the comments, you could opt to use CLP(FD) to make the predicate work both ways. In that case the predicate resembles a true relation so it'd be appropriate to give it a more descriptive name that reflects this fact, say list_minsquare/2. And since you are interested in the smallest square, why not pass around the squares as arguments rather than the numbers? Worst case: the root of the smallest square is the last list element, then there's no difference. Best case: the root of the smallest square is the first list element, then you only calculate it once instead of length-of-list times. Putting all this together:
:- use_module(library(clpfd)).
list_minsquare([H|T],X) :-
S #= H*H,
list_square_minsquare(T,S,X).
list_square_minsquare([],S,S).
list_square_minsquare([H|T],S,Result) :-
S #< (H*H),
list_square_minsquare(T,S,Result).
list_square_minsquare([H|T],S,Result) :-
H2 #= (H*H),
S #>= H2,
list_square_minsquare(T,H2,Result).
Now let's see some action. Your example query yields the desired result:
?- list_minsquare([7,4,2],X).
X = 4.
Consecutive repetitions also don't cause troubles:
?- list_minsquare([7,7],X).
X = 49.
Partially instantiated lists lead to all possible solutions being produced:
?- list_minsquare([7,Y,2],X).
X = 4, % <- 1st answer: X=4 if
Y^2#=_G670,
_G670 in 50..sup ; % Y^2 is between 50 and sup
Y in -1..1, % <- 2nd answer: if Y in -1..1
Y^2#=X, % then X=Y^2
X in 0..1 ;
X = 4, % <- 3rd answer: X=4
Y in -7.. -1\/1..7, % if Y in -7..-1 or 1..7
Y^2#=_G1754,
_G1754 in 4..49. % and Y^2 in 4..49
In the above example there are three possibilities for Y none of which has a unique solution, hence you get residual goals in the answers. If you wish to get concrete solutions you can constrain the range of Y and ask for concrete numbers with label/1:
?- Y in 0..3, list_minsquare([7,Y,2],X), label([Y]).
Y = X, X = 0 ;
Y = X, X = 1 ;
Y = 2,
X = 4 ;
Y = 3,
X = 4.
The most general query works as well. However, it is listing the solutions in an unfair manner:
?- list_minsquare(L,X).
L = [_G97], % <- 1st solution
_G97^2#=X,
X in 0..sup ;
L = [_G266, _G269], % <- 2nd solution
_G266^2#=X,
X in 0..sup,
X+1#=_G309,
_G309 in 1..sup,
_G332#>=_G309,
_G332 in 1..sup,
_G269^2#=_G332 ;
L = [_G494, _G497, _G500], % <- 3rd solution
_G494^2#=X,
X in 0..sup,
X+1#=_G540,
X+1#=_G552,
_G540 in 1..sup,
_G575#>=_G540,
_G575 in 1..sup,
_G500^2#=_G575,
_G552 in 1..sup,
_G620#>=_G552,
_G620 in 1..sup,
_G497^2#=_G620 ;
.
.
.
You only get one solution for every list length before moving on to the next length. You can get a fair ordering by prefixing a goal length/2 in the query. Then you'll get all possibilities for every list length before moving on:
?- length(L,_), list_minsquare(L,X).
L = [_G339], % <- 1st solution: list with one element
_G339^2#=X,
X in 0..sup ;
L = [_G1036, _G1039], % <- 2nd solution: list with two elements
_G1036^2#=X, % X is square of 1st element
X in 0..sup,
X+1#=_G1079,
_G1079 in 1..sup,
_G1102#>=_G1079,
_G1102 in 1..sup,
_G1039^2#=_G1102 ;
L = [_G935, _G938], % <- 3rd solution: list with two elements
_G935^2#=_G954,
_G954 in 0..sup,
_G954#>=X,
X in 0..sup,
_G938^2#=X ; % X is square of 2nd element
.
.
.
Of course you can also constrain and label the numbers in the list for the above query and you'll get concrete numbers in the still infinitely many solutions (since there are infinitely many list lengths).
?- length(L,_), L ins 1..2, list_minsquare(L,X), label(L).
L = [1],
X = 1 ;
L = [2],
X = 4 ;
L = [1, 2],
X = 1 ;
L = [1, 1],
X = 1 ;
L = [2, 1],
X = 1 ;
L = [2, 2],
X = 4 ;
L = [1, 2, 2],
X = 1 ;
L = [1, 2, 1],
X = 1 ;
L = [1, 1, 2],
X = 1 ;
L = [2, 1, 2],
X = 1 ;
.
.
.
Let's say that I want to find two numbers where the sum of these are 8, are from 1-9 and must be different(it is obvious that these numbers are (7,1),(6,2),etc).So I wrote.
dif_list([H|T]):- \+ member(H,T),dif_list(T).
dif_list([]).
check1_9([H|T]):-H>=1,H=<9,check1_9(T).
check1_9([]).
find_number([A,B],N) :- N =:= A+B,dif_list([A,B]),check1_9([A,B]).
Afterwards I will ask prolog
?-find_number([A,B],8).
ERROR: =:=/2: Arguments are not sufficiently instantiated
My goal is that prolog will print for me the results.For example:
?-find_number([A,B],8).
A = 7,
B = 1 ;
A = 6,
B = 2 ;
...
The best way to handle this kind of problem in Prolog is to use the CLP(FD) library:
:- [library(clpfd)].
sum_of(A, B, Sum) :-
A #> 0,
B #> 0,
A + B #= Sum.
?- sum_of(A, B, 8), label([A, B]).
A = 1,
B = 7 ;
A = 2,
B = 6 ;
A = 3,
B = 5 ;
A = B, B = 4 ;
A = 5,
B = 3 ;
A = 6,
B = 2 ;
A = 7,
B = 1.
?-
If you want the addends to be unique, you can further constrain it:
sum_of(A, B, Sum) :-
A #> 0,
B #>= A,
A + B #= Sum.
There's really no need to use a list to manage the variables A and B, but you can if you wish: sum_of([A,B], Sum).
Prolog is not that declarative: there are indeed answer set programming (ASP) or constraint logic programming (clp) languages where you can simply define a set of constraints and a finite domain solver aims to solve it (but these will take considerable time).
I would suggest that you define your program as follows:
find_number(A,B,N) :-
member(A,[1,2,3,4,5,6,7,8,9]),
member(B,[1,2,3,4,5,6,7,8,9]),
N is A+B,
A \= B.
Here member/2 will instantiate A and B to values that are provided by the list, so 1..9, next you use is/2 to calculate the sum and verify that the sum is equal to N. You can only call N is A+B if A and B are given a proper value. Finally we say A \= B (A is not equal to B).
When you run this predicate, it produces:
?- find_number(A,B,8).
A = 1,
B = 7 ;
A = 2,
B = 6 ;
A = 3,
B = 5 ;
A = 5,
B = 3 ;
A = 6,
B = 2 ;
A = 7,
B = 1 ;
false.
You can however also query with A and B already filled in, or one of them filled in, or where the sum is left open. So:
?- find_number(A,2,8).
A = 6 ;
false.
or:
?- find_number(A,2,N).
A = 1,
N = 3 ;
A = 3,
N = 5 ;
A = 4,
N = 6 ;
A = 5,
N = 7 ;
A = 6,
N = 8 ;
A = 7,
N = 9 ;
A = 8,
N = 10 ;
A = 9,
N = 11 ;
false.