replacing each element of a list by a specific list - list

I try to define replaceEltByclass(E1:list,E2:list) E is a list without sublist. each element of E1 belonging to a class C is replaced by the
elements of C. The final result is put in E2. For example, the goal rep_class([e1,e4,e6,e11], E2) will provide the list E2 : [[e1,e8,e10], e4,[e3,e6,e7],e11]. I don't have the good results.
/*The code*/
/*facts*/
class(c1,[e3, e6, e7]).
class(c2,[e1, e8, e10]).
/*rules*/
rep_class([],[]).
rep_class([E|Q],E2) :-
class(C,L),
not(member(E,L)),
concat(E2,E,E2),
rep_class(Q,E2).
rep_class([E|Q],E2) :-
class(C,L),
member(E,L),
concat(E2,L,E2),
rep_class(Q,E2).
/*conventional concat*/
concat([],L,L).
concat([H|T],L,[H|Res]) :- concat(T,L,Res).

The problem is in: class(C,L),not(member(E,L)), because it will give two solution one if C=C2 and then for example e1 belongs in C2 so it will replace it with L and one solution when C=C1 where it will leave it as e1. You need to write "does C exists such member(e1,L)??" so you have to collect all possible lists and see if member(e1,L) stands for a list L. So with some changes my version is :
class(c1,[e3, e6, e7]).
class(c2,[e1, e8, e10]).
rep_class([],[]).
rep_class([E|Q],[E|E2]) :-
findall(L,class(_,L),List),
not(find(List,E,_)),
rep_class(Q,E2).
rep_class([E|Q],[Lout|E2]) :-
findall(L,class(_,L),List),
find(List,E,Lout),
rep_class(Q,E2).
find([Lin|_],E,Lin):-member(E,Lin).
find([Lin|T],E,Lout):-not(member(E,Lin)),find(T,E,Lout).
As an example:
?- rep_class([e1,e4,e6,e11], E2).
E2 = [[e1, e8, e10], e4, [e3, e6, e7], e11] ;
false.

Related

Listing elemets of a list as i want, in Prolog

This is my list in Prolog:
myList([a,b,c,d,e]).
I am trying to write a predicate. That predicate should give me this result:
ab
ac
ad
ae
bc
bd
be
cd
ce
de
I found a solution that's near to my goal. But it is not exactly what I want.
?- L=[a,b,c], findall(foo(X,Y), (member(X,L),member(Y,L)), R).
L = [a, b, c],
R = [foo(a, a), foo(a, b), foo(a, c), foo(b, a), foo(b, b), foo(b, c), foo(c, a), foo(c, b), foo(..., ...)].
For example i dont want to aa or bb or cc. Also, there is already ac result. So i dont want to again ca.
Sorry for my English.
Thanks.
?- set_prolog_flag(double_quotes, chars).
true.
?- List = "abcde",
bagof(X-Y, Pre^Ys^( append(Pre, [X|Ys], List), member(Y,Ys) ), XYs).
List = "abcde", XYs = [a-b,a-c,a-d,a-e,b-c,b-d,b-e,c-d,c-e,d-e].
?- List = [A,B,C,D,E],
bagof(X-Y, Pre^Ys^( append(Pre, [X|Ys], List), member(Y,Ys) ), XYs).
List = [A,B,C,D,E], XYs = [A-B,A-C,A-D,A-E,B-C,B-D,B-E,C-D,C-E,D-E].
From your question it is not that evident what you want but it seems you are happy to use findall/3. Above solutions use bagof/3 which is a somewhat more civilized version of findall/3. bagof/3 takes into account variables, and thus you get the same result with concrete characters [a,b,c,d,e] or with a list of variables [A,B,C,D,E].
You have used terms foo(a,b), in such situations it is more common (and convenient) to say a-b.
Here is another solution that does not need any of the higher-order predicates.
:- set_prolog_flag(double_quotes, chars).
:- use_module(library(double_quotes)).
list_pairwise([], []).
list_pairwise([E|Es], Fs0) :-
phrase(values_key(Es, E), Fs0,Fs),
list_pairwise(Es, Fs).
values_key([], _K) --> [].
values_key([V|Vs], K) -->
[K-V],
values_key(Vs, K).
?- list_pairwise("abcde", KVs).
KVs = [a-b,a-c,a-d,a-e,b-c,b-d,b-e,c-d,c-e,d-e].
?- list_pairwise(L, [a-b,a-c,a-d,a-e,b-c,b-d,b-e,c-d,c-e,d-e]).
L = "abcde"
; false.
?- list_pairwise(L, [A-B,A-C,A-D,A-E,B-C,B-D,B-E,C-D,C-E,D-E]).
L = [A,B,C,D,E]
; false.
?- KVs = [K1-_,K1-_,K2-_|_], dif(K1,K2), list_pairwise(Ks,KVs).
KVs = [K1-K2,K1-_A,K2-_A], Ks = [K1,K2,_A], dif:dif(K1,K2)
; false.
In the last query we show that a sequence starting with keys, K1, K1, K2 can only result in the sequence of three elements.
What about a couple of predicates as follows ?
printCouples(_, []).
printCouples(E1, [E2 | T]) :-
write(E1), write(E2), nl,
printCouples(E1, T).
printList([]).
printList([H | T]) :-
printCouples(H, T),
printList(T).
From
printList([a, b, c, d])
you get
ab
ac
ad
bc
bd
cd

Swapping elements based on index given from another list

Hello my task is to swap elements of list, with the index that needs to be swapped in another list, so fx:
If I have:
[3,1,2] as the list
And:
[[1,2],[2,3]] as the index that needs to be swapped
Then it should go like:
[1,2] = 3 and 1 getting swapped
[2,3] = 3 and 2 getting swapped
So i would end up with Output = [1,2,3]
The predicate is specified to be like this:
swap(C,Input,Output)
Where C is the list of which elemenst that should be swapped.
Input is the list that should be swapped.
Output is the swapped list.
I would like some advice on how to swapping those elements based on this, I have already looked at this: swap two elements from list with specified indices
Hope that someone can help me with this.
Edit:
So far I have tried something like this:
swap( Input,[I|J], Input ) :-
I = J.
swap( Input, [I|J], Output ) :-
swap( Input, [I|J], Output, _, _ ).
swap( Input, [I|J], Output ) :-
swap( Input, J, I, Output, _, _ ).
swap( [E2|Ls], I, 0, [E1|Ls], E1, E2 ):-!.
swap( [E1|Es], 0, J, [E2|Rs], E1, E2 ) :-
N2 is J - 1,
swap( Es, -1, N2, Rs, E1, E2 ),!.
swap( [E|Es], [I|J], [E|Rs], E1, E2 ) :-
N1 is I - 1,
N2 is J - 1,
swap( Es, N1, N2, Rs, E1, E2 ).
But I am only able to use "one" list as the indexes of what that has to be swapped, like [1,2], what I am looking for is being able to use multiple like [[1,2],[2,3]] and so on.
This answer is based on this previous answer by #user27815.
Here comes the lambda + meta-predicate variant!
:- use_module(library(lambda)).
swap2(Ls0, Swaps, Ls) :-
foldl(\[I,J]^S0^S^list_i_j_swapped(S0,I,J,S), Swaps, Ls0,Ls).
Sample query:
?- swap2([3,1,2], [[0,1],[1,2]], Xs).
X = [1,2,3]
; false.
Using list_i_j_swapped/4
list_i_j_swapped(As,I,J,Cs) :-
same_length(As,Cs),
append(BeforeI,[AtI|PastI],As),
append(BeforeI,[AtJ|PastI],Bs),
append(BeforeJ,[AtJ|PastJ],Bs),
append(BeforeJ,[AtI|PastJ],Cs),
length(BeforeI,I),
length(BeforeJ,J).
swap(List,[],List).
swap(List1,Swaps,ListSwapped):-
Swaps =[[Index1,Index2]|T],
list_i_j_swapped(List1,Index1,Index2,List2),
swap(List2,T,ListSwapped).
Q:
?- swap([3,1,2],[[0,1],[1,2]],X).
X = [1, 2, 3] ;
false.
The positions are zero indexed.

Flattening only one level of a list in Prolog

I'm working on a problem to flatten only one level of a list in Prolog. For example, [[1],[2,3]] would become [1,2,3], but [[1,[2]],3] would only flatten down to [1,[2],3]. I went through some other questions on the site, but none thoroughly answered this question, and I just can't get my code to work on all my test cases.
Update: the code works! Here is the eventual answer that I came to:
my_flatten([], []).
my_flatten([A|B],L) :- is_list(A), my_flatten(B,B1), !, append(A,B1,L).
my_flatten([A|B],[A|B1]) :- my_flatten(B,B1).
You need 3 simple clauses, I will show just the most complex one
flat([H|T],R) :- is_list(H), flat(T,T1), append(H,T1,R).
other two clauses are the base recursion case, and a copy as is of head to result.
You should also place a cut in the clause I've shown, otherwise on backtracking you'll get wrong results (due to firing of the clause copy as is)
This are the results obtained with the predicate described at the bottom. With flat_lvl predicate u can specify the desired level for flat a list.
Examples:
% Lis= [[e1, e2, [e31, e32]], [e4, e5, e6, e7], [e8, e9]],
% flat_lvl(Lis, FlatLis, 2).
%
% ---> FlatLis = [e1, e2, e3, e4, e5, e6, e7, e8, e9]
% Lis= [[e1, e2, [e31, e32]], [e4, e5, e6, e7], [e8, e9]],
% flat_lvl(Lis, FlatLis, 1).
%
% ---> FlatLis = [e1, e2, [e31, e32], e4, e5, e6, e7, e8, e9]
% Lis= [[e1, e2, [e31, e32]], [e4, e5, e6, e7], [e8, e9]],
% flat_lvl(Lis, FlatLis, 0).
%
% ---> FlatLis = [[e1, e2, [e31, e32]], [e4, e5, e6, e7], [e8, e9]]
The predicate to flat a list with a specified level is the following, so just set DeepLvl to 1:
flat_lvl([],[],_).
flat_lvl([LisH| LisT], FlatLis, DeepLvl):-
Lvl is DeepLvl - 1, Lvl >= -1,
(flat_lvl(LisH, FlatH, Lvl); FlatH= [LisH]),
flat_lvl(LisT, FlatTail, DeepLvl),
append(FlatH, FlatTail, FlatLis), !.
?- flat_lvl(List, 1).

Grouping lists by common elements

I'm looking for a clever/fast C++ algorithm, which would allow me to do grouping of several lists of objects when they contain common objects inside. Let's say I have N lists, each containing 1..M objects (O) associated with one element E:
[O1, O2] -> E1
[O3] -> E2
[O1, O4, O5] -> E3
[O2, O5] -> E4
[O3, O6] -> E5
I wish to rearrange them into the following:
[O1, O2, O4, O5] -> [E1, E3, E4]
[O3, O6] -> [E2, E5]
The result has all common objects grouped together with all associated elements. No object is shared in the end between lists.
For each object, calculate which elements contain it.
i.e.
01 -> [E1, E3]
02 -> [E4]
03 -> [E2, E5]
04 -> [E3]
05 -> [E3, E4]
06 -> [E5]
These lists induce a graph: there's a vertex per element, and two vertices are connected if the corresponding elements show up in the same list.
It seems to me that what you want to calculate are the connected components of the graph.

Decrementing ranges in Haskell

I am very new to Haskell. Could someone please explain why defining a list like this returns an null list
ghci> let myList = [10..1]
ghci> myList
[]
However this works correctly.
ghci> let myList = [10, 9..1]
ghci> myList
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
Basically, because [10..1] is translated to enumFromTo 10 1 which itself has the semantics to create a list by taking all elements less-than 1 which result from counting upward (with step-size +1) from (including) 10.
Whereas [10, 9..1] is translated to enumFromToThen 10 9 1 which explicitly states the counting step-size as 9-10, i.e. -1 (which is hard-coded to +1 for enumFromTo)
A more accurate specification can be found in the Haskell Report (6.3.4 The Enum Class):
enumFrom :: a -> [a] -- [n..]
enumFromThen :: a -> a -> [a] -- [n,n'..]
enumFromTo :: a -> a -> [a] -- [n..m]
enumFromThenTo :: a -> a -> a -> [a] -- [n,n'..m]
For the types Int and Integer, the enumeration functions have the following meaning:
The sequence enumFrom e1 is the list [e1,e1+1,e1+2,...].
The sequence enumFromThen e1 e2 is the list [e1,e1+i,e1+2i,...], where the increment, i, is e2-e1. The increment may be zero or negative. If the increment is zero, all the list elements are the same.
The sequence enumFromTo e1 e3 is the list [e1,e1+1,e1+2,...e3]. The list is empty if e1 > e3.
The sequence enumFromThenTo e1 e2 e3 is the list [e1,e1+i,e1+2i,...e3], where the increment, i, is e2-e1. If the increment is positive or zero, the list terminates when the next element would be greater than e3; the list is empty if e1 > e3. If the increment is negative, the list terminates when the next element would be less than e3; the list is empty if e1 < e3.
Arithmetic sequence notation is just syntactic sugar for functions from the Enum class.
[a..] = enumFrom a
[a..b] = enumFromTo a b
[a, b..] = enumFromThen a b
[a, b..c] = enumFromThenTo a b c
As for why they weren't defined to automatically reverse, I can only speculate but here are some possible reasons:
If a and b are defined elsewhere, it would be harder to tell at a glance in which direction [a..b] would go.
It has nicer mathematical properties to reason about. You don't have to add special cases for when the sequence would be reversed.
If you want to generate a list from a to b regardless of whether a < b, you can use the following:
[a, a + (signum $ b - a)..b]
For newbies.
To make a list with all the numbers from 20 to 1, you can't just do
[20..1]
you have to specify as such:
[20,19..1]