Search code examples
prologlogicdcg

Trying to break elements which are lists in a list?


I am trying to write a program which make the following:

?- g([2,3, [22,[3],9] ,4,[5],99],X).

X= [2,3,22,[3],9 ,4,5,99]

So it searches for lists in the given list and replace it by their elements without brackets [].

So I wrote this program:

The first block just searches for the first element in the list which is list
If there is no such element it returns [there_is_no_list].

first_list_in_the_list([],[there_is_no_list]):-!.  
first_list_in_the_list([H|_],X):-is_list(H),X=H,!.  
first_list_in_the_list([_|T],X):-first_list_in_the_list(T,X).

The first block works in prolog perfectly.

The second block just search in the list for an element X and then split the list into a two lists one is the list of all elements before X and the second is the elements after X.

splite_when_find_element([H|T],H,[],T):-!.  
splite_when_find_element([H|T],X,F,G):-
    splite_when_find_element(T,X,F1,G),append([H],F1,F).

it also works fine in Prolog.

and the third block is append, and it joins two list together in a new list.

append([],L,L).  
append([H|T],L,[H|U1]):- append(T,L,U1).

and the last part is:

gg(L,L):-first_list_in_the_list(L,[there_is_no_list]),!.    
gg(L,U):-first_list_in_the_list(L,X),
         splite_when_find_element(L,X,F,G),gg(G,R),append(F,X,E),
         append(E,R,U).

When I give a query [2,[3],5] I get also [2,[3],5] and I really don't understand why it does this.


Solution

  • A simple recursive solution will also work. Recursion is done by the head of the input list. In the non-trivial case, when the head is a list itself, we just append the rest of the flattened list to it. In the code below, it has not flattened Rest yet in append(H, Rest, Out), but it will be, after the recursive call of g(In, Rest). Cut after the append call ensures that backtracking won't consider the last case, where the head will appear in the output as-is.

    % Base case, empty list.
    
    g([], []).
    
    % First recursive case: head is list.
    % Append remaining elements to it.
    
    g([H|In], Out):-
        append(H, Rest, Out), !,
        g(In, Rest).
    
    % Second recursive case: head is not list.
    % Will appear as-is in the output.
    
    g([H|In], [H|Out]):-
        g(In, Out).