Prolog pythagorean triplet - prolog

I'm trying to solve project Euler problem 9 using prolog. I'm a 100% n00b with prolog and I'm just trying to understand the basics right now.
I'm trying to use findall to get all triplets that would add up to 1000, but I can't really figure out the syntax.
What I'm hoping for is something like:
pythag_trip(A, B, C, D) :- D is (A * A) + (B * B) + (C * C).
one_thou_pythag(A, B, C) :- pythag_trip(A, B, C, 1000).
product_trip(A, B, C, D) :- D is A * B * C.
findall([A, B, C], one_thou_pythag(A, B, C) , Bag)).
writeln(Bag).
I know that doesn't work because it's saying Bag is not instantiated. But there are still some basics that I don't understand about the language, too.
1: can I even do this? With multiple moving pieces at once? Can I find all triplets satisfying a condition? Do I need to go down a completely different like like using clpfd?
2: What is supposed to be going in that last argument where I put Bag?
3: Is it possible to create data types? I was thinking it might be good to create a triplet set type and an operation to get the pythagorean triplet sum of them if I have to find some way to generate all the possibilities on my own
Basically those questions and then, I could use some pointing in the right direction if anyone has tips

Sorry but I don't answer your questions. It seems to me that you're trying not a prolog-like approach.
You should try to solve it logically.
So do this problem from the top to bottom.
We want to have 3 numbers that sum to 1000.
between(1,1000,A), between(A,1000,B), between(B,1000,C), C is 1000-A-B.
In that case, we will have them sorted and we won't take permutations.
So let's go a step further. We want them to be pythagorem triplet.
between(1,1000,A), between(A,1000,B), between(B,1000,C), C is 1000-A-B, is_triplet(A,B,C).
But we don't have is_triplet/3 predicate, so let's create it
is_triplet(A,B,C) :- D is C*C - A*A -B*B, D=0.
And that's actually it.
So let's sum it up
is_triple(A, B, C) :- D is C*C - A*A - B*B, D = 0.
triplet(A,B,C) :- between(1,1000,A), between(A,1000,B), C is 1000-A-B, between(B,1000,C), C is 1000-A-B, is_triple(A,B,C).
When you call triplet(A,B,C) you should get an answer.
Notice one thing, that at the end I've swapped C is 1000-A-B with between(B,1000,C). It makes the program much faster, try to think why.

Related

How to solve complex matrix equations in Go using mat64

I'm doing matrix math in Go using mat64. I have a matrix equation I want to solve, something like: (a * b + c) / (d - e) where a, b, c, d, and e are all matrices with real numbers as elements.
mat64 implements matrix math functions as methods. So, if you wanted to multiply matrix a by b, you'd do something like:
// Multiply a by b:
new := mat64.NewDense(x, y, nil)
new.Mul(a, b)
However, this method becomes unwieldy when you're looking at more complex equations with a whole bunch of steps such as my example above.
So, is there any way to invoke these routines (or methods in Go in general) without using receivers, forcing me to create a boatload of temporary matrices in order to solve a more complex equation, or am I stuck doing this the ugly way?

Prolog recursive subtraction

I picked up prolog a couple of days ago and I 'm kind of stuck to this question. I want to subtract a number recursively until that number becomes less than 0. In pseudocode that would be like:
N:=0
while(Y>=X)
{
Y := Y-X
N := N+1
Y := Y+2
}
So for example if I have Y=20 and X=10 then we would get N=2 and Y=4.
Any ideas? Thanks in advance. Any help appreciated. I'm using SWI Prolog.
EDIT 1
What I've accomplished so far is(although I'm not sure even if its correct):
sufficient(X, Y, M, N, F) :-
F is Y-X,
Y>=X,
plus(M, 1, N),
sufficient(X, F, N, N, F).
I have problem finding my base case, I'm confused on how to implement it. Also, in the sufficient I have implemented, obviously when Y<X it terminates returning false. Is there a way to get the N and F before terminating? I am feeling that I am not thinking the "prolog" way, since I am mostly used on C and that vagues my thinking. Thanks.
EDIT 2
I have found my base case and I can stop recursion however, I can't manage to ge the correct values. My code:
sufficient(X, Y, M, N, F) :- Y<X.
sufficient(X, Y, M, N, F) :-
F is Y-X,
plus(M, 1, N),
sufficient(X, F, N, D, E).
Thing is after the first recursion, if for example I call sufficient as sufficient(10,21,0,N,F). from the swi prolog command prompt, I 'll get N=1 and F=11. That happens because I make 2 new variables D and E. If I don't make those 2 new variables(D and E), and at the 3rd sufficient in the code I call N and F instead of D and E at the line F is Y-X, I get a false, because F is 11 and Y-X is 1. Do I have to set the a subtraction function myself, since F is Y-X is not exactly a subtraction? Any ideas on how to do it?
All recursive functions need at least one base case. In what circumstance should your function say, OK, I have the answer, no need to recurse?
It would be the case in which your pseudocode loop is done, right?
Usually we write it in this format:
factorial(0,1). % The factorial of 0 is 1.
factorial(N,Factorial) :-
N>0, % You may need to test applicability
% of this recursive clause
NMinus1 is N-1, % maybe some setup
factorial(NMinus1,FactorialOfNMinus1), %recursive call
Factorial is N*FactorialOfNMinus1). %and maybe some code after
I wouldn't want to do your homework for you, but this should get you going:
sufficient(X,Y,M,N,F) :- %whatever condition means you're done,
% and results = whatever they should
sufficient(X,Y,M,N,F) :- %whatever condition means you aren't done
% and setting up results w/ a recursive call
One more hint: looks like M is a temporary variable and need not be a parameter.

Prolog program to get an (integer) number as the sum of two integer squares, why does it not work?

I'm starting learning Prolog and I want a program that given a integer P gives to integers A and B such that P = A² + B². If there aren't values of A and B that satisfy this equation, false should be returned
For example: if P = 5, it should give A = 1 and B = 2 (or A = 2 and B = 1) because 1² + 2² = 5.
I was thinking this should work:
giveSum(P, A, B) :- integer(A), integer(B), integer(P), P is A*A + B*B.
with the query:
giveSum(5, A, B).
However, it does not. What should I do? I'm very new to Prolog so I'm still making lot of mistakes.
Thanks in advance!
integer/1 is a non-monotonic predicate. It is not a relation that allows the reasoning you expect to apply in this case. To exemplify this:
?- integer(I).
false.
No integer exists, yes? Colour me surprised, to say the least!
Instead of such non-relational constructs, use your Prolog system's CLP(FD) constraints to reason about integers.
For example:
?- 5 #= A*A + B*B.
A in -2..-1\/1..2,
A^2#=_G1025,
_G1025 in 1..4,
_G1025+_G1052#=5,
_G1052 in 1..4,
B^2#=_G406,
B in -2..-1\/1..2
And for concrete solutions:
?- 5 #= A*A + B*B, label([A,B]).
A = -2,
B = -1 ;
A = -2,
B = 1 ;
A = -1,
B = -2 ;
etc.
CLP(FD) constraints are completely pure relations that can be used in the way you expect. See clpfd for more information.
Other things I noticed:
use_underscores_for_readability_as_is_the_convention_in_prolog instead ofMixingTheCasesToMakePredicatesHardToRead.
use declarative names, avoid imperatives. For example, why call it give_sum? This predicate also makes perfect sense if the sum is already given. So, what about sum_of_squares/3, for example?
For efficiency sake, Prolog implementers have choosen - many,many years ago - some compromise. Now, there are chances your Prolog implements advanced integer arithmetic, like CLP(FD) does. If this is the case, mat' answer is perfect. But some Prologs (maybe a naive ISO Prolog compliant processor), could complain about missing label/1, and (#=)/2. So, a traditional Prolog solution: the technique is called generate and test:
giveSum(P, A, B) :-
( integer(P) -> between(1,P,A), between(1,P,B) ; integer(A),integer(B) ),
P is A*A + B*B.
between/3 it's not an ISO builtin, but it's rather easier than (#=)/2 and label/1 to write :)
Anyway, please follow mat' advice and avoid 'imperative' naming. Often a description of the relation is better, because Prolog it's just that: a relational language.

Construction from many sets

I have four sets:
A={a,b,c}, B={d,e}, C={c,d}, D={a,b,c,e}
I want to search the sequence of sets that give me: a b c d
Example: the sequence A A A C can give me a b c d because "a" is an element of A, "b" is an element of A, "c" is an element of A and "d" is an element of C.
The same thing for : D A C B, etc.
I want an algorithm to enumerate all sequences possibles or a mathematical method to find the sequences.
You should really come up with some code of your own and then ask specific questions about problems with it. But it's interesting, so I'll share some thoughts.
You want a b c d.
a can come from A, D
b can come from A, D
c can come from A, C, D
d can come from B, C
So the problem reduces to finding all of the 2*2*3*2=24 ways to combine those options.
One way is recursion with backtracking. Build it from left to right, output when you have a complete set. Like the 8 queens problem, but much simpler since everything is independent.
Another way is to count the integers and map them into a mixed-base system. First digit base 2, then 2, 3, 2. So 0 becomes AAAB, 1 is AAAC, 2 is AACB, etc. 23 is DDDC and 24 needs five digits so you stop there.

Prolog confusion. Can someone explain how minimal works?

I understand the code up to minimal but after that there's too many variables and I keep losing track of what each one is doing. If someone could explain it or do it with renamed variables that would be an amazing help, as I think this code will probably come up on my Christmas exam and I want to be able to explain what's going on.
road(a, b, 1).
road(b, c, 1).
road(a, c, 13).
road(d, a, 1).
/*Getting from A to B through a list of places R in N kms*/
route(A,B,R,N) :- travel(A,B,[A],Q,N), reverse(Q,R).
/*Travelling from A to B through P a list of towns B|P of distance L*/
travel(A,B,P,[B|P],Dist) :- road(A,B,Dist).
/*Travelling from A to B through Visited, on your Route R with distance Distance*/
/*Find if there is a road from A to b and store the distance. Make sure C is not equal to B*/
travel(A,B,Visited,R,Distance) :-
road(A,C,Dist), C \== B,
/*Make sure C is not in Visited to avoid infinite loop,
use recursion to find the full route and distance */
\+member(C,Visited), travel(C,B,[C|Visited],R,Dist1), Distance is Dist + Dist1.
/*Find the shortest route from A to B*/
shortest(A,B,R,N) :-
setof([Route,Dist],route(A,B,Route,Dist),Set),
Set = [_|_], minimal(Set,[R,N]).
minimal([F|R],M) :- min(R,F,M).
/*The shortest path*/
min([],M,M).
min([[P,L]|R],[_,M],Min):- L < M, !, min(R,[P,L],Min).
min([_|R],M,Min) :- min(R,M,Min).
since setof gives a sorted list of solutions, it's sufficient to produce solutions of appropriate 'shape', placing first the value you want to minimize: try
shortest(A,B,R,N) :-
setof((Dist,Route), route(A,B,Route,Dist), [(N,R)|_]).

Resources