Prolog enumerate and test, will recursion work? - prolog

I have to make a predicate which will take 2 numbers N,M and will output "yes" when N,M are positive numbers and there are two numbers A,B such that A+B = M and A*B = N.
EDITED CODE:
For example M = 18, N = 45:
A = 0, B = 18, M = 0+18 (true), N = 0*18 (false) so it has to go next with A = 1 & B = 17 and check again...
numbers(M,N) :-
M>0 ,
N>0 ,
A is 0,
B is M,
numbers(N,M,A,B).
numbers(M,N,A,B) :-
M =:= A+B,
N =:= A*B.
numbers(M,N,A,B) :-
M =:= A+B,
not( N =:= A*B),
A is A+1,
B is B-1,
numbers(M,N,A,B).
I don't know how to enumerate A and B variables. Any help will be appreciated.

just add and multiply and check... see is/2 for arithmetic
edit my advice was a bit simplistic, I totally forgot a hint to easily generate integers ranges in Prolog, using nondeterminism:
numbers(M,N) :-
between(1,M,A),between(1,N,B), M =:= A+B, N =:= A*B, writeln((A,B)).
?- numbers(18,45).
3,15
true ;
15,3
true ;
false.

I look at it as a factoring problem:
%
% are M and N magic?
%
magic(M,N) :-
M > 0 ,
N > 0 ,
factor(N,A,B),
M is A+B
.
%
% factor/3: compute the factors of a positive integer
%
factor(N,F1,F2) :-
N > 0 ,
Limit is floor(sqrt(N)) ,
factor(1,Limit,N,F1,F2)
.
factor(F1,Limit,N,F1,F2) :-
F1 =< Limit ,
F2 is N div F1 ,
0 is N mod F1
.
factor(X,Limit,N,F1,F2) :-
X < Limit ,
X1 is X+1 ,
factor(X1,Limit,N,F1,F2)
.

Related

Composition of substitutions for unary addition in prolog?

Can someone explain how the logic of the composition of substitutions works with the following block of code?
plus2(0, X, X). % 0+X = X
plus2(s(X), Y, s(Z)) :-
plus2(Y, X, Z). % (X+1) + Y = Z+1 therefore Y+X=Z
Here is better naming:
% Reduced to zero
peano_add(0, Sum, Sum).
peano_add(s(N), M, s(Sum)) :-
% Decrement towards 0
% Swap N & M, because N + M is M + N
peano_add(M, N, Sum).
This is using Peano arithmetic, which represents natural numbers (i.e. integers starting from zero) in a relative way, as compound terms, as successors ultimately of 0. For example, s(s(0)) represents 2. Such relativity is convenient and elegant for Prolog, because it can be used ("reasoned with") in an uninstantiated (var) variable.
In swi-prolog, this produces:
?- peano_add(N, M, Sum).
N = 0,
M = Sum ; % When N is zero, M is same as Sum - could be 0 or successor
N = Sum, Sum = s(_),
M = 0 ; % When M is zero, N is same as Sum
N = s(0),
M = s(_A),
Sum = s(s(_A)) ; % 1 + 1 = 2
N = s(s(_A)),
M = s(0),
Sum = s(s(s(_A))) ; % 2 + 1 = 3
N = s(s(0)),
M = s(s(_A)),
Sum = s(s(s(s(_A)))) ; % 2 + 2 = 4
N = s(s(s(_A))),
M = s(s(0)),
Sum = s(s(s(s(s(_A))))) % 3 + 2 = 5 etc.
... and if we ask it how we can add two natural numbers to sum to 2:
?- peano_add(N, M, s(s(0))).
N = 0,
M = s(s(0)) ; % 0 + 2
N = s(s(0)),
M = 0 ; % 2 + 0
N = M, M = s(0) ; % 1 + 1
false.
Whereas if we don't swap the arguments:
% Reduced to zero
peano_add(0, Sum, Sum).
peano_add(s(N), M, s(Sum)) :-
% Decrement towards 0
% Not swapping args, to demonstrate weakness
peano_add(N, M, Sum).
... we get:
?- peano_add(N, M, Sum).
N = 0,
M = Sum ;
N = s(0),
Sum = s(M) ;
N = s(s(0)),
Sum = s(s(M)) ;
N = s(s(s(0))),
Sum = s(s(s(M))) ;
N = s(s(s(s(0)))),
Sum = s(s(s(s(M)))) ;
... which is still correct, but doesn't "involve" M as much as it could.
Both methods are counting from 0 upwards to infinity.
Swapping the parameters brings the advantage of checking the 2nd argument, to fail both fast and when appropriate:
?- peano_add(s(s(N)), z, Sum).
false. % Correct, because z is not valid
% Versus, when unswapped, this undesirable:
?- peano_add(s(s(N)), z, Sum).
N = 0,
Sum = s(s(z)) ; % Wrong - did not check whether z is valid
N = s(0),
Sum = s(s(s(z))) ; % Still wrong
N = s(s(0)),
Sum = s(s(s(s(z)))) ; % Will keep being wrong
Sadly, there is a common practice in Prolog example code of using meaningless variable names (such as A, B, X, Y), which adds confusion and should be generally avoided.

CLPFD constraint: is a prime number

I'm not even sure if this is possible, but I'm trying to write a predicate prime/1 which constrains its argument to be a prime number.
The problem I have is that I haven't found any way of expressing “apply that constraint to all integers less than the variable integer”.
Here is an attempt which doesn't work:
prime(N) :-
N #> 1 #/\ % Has to be strictly greater than 1
(
N #= 2 % Can be 2
#\/ % Or
(
N #> 2 #/\ % A number strictly greater than 2
N mod 2 #= 1 #/\ % which is odd
K #< N #/\
K #> 1 #/\
(#\ (
N mod K #= 0 % A non working attempt at expressing:
“there is no 1 < K < N such that K divides N”
))
)
).
I hoped that #\ would act like \+ and check that it is false for all possible cases but this doesn't seem to be the case, since this implementation does this:
?- X #< 100, prime(X), indomain(X).
X = 2 ; % Correct
X = 3 ; % Correct
X = 5 ; % Correct
X = 7 ; % Correct
X = 9 ; % Incorrect ; multiple of 3
X = 11 ; % Correct
X = 13 ; % Correct
X = 15 % Incorrect ; multiple of 5
…
Basically this unifies with 2\/{Odd integers greater than 2}.
EDIT
Expressing that a number is not prime is very easy:
composite(N) :-
I #>= J,
J #> 1,
N #= I*J.
Basically: “N is composite if it can be written as I*J with I >= J > 1”.
I am still unable to “negate” those constraints. I have tried using things like #==> (implies) but this doesn't seem to be implification at all! N #= I*J #==> J #= 1 will work for composite numbers, even though 12 = I*J doesn't imply that necessarily J = 1!
prime/1
This took me quite a while and I'm sure it's far from being very efficient but this seems to work, so here goes nothing:
We create a custom constraint propagator (following this example) for the constraint prime/1, as such:
:- use_module(library(clpfd)).
:- multifile clpfd:run_propagator/2.
prime(N) :-
clpfd:make_propagator(prime(N), Prop),
clpfd:init_propagator(N, Prop),
clpfd:trigger_once(Prop).
clpfd:run_propagator(prime(N), MState) :-
(
nonvar(N) -> clpfd:kill(MState), prime_decomposition(N, [_])
;
clpfd:fd_get(N, ND, NL, NU, NPs),
clpfd:cis_max(NL, n(2), NNL),
clpfd:update_bounds(N, ND, NPs, NL, NU, NNL, NU)
).
If N is a variable, we constrain its lower bound to be 2, or keep its original lower bound if it is bigger than 2.
If N is ground, then we check that N is prime, using this prime_decomposition/2 predicate:
prime_decomposition(2, [2]).
prime_decomposition(N, Z) :-
N #> 0,
indomain(N),
SN is ceiling(sqrt(N)),
prime_decomposition_1(N, SN, 2, [], Z).
prime_decomposition_1(1, _, _, L, L) :- !.
prime_decomposition_1(N, SN, D, L, LF) :-
(
0 #= N mod D -> !, false
;
D1 #= D+1,
(
D1 #> SN ->
LF = [N |L]
;
prime_decomposition_2(N, SN, D1, L, LF)
)
).
prime_decomposition_2(1, _, _, L, L) :- !.
prime_decomposition_2(N, SN, D, L, LF) :-
(
0 #= N mod D -> !, false
;
D1 #= D+2,
(
D1 #> SN ->
LF = [N |L]
;
prime_decomposition_2(N, SN, D1, L, LF)
)
).
You could obviously replace this predicate with any deterministic prime checking algorithm. This one is a modification of a prime factorization algorithm which has been modified to fail as soon as one factor is found.
Some queries
?- prime(X).
X in 2..sup,
prime(X).
?- X in -100..100, prime(X).
X in 2..100,
prime(X).
?- X in -100..0, prime(X).
false.
?- X in 100..200, prime(X).
X in 100..200,
prime(X).
?- X #< 20, prime(X), indomain(X).
X = 2 ;
X = 3 ;
X = 5 ;
X = 7 ;
X = 11 ;
X = 13 ;
X = 17 ;
X = 19.
?- prime(X), prime(Y), [X, Y] ins 123456789..1234567890, Y-X #= 2, indomain(Y).
X = 123457127,
Y = 123457129 ;
X = 123457289,
Y = 123457291 ;
X = 123457967,
Y = 123457969
…
?- time((X in 123456787654321..1234567876543210, prime(X), indomain(X))).
% 113,041,584 inferences, 5.070 CPU in 5.063 seconds (100% CPU, 22296027 Lips)
X = 123456787654391 .
Some problems
This constraint does not propagate as strongly as it should. For example:
?- prime(X), X in {2,3,8,16}.
X in 2..3\/8\/16,
prime(X).
when we should know that 8 and 16 are not possible since they are even numbers.
I have tried to add other constraints in the propagator but they seem to slow it down more than anything else, so I'm not sure if I was doing something wrong or if it is slower to update constaints than check for primeness when labeling.

Finding the k'th occurence of a given element

I just started in Prolog and have the problem:
(a) Given a list L, an object X, and a positive integer K, it returns
the position of the K-th occurrence of X in L if X appears at least K
times in L otherwise 0.
The goal pos([a,b,c,b],b,2,Z) should succeed with the answer Z = 4.
So far I have:
pos1([],H,K,F).
pos1([H],H,1,F).
pos1([H|T],H,K,F):- NewK is K - 1, pos1(T,H,NewK,F), F is F + 1.
pos1([H|T],X,K,F):- pos1(T,X,K,F).
But I can't figure out why I'm getting:
ERROR: is/2: Arguments are not sufficiently instantiated
Any help would be much appreciated!
Use clpfd!
:- use_module(library(clpfd)).
We define pos/4 based on (#>)/2, (#=)/2, if_/3, dif/3, and (#<)/3:
pos(Xs,E,K,P) :-
K #> 0,
pos_aux(Xs,E,K,1,P).
pos_aux([X|Xs],E,K,P0,P) :-
P0+1 #= P1,
if_(dif(X,E),
pos_aux(Xs,E,K,P1,P),
if_(K #< 2,
P0 = P,
(K0+1 #= K,
pos_aux(Xs,E,K0,P1,P)))).
Sample query as given by the OP:
?- X = b, N = 2, pos([a,b,c,b],X,N,P).
X = b, N = 2, P = 4. % succeeds deterministically
How about the following more general query?
?- pos([a,b,c,b],X,N,P).
X = a, N = 1, P = 1
; X = b, N = 1, P = 2
; X = b, N = 2, P = 4 % (exactly like in above query)
; X = c, N = 1, P = 3
; false.
Let's take a high-level approach to it, trading the efficiency of the resulting code for the ease of development:
pos(L,X,K,P):-
numerate(L,X,LN,1), %// [A1,A2,A3...] -> [A1-1,A2-2,A3-3...], where Ai = X.
( drop1(K,LN,[X-P|_]) -> true ; P=0 ).
Now we just implement the two new predicates. drop1(K,L,L2) drops K-1 elements from L, so we're left with L2:
drop1(K,L2,L2):- K<2, !.
drop1(K,[_|T],L2):- K1 is K-1, drop1(K1,T,L2).
numerate(L,X,LN,I) adds an I-based index to each element of L, but keeps only Xs:
numerate([],_,[],_).
numerate([A|B],X,R,I):- I1 is I+1, ( A=X -> R=[A-I|C] ; R=C ), numerate(B,X,C,I1).
Testing:
5 ?- numerate([1,b,2,b],b,R,1).
R = [b-2, b-4].
6 ?- pos([1,b,2,b],b,2,P).
P = 4.
7 ?- pos([1,b,2,b],b,3,P).
P = 0.
I've corrected your code, without changing the logic, that seems already simple enough.
Just added a 'top level' handler, passing to actual worker pos1/4 and testing if worked, else returning 0 - a debatable way in Prolog, imo is better to allow to fail, I hope you will appreciate how adopting this (see comments) simplified your code...
pos(L,X,K,F):- pos1(L,X,K,F) -> true ; F=0.
% pos1([],H,K,F). useless: let it fail
% pos1([H],H,1,F). useless: already handled immediatly bottom
pos1([H|T],H,K,P):- K==1 -> P=1 ; NewK is K - 1, pos1(T,H,NewK,F), P is F + 1.
pos1([_|T],X,K,P):- pos1(T,X,K,F),P is F+1.
I hope you're allowed to use the if/then/else construct. Anyway, yields
7 ?- pos([a,b,c,b],b,2,Z).
Z = 4.
8 ?- pos([a,b,c,b],b,3,Z).
Z = 0.
Something like this. An outer predicate (this one enforces the specified constraints) that invokes an inner worker predicate:
kth( L , X , K , P ) :-
is_list( L ) , % constraint: L must be a list
nonvar(X) , % constriant: X must be an object
integer(K) , K > 0 % constraint: K must be a positive integer
kth( Ls , X , K , 1 , P ) % invoke the worker predicate with its accumulator seeded to 1
. % easy!
is_list/2 ensures you've got a list:
is_list(X) :- var(X) , !, fail .
is_list([]).
is_list([_|_]).
The predicate that does all the work is this one:
kth( [] , _ , _ , _ , 0 ) . % if we hit the end of the list, P is 0.
kth( [X|Ls] , X , K , K , K ) :- ! . % if we find the Kth desired element, succeed (and cut: we won't find another Kth element)
kth( [_|Ls] , X , K , N , P ) :- % otherwise
N < K , % - if we haven't got to K yet ...
N1 is N+1 , % - increment our accumulator , and
kth(Ls,X,K,N1,P) % - recurse down.
. % easy!
Though the notion of returning 0 instead of failure is Not the Prolog Way, if you ask me.

Prolog - dyck path from origin to (2N,0)

Is called Dyck Path.
It is a plane of x and y axis,
where each step will be only (x+1,y+1) or (x+1,y-1)
and will always stay above x-axis
K should means the peak of the Dyck path.
When K is 2 it should means that the peak is 2 and 3.
to form a legal sequence list of matching the parentheses a = '(', and b = ')' and has length 2N
Eg. [a,a,b,b] and [a,b,a,b] are the legal list for N = 2
[a,b,b,a] and [b,a,b,a] do not satisfies for N = 2
need to define the predicate
listFind(L,K,N) satisfies when L has list of order of 2N, for some k >= K
For example
|?- listFind(L,1,3).
L = [a,b,a,b,a,b] ? ;
L = [a,b,a,a,b,b] ? ;
L = [a,a,b,b,a,b] ? ;
L = [a,a,b,a,b,b] ? ;
L = [a,a,a,b,b,b] ? ;
no
|?- listFind(L,2,3).
L = [a,a,b,b,a,b] ? ;
L = [a,a,b,a,b,b] ? ;
L = [a,a,a,b,b,b] ? ;
no
Thanks in advance.
the role of K is unclear to me. Anyway, here is a snippet satisying your test case:
listFind(L, K, N) :-
N2 is N*2,
length(L, N2),
phrase(dyck, L),
% satisfy condition on K
run_length_encoded(L, RLE),
[X-a|_] = RLE, X >= K.
% DCG for Dyck' language over alphabet `a,b`
dyck --> [] ; [a], dyck, [b], dyck.
run_length_encoded([X|S], C) :-
run_length_encoded(S, X, 1, C).
run_length_encoded([Y|S], X, N, E) :-
( X == Y
-> M is N + 1,
run_length_encoded(S, X, M, E)
; E = [N-X|T],
run_length_encoded(S, Y, 1, T)
).
run_length_encoded([], X, C, [C-X]).
As you can see, the interpretation of K is
the sequence must start with at least K consecutives a

Beginner - add multiples of 3 and 5

I'm trying to find the sum of all positive multiples of 3 and 5 below 1000. After adding the portion that's supposed to remove the multiples of 3 from the sum of the multiples of 5, gprolog will keep spitting out "No" for the query ?- sigma(1000,N).
The problem apparently lies in sigma5, but I can't quite spot it:
sigma(Num, Result) :- sigma3(Num, 3, Result3),
sigma5(Num, 5, Result5),
Result is Result3 + Result5.
sigma3(Num, A, Result) :- A < Num,
Ax is A+3,
sigma3(Num, Ax, ResultX),
Result is ResultX + A.
sigma3(Num, A, Result) :- A >= Num,
Result is 0.
sigma5(Num, A, Result) :- A < Num,
mod3 is A mod 3,
0 \= mod3,
Ax is A+5,
sigma5(Num, Ax, ResultX),
Result is ResultX + A.
sigma5(Num, A, Result) :- A < Num,
mod3 is A mod 3,
0 == mod3,
Ax is A+5,
sigma5(Num, Ax, ResultX),
Result is ResultX.
sigma5(Num, A, Result) :- A >= Num,
Result is 0.
What's the problem with my code?
As integers are involved, consider using finite domain constraints. For example, with SWI-Prolog:
?- use_module(library(clpfd)).
true.
?- findall(N, (N mod 3 #= 0 #\/ N mod 5 #= 0, N in 0..999, indomain(N)), Ns),
sum(Ns, #=, Sum).
Ns = [0, 3, 5, 6, 9, 10, 12, 15, 18|...],
Sum = 233168.
Prolog has never been popular for it's arithmetic capabilities.
This is due to the need to represent 'term constructors' for symbolic processing, without undue evaluation, so when actual arithmetic is required we must explicitly allocate the 'space' (a variable) for the result, instead that 'passing down' an expression. This lead to rather verbose and unpleasant code.
But using some popular extension, like CLP(FD), available in GProlog as well as SWI-Prolog, we get much better results, not readily available in other languages: namely, a closure of the integer domain over the usual arithmetic operations. For instance, from the SWI-Prolog CLP(FD) library, a 'bidirectional' factorial
n_factorial(0, 1).
n_factorial(N, F) :- N #> 0, N1 #= N - 1, F #= N * F1, n_factorial(N1, F1).
?- n_factorial(X, 3628800).
X = 10 .
Anyway, here is a simple minded solution to the original problem, similar to what you attempted, but using an accumulator to compute result. This simple trick allows writing a tail recursive procedure, that turns out in better efficiency.
sigma(Num, Result) :-
sigma(1, Num, 0, Result).
sigma(N, M, Acc, Tot) :-
( N < M, !,
( (0 is N mod 3 ; 0 is N mod 5)
-> Sum is Acc + N
; Sum is Acc
),
N1 is N + 1,
sigma(N1, M, Sum, Tot)
; Tot is Acc
).
Test:
?- sigma(1000, X).
X = 233168 .
mod3 is A mod 3,
(as well all the other occurrences of mod3) should be Mod3 since it is a variable.
with that fix, the program runs correctly (at least for N=1000)
btw here is my solution (using higher-order predicates):
sum(S):-
findall(X,between(1,999,X),L), % create a list with all numbers between 1 and 999
include(div(3),L,L3), % get the numbers of list L which are divisible by 3
include(div(5),L,L5), % get the numbers of list L which are divisible by 5
append(L3,L5,LF), % merge the two lists
list_to_set(LF,SF), % eliminate double elements
sumlist(SF,S). % find the sum of the members of the list
div(N,M):-
0 is M mod N.
it's less efficient of course but the input is too small to make a noticeable difference
This all seems very complicated to me.
sum_of( L , S ) :-
L > 0 ,
sum_of( 0 , L , 0 , S )
.
sum_of( X , X , S , S ) . % if we hit the upper bound, we're done.
sum_of( X , L , T , S ) :- % if not, look at it.
X < L , % - backtracking once we succeeded.
add_mult35( X , T , T1 ) , % - add any multiple of 3 or 5 to the accumulator
X1 is X + 1 , % - next X
sum_of( X1 , L , T1 , S ) % - recurse
.
add_mult35( X , T , T ) :- % no-op if X is
X mod 3 =\= 0 , % - not a multiple of 3, and
X mod 5 =\= 0 , % - not a multiple of 5
!. %
add_mult35( X , T , T1 ) :- % otherwise,
T1 is T + X % increment the accumulator by X
.
This could be even more concise than it is.
Aside from my code probably being extraordinarily horrible (it's actually longer than my C solution, which is quite a feat on it's own),
ANSI C:
int sum_multiples_of_three_and_five( int lower_bound , int upper_bound )
{
int sum = 0 ;
for ( int i = lower_bound ; i <= upper_bound ; ++i )
{
if ( 0 == i % 3 || 0 == i % 5 )
{
sum += i ;
}
}
return sum ;
}

Resources