简体   繁体   中英

Prolog Lists from List Predicate

I am trying to make a code in which the input is a list with lists and non-lists within it and the output is a list with the lists from the first input. So, for example input listsFromList([2,3,6,[a,g],2,3,[c,d]],X) . The output would be X = [[a,g],[c,d]] . I am trying to do it with an accumulator. So I made this code:

listsFromList([],A) :- A.

listsFromList([H|SOURCEs],A) :-
        is_list(H),
        append([A],H,A),
        listsFromList(SOURCEs,A).

listsFromList([H|SOURCEs],A) :-
        \+ is_list(H),
        listsFromList(SOURCEs,A).

It does not work if I put more than one list in the first list and also it gives a wrong output when I put one list in it. Can anyone help?

You need to modify few things. Here a solution with the same number of arguments:

listsFromList([],[]).    
listsFromList([H|SOURCEs],[H|A1]) :-
        is_list(H),
        listsFromList(SOURCEs,A1).    
listsFromList([H|SOURCEs],A) :-
        \+ is_list(H),
        listsFromList(SOURCEs,A).

?- listsFromList([2,3,6,[a,g],2,3,[c,d]],X). 
X = [[a, g], [c, d]];
false

If you want to use append/3 , you could add an accumulator list (so increase the arity form 2 to 3), but this is unnecessary, or swap the position of append/3. Furthermore, you can add a cut ( ! ) to avoid the false solution.

Solution wiht accumulator:

listsFromList([],L,L).    
listsFromList([H|SOURCEs],LIn,LO) :-
    is_list(H),
    append([H],LIn,L),
    listsFromList(SOURCEs,L,LO).    
listsFromList([H|SOURCEs],L,LO) :-
    \+ is_list(H),
    listsFromList(SOURCEs,L,LO).

?- listsFromList([2,3,6,[a,g],2,3,[c,d]],[],X).
X = [[c, d], [a, g]]
false

If you want to use append/2 with arity 2 of the main predicate, use:

listsFromList([],[]).    
listsFromList([H|SOURCEs],L) :-
    is_list(H),
    listsFromList(SOURCEs,L1),
    append([H],L1,L).
listsFromList([H|SOURCEs],A) :-
    \+ is_list(H),
    listsFromList(SOURCEs,A).

?- listsFromList([2,3,6,[a,g],2,3,[c,d]],X).
X = [[a, g], [c, d]]
false

If you want to be super fancy and super short, you can solve your problem (assuming you are running SWI Prolog) with one line:

?- include(is_list,[2,3,6,[a,g],2,3,[c,d]],X). 
X = [[a, g], [c, d]]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM