从矩阵获取对角线

时间:2018-11-11 14:13:43

标签: prolog

我想获取包含具有给定列索引和行索引的元素的矩阵的左右对角线。

例如:

rightDiagonal([[1,2,3],[4,5,6],[7,8,9]], 1, 0, Diagonal).
Diagonal = [2,4]

leftDiagonal([[1,2,3],[4,5,6],[7,8,9]], 1, 0, Diagonal).
Diagonal = [4,8]

谢谢。

这是我的尝试:

left_diagonal_left(Board, 0, Column_Index, List, New_List) :-
    get_value_from_matrix(Board, Row_Index, Column_Index, Value),
    append(List, Value, New_List).

left_diagonal_left(Board, Row_Index, 0, List, New_List) :-
    get_value_from_matrix(Board, Row_Index, Column_Index, Value),
    append(List, Value, New_List).

left_diagonal_left(Board, Row_Index, Column_Index, List, New_List) :-
    get_value_from_matrix(Board, Row_Index, Column_Index, Value),
    append(List, Value, New_List),
    R = Row_Index - 1,
    C = Column_Index - 1,
    left_diagonal_left(Board, R, C, New_List, Newer_List).

left_diagonal_right(Board, 6, Column_Index, List, New_List).
left_diagonal_right(Board, Row_Index, 6, List, New_List).   

left_diagonal_right(Board, Row_Index, Column_Index, List, New_List)  :-
    get_value_from_matrix(Board, Row_Index, Column_Index, Value),
    append(List, Value, New_List),
    R = Row_Index + 1,
    C = Column_Index + 1,
    left_diagonal_right(Board, R, C, New_List, Newer_List).

left_diagonal(Board, Row_Index, Column_Index, List, Newer_List) :-
    left_diagonal_left(Board, Row_Index, Column_Index, List, New_List),
    R = Row_Index + 1,
    C = Column_Index + 1,
    left_diagonal_right(Board, R, C, New_List, Newer_List). 

问题在于append()失败。

1 个答案:

答案 0 :(得分:0)

我们可以创建一个可以在两个方向(向左和向右)行走的通用谓词。

我们这里基本上需要两个参数: first 列的索引和行进的“方向”,“ {right”是-1,{{ 1}}代表“左”。

因此,我们可以实现一个谓词1,该谓词将产生这种关系。

基本上,我们需要考虑三种情况:

  1. 矩阵没有“行”,在这种情况下,对角线是一个空列表;
  2. 矩阵至少有一行,但是索引太低/太高,在这种情况下,对角线也是一个空列表;和
  3. 矩阵至少有一行,并且索引不超出范围,在这种情况下,我们为给定列添加第一行的元素,然后递归调用谓词,将列向右移一,或向左一个。

因此我们可以通过以下方式实现此目标:

diagonal/4

现在我们可以通过以下方式获得对角线:

diagonal([], _, _, []).
diagonal([Row|Rest], Col, DCol, Result) :-
    (  nth0(Col, Row, El)
    -> (Result = [El | R2],
        Col2 is Col + DCol,
        diagonal(Rest, Col2, DCol, R2))
    ;  Result = []).

当然,以上内容尚未完成:由于在问题中,一个输入两个坐标。但是,如果我们采用正确的坐标,则对于坐标对?- diagonal([[4,5,6],[7,8,9]], 1, -1, Diagonal). Diagonal = [5, 7]. ?- diagonal([[1,2,3],[4,5,6],[7,8,9]], 1, -1, Diagonal). Diagonal = [2, 4]. ?- diagonal([[4,5,6],[7,8,9]], 0, 1, Diagonal). Diagonal = [4, 8]. ,这等效于(X, Y)。左对角线相同:包含(X+Y, 0)的对角线与包含(X, Y)的对角线相同。但是请注意,(0, Y-X)X+Y可能超出范围,因此我们可以首先对坐标进行“规范化”,但是如果坐标“过高”或“过低” ,因此,我们将需要删除一定数量的行,并且每次更新该行直到达到范围内的值。

因此,我们可以实现一个谓词,该谓词首先进行一些迭代,直到找到有效索引为止,然后将控制权传递给Y-X谓词,例如diagonal/4

prediagonal/4

所以现在我们可以用prediagonal([], _, _, []). prediagonal([Row|Rest], Col, DCol, Result) :- Col2 is Col + DCol, ( nth0(Col, Row, El) -> (Result = [El | R2], diagonal(Rest, Col2, DCol, R2)) ; prediagonal(Rest, Col2, DCol, Result)). 来写left_diagonal/4right_diagonal

prediagonal/4

然后这给了我们

left_diagonal(M, R, C, Diagonal) :-
    Delta is C-R,
    prediagonal(M, Delta, 1, Diagonal).

right_diagonal(M, R, C, Diagonal) :-
    Delta is R+C,
    prediagonal(M, Delta, -1, Diagonal).

以上并不是最优雅的解决方案。最好将“ ?- right_diagonal([[1,2,3],[4,5,6],[7,8,9]], 1, 0, Diagonal). Diagonal = [2, 4]. ?- left_diagonal([[1,2,3],[4,5,6],[7,8,9]], 1, 0, Diagonal). Diagonal = [4, 8]. ”和“ diagonal/4”合并到一个谓词中。我将其保留为练习。