Yi Justin
Yi Justin

Reputation: 53

Prolog, how should I construct a list of list to a single list?

I want to construct a list of list to interleave each other to a single list like: coon([[1,4],[2,5],[3,6]], X) should return X=1,2,3,4,5,6. and there is a condition that each sublist should only have the same length, otherwise, it should fail such as [[q,r,y],[a,e],[c,g,t],X] shouid fail, and coon([A,B,C],[q,w,e,r,t,y]) should only return one solution, that is A=[q,r],B=[w,t],C=[e,y]. my recent approach is.

  conns([],[]).
  conns([[Head|Tail]|X],[Head|Y]):-
    append(X,[Tail],X2),
    conns(X2,Y).                                                

conns([[]|T],A):-
    conns(T,A).

It gives me multiple solutions when I try coon([A,B,C],[q,w,e,r,t,y]). I have been trying hours to figure it out but all failed. How should I return the single list to each sub-lists that contain the same length? Thank you so much!

Upvotes: 5

Views: 465

Answers (2)

false
false

Reputation: 10102

:- use_module(library(clpfd),[transpose/2]).

connsx(Xss, Xs) :-
   transpose(Xss, XssT),
   append(XssT, Xs).

Upvotes: 5

lurker
lurker

Reputation: 58244

The problem you are having is with this predicate clause:

conns([[]|T],A):-
    conns(T,A).

This allows solutions more general than you are wanting to define. Specifically, if I understand the problem correctly, the first argument to conns should always be a list whose elements are lists all of equal length. That would mean that if [[]|T] is the first argument and you expect conns([[]|T], A) to succeed, then T should also look like [[]|R] or []. That is, it should be a (possibly empty) list of empty lists.

If you revise the empty list case according to this constraint, your solution will work:

% The case where the first argument consists of non-empty lists    
conns([[Head|Tail]|X], [Head|Y]):-
    append(X, [Tail], X2),
    conns(X2, Y).

% Base case in which first argument is a list of empty lists
conns([], []).
conns([[]|T], []) :-
    conns(T, []).

Now when you run the query, you get this:

| ?- conns([[1,4],[2,5],[3,6]], R).

R = [1,2,3,4,5,6] ? ;

no
| ?-

As well as:

| ?-  conns([A,B,C], [q,w,e,r,t,y]).

A = [q,r]
B = [w,t]
C = [e,y] ? a

no
| ?-

This solution does leave a choice point, which I'll leave as an exercise to eliminate if you wish.

Upvotes: 4

Related Questions