Splitting a list into two Separate lists - prolog

I'm trying to iterate through a given list and put all the positive numbers into Y and all negatives into Z. My code works until I go to add a second element to either Y or Z. If I run the code like so "divide([1,-2],Y,Z)" the code executes with no errors its only if I were to enter "divide([1,-2,3],Y,Z)" it will fail when trying to add 3 to Y.
divide([],[Y],[Z]):- write(Y), write(Z).
divide([H|T],[Y],[Z]):- split(H,Y,Z), divide(T,Y,Z).
split(H,Y,Z):- (H>0 -> append([H],[],Y); append([H],[],Z)).

SWI-Prolog library(apply) offers partition/4, a builtin for your problem, but since I think that for learning you're better to correct your own code here is my advise. Keep it simpler: the base case, i.e. when you are given an empty list, would be just this simple clause:
divide([],[],[]).
Then you must handle a non empty list. If the value is positive, put it in the second list. Otherwise, put it in the third list. You see, we need two more clauses, I will show partially the second one:
divide([V|Vs],[V|Ps],Ns) :-
V>=0,
...
As you see, the head parameters act as both destructuring as well as constructing the relevant values. Put a recursive call instead of the three dots, and write the third clause to handle the case V<0.
I've attempted to use descriptive variables names: Vs stands for values, Ps for positives, Ns for negatives.

I see the other answer and I am confuse. I have been learning by copying others who know better than me my whole life. Maybe this is why I ended up as a teaching assistant intern, instead of a real job.
Here is what I get when I follow the instructions and try to learn by imitating:
list_pos_neg([], [], []).
list_pos_neg([H|T], P, N) :-
( H >= 0
-> P = [H|P0],
list_pos_neg(T, P0, N)
; N = [H|N0],
list_pos_neg(T, P, N0)
).

I usually try to avoid the cut and use -> ; instead. But in this case, I think it is clearer this way:
div_pos_neg([], [], []).
div_pos_neg([H|T], [H|P], N) :- H >= 0, !, div_pos_neg(T, P, N).
div_pos_neg([H|T], P, [H|N]) :- H < 0, div_pos_neg(T, P, N).
Note that the condition is still necessary in the last clause so that calls like div_post_neg([1,2], [], [1, 2]) return the right answer (failure!).

That seems ... complicated. How about just
partition( [] , [] , [] ) .
partition( [X|Xs] , [X|Ns] , Ps ) :- X < 0 , partition(Xs,Ns,Ps) .
partition( [X|Xs] , Ns , [X|Ps] ) :- X >= 0 , partition(Xs,Ns,Ps) .

Related

Recursivity | Natural numbers in list swish prolog

i have the next problem,
"return the numbers of natural numbers of an array"
ex. naturales(R,[6,-7,-4,3,2,8]).
R = 4
when a negative numbers appears return false and break my recursivity
naturales(R,[Head|Tail]):-naturales(R1,Tail), Head >= 0, R is R1+1.
naturales(0,[]).
Here is a very short solution :
naturales(In, Out) :-
aggregate(count,X^(member(X, In), X >= 0), Out).
If your predicate really needs to have only 2 arguments, one being the result, R, and the other one the given list, [H|T], you can do something like this. Note that the first predicate calls the second "naturales" with 3 arguments and then, that one starts the recursive process. The C is only a counter where you can add the number of positive elements and then copy that value to the result, in the last line of code. The first line just its just to make sure the empty list returns 0 positive elements. There is probably better ways to do this, this one is probably the most intuitive.
naturales(X, []):- X = 0.
naturales(R, [H|T]):- naturales(R, [H|T], 0).
naturales(R, [H|T], C):- (H > 0, C1 is C + 1, naturales(R1, T, C1), R = R1) ; naturales(R1, T, C), R = R1.
naturales(X, [], X).
A common prolog idiom is the use of a helper predicate with an accumulator (extra) variable. Try something like this:
natural_numbers( Xs, N ) :- natural_numbers( Xs, 0, N ).
natural_numbers( [] , N , N ) .
natural_numbers( [X|Xs] , T , N ) :-
( X > 0 -> T1 is T+1 ; T1 = T ) ,
natural_numbers( Xs, T1, N ).
As others pointed out, the recursive call cannot complete when there are negative numbers. So, you can just patch your program in this way
naturales(R,[Head|Tail]):-naturales(R1,Tail), (Head >= 0, R is R1+1 ; R=R1).
naturales(0,[]).
Now, nearly every Prolog out there (except mine :) implements (->)/2, also know as 'if-then-else'. So, the patch could also be written like
naturales(R,[Head|Tail]):-naturales(R1,Tail), (Head >= 0 -> R is R1+1 ; R=R1).
naturales(0,[]).
Given that naturales/2 is anyway not tail recursive (see #NicholasCarey answer for that), I think it has no practical relevance for you.

Find the minimum in a mixed list in Prolog

I am new to prolog, I am just learning about lists and I came across this question. The answer works perfect for a list of integers.
minimo([X], X) :- !.
minimo([X,Y|Tail], N):-
( X > Y ->
minimo([Y|Tail], N)
;
minimo([X|Tail], N)
).
How can I change this code to get the smallest int from a mixed list?
This
sint([a,b,3,2,1],S)
should give an answer:
S=1
you could just ignore the problem, changing the comparison operator (>)/2 (a binary builtin predicate, actually) to the more general (#>)/2:
minimo([X], X) :- !.
minimo([X,Y|Tail], N):-
( X #> Y ->
minimo([Y|Tail], N)
;
minimo([X|Tail], N)
).
?- minimo([a,b,3,2,1],S).
S = 1.
First of all, I don't think the proposed implementation is very elegant: here they pass the minimum found element thus far by constructing a new list each time. Using an additional parameter (we call an accumulator) is usually the way to go (and is probably more efficient as well).
In order to solve the problem, we first have to find an integer. We can do this like:
sint([H|T],R) :-
integer(H),
!,
sint(T,H,R).
sint([_|T],R) :-
sint(T,R).
So here we check if the head H is an integer/1. If that is the case, we call a predicate sint/3 (not to be confused with sint/2). Otherwise we call recursively sint/2 with the tail T of the list.
Now we still need to define sint/3. In case we have reached the end of the list [], we simply return the minum found thus far:
sint([],R,R).
Otherwise there are two cases:
the head H is an integer and smaller than the element found thus far, in that case we perform recursion with the head as new current minimum:
sint([H|T],M,R):
integer(H),
H < M,
!,
sint(T,H,R).
otherwise, we simply ignore the head, and perform recursion with the tail T.
sint([_|T],M,R) :-
sint(T,M,R).
We can put the recursive clauses in an if-then-else structure. Together with the earlier defined predicate, the full program then is:
sint([H|T],R) :-
integer(H),
!,
sint(T,H,R).
sint([_|T],R) :-
sint(T,R).
sint([],R,R).
sint([H|T],M,R):
(
(integer(H),H < M)
-> sint(T,H,R)
; sint(T,M,R)
).
The advantage of this approach is that filtering and comparing (to obtain the minimum) is done at the same time, so we only iterate once over the list. This will usually result in a performance boost since the "control structures" are only executed once: more is done in an iteration, but we only iterate once.
We can generalize the approach by making the filter generic:
filter_minimum(Filter,[H|T],R) :-
Goal =.. [Filter,H],
call(Goal),
!,
filter_minimum(Filter,T,H,R).
filter_minimum(Filter,[_|T],R) :-
filter_minimum(Filter,T,R).
filter_minimum(_,[],R,R).
filter_minimum(Filter,[H|T],M,R) :-
Goal =.. [Filter,H],
(
(call(Goal),H < M)
-> filter_minimum(Filter,T,H,R)
; filter_minimum(Filter,T,M,R)
).
You can then call it with:
filter_minimum(integer,[a,b,3,2,1],R).
to filter with integer/1 and calculate the minimum.
You could just write a predicate that returns a list with the numbers and the use the above minimo/2 predicate:
only_numbers([],[]).
only_numbers([H|T],[H|T1]):-integer(H),only_numbers(T,T1).
only_numbers([H|T],L):- \+integer(H),only_numbers(T,L).
sint(L,S):-only_numbers(L,L1),minimo(L1,S).

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.

Checking if the second list is half the size of first list

I am a noob prolog programmer and facing a difficulty with one of the basic problems that have been given in the book where I am learning from. The question. The question basically asks us to write down a Prolog procedure that takes two lists as arguments, and succeeds if the first list is twice the size of the second list and the two lists start with the same element. The procedure should return false if the two lists are empty.
For example it should return true if we pass the query:
a2b([a,a,a,a],[a,b]).
and would fail with a query like:
a2b([a,a],[a,b,b,b]).
I don't know how to solve this problem recursively, any help would be appreciated. Thanks!
First, the request about lengths:
/* empty list fulfills request */
a2b_length([],[]).
/* non-empty: discard two elements of first list,
one of second list, and verify
remainder */
a2b_length([_,_|Q1],[_|Q2]) :-
a2b_length(Q1,Q2).
Now, we can add the requirement "starts by the same term and are non empty", and write the last clause:
a2b([X,_|Q1],[X|Q2]) :-
a2b_length(Q1,Q2).
Cute problem. It can be solved using the following code:
% fail of the first element of each list don't unify
% or if one or both lists are empty
a2b([First| List1], [First| List2]) :-
% calculate the length of the second list
% while traversing both lists in parallel
a2b_first(List2, 1, N, List1, Rest1),
% check that the length of the rest of the first
% list is equal to the length of the second list
a2b_second(Rest1, N).
a2b_first([], N, N, Tail1, Tail1).
a2b_first([_| Tail2], N0, N, [_| Tail1], Rest1) :-
N1 is N0 + 1,
a2b_first(Tail2, N1, N, Tail1, Rest1).
a2b_second([], 0).
a2b_second([_| Tail1], N) :-
M is N - 1,
a2b_second(Tail1, M).
Of course, there's a simpler (but not as fun to code!) solution:
% fail of the first element of each list don't unify
% or if one or both lists are empty
a2b([First| List1], [First| List2]) :-
length([First| List1], N1),
length([First| List2], N2),
N1 is 2 * N2.
The length/2 predicate is usually available either as a built-in predicate or as a library predicate.
For learning Prolog, studying the first solution is interesting. For example, it exemplifies how to take advantage of first-argument indexing and how to use accumulators for writing predicates that are tail-recursive (and thus space efficient).
Also, the first solution can be more efficient than the second solution. In the second solution, we always traverse both lists to the end to find their lengths. But, in the first solution, that is not always necessary.
Don't overthink things: just describe the solution and let Prolog sort it out.
The solution doesn't require counting or predicates other than its trivial self. It's all pattern matching. We have a special (terminating case), asserting that a list of length 2 is twice as long as a list of length 1 (which should be pretty obvious):
is_twice_as_long_as( [_,_] , [_] ) .
Then there is the general case, which asserts that given two lists of arbitrary length, the left is twice as long as the right IF we can (A) remove 2 items from the left, (B) remove 1 item from right, and recursively assert that their respective remainders are likewise twice as long:
is_twice_as_long_as( [_,_|A] , [_|B] ) :- is_twice_as_long_as( A , B ) .
Giving us the finished product:
is_twice_as_long_as( [_,_] , [_] ) .
is_twice_as_long_as( [_,_|A] , [_|B] ) :- is_twice_as_long_as( A , B ) .
Easy!
Edited to note the requirement that the two lists begin with the same element:
Depending on how that is interpreted...
this requires that the lists have a common head on each iteration:
is_twice_as_long_as( [A,_] , [A] ) .
is_twice_as_long_as( [A,_|L] , [A|R] ) :- is_twice_as_long_as( L , R ) .
this does the check for a common head just once::
is_twice_as_long_as( [A|As] , [A|Bs] ) :-
is_2x([A|As],[A|Bs]) .
is_2x( [_,_] , [_] ) .
is_2x( [_,_|L] , [_|R] ) :- is_2x( L , R ) .

Prolog - How this program work

I have this program written in prolog language.
The problem is that i cant understand how it works.
even_number([],[]).
even_number([H|T],S):-even_number(T,W),Z is H mod 2,Z==0,S=[H|W].
even_number([_|T],S):-even_number(T,S).
All it does is to extract the even numbers from a list and store it to another list.
I know that it works using recursion but i cant understand the steps that are made during execution.
Can anyone explain?
The program consists of three rules that are applied as a group. They work together basically as if ... else if ... else if ... [else fail].
The first rule is: the even numbers in an empty list is the empty list. This is easy enough.
The second rule is applied if the first rule fails (i.e., the first argument isn't the empty list). This is a bit more complicated, but basically says to include the first element of the list if it is even. The logic breaks down as follows. The even numbers in a list that starts with H and has a tail of T is S if all the terms on the right are true: that the even numbers in T is some list W; that Z is the remainder after dividing H by 2; that Z is zero; and that S is H followed by W (whatever W turned out to be). (Note that this rule would be more efficient if the first term was moved to after the test Z==0.)
If that rule fails (i.e., H is odd), then the last rule is applied: the even numbers in the list are the even numbers in the tail of the list.
It's written rather poorly. It might be easier to understand if you refactor it a bit and make it tail recursive:
even_numbers( X , R ) :-
even_numbers( X , [] , T ) ,
reverse( T , R ).
even_numbers( [] , T , T ).
even_numbers( [X|Xs] , T , R ) :-
Z is X mod 2 ,
Z == 0 ,
! ,
even_numbers( Xs , [X|T] , R ).
even_numbers( [_|Xs] , T , R ) :-
even_numbers( Xs , T , R ).
The first predicate, even_numbers/2 predicate is the public wrapper. It invokes the private helper, even_numbers/3, which hands back the list of even numbers in reverse order. It reverses that and tries to unify it with the result passed in the wrapper.
The helper method does this:
if the source list is empty: unify the accumulator (T) with the result.
if the source list is not empty, and the head of the list (X) is even,
recurse down on the tail of the list (Xs), pushing X onto the accumulator.
if the source list is not empty, and the head of the list (X) is odd,
recurse down on the tail of the list (Xs) without modifying the accumulator.
But as noted by #André Paramés, work through it in the debugger and it will become clear what's going on.

Resources