Related
Goldbach’s Conjecture : Every positive even number greater than 2 is the sum of two prime numbers. Eg 28 (5,23 and 11,17)
I want Prolog code to print below (all combinations) :
?- goldbach(28, L).
Output :
L = [5,23];
L = [11, 17];
I have a code which prints single combination[5,23], but not the next [11,17].
is_prime(2).
is_prime(3).
is_prime(P) :- integer(P), P > 3, P mod 2 =\= 0, \+ has_factor(P,3).
has_factor(N,L) :- N mod L =:= 0.
has_factor(N,L) :- L * L < N, L2 is L + 2, has_factor(N,L2).
goldbach(4,[2,2]) :- !.
goldbach(N,L) :- N mod 2 =:= 0, N > 4, goldbach(N,L,3).
goldbach(N,[P,Q],P) :- Q is N - P, is_prime(Q), !.
goldbach(N,L,P) :- P < N, next_prime(P,P1), goldbach(N,L,P1).
next_prime(P,P1) :- P1 is P + 2, is_prime(P1), !.
next_prime(P,P1) :- P2 is P + 2, next_prime(P2,P1).
Drop the cuts (and add a condition to avoid duplicate answers).
goldbach(4,[2,2]).
goldbach(N,L) :-
N mod 2 =:= 0,
N > 4,
goldbach(N,L,3).
goldbach(N,[P,Q],P) :-
Q is N - P,
is_prime(Q), P < Q.
goldbach(N,L,P) :-
P < N,
next_prime(P,P1),
goldbach(N,L,P1).
Suppose I want to represent integers like so: integer:Sign:[FirstDigit,SecondDigit,...]. For instance, 42 would be represented as integer:positive:[4,2].
I need a predicate that generates the value of the integer based on this representation and vice versa.
Here is what I came up with:
integer_value_('integer':Sign:[H],E) :-
H in 0..9,
(
Sign = 'positive',
E #= H
;
Sign = 'negative',
E #= -H
).
integer_value_('integer':Sign:[H,I|T],E) :-
H in 0..9,
length([I|T],L),
(
Sign = 'positive',
E #= F + H * 10^L
;
Sign = 'negative',
E #= F - H * 10^L
),
integer_value_('integer':Sign:[I|T],F).
This works as expected. However, it has the unfortunate property of accepting things like integer:positive:[0,1], that is, leading zeroes at the beginning of the list. This is especially problematic when I enumerate all possible integers using integer_value_(I,J), label([J]).: the ones with leading zeroes also show up.
I then attempted to correct this by using integer_value_ only for all but the first digit, and using integer_value for the first one (keeping in mind that we need to accomodate for 0 being represented with a list containing only 0):
integer_value('integer':Sign:[H],E) :-
abs(E) #< 10,
abs(E) #> -1,
integer_value_('integer':Sign:[H],E).
integer_value('integer':Sign:[H,I|T],E) :-
H in 1..9,
length([I|T],L),
(
Sign = 'positive',
E #= F + H * 10^L
;
Sign = 'negative',
E #= F - H * 10^L
),
integer_value_('integer':Sign:[I|T],F).
However now it does not behave properly. For example, integer_value(I,-19). returns I = integer:negative:[1, 9], but if we ask for another answer Prolog goes into an infinite loop for reasons I don't understand (it should say false, or already know there are no other answers).
This problem does not occur with the "opposite" query integer_value(integer:negative:[1,9],Z). which returns Z = 19 and then false, nor does it occur when both arguments are Variables (it enumerates numbers properly, with no leading zeroes), which is surprising to me.
Any idea what that infinite loop occurs, and if there's an easy way to fix it?
To see the problem, it is sufficient to look at a tiny fraction of your program. In fact the following failure-slice is sufficient:
integer_value('integer':Sign:[H],E) :- false,
abs(E) #< 10,
abs(E) #> -1,
integer_value_('integer':Sign:[H],E).
integer_value('integer':Sign:[H,I|T],E) :-
H in 1..9,
length([I|T],L), false,
( Sign = 'positive',
E #= F + H * 10^L
;
Sign = 'negative',
E #= F - H * 10^L
),
integer_value_('integer':Sign:[I|T],F).
L occurs here for the first time, so any length is possible.
You will have to modify the length-goal somehow.
I managed to solve my problem using this other answer pointed out by #false
One of the catch is to decide of the sign of the number as the last step, so that when iterating through possible integers we get alternating answers between positive and negative numbers: after reaching 9 (1 digit), it will unify with -9, then -8, etc. After -1, it will unify with 10, 11, etc. After 99, it will unify with -99, -98, etc. You get the point.
integer_value('integer':Sign:I,E) :-
integer_value('integer':Sign:I,0,E,E).
integer_value('integer':Sign:[H],N0,N,M) :-
H in 0..9,
N1 #= H + N0 * 10,
abs(M) #>= abs(N1),
integer_value_('integer':Sign:[],N1,N,M).
integer_value('integer':Sign:[H,I|T],N0,N,M) :-
H in 1..9,
N1 #= H + N0 * 10,
abs(M) #>= abs(N1),
integer_value_('integer':Sign:[I|T],N1,N,M).
integer_value_('integer':Sign:[],N0,N,_) :-
(
Sign = 'positive',
N #= N0
;
Sign = 'negative',
N #\= 0,
N #= - N0
).
integer_value_('integer':Sign:[H],N0,N,M) :-
H in 0..9,
N1 #= H + N0 * 10,
abs(M) #>= abs(N1),
integer_value_('integer':Sign:[],N1,N,M).
integer_value_('integer':Sign:[H,I|T],N0,N,M) :-
H in 0..9,
N1 #= H + N0 * 10,
abs(M) #>= abs(N1),
integer_value_('integer':Sign:[I|T],N1,N,M).
I have this predicate which returns true if S is equal to some equation say K + 2N + 3L = S. The money we have are 1, 5, and 10 respectively for K, N, L.
I don't want to use :- use_module(library(clpfd)), I want to solve this without it.
My intuition was to break this into subproblems like write a function breakMoney1(S,K) :- K is S. and create more helpers with one more parameter added however I am struggling with the problem of getting uninstantiated variables, when I compare.
breakMoney(S,K,N,L) :-
This is easier than you think, probably. A very naive solution following #Will Ness' suggestion would be:
break(Sum, K, N, L) :- integer(Sum), Sum >= 0,
% upper bounds for K, N, and L
K_Max is Sum div 1,
N_Max is Sum div 5,
L_Max is Sum div 10,
% enumerate possible values for K, N, and L
between(0, L_Max, L),
between(0, N_Max, N),
between(0, K_Max, K),
Sum =:= K + 5*N + 10*L.
This will "magically" turn into a clp(fd) solution with very little effort: for example, replace between with X in 0..Max, and the =:= with #=. Although, it should be enough to simply say that X #>= 0 for each of the denominations. It is a good exercise to see how much of the constraints you can remove and still get an answer:
break(Sum, K, N, L) :-
K #>= 0, N #>= 0, L #>= 0,
Sum #= K + 5*N + 10*L.
Depending on how you instantiate the arguments, you might immediately get a unique answer, or you might need to use label/1:
?- break(100, P, 8, 5).
P = 10.
?- break(10, K, N, L).
K in 0..10,
-1*K+ -5*N+ -10*L#= -10,
N in 0..2,
L in 0..1.
?- break(10, K, N, L), label([K, N, L]).
K = N, N = 0,
L = 1 ;
K = L, L = 0,
N = 2 ;
K = 5,
N = 1,
L = 0 ;
K = 10,
N = L, L = 0.
But as #lurker has pointed out, there is very little reason not to use constraint programming for this problem. Unless, of course, you have a very clever algorithm for solving this particular problem and you know for a fact that it will outsmart the generic clp(fd) solution. Even then, it might be possible to achieve the same effect by using the options to labelling/2.
I'm trying to learn myself Prolog and need a little help.
Could someone solve and explain this problem:
Define a p(A, M/N, K/L), which generates all possible rational fractions M/N and K/L, where:
N>M>0, K>L>0, (M/N)*(K/L) = 2 and (M+K)<A
Your description is not that clear to me, I am rather guessing which values should be known and which are asked. So I will rather use library(clpfd) where I do not have to make such considerations myself.
N>M>0, K>L>0, (M/N)*(K/L) = 2 and (M+K)<A
p(A, M/N, K/L) :-
N #> M, M #> 0,
K #> L, L #> 0,
M+K #< A,
(M/N) * (K/L) #= 2.
?- 3/2 #= F.
F = 1.
?- (3/2)*2 #= F.
F = 2.
Oh, clpfd is on the integers so fractions are truncated. I need some algebra first, multiplying both sides with (N*L) (they are both not 0...):
p(A, M/N, K/L) :-
N #> M, M #> 0,
K #> L, L #> 0,
M+K #< A,
M*K #= 2*N*L.
?- p(A, M/N, K/L).
A in 4..sup, M+K+ -1*A#=< -1, M in 1..sup,
M#=<N+ -1, M*K#=_A, N in 2..sup, 2*N#=_B,
_B in 4..sup, _B*L#=_A, L in 1..sup, L#=<K+ -1,
K in 2..sup, _A in 4..sup.
So Prolog says: Yes! That is true provided all this very fine print is true. The first line is the most interesting A in 4..sup which means that there is no upper bound for A. To get concrete solutions, A must be known:
?- A #= 10, p(A, M/N, K/L).
A = 10, M in 1..7, M+K#=_A, M#=<N+ -1,
M*K#=_B, K in 2..8, L#=<K+ -1, L in 1..7,
_C*L#=_B, _C in 4..56, 2*N#=_C, N in 2..28,
_B in 4..56, _A in 3..9.
Not enough! But now K, L, M, N have all finite domains, so we can enumerate them using labeling([], [K,L,M,N]).
?- A = 10, p(A,M/N,K/L),labeling([],[M,N,K,L]).
A = 10, M = L, L = 1, N = 2, K = 4
; A = 10, M = 1, N = L, L = 2, K = 8
; A = 10, M = L, L = 1, N = 3, K = 6
; ... .
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)
.