I have a list of tuples:
L = [{1, [a, b, c]}, {2, [d, e, f]}, {3, [[h, i, j], [k, l, m]]}]
this is what I have
lists:map(fun({_, B}-> B end, L).
the output is
[[a, b, c], [d, e, f], [[h, i, j], [k, l, m]]]
what I want is:
[[a, b, c], [d, e, f], [h, i, j], [k, l, m]]
it seems a pretty easy problem, but I can't figure out how to do it.
Please help!
Let's see...
1> L = [{1, [a, b, c]}, {2, [d, e, f]}, {3, [[h, i, j], [k, l, m]]}].
[{1,[a,b,c]},{2,[d,e,f]},{3,[[h,i,j],[k,l,m]]}]
Trivial and straightforward, but not tail-recursive:
2> lists:foldr(fun ({_,[X|_]=E},A) when is_list(X) -> lists:append(A,E);
({_,E},A) -> [E|A] end,
[], L).
[[a,b,c],[d,e,f],[h,i,j],[k,l,m]]
Not being tail-recursive is not very nice, though, but...
3> lists:reverse(lists:foldl(fun ({_,[X|_]=E},A) when is_list(X) ->
lists:reverse(E,A);
({_,E},A) -> [E|A] end,
[], L)).
[[a,b,c],[d,e,f],[h,i,j],[k,l,m]]
...the tail-recursive version also works (thanks to Zed for pointing out lists:reverse/2).
For your specific example case, you can define the following function:
group3([], Acc) ->
Acc;
group3([A,B,C|Tl], Acc) ->
group3(Tl, [[A,B,C]] ++ Acc).
group3(L) ->
lists:reverse(group3(L, [])).
and invoke it like this:
group3(lists:flatten(lists:map(fun({_, B}) -> B end, L))).
Hopefully that's enough to give you a general strategy.
-module(z).
-export([do/1]).
do([{_,[X|_] = L}|Tl]) when is_list(X) -> L ++ do(Tl);
do([{_, L} |Tl]) -> [L|do(Tl)];
do([]) -> [].
test:
1> z:do(L).
[[a,b,c],[d,e,f],[h,i,j],[k,l,m]]
Related
So i have this predicate letras_comuns(Lst_Pals, Letras_comuns) in which Lst_Pals is a list of like [[a,t,o],[a,c,o],[a,n,o]] and Letras_comuns is the a list with all the elements common in every word at a given index, e.g. [(1,a), (3,o)].
Example:
?- Lst_Pals = [[a,t,o], [a,c,o], [a,n,o], [a,l,o]],
letras_comuns(Lst_Pals, Letras_comuns).
Lst_Pals = [[a, t, o], [a, c, o], [a, n, o], [a, l, o]],
Letras_comuns = [(a, 1), (o, 3)].
So basically what this means is that all the words in Lst_pals have an a in the 1st index and an o in the 3rd/last index.
The problem is that i want to access to the elements inside the parenthesis and i know if put (X,Y) = (a,1) i can access its elements, the thing is that this only works for 1 and i want to access to all of them, so anyone can tell me how because i'm clueless on how to do this.
You can define
p( (X,Y), X, Y ).
then use it:
?- p( (a,1), A, I ).
A = a,
I = 1.
or
?- maplist( p, [(a, 1), (o, 3)], AS, IS).
AS = [a, o],
IS = [1, 3].
So i have this predicate letras_comuns(Lst,Common_ltrs) in which Lst is a list of words like [[a,n,o],[a,c,o],[a,t,o]] and Commons_ltrs is the result of the common letters in all of those words at a certain index.
Example:
Lst_Pals = [[a,t,o], [a, c, o], [a,n,o], [a,l,o]], letras_comuns(Lst_Pals, Letras_comuns).
Lst_Pals = [[a,t,o], [a, c, o], [a,n,o], [a,l,o]],
Letras_comuns = [(1, a),(3, o)].
So what this [(1, a), (3, o)]. means is that all of the words have an a at the first index and that all of the words have an o at the 3rd index
Well to this i did this auxiliar predicate letras_comuns_aux(Lst,Letra_comum,Index). in which Lst is the same as before, Letra_comum is the common letter in all of the words at a given index, like [(1, a)] and index the specific index.
Example:
?- letras_comuns_aux([[a,t,o], [a, c, o], [a,n,o], [a,l,o]],Letra_comum,1).
Letra_comum = [(1, a)].
?- letras_comuns_aux([[a,t,o], [a, c, o], [a,n,o], [a,l,o]],Letra_comum,3).
Letra_comum = [(3, o)].
So basically this is giving the result i want at given index and this predicate is working fine, having said this what i tried to do is to do this verification for all indexes in Lst.
The problem is that for some reason this is giving an infinite cicle and i dont understand why.
Program:
letras_comuns_aux([],AC,_,_,AC) :- !.
letras_comuns_aux([P|R],Letra_comum,Index,El,_) :-
nth1(Index,P,Ind_P),
Ind_P == El,!,
NAC = [(Index,El)],
letras_comuns_aux(R,Letra_comum,Index,El,NAC).
letras_comuns_aux(_,Letra_comum,Index,El,_) :-
NAC = [],!,
letras_comuns_aux([],Letra_comum,Index,El,NAC).
letras_comuns(Lst_Pals, Letras_comuns) :-
length(Lst_Pals,C),
NC is C + 1,
letras_comuns(Lst_Pals,Letras_comuns,[],NC,1).
letras_comuns(_, AC,AC,Comp,Comp).
letras_comuns(Lst_Pals, Letras_comuns,AC,Comp,Cont) :-
letras_comuns_aux(Lst_Pals,Letra_comum,Cont),
append(AC,Letra_comum,NAC),
NCont is Cont +1,
letras_comuns(Lst_Pals, Letras_comuns,NAC,Comp,NCont).
This is clearly an endless loop:
letras_comuns_aux(_,Letra_comum,Index,El,_) :-
NAC = [],!,
letras_comuns_aux([],Letra_comum,Index,El,NAC).
At every call, NAC is a fresh variable, that thereof will obviously will bind the empty list, and the recursive call then will receive such empty list as last parameter. What's the purpose of it ?
Now forgive my lazyness, but to understand your program is clearly more work than suggest a simpler idiomatic way:
letras_comuns(Lst_Pals, Letras_comuns) :-
findall((L,I), foreach(member(X,Lst_Pals),nth1(I,X,L)), Letras_comuns).
This gives
?- Lst_Pals = [[a,t,o], [a, c, o], [a,n,o], [a,l,o]],
| letras_comuns(Lst_Pals, Letras_comuns).
Lst_Pals = [[a, t, o], [a, c, o], [a, n, o], [a, l, o]],
Letras_comuns = [(a, 1), (o, 3)].
and is made possible by foreach/2, that keeps variables bindings among successive calls of Generator.
I am writing a predicate in Prolog to divide a list into two equal in length lists. For example :
spliting([a, b, c, d, e], L1, L2)
produces:
L1 = [a, b, c], L2 = [d, e].
My code:
parimpar(L, A, B) :-
split(L, L, A, B).
split(B, [], [], B).
split([H|T], [_, _|T1], [H | T2], B) :-
split(T, T1, T2, B).
But it is working only the list to split is of even length.
How can I resolve that?
I have written the following code to check whether it is a palindrome or not. I have also created the logic to insert elements when the list is not a palindrome
reverse_list(Inputlist, Outputlist) :-
reverse(Inputlist, [], Outputlist).
reverse([], Outputlist, Outputlist).
reverse([Head|Tail], List1, List2) :-
reverse(Tail, [Head|List1], List2).
printList([]).
printList([X|List]) :-
write(X),
write(' '),
printList(List).
palindrome(List1) :-
reverse_list(List1, List2),
compareLists(List1, List1, List2, List2).
compareLists(L1, [], [], L2) :-
write("\nList is Palindrome").
compareLists(L1, [X|List1], [X|List2], L2) :-
compareLists(L1, List1, List2, L2),
!.
compareLists(L1, [X|List1], [Y|List2], [Z|L2]) :-
write("\nList is not Palindrome. "),
append(L1, L2, L),
printList(L).
The code gives the correct output for
palindrome([a,b,c,a]).
List is not Palindrome. a b c a c b a
palindrome([a,b,c]).
List is not Palindrome. a b c b a
However, for an input such as
palindrome([a,b,c,b]).
List is not Palindrome. a b c b c b a
The optimal solution however should be
a b c b a
What changes should I incorporate to be able to achieve this?
The first 3 equations of a DCG capture the palindrome pattern.
Add a fourth, covering the mismatch, to complete the specification:
p([]) --> [].
p([T]) --> [T].
p([T|R]) --> [T], p(P), [T], {append(P,[T],R)}.
p([T|R]) --> [T], p(P), {append(P,[T],R)}.
?- phrase(p(L), [a,b,c,b]).
L = [a, b, c, b, a] ;
L = [a, b, c, c, b, a] ;
L = [a, b, c, b, c, b, a] ;
L = [a, b, c, b, b, c, b, a] ;
false.
I think you need a predicate with two Args, In and Out :
pal([], []).
pal([X], [X]).
pal(In, Out) :-
% first we check if the first and last letter are the same
( append([H|T], [H], In)
% we must check that the middle is a palindrome
-> pal(T, T1),
append([H|T1], [H], Out)
; % if not, we remove the first letter
% and we work with the rest
In = [H|T],
% we compute the palindrome from T
pal(T,T1),
% and we complete the palindrome to
% fit the first letter of the input
append([H|T1], [H], Out)).
EDIT1
This code looks good but there is a bug for
? pal([a,b,c,a], P).
P = [a, b, c, b, a] .
Should be [a,b,c,a,c,b,a]
I'll try to fix it.
EDIT2
Looks correct :
build_pal([H|T], Out):-
pal(T,T1),
append([H|T1], [H], Out).
pal([], []).
pal([X], [X]).
pal(In, Out) :-
( append([H|T], [H], In)
-> pal(T, T1),
( T = T1
-> append([H|T1], [H], Out)
; build_pal(In, Out))
; build_pal(In, Out)).
with output :
?- pal([a,b,c], P).
P = [a, b, c, b, a] .
?- pal([a,b,a], P).
P = [a, b, a] .
?- pal([a,b,c,b], P).
P = [a, b, c, b, a] .
?- pal([a,b,c,a], P).
P = [a, b, c, a, c, b, a] .
?- pal([a,b,a,c,a], P).
P = [a, b, a, c, a, b, a] .
I'm new in Prolog.
I have a problem about predicate prefix but a little bit different.
I want to get a prefix of a list but until an element
The list can have repeat elements.
An example:
prefix(Element, List, Prefix)
prefix(c, [a,b,c,d,e,f], [a, b])
The element is not included.
What I have so far is this
prefix(X, [X|T], []).
prefix(X, [Y|T], [Y|Z]):-
prefix(X, T, Z).
But it does not work.
L = [a,b,c] ? prefix(b, L, Prefix).
no
?-
Thanks
With dif/2 you can explicitly state that for any member X preceding Element, X \== Element:
prefix(Element, [Element|_], []).
prefix(Element, [Head|List], [Head|Prefix]) :-
dif(Element, Head),
prefix(Element, List, Prefix).
or equally, because I wanted to use append/3 in the first iteration of my answer:
prefix(Element, List, Prefix) :-
append(Prefix, [Element|_Suffix], List),
maplist(dif(Element), Prefix).
For the suffix it is basically the same:
suffix(Element, List, Suffix) :-
append(_Prefix, [Element|Suffix], List),
maplist(dif(Element), Suffix).
If you don't want to use maplist(dif(Element), List):
all_dif(_, []).
all_dif(X, [H|T]) :- dif(X, H), all_dif(X, T).
Here is a solution using Definite Clause Grammars dcg and the non-terminal all_seq//2:
prefix(X, Xs, Ys) :-
phrase( ( all_seq(dif(X), Ys), [X], ... ), Xs).
... --> [] | [_], ... .
So the grammar (within phrase/2) reads:
There is
1. an initial sequence Ys with all elements different to X, followed by 2. X, followed by 3. anything.
There is still a downside, which is often the case when using DCGs: The implementation is not as determinate as it could be and thus leaves superfluous choicepoints around.
prefix(X,[X|T],[]).
prefix(X,[Y|T],Z) :- prefix(X,T,M) , Z = [Y|M].
output:
?- L = [a,b,c,d,e,f] , prefix(d,L,G). L = [a, b, c, d, e, f], G = [a,
b, c] .
?- L = [a,b,c,d,e,f] , prefix(e,L,G). L = [a, b, c, d, e, f], G = [a,
b, c, d] .
EDIT #1
the original code is working , use (,) instead of (?) as following.
prefix(X,[X|T],[]).
prefix(X,[Y|T],[Y|Z]) :- prefix(X,T,Z).
output:
?- prefix(d , [a,b,c,d,e] , G). G = [a, b, c]
?- L = [a,b,c] , prefix(b, L, Prefix).
L = [a, b, c],
Prefix = [a] .
EDIT #2
as user false mentioned in comment, I can confirm that you are right, but in my solution, I assume that the list contains unique elements:
prefix(d,[d,d],[d]) succeeds - it should fail ,