Joao
Joao

Reputation: 29

Prolog Convert a list in a list of lists

I need to convert a list of elements into a list of lists. For example, if i have the list [1,2,3,4] the output must be [[1],[2],[3],[4]], one element per list.

create([],_, _, _).
create([H|T], Aux, X, Result) :-
   append([H], Aux, X),
   Result = [X],
   create(T, X, _, Result).

I always get false... is this even possible to do?

Upvotes: 0

Views: 2001

Answers (2)

tas
tas

Reputation: 8140

Another possibility to define this relation is by using DCGs. They yield easily readable code when describing lists. Let's stick with the name singletons as suggested by @false in the comments:

singletons([]) -->        % the empty list
   [].                    % is empty
singletons([H|T]) -->     % the head of a nonempty list
   [[H]],                 % is a list on its own
   singletons(T).         % and so is the tail

You can query this directly with phrase/2:

   ?- phrase(singletons([1,2,3,4]),X).
X = [[1],[2],[3],[4]]

Or write a wrapper-predicate with phrase/2 as the single goal:

singletons(L,Ls) :-
   phrase(singletons(L),Ls).

And query that:

   ?- singletons([1,2,3,4],Ls).
Ls = [[1],[2],[3],[4]]

The predicate also works the other way around:

   ?- singletons(L,[[1],[2],[3],[4]]).
L = [1,2,3,4] ? ;
no

As well as the most general query:

   ?- singletons(L,Ls).
L = Ls = [] ? ;
L = [_A],
Ls = [[_A]] ? ;
L = [_A,_B],
Ls = [[_A],[_B]] ?
...

Alternatively you can also define a simple predicate that describes a relation between an arbitrary element and itself in brackets and then use maplist/3 from library(apply) to apply it on every element of a list:

:- use_module(library(apply)).

embraced(X,[X]).

singletons(L,Ls) :-
   maplist(embraced,L,Ls).

This version yields the same results for the above queries. However, it is more efficient. To see that consider the following query from above:

   ?- singletons(L,[[1],[2],[3],[4]]).
L = [1,2,3,4]

Above you had to enter ; to make Prolog search for further solutions and subsequently fail (indicated by no). With this version there are no unnecessary choice points left and Prolog is succeeding deterministically for the query.

Upvotes: 2

Mostafa El-Messiry
Mostafa El-Messiry

Reputation: 380

Try this

create([],[]).

create([H|T],[[H]|T2]):- create(T,T2).

I tried

?- create([1,2,3,4],X).

and the result was

X = [[1], [2], [3], [4]].

Upvotes: 1

Related Questions