Reorganizing the list in the prologue

I'm trying to write Prolog code to take a list like:

[[park, joe], [park, bob], [park, kate], [school, joe], [zoo, amy], [zoo, ted]]. 

      

and orders the list in the form:

[[park,[joe, bob, kate]], [school,[joe]], [zoo,[amy, ted]]]. 

      

It can be assumed that all of the matching heads of each item (park = park, zoo = zoo) are directly next to each other in the list, because the code I created to create the list sorts it alphabetically. I can't seem to figure out how to do this, and I seem to get errors every time :( Below is the code that I have so far in the last state that it works without errors, and I will try to explain what I am thinking.

merge([],[]).
merge([First|Rest], Z) :- 
merge(Rest, U),
[Meet1, Person1] = First,
( =(U, []) ->   % beginning case from recursion, U is empty
    Meet2 = [],
    Person2 = [];
    [[Meet2|Person2]|_] = U),
 ( =(Meet1, Meet2) -> % Case of matching heads, combine the tails
    print('Match '),
    append([First], U, Z); 
 print('No-match '), % otherwise, not matching
append([First], U, Z) ).

      

So what I was trying to do was use appendices to add all changes to U and return them to the console with Z. for example

( =(Meet1, Meet2) ->
  append(Person1, Person2, Combpersons),
  append([Meet1], [Combpersons], T),
  append(T, U, Z);
   ...no match code here..).

      

However, my code prematurely ends up false when I try to modify or add additions like in the first block of code I put here. Even a change like including append ([First], U, Z) in append ([Meet1], U, Z) makes my code complete false, and I don't understand why. Any help / advice on building a solution would be appreciated.

+3


source to share


3 answers


I think that learning any language is a process in which low and high level problems should alternate. While you are learning the basic syntax. But why do you use such unreadable constructs? And, of course, any programming language relies on a set of templates usually covered by the library . Consider

l2p([A,B],A-B).

?- maplist(l2p,[[park, joe], [park, bob], [park, kate], [school, joe], [zoo, amy], [zoo, ted]], L),group_pairs_by_key(L,G).
L = [park-joe, park-bob, park-kate, school-joe, zoo-amy, zoo-ted],
G = [park-[joe, bob, kate], school-[joe], zoo-[amy, ted]].

      



Anyway, here's your code modified:

merge([],[]).
merge([[Meet, Person]|Rest], Z) :- 
    merge(Rest, U),
    (   U = []
    ->  % beginning case from recursion, U is empty
        Z = [[Meet, [Person]]]
    ;   U = [[Meet, Persons] | Rest1]
    ->  % Case of matching heads, combine the tails
        Z = [[Meet, [Person | Persons]] | Rest1]
    ;   % otherwise, not matching
        Z = [[Meet, [Person]] | U]
    ).

      

+1


source


If you have your initial list as a list of pairs, you can use the library (pairs) available in SWI-Prolog.

?- group_pairs_by_key([park-joe, park-bob, park-kate, school-joe, zoo-amy, zoo-ted], G).
G = [park-[joe, bob, kate], school-[joe], zoo-[amy, ted]].

      



Using a library gives you more than just this "refactoring". There is also a library (ugraphs) which may be better suited depending on what you are doing.

+1


source


Your code is crashing because you are trying to extract place and person before checking to see if they are there.

Not used for here append

, reordering looks pretty tricky, but I've done my best with variable names. In addition, you only need one ->

: if you don't find a tuple with the same first coordinate, you will need to start a new one, it doesn't matter if you haven't.

merge([],[]).
merge([[Place,Person]|Rest], [[Place,Group]|OtherGroups]) :- 
    merge(Rest, U),
    (U = [[Place,Others]|OtherGroups] ->
     Group = [Person|Others];
     [OtherGroups,Group] = [U, [Person]]).

      

Edit: I changed the solution for readability reasons.

0


source







All Articles