Prolog recursive subtraction - prolog

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.

Related

Can anyone explain to me what this Prolog code is doing?

So I have a question I need to answer commenting on how this code is executed and what it is doing and I am not sure what is going on in it. I think it is something to do with if the values appear in the list? No idea however any help is appreciated!!
I also need to explain what the output of this query is regarding the code below p([5,3,6,3,7],L,4,7).
p([],[],_).
p([H|T],[H|R],N,M) :-H >= N, H =< M, p(T,R,N,M).
p([H|T],R,N,M) :- H < N, p(T,R,N,M).
p([H|T],R,N,M) :- H > M, p(T,R,N,M).
(Let's assume the first line has a typo and should have two _ in it rather than one).
Instead of trying to unpick the variables and follow them through, step back and look at the shape, and the general patterns; first note the pattern of how the predicates are all p/4 and start like this:
p([],
p([H|T],
p([H|T],
p([H|T],
It's common to put lists in the first position, as Prolog systems tend do more optimisation on the first position, and this is a common pattern for a recursive list walk down to the empty-list end of a list.
Then note that the last two lines have the same header and the same recursive call:
p([H|T],R,N,M) :- , p(T,R,N,M).
p([H|T],R,N,M) :- , p(T,R,N,M).
And the recursive call changes [H|T] into T, so yes, recursive list walk looks likely. Bit suspicious that they have the same call at the end in both cases. What's different about them, and why does it matter?
H < N,
H > M,
It is common to write if/else like this, as two separate rules, one rule for each case, e.g. a cutoff value, one for being above it and another for beign below it. This is not that because both rules describe the same behaviour; H is being compared with N in one rule and M in the other. H is outside either end of a boundary, do nothing?
What's the second line?
p([H|T],[H|R],N,M) :- H >= N, H =< M, p(T,R,N,M).
It has the same recursive call but it has a different header where H merges into the second parameter, and the conditions are H >= N, H =< M; that's H being inside the boundary.
So, it's a filter; in p([5,3,6,3,7],L,4,7) the list elemetns between N and M (inclusive) get merged into L, the rest are ignored. It's very similar to:
?- include(between(4, 7), [5,3,6,3,7], L).

Prolog factorial non-recursive

How would you convert this to non-recursive. This code puts out the factorial of N.
fakultaet(0, 1).
fakultaet(N, F) :-
N > 0,
N1 is N – 1,
fakultaet(N1, F1),
F is N * F1.
One way to do it without a recursive call in your definition would be:
factorial(0, 1).
factorial(1, 1).
factorial(N, F) :-
% the call to numlist/3 will fail if N < 2
numlist(2, N, [X|Xs]), % [X|Xs] = [2,3,...,N]
foldl(mult, Xs, X, P), % P = 2*3*...*N
F is P.
mult(A, B, B*A).
This approach avoids recursion on syntactic level in your definition. Both numlist/2 and foldl/4 would most probably have a recursive definition, but you don't have to look at it. This probably falls into the "d) something else I am missing" category from my comment to your question.
if your Prolog has global variables, you can do
fakultaet(N,F) :-
nb_setval(f,1),
forall(between(2,N,I), (nb_getval(f,T), G is T*I, nb_setval(f,G))),
nb_getval(f,F).
This particular usage of nb_setval/2, nb_getval/2 could be partially simulated with assert/1, retract/1, but the resulting program would be very, very inefficient

How can I verify if a coordinate is in a list

I'm generating random coordinates and adding on my list, but first I need verify if that coordinate already exists. I'm trying to use member but when I was debugging I saw that isn't working:
My code is basically this:
% L is a list and Q is a count that define the number of coordinate
% X and Y are the coordinate members
% check if the coordniate already exists
% if exists, R is 0 and if not, R is 1
createCoordinates(L,Q) :-
random(1,10,X),
random(1,10,Y),
convertNumber(X,Z),
checkCoordinate([Z,Y],L,R),
(R is 0 -> print('member'), createCoordinates(L,Q); print('not member'),createCoordinates(L,Q-1).
checkCoordinate(C,L,R) :-
(member(C,L) -> R is 0; R is 1).
% transforms the number N in a letter L
convertNumber(N,L) :-
N is 1, L = 'A';
N is 2, L = 'B';
...
N is 10, L = 'J'.
%call createCoordinates
createCoordinates(L,20).
When I was debugging this was the output:
In this picture I'm in the firts interation and L is empty, so R should be 1 but always is 0, the coordinate always is part of the list.
I have the impression that the member clause is adding the coordinate at my list and does'nt make sense
First off, I would recommend breaking your problem down into smaller pieces. You should have a procedure for making a random coordinate:
random_coordinate([X,Y]) :-
random(1, 10, XN), convertNumber(XN, X),
random(1, 10, Y).
Second, your checkCoordinate/3 is converting Prolog's success/failure into an integer, which is just busy work for Prolog and not really improving life for you. memberchk/2 is completely sufficient to your task (member/2 would work too but is more powerful than necessary). The real problem here is not that member/2 didn't work, it's that you are trying to build up this list parameter on the way out, but you need it to exist on the way in to examine it.
We usually solve this kind of problem in Prolog by adding a third parameter and prepending values to the list on the way through. The base case then equates that list with the outbound list and we protect the whole thing with a lower-arity procedure. In other words, we do this:
random_coordinates(N, Coordinates) :- random_coordinates(N, [], Coordinates).
random_coordinates(0, Result, Result).
random_coordinates(N, CoordinatesSoFar, FinalResult) :- ...
Now that we have two things, memberchk/2 should work the way we need it to:
random_coordinates(N, CoordinatesSoFar, FinalResult) :-
N > 0, succ(N0, N), % count down, will need for recursive call
random_coordinate(Coord),
(memberchk(Coord, CoordinatesSoFar) ->
random_coordinates(N, CoordinatesSoFar, FinalResult)
;
random_coordinates(N0, [Coord|CoordinatesSoFar], FinalResult)
).
And this seems to do what we want:
?- random_coordinates(10, L), write(L), nl.
[[G,7],[G,3],[H,9],[H,8],[A,4],[G,1],[I,9],[H,6],[E,5],[G,8]]
?- random_coordinates(10, L), write(L), nl.
[[F,1],[I,8],[H,4],[I,1],[D,3],[I,6],[E,9],[D,1],[C,5],[F,8]]
Finally, I note you continue to use this syntax: N is 1, .... I caution you that this looks like an error to me because there is no distinction between this and N = 1, and your predicate could be stated somewhat tiresomely just with this:
convertNumber(1, 'A').
convertNumber(2, 'B').
...
My inclination would be to do it computationally with char_code/2 but this construction is actually probably better.
Another hint that you are doing something wrong is that the parameter L to createCoordinates/2 gets passed along in all cases and is not examined in any of them. In Prolog, we often have variables that appear to just be passed around meaninglessly, but they usually change positions or are used multiple times, as in random_coordinates(0, Result, Result); while nothing appears to be happening there, what's actually happening is plumbing: the built-up parameter becomes the result value. Nothing interesting is happening to the variable directly there, but it is being plumbed around. But nothing is happening at all to L in your code, except it is supposedly being checked for a new coordinate. But you're never actually appending anything to it, so there's no reason to expect that anything would wind up in L.
Edit Notice that #lambda.xy.x solves the problem in their answer by prepending the new coordinate in the head of the clause and examining the list only after the recursive call in the body, obviating the need for the second list parameter.
Edit 2 Also take a look at #lambda.xy.x's other solution as it has better time complexity as N approaches 100.
Since i had already written it, here is an alternative solution: The building block is gen_coord_notin/2 which guarantees a fresh solution C with regard to an exclusion list Excl.
gen_coord_notin(C, Excl) :-
random(1,10,X),
random(1,10,Y),
( memberchk(X-Y, Excl) ->
gen_coord_notin(C, Excl)
;
C = X-Y
).
The trick is that we only unify C with the new result, if it is fresh.
Then we only have to fold the generations into N iterations:
gen_coords([], 0).
gen_coords([X|Xs], N) :-
N > 0,
M is N - 1,
gen_coords(Xs, M),
gen_coord_notin(X, Xs).
Remark 1: since coordinates are always 2-tuples, a list representation invites unwanted errors (e.g. writing [X|Y] instead of [X,Y]). Traditionally, an infix operator like - is used to seperate tuples, but it's not any different than using coord(X,Y).
Remark 2: this predicate is inherently non-logical (i.e. calling gen_coords(X, 20) twice will result in different substitutions for X). You might use the meta-level predicates var/1, nonvar/1, ground/1, integer, etc. to guard against non-sensical calls like gen_coord(1-2, [1-1]).
Remark 3: it is also important that the conditional does not have multiple solutions (compare member(X,[A,B]) and memberchk(X,[A,B])). In general, this can be achieved by calling once/1 but there is a specialized predicate memberchk/2 which I used here.
I just realized that the performance of my other solutions is very bad for N close to 100. The reason is that with diminishing possible coordinates, the generate and test approach will take longer and longer. There's an alternative solution which generates all coordinates and picks N random ones:
all_pairs(Ls) :-
findall(X-Y, (between(1,10,X), between(1,10,Y)), Ls).
remove_index(X,[X|Xs],Xs,0).
remove_index(I,[X|Xs],[X|Rest],N) :-
N > 0,
M is N - 1,
remove_index(I,Xs,Rest,M).
n_from_pool(_Pool, [], 0).
n_from_pool(Pool, [C|Cs], N) :-
N > 0,
M is N - 1,
length(Pool, L),
random(0,L,R),
remove_index(C,Pool,NPool,R),
n_from_pool(NPool, Cs, M).
gen_coords2(Xs, N) :-
all_pairs(Pool),
n_from_pool(Pool, Xs, N).
Now the query
?- gen_coords2(Xs, 100).
Xs = [4-6, 5-6, 5-8, 9-6, 3-1, 1-3, 9-4, 6-1, ... - ...|...] ;
false.
succeeds as expected. The error message
?- gen_coords2(Xs, 101).
ERROR: random/1: Domain error: not_less_than_one' expected, found0'
when we try to generate more distinct elements than possible is not nice, but better than non-termination.

Not able to reach base case in fibonacci sequence

I'm quite new to Prolog, and this way of thinking is kind of messing with my mind. I'm currently using SWI-Prolog to run and debug my code. I have implemented a tail recursive algorithm to solve the N'th fibonnaci-number. I have tried debugging step by step, and I cannot explain why my implementation is skipping the base case. Where am I thinking wrong?
fib(0, A,_, A). %Base case, when we reach N = 0, return.
%Tail recursion. Use N as counter, iterate until base value (N=0) is reached.
fib(N, A, B, F) :-
Nnew is N - 1,
Sum is (A + B),
fib(Nnew, B, Sum, F).
fib(N, F) :-
fib(N, 0, 1, F). %set start values for when fib(N,F). is called
My implementation is working great (and fast) if I want to calculate the nth fib number. For example, if I run ?- fib(5,F)., I get F = 5 back. Great. If I want to check ?- fib(5,5). I get True back, which is correct. Great.
But, if I input a false statement, for example: ?- fib(5,4). then the program is looping forever. What happens is that N passes 0, ignores the base case(?), and continues on to be decremented. Why is the base case skipped? In my eyes, fib(0,A,_,A). is satisfied. Where am I wrong?
You should add the condition N>0 to the second clause of your predicate fib/3, otherwise the predicate fib/3 will continue trying with the negative numbers if the base-case fails. Lets see the case when you consult ?- fib(0,1):
This case will unified the second clause fib(0,0,1,1), where Nnew will be instantiated to the value -1. From here Nnew will be infinitely decremented, and the base-case will never be unified.
Any other false case, like ?- fib(5,4) will try to decrement N until the base case is unified, and that won't happen unless after 5 iteration, the sum of the fibonacci numbers are equal to 4. So, there's is no point on try with more attempts.

generate a range of ints -- "out of local stack" [beginner]

gen(N,R):
R is value between 0 and N-1, in order.
Nnon-zero positive int. N will always be given.
For example: ?- genN(2,R). gives R=0;R=1. I implemented like this, but it has "out of local static error":
gen(X,0).
gen(X,R) :-
gen(X,R1),
R is R1+1,
R<X, % why this line
R>=0. % and this line can't keep the range successfully?
Result:
?- genN2(3,R).
R = 0 ;
R = 1 ;
R = 2 ;
ERROR: Out of local stack
To understand why your program does not terminate, use a failure-slice. To this end, we will insert some extra goals false that help to understand why the goals you added are irrelevant. If this resulting fragment does not terminate, then your original program does not terminate either. As you can see, there is not much happening in that part. In fact your program will terminate never.
gen(_X,0) :- false.
gen(X,R) :-
gen(X,R1), false,
R is R1+1,
R<X,
R>=0.
(There are some more issues: your definition would be true also for a goal like gen(-1,0) which is probably not what you intended.)
The best way to solve this all at once is to use clpfd instead of the more complex to handle (is)/2 or simply to use between/3:
gen(N0, R) :-
N1 is N0-1,
between(0, N1, R).

Resources