1
votes

Trying to figure it out, how can I merge output like this one in Prolog:

[[z], [l, e, d], [j, i, d, c, a], [g, f, b], [h, b]]

to get result:

[z]

[l,e,d,j,i,c,a]

[g,f,b,h]

Not sure how to merge multiple lists containing at least one similar character.

I would appreciate any help from more experienced guys, cause I am just beginner and this task is quite tricky.

Thanks.

EDIT

Task is to get from edges defined by user all connected components and print them on output.

For instance user input edges:

data([[z,z],[a,c],[c,d],[d,i],[i,j],[d,e],[e,l],[b,f],[f,g],[b,h]]).

So I'm trying to figure it out how to solve this problem. What I've just did:

data(Edges):-
    dbH(Edges),
    searching,
    print,
    retractall(e(_,_)),
    retractall(lists(_)).

dbH([]).
dbH([[X, Y] | Body ]) :-
    assertz(e(X,Y)),
    dbH(Body).

oe(X,Y):-
    e(X,Y);
    e(Y,X).

searching:-
    nextE.

searching([Act | RouteStartAct]):-
    nextE([Act | RouteStartAct]).

nextE:-
    oe(Act,New),!,
    delE(Act,New),
    cycle([Act],New).
nextE:-
    !.

nextE([Act | RouteStartAct]):-
    oe(Act,New),!,
    delE(Act,New),
    cycle([Act | RouteStartAct],New).
nextE(Act):-
    assertz(lists(Act)),
    searching.

delE(X,Y):-
    retract(e(X,Y));
    retract(e(Y,X)).

cycle(Act,New):-
    not(mbr(New, Act)), !,
    searching([New|Act]).
cycle(Act,New):-
    assertz(lists(Act)),
    searching.

mbr(Element, [Element|_]).
mbr(Element, [_|Body]) :- 
    mbr(Element, Body).

print:-
    findall(C,lists(C),L),
    write(L).

At the end write(L) prints list of lists which I need to further merge based on the similar elements in each list. Like connect parts of one graph together and print them.

EDIT2 The result of this command:

?- data([[a, c], [c, d], [d, i], [i, j], [d, e], [e, l], [b, f], [f, g], [b, h]]).

is

[[j, i, d, c, a], [l, e, d], [g, f, b], [h, b]]

so from this output is obvious, that list [j, i, d, c, a] and [l, e, d] can be merged into one list [j, i, d, c, a, l, e]. Same for the lists [g, f, b] and [h, b], these two lists have common character b , so the output should be [g, f, b, h]. As a result of these two merges final output should look like:

[j, i, d, c, a, l, e]

[g, f, b, h]

Is it more obvious know?

2
You need to show what you have tried even if does not work and explain what you intended it to do and what it did instead. Questions without this typically don't get answers. In other words it looks like a homework problem an most people don't give answers to homework, only help. - Guy Coder
Thanks for response, you're right. What I can do is to compare two lists (A and B) and if there is one similar character in list B from list A, then I can join these two lists together, but what if there is no connection at all? Leave them as they are, but what if there are other 10 lists to compare? Numerous of lists complicated situation for me... - Ondrej Franek
Can you show the expected answer for the input given. At present I would have to guess. - Guy Coder
You have to join only consecutive lists or A and B can be not consecutive? I mean: what do you want from data([[a, b], [d], [b, c]])? [[a, b, c], [d]] or [[a, b], [d], [b, c]]? Anyway, if you can show us the expected answer from the given input can be helpfull. - max66
"...get all connected components". What do you mean by "component"? - lurker

2 Answers

1
votes

You could start with

touching(A,B):- memberchk(E,A), memberchk(E,B).

joined(A,B,C):- touching(A,B), setof(X, (member(X,A) ; member(X,B)), C).

Now you are left with the task of formulating a step relation which will find any two members of a given list for which touching/2 succeeds, and update the list with the new joined/3 entry; and repeat this step until it can't be performed any more; thus arriving at the solution.

0
votes

@WillNess Hi again Will, I've spent another day trying to implement your hint to my situation, but unfortunately I am not able to rework your source in order to work properly for my case. Especially I strungle with situation when I need to use recursion to operate through all lists and if I find that two lists have at least one similar element I can join them together through setof function and continue with this new list to compare rest. However what first two lists dont have any similar element? Giving an example: [[a,b,c,d], [e,f,g],[i,j,k],[e,a,b]]. In this situation if I try to compare list [a,b,c,d] and [e,f,g] then I give fail to connect these two lists together, because they dont have any similar character. But at the end after connection [a,b,c,d] and [e,a,b] I am able to connect also the first situation [a,b,c,d] and [e,f,g]. Can you see my point? I need to somehow iterate from one way and back as well. This kind of situation is absolutely dead end for me. Wondering if there is better solution to my main goal which is print all parts of disconnected graph based on the edges inserted by the user.