Reverse lists in list of lists prolog - list

I want to reverse each list from a list of lists.
I have something which looks like:
[[a,b],[],[c,d,e],[],[],[f,g]]
What I want is to read through the list of lists and reverse each list and get this result:
[[b,a],[],[e,d,c],[],[],[g,f]]
I already have a reverse function:
reverse(L, R) :- reverse(L, [], R).
reverse([], R, R).
reverse([H|T], A, R) :- reverse(T, [H|A], R).
How can I manage to read through the list?
Will a recursive function like this one work ?
reverseLL([H|T], L) :-
reverse(H,NH),
reverseLL([T],[NH|L]).
reverseLL([],L).

reverseInList([],[]).
reverseInList([H|Ts],[H1|R]):-
reverse(H,H1),
reverseInList(Ts,R).
This works by recursing over the list and using the library function 'reverse/2' to reverse each sublist.

Related

Get duplicate items in a list and display answer in a list

I'm trying to find duplicate (non unique) items in a list.
For example from
duplicate([a,b,c,a,b,r,d,c], R).
I need to get [a,b,c].
I've written so far prolog program that finds duplicate elements in a list.
However, I get the answer as single elements.
R = a
R = b
R = c
And I have to get them in a list as [a,b,c]
duplicate([First|Rest], Element) :-
duplicate_first(Rest, First, Element).
duplicate_first([Head|Rest], X, X) :-
duplicate_second(Rest, Head, X).
duplicate_first([Head|Rest], _, X) :-
duplicate_first(Rest, Head, X).
duplicate_second(_, X, X).
duplicate_second([Head|Rest], _, X) :-
duplicate_second(Rest, Head, X).
P.S. I don't want to use any swi-prolog build in functions.
I find it a bit of a straightjacket to ignore the standard library. But you can fulfill the requirement by implementing the two predicates you need, which are member/2 and delete/3, yourself:
my_member(X, [X|_]).
my_member(X, [_|Xs]) :- my_member(X, Xs).
This is probably the most straightforward way to implement member/2, although it isn't exactly the same as in the SWI library.
my_delete([], _, []).
my_delete([X|Xs], X, Ys) :- my_delete(Xs, X, Ys).
my_delete([Y|Xs], X, [Y|Ys]) :- X \= Y, my_delete(Xs, X, Ys).
I just sort of took a crack at this and it seems to be OK. A better implementation would probably use something like X = Y -> ... but that can lead to issues with backtracking so I am using this variation which probably has other problems.
Now that you have the preliminaries, the actual implementation is not that hard. First your base case. There are no duplicates in the empty list.
duplicates([], []).
Now you have two inductive cases. One, in which the head of the list occurs inside the tail of the list. When that happens you add it to the result and remove it from the tail (or you'll get duplicates in your list of duplicates).
duplicates([X|Xs], [X|Ys]) :-
my_member(X, Xs),
my_delete(Xs, X, XsWithoutX),
duplicates(XsWithoutX, Ys).
Your other case is when the head element does not appear in the tail, so you can simply recur and find the rest of the duplicates:
duplicates([X|Xs], Ys) :-
\+ my_member(X, Xs),
duplicates(Xs, Ys).
I'm a little out of practice so the following code can be simplified but... given a filter function (that remove the Val correspondences from a list and return [Val] if correspondence is found or empty list otherwise)
filter(_, [], [], []).
filter(Val, [Val | Rest], [Val], LR) :-
filter(Val, Rest, _, LR).
filter(Val1, [Val2 | Rest], LO, [Val2 | LR]) :-
Val1 \= Val2,
filter(Val1, Rest, LO, LR).
and given a sort of optional adder in front of a list
addOptional([], L, L).
addOptional([O], L, [O | L]).
I suppose you can write duplicate/2 as follows
duplicate([], []).
duplicate([First | Rest], Result) :-
filter(First, Rest, Opt, Filtered),
duplicate(Filtered, Res2),
addOptional(Opt, Res2, Result).

Prolog: apply predicate to all list elements and sum results

I have a certain list which is generated from a predicate and looks like this:
[a, b, c]
I also have a following predicate p/3 that could be applied to each element of my list:
?- p(a, NewList, Number).
and it will return:
NewList = [c, d],
Number = 2.
where NewList is a newly generated list from a element, and Number is the NewList length.
Problem:
I want to apply the p/3 predicate to all elements, and get
one list which consists of all elements from all NewLists aka all NewLists appended together
and the sum of all Numbers.
I tried to do it like this:
loop_list([Element|[]], NewList, Number) :-
p(Element, NewList, Number).
loop_list([Head|Tail], [Tmp|NewList], Number) :-
loop_list(Tail, Tmp, Number).
but failed.
It is often better to separate your concerns, and solve one task at once. You can use maplist/4 [swi-doc] here to call the predicate over all the elements in the list. This will then unify the third and the fourth element with the results of p/3.
Next we can make use of append/2 [swi-doc] to append lists together, and sumlist/2 [swi-doc] to sum the elements of a list together.
We thus can implement this as:
loop_list(Ls, Xs, Sum) :-
maplist(p, Ls, Xss, Items),
append(Xss, Xs),
sumlist(Items, Sum).

Prolog: Maplist appending results to main list instead of sublists

So I have the simple predicate defined as
pred(Info, List, Result) :-
maplist(pred_calculate(Info), List, Result).
pred_calculate returns a list of X elements after an operation on a element of list, so for example pred_calculate(Info, List, Result) would return something like [2,3,5]
I want to add all the results of applying the pred_calculate predicate to all the elements of List, the problem I'm running into is that at the moment it's adding all the results from pred_calculate as sublists instead of adding to the single main list only.
So at the moment Result returns
[[2,3,5],[5,7,8],[8,9,11]] when it should return only [2,3,5,5,7,8,8,9,11]
How would I go about changing it to fix this behaviour?
When using foldl/4 with append/3, you have to pass the arguments in the correct order to append, if the order of the items is important1:
pred(Info, List, Result) :-
maplist(pred_calculate(Info), List, List1),
foldl([A, B, C] >> append(B, A, C), List1, [], Result).
Also, flatten/2 would achieve the same result, i.e.:
pred(Info, List, Result) :-
maplist(pred_calculate(Info), List, List1),
flatten(List1, Result).
1: foldl(append, List1, [], Result) would give you [8,9,11,5,7,8,2,3,5] as result.
maplist calls pred_calculate(Info) on every corresponding element of List and Result. Perhaps maplist is not what you really want to use here if pred_calculate results in a list on each call since it's not a 1-1 correspondence. You have a 1-to-many and you want the many in one big, flat list. You could use flatten or fold as !joel76 suggests. Or, you could "manually" write your own maplist-like predicate which is very simple - just a basic list recursion and probably using append to achieve each step:
pred(Info, List, Result) :-
pred(Info, List, [], Result).
pred(Info, [], Result, Result).
pred(Info, [H|T], Acc, Result) :-
pred_calculate(Info, H, R),
append(Acc, R, Acc1),
pred(Info, T, Acc1, Result).

Reversing list in Prolog

I am starting with prolog, and as an exercise I am trying to reverse a list.
For example, inv([1,2,3], S) should give S = [3,2,1].
Below is what a partner and I have already done:
conc([], L, L).
conc([X|L1], L2, [X|L3]) :- conc(L1, L2, L3).
tail([X|Y], S) :- conc([], Y, S).
inv([X|Y], S) :- tail([X|Y], TAIL), inv(TAIL, R_TAIL), conc(R_TAIL, X, S).
inv([], []).
The first three lines work fine. But really don't understand what's going on with the last two, and therefore how to fix it.
I just wanna find the tail (this is working, when I just use the tail function) of the list, reverse it and then append it to the head of the list.
Could you help me guys?
Alternative foldl/4 based solution:
prepend_element(E, L, [E|L]).
inv(List, Reversed) :-
foldl(prepend_element, List, [], Reversed).
Your code doesn't work for me.
Try this way instead:
?- reverse([1,2,3],Xs), write(Xs).
reverse(Xs,Ys) :- reverse(Xs,[],Ys).
reverse([],A,A).
reverse([H|T],R,A) :- reverse(T,[H|R],A).

Custom reverse of a list in Prolog

I am trying to write a predicate that given the following list in Prolog:
[[1,a,b],[2,c,d],[[3,e,f],[4,g,h],[5,i,j]],[6,k,l]]
will produce the following list:
[[6,k,l],[[5,i,j],[4,g,h],[3,e,f]],[2,c,d],[1,a,b]]
As you can see I would like to preserve the order of the elements at the lowest level, to produce elements in the order 1, a, b and NOT b, a, 1.
I would also like to preserve the depth of the lists, that is, lists that are originally nested are returned as such, but in reverse order.
I have managed to achieve the desired order with the following code, but the depth is lost, i.e. lists are no longer nested correctly:
accRev([F,S,T],A,R) :- F \= [_|_], S \= [_|_], T \= [_|_],
accRev([],[[F,S,T]|A],R).
accRev([H|T],A,R) :- accRev(H,[],R1), accRev(T,[],R2), append(R2,R1,R).
accRev([],A,A).
rev(A,B) :- accRev(A,[],B).
I would appreciate help in correcting the code to preserve the correct nesting of lists. Thanks!
Two suggestions. First, here's one (rev_lists/2) which uses a bunch of SWI-PROLOG built-ins:
rev_lists(L, RL) :-
forall(member(M, L), is_list(M)), !,
maplist(rev_lists, L, L0),
reverse(L0, RL).
rev_lists(L, L).
This one works by testing if all elements of a list L are themselves lists (M); if so, it will recursively apply itself (via maplist) over all individual sub-lists, else it will return the same list. This has the required effect.
Secondly, here's rev_lists/2 again, but written such that it doesn't rely on built-ins except member/2 (which is common):
rev_lists(L, RL) :-
reversible_list(L), !,
rev_lists(L, [], RL).
rev_lists(L, L).
rev_lists([], Acc, Acc).
rev_lists([L|Ls], Acc, R) :-
( rev_lists(L, RL), !
; RL = L
),
rev_lists(Ls, [RL|Acc], R).
reversible_list(L) :-
is_a_list(L),
\+ (
member(M, L),
\+ is_a_list(M)
).
is_a_list([]).
is_a_list([_|_]).
It's basically the same strategy, but uses an accumulator to build up reverse lists at each level, iff they are comprised exclusively of lists; otherwise, the same list is returned.