How to transpose a matrix in prolog

后端 未结 8 1888
悲&欢浪女
悲&欢浪女 2020-12-06 18:40

How can I transpose a list like [[1,2,3][4,5,6][6,7,8]] to [[1,4,6],[2,7,8],[3,6,9]]?

To depict it: I\'d like to flip the matrix 90 degree

相关标签:
8条回答
  • 2020-12-06 18:57

    This is the smallest solution I could come up with.

    Code

    transpose([[]|_], []).
    transpose(Matrix, [Row|Rows]) :- transpose_1st_col(Matrix, Row, RestMatrix),
                                     transpose(RestMatrix, Rows).
    transpose_1st_col([], [], []).
    transpose_1st_col([[H|T]|Rows], [H|Hs], [T|Ts]) :- transpose_1st_col(Rows, Hs, Ts).
    

    Test

    :- transpose([[1,2,3],
                  [4,5,6],
                  [7,8,9]], R),
       print(R).
    

    Prints:

    [[1,4,7],
     [2,5,8],
     [3,6,9]]
    

    Explanation

    The way it works is that transpose will recursively call transpose_1st_col which extracts and transposes the first column of the matrix. For example:

    :- transpose_1st_col([[1,2,3],
                          [4,5,6],
                          [7,8,9]], Row, RestMatrix),
       print(Row),
       print(RestMatrix).
    

    will print

    [1,4,7]
    

    and

    [[2,3],
     [5,6],
     [8,9]]
    

    This is repeated until the input matrix is empty, at which point all columns have been transposed. The transposed columns are then joined into the transposed matrix.

    0 讨论(0)
  • 2020-12-06 19:08

    An iterative approach:

    trans([H|R],[H1|R1]):-trans2([H|R],[H|R],[],[H1|R1],0),!.
    trans2([A|_],_,_,[],N):-length(A,N).
    trans2(M,[],H1,[H1|R1],N):-N1 is N+1, trans2(M,M,[],R1,N1).
    trans2(M,[H|R],L,[H1|R1],N):-nth0(N,H,X),
       append(L,[X],L1),trans2(M,R,L1,[H1|R1],N).
    
    0 讨论(0)
  • 2020-12-06 19:10

    Another simple approach:

    transpose(M0, M) :-
        nonvar(M0),
        findall(L, maplist(nth1(_), M0, L), M).
    
    ?- transpose([[1,2,3],[4,5,6],[7,8,9]], M). 
    M = [[1, 4, 7], [2, 5, 8], [3, 6, 9]]. `
    
    0 讨论(0)
  • 2020-12-06 19:11

    Another approach:

    delete_one_list([], []).
    delete_one_list([[_|L]|LLs], [L|Ls]) :-
      delete_one_list(LLs, Ls).
    
    transpose_helper([], []).
    transpose_helper([[X|_]|Xs], [X|Ys]) :-
      transpose_helper(Xs, Ys).
    
    transpose([[]|_], []).
    transpose(List, [L|Ls]) :-
      transpose_helper(List, L),
      delete_one_list(List, NewList),
      transpose(NewList, Ls).
    
    0 讨论(0)
  • 2020-12-06 19:15

    Here's a fragment of a larger answer:

    % transposed(+A, ?B) iff matrix B is transposed matrix A
    transposed(A, B) :- transposed(A, [], B).
    transposed(M, X, X) :- empty(M), !.
    transposed(M, A, X) :- columns(M, Hs, Ts), transposed(Ts, [Hs|A], X).
    
    % empty(+A) iff A is empty list or a list of empty lists
    empty([[]|A]) :- empty(A).
    empty([]).
    
    % columns(+M, ?Hs, ?Ts) iff Hs is the first column
    %   of matrix M and Ts is the rest of matrix M
    columns([[Rh|Rt]|Rs], [Rh|Hs], [Rt|Ts]) :- columns(Rs, Hs, Ts).
    columns([[]], [], []).
    columns([], [], []).
    
    0 讨论(0)
  • 2020-12-06 19:19

    My solution with full names for a better understanding:

    % emptyMatrix(Line, EmptyMatrix)
    emptyMatrix([],[]).
    emptyMatrix([_|T1],[[]|T2]):-emptyMatrix(T1,T2).
    % only length of parameter 'Line' is interesting. It ignores its content.    
    
    % appendElement(Element, InputList, OutputList)
    appendElement(E,[],[E]).
    appendElement(E,[H|T],[H|L]):-appendElement(E,T,L).
    
    % appendTransposed(NestedList, InputMatrix, OutputMatrix)
    appendTransposed([],[],[]).
    appendTransposed([X|T1],[],[[X]|T3]):-appendTransposed(T1,[],T3).
    appendTransposed([X|T1],[R|T2],[C|T3]):-appendElement(X,R,C),appendTransposed(T1,T2,T3).
    
    % transposeMatrix(InputMatrix, TransposedMatrix)
    transposeMatrix([L|M],T):-emptyMatrix(L,A),transpose([L|M],T,A).
    transpose([],T,T).
    transpose([L|M],T,A):-appendTransposed(L,A,B),transpose(M,T,B).
    

    A 'line' can be a col or a row.

    The idea lies in appending the elements into the lists of an empty matrix. (e.g. all elements of the first row = the first elements of all cols => all elements of the first i-nth row = the i-nth elements of all cols)

    It works on my machine as this session protocol shows to me:

    5 ?- transposeMatrix([[1,2],[3,4]],T).
    T = [[1, 3], [2, 4]] ;
    false.
    
    6 ?- transposeMatrix([[1],[2]],T).
    T = [[1, 2]] ;
    false.
    
    7 ?- transposeMatrix([[1,2,3],[4,5,6]],T).
    T = [[1, 4], [2, 5], [3, 6]] ;
    false.
    
    8 ?- transposeMatrix([[1]],T).
    T = [[1]] ;
    false.
    
    0 讨论(0)
提交回复
热议问题