Prolog:给定矩阵创建转置

Prolog: Given a Matrix create the transpose

我正在努力学习如何使用 Prolog。

我有一个矩阵,我应该对这个矩阵进行转置。

我这样做过:

transpose_matrix([], []).
transpose_matrix(Matrix, New_Matrix):-
    length(Matrix, Num_Rows),
    nth0(0, Matrix, First_Row),
    length(First_Row, Num_Cols),
    Num_Rows == Num_Cols,
    transpose_matrix(Matrix, Num_Rows, 0, 0, New_Matrix).

transpose_matrix(Matrix, Num_Rows, Row, Col, [[Element|Rest]|Rest1]):-
    Row < Num_Rows,
    nth0(Row,Matrix,Current_Row),
    nth0(Col,Current_Row,Element),
    Row1 is Row + 1,
    transpose_matrix(Matrix, Num_Rows, Row1, Col, [Rest|Rest1]).

transpose_matrix(Matrix, Num_Rows, Row, Col, [[_Element|_Rest]|Rest1]):-
    Row >= Num_Rows,
    Col1 is Col + 1,
    transpose_matrix(Matrix, Num_Rows, 0, Col1, Rest1).

transpose_matrix(_Matrix, Num_Rows, _Row, Col, _New_Matrix):-
    Col == Num_Rows.

以这种方式,当我将 1 加到 Row 上以选择正确的元素时,当 Row 等于 Length 时,我更新 Col 并将行值设置为 0。

现在这个方法似乎行得通了,我的问题是这些值是如何打印的:

transpose_matrix([[6, 3, 2], [8, 1, 4], [3, 5, 9]], New_Matrix).
New_Matrix = [[6, 8, 3, _17602|_17604], [3, 1, 5, _17650|_17652], [2, 4, 9, _17698|_17700]|_17658] 

如何删除:

_17602| _17604...._17650|_17652..._17698|_17700]|_17658 ?

谢谢。

这可能对您有所帮助:

1- transp 谓词将采用任意长度的矩阵,并在 MatrixOut 中给出转置列表。

2- add_col 谓词可以让您免于 -1708,... 类型值的麻烦。

% transp(MatrixIn,MatrixOut)
transp([],[]).
transp([Row|Rows],Transpose) :-
transp(Rows,RowsT),
add_col(Row,RowsT,Transpose).

% add_col(Col,MatrixIn,MatrixOut)
add_col([],_,[]) :- !.
add_col([X|Col],[],[[X]|Rows]) :- !,
add_col(Col,[],Rows).
add_col([X|Col],[Row|Rows],[NewRow|NewRows]) :-
NewRow = [X|Row],
add_col(Col,Rows,NewRows).

示例

?-transp([[2,0,1],[3,4,5],[6,7,8]],Out)
Out = [[2, 3, 6], [0, 4, 7], [1, 5, 8]]

?-transp([[6, 3, 2], [8, 1, 4], [3, 5, 9]],Out)
Out = [[6, 8, 3], [3, 1, 5], [2, 4, 9]]

?-transp([[6, 3, 2, 5, 3, 2], [8, 1, 4, 7, 4, 2], [3, 5, 9, 8, 5, 4],[6, 4, 5, 7, 8, 9]],Out)
Out = [[6, 8, 3, 6], [3, 1, 5, 4], [2, 4, 9, 5], [5, 7, 8, 7], [3, 4, 5, 8], [2, 2, 4, 9]]

注:解法来自我老师的Lecture

一个非常简洁的解决方案是:

transpose(Matrix, NewMatrix) :-
    nonvar(Matrix),
    findall(Row, maplist(nth1(_), Matrix, Row), NewMatrix).

这里有一些例子:

?- transpose([[1,2], [3,4]], M).
M = [[1, 3], [2, 4]].

?- transpose([[6,3,2], [8,1,4], [3,5,9]], Matrix).
Matrix = [[6, 8, 3], [3, 1, 5], [2, 4, 9]].

?- transpose([[1,2,3], [4,5,6], [7,8,9]], M), maplist(writeln,M).
[1,4,7]
[2,5,8]
[3,6,9]
M = [[1, 4, 7], [2, 5, 8], [3, 6, 9]].

工作原理:

  • nth1/3 生成元素(通过回溯)。
  • maplist/3 生成行(通过回溯)。
  • findall/3 收集所有行。