Prolog how to print first 3 elements in a list - prolog

How can I print the first 3 elements in a list.
I have a print method
print([]).
print([X]) :- !, write(X).
print([X|T]) :- write(X), write(', '), print(T), nl.

In Prolog, the typical way to implement iteration is recursion:
print(0, _) :- !.
print(_, []).
print(N, [H|T]) :- write(H), nl, N1 is N - 1, print(N1, T).
If we reached zero or have an empty list, do nothing. If we should do something, print the first item in the list, compute the new N and recursively call itself.
The cut (!) in the first clause is necessary, otherwise we would need a condition for N in the last one.

If you always have at least tree elements ist very simple
print_first_three([A,B,C|_]) :- print(A), print(B), print(C).

Related

Prolog recursion code returning false, add in variables as input to recursive list parse

Im writing prolog to print out each element of a list, as long as a counter is > 0.
printLN([],_).
printLN(_,-1).
printLN([[x,y] | T], N) :-
write(x), write(y), nl,
N2 is N-1,
printLN(T, N2).
This should print the 3 pairs.
printLN([[1,2],[3,4],[5,6]], 2).
This should print the 3 pairs.
printLN([[1,2],[3,4],[5,6]], 8).
This should print first pair.
printLN([[1,2],[3,4],[5,6]], 0).
I keep getting false though. Anyone know why this may be the case?
As well, how could i execute something like:
getPartialList(N) :-
getList(LIST), printLN(LIST, N).
where getList returns a list of pairs like:
getList([[1,2],[3,4],[5,6]]).
I keep getting false though. Anyone know why this may be the case?
Two errors:
a) write(x) should be written write(X) where X is a logical variable (in capitals).
b) Your third clause keeps Calling recursively even if N < 0. To correct this, put a test N > 0 into this clause.
printLN([],_).
printLN(_, -1) :- !.
printLN([[X,Y] | T], N) :-
N > 0,
write(X), write(Y), nl,
N2 is N-1,
printLN(T, N2).

adjacent involving first and last element, Prolog

HI I would like to know how a method that finds out if two members of a list in Prolog are adjacent as the catch is that the first and the last elements are checked if they are adjacent something like
(b,c,[b,a,d,c])
would give yes they are adjacent. I already have this code
adjacent(X, Y, [X,Y|_]).
adjacent(X, Y, [_|Tail]) :-
adjacent(X, Y, Tail).
but I do not know how to include the head of the list and the last elments as well being compared for being adjacent. If you are really good maybe you can tell me also how it is possible to make something like this
(c,b,[a,b,c,d])
to be true I mean the elements are adjacent no matter which exactly is first.
You can make use of last/2 predicate [swi-doc] to obtain the last element of the list. But you can not use this in the recursive call, since otherwise it will each element in the list pair with the last element as well.
The trick is to make a helper predicate for the recursive part, and then make the adjacent/3 predicate to call the recursive one you wrote yourself, or one where we match with the last element:
adjacent(X, Y, L) :-
adj(X, Y, L).
adjacent(X, Y, [Y|T]) :-
last(T, X).
adj(X, Y, [X,Y|_]).
adj(X, Y, [_|T]) :-
adj(X, Y, T).
Relations about lists can often be described with a Definite Clause Grammar dcg.
A first attempt might be:
adjacent(A, B, L) :-
phrase(adjacent(A, B), L). % interface to DCG
adjacent(A,B) -->
..., ( [A,B] | [B,A] ), ... .
... --> [] | [_], ... .
Yet, this leaves out cases like adjacent(a,d,[a,b,c,d]). One possibility would be to add another rule, or maybe simply extend the list to be considered.
adjacent(A, B, L) :-
L = [E,_|_],
append(L, [E], M),
phrase(adjacent(A, B), L).

Print elements of a list but handle last element differently

I have written a predicate that prints out each element in the list except the last. The last element should be handled differently; it should print LAST! instead. This is what I have.
write_data([]).
write_data([X]) :-
!, write('LAST!'), nl.
write_data([X | Rest]) :-
write(x), nl,
write_data(Rest).
Is there a better way? Is there a way to do this without the cut?
You can avoid the cut, by performing unification with a list that has at least two elements, like:
write_data([]).
write_data([_]) :-
write('LAST!'),
nl.
write_data([X|Rest]) :-
Rest = [_|_],
write(X), nl,
write_data(Rest).
We can furthermore avoid the double unpacking with a helper predicate:
write_data([]).
write_data([H|T]) :-
write_data(T, H).
write_data([], _) :-
write('LAST!'), nl.
write_data([H|T], X) :-
write(X), nl,
write_data(T, H).
A common definition for a last/2 predicate that provides access to the last element of a list is:
last([Head| Tail], Last) :-
last(Tail, Head, Last).
last([], Last, Last).
last([Head| Tail], _, Last) :-
last(Tail, Head, Last).
When called with the first argument bound to a closed list, the auxiliary predicate, last/3, avoids spurious choice-points assuming a Prolog system implementing, as common, first-argument indexing. Can you modify this predicate to do what you want?
The general rule of thumb for cut removal is to note what was true in the clause that contains the cut , then make sure that is false in the other clause(s) .
Thus :
write_data([]).
write_data([X]) :-
/*!,*/write('LAST!'), nl.
write_data([X | Rest]) :-
dif(Rest,[]) , /**/
write(x), nl,
write_data(Rest).

How to split list in Prolog?

I want to write a predicate split(List, Pivot, Result) holds when Result is a list of sublists that List divided by Pivot. For example split(['_', '_', '#', '_', '#', '_'], '#', [['_','_'], ['_'], ['_']]) is true.
My code is like this and it doesn't work:
split(List, Pivot, Result) :-
split(List, Pivot, _, _, Result).
split(List, Pivot, Left, Right, X|Xs) :-
append(Left, [Pivot|Right], List),
!,
member(Pivot, Right)
-> X = [Left],
split(Right, Pivot, _, _, Xs)
; X = [[Left]|[Right]].
I don't think my approach is clever either. Can someone give me some advice? Thank you.
We can preserve logical-purity and get the job done in no time, simply by using the right tools!
Let's use the meta-predicate splitlistIf/3 and the reified equality predicate (=)/3 in a query:
?- Xs = ['_','_',#,'_',#,'_'], splitlistIf(=(#),Xs,Ys).
Xs = [ '_','_' ,#,'_',#,'_' ]
Ys = [['_','_'], ['_'],['_']]. % succeeds deterministically
Here is one way of doing it:
split(L,P,R):-split(L,P,[],R).
split([],_,[],[]).
split([],_,S,[S]) :- S \= [].
split([P|T],P,[],R) :- split(T,P,[],R).
split([P|T],P,L,[L|R]) :- L \= [], split(T,P,[],R).
split([H|T],P,S,R) :- H \= P, append(S, [H], S2), split(T,P,S2,R).
Demo.
split/4 predicate adds a parameter at position 3 which means "list constructed so far". split/3 is a simple redirection with the "list so far" set to [].
Clauses on lines 2 and 4 handle situations when two Pivots are in a row, and when the pivot is detected at the end of the sequence. These clauses prevent insertion of empty lists.

Prolog: Removing Duplicates

I am trying to remove duplicate entries from a list in prolog. So a list [a,b,a,c,b,a] would return [a,b,c]. I can not use any built in functions. I searched here and found this code.
member(X,[X|_]) :- !.
member(X,[_|T]) :- member(X,T).
set([],[]).
set([H|T],[H|Out]) :- not(member(H,T)), set(T,Out).
set([H|T],Out) :- member(H,T), set(T,Out).
But that would take my list and return [c,b,a] not [a,b,c]
I have remove code that will take an element and a list and return a list with occurrences of that element in the list removed. So I tried to incorporate that into my remove duplicate method but I don't really understand prolog very well so it is not working. Logically I want to take a list cons the head with the recursive call on the new list minus all occurrences of the head. This is what the code would look like in sml.
fun remv(_,nil) = nil
| remv(a,x::xs) = if x=a then remv(a,xs) else x::remv(a,xs);
fun remvdub (nil) = nil
| remvdub(x::xs) = x::remvdub(remv(x,xs));
So this is what I tried in prolog
remv(_,[],[]).
remv(X,[X|T],Ans) :- remv(X,T,Ans).
remv(X,[H|T],[H|K]) :- remv(X,T,K).
remvdub([],[]).
remvdub([H|T],[H|Ans]) :- remvdub(Ans1,Ans), remv(H,T,Ans1).
What am I missing?
% An empty list is a set.
set([], []).
% Put the head in the result,
% remove all occurrences of the head from the tail,
% make a set out of that.
set([H|T], [H|T1]) :-
remv(H, T, T2),
set(T2, T1).
% Removing anything from an empty list yields an empty list.
remv(_, [], []).
% If the head is the element we want to remove,
% do not keep the head and
% remove the element from the tail to get the new list.
remv(X, [X|T], T1) :- remv(X, T, T1).
% If the head is NOT the element we want to remove,
% keep the head and
% remove the element from the tail to get the new tail.
remv(X, [H|T], [H|T1]) :-
X \= H,
remv(X, T, T1).
The snippet of Prolog code that you posted is logically correct. If you would like to keep the first, as opposed to the last, copy of each duplicated item, you can change your code as follows:
member(X,[X|_]) :- !.
member(X,[_|T]) :- member(X,T).
set(A,B) :- set(A, B, []).
set([],[],_).
set([H|T],[H|Out],Seen) :- not(member(H,Seen)), set(T,Out, [H|Seen]).
set([H|T],Out, Seen) :- member(H,Seen), set(T,Out,Seen).
The idea is to add a third parameter, which represents the list of items that you have seen so far, and check the membership against it, rather than checking the membership against the remaining list. Note that set/2 is added to hide this third argument from the users of your predicate.
Demo on ideone.

Resources