0
votes

I have a problem with list of lists in Prolog. For example, I have these facts:

fact(1, 'hello').
fact(2,  'boy').
fact(3, 'hello').
fact(4, 'girl').

and a list made of pairs like (Character, Id):

list([b, 1, b, 2, g, 3, g, 4]).

my goal is to return a list of lists like this:

newList(['hello', boy'], ['hello', 'girl']).

EDIT: The first list have to be split in more lists that share the same Character

list([b, 1, b, 2], [g, 3, g, 4]).

then, should be removed the Character

list([1, 2], [3, 4]).

and substitute the id with the corresponding atom like this:

list(['hello', 'boy'], ['hello', 'girl']).
2
It is not very clear how your facts and the initial list transform into the result you are aiming at. What is the logic behind it? - user1812457
Hope now the problem is explained better. - user840718
Why does fact use 'boy' and 'girl' instead of 'b' and 'g'? Also, seems to be some implicit knowledge built into this scheme that says even numbers are gender, and odd numbers are something else. - lurker

2 Answers

5
votes

A weird question altogether. If you cared to give some context, you might get a more meaningful answer about how to do things in Prolog, in general.

Anyway:

First, if this is indeed a list of pairs, represent it as such:

char_id([b-1, b-2, g-3, g-4]).

If you want to do it programatically,

flat_to_pairs([], []).
flat_to_pairs([A,B|Flat], [A-B|Pairs]) :- flat_to_pairs(Flat, Pairs).

Then, you can use:

?- group_pairs_by_key([b-1, b-2, g-3, g-4], G).
G = [b-[1, 2], g-[3, 4]].

you can then map the IDs to the corresponding words:

collect_words([], []).
collect_words([C-IDs|ID_Groups], [C-Words|Word_Groups]) :-
    maplist(fact, IDs, Words),
    collect_words(ID_Groups, Word_Groups).

As a bonus, your words are marked with the initial character.

But as I said this all feels wrong on many levels.

1
votes

Well, here is a plain Prolog definition

list([], []).
list([S|R], [L|T]) :-
    capture(S, [S|R], L, Q),
    list(Q, T).

capture(S, [S,I|R], [N|Ns], Q) :-
    !, fact(I, N),
    capture(S, R, Ns, Q).
capture(_, Q, [], Q).

note: the cut is required for correctness of the procedure. It yields

?- list([b, 1, b, 2, g, 3, g, 4], R).
R = [[hello, boy], [hello, girl]].