Получить диагональ от матрицы - PullRequest
0 голосов
/ 11 ноября 2018

Я хочу получить левую и правую диагонали матрицы, содержащей элемент с указанными индексами столбцов и строк.

Например:

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 голосов
/ 11 ноября 2018

Мы можем сделать общий предикат, который может идти в обоих направлениях (влево и вправо).

Нам в основном здесь нужны два параметра: индекс первого столбца 1004 * и «направление», в котором мы идем, это -1 для «правильного» и 1 для « левый».

Таким образом, мы можем реализовать предикат diagonal/4, который будет генерировать такой диагональ.

По сути, мы должны принять во внимание три случая:

  1. матрица не имеет строк, в этом случае диагональ представляет собой пустой список;
  2. матрица имеет хотя бы одну строку, но индекс слишком низкий / высокий, в этом случае диагональ также является пустым списком; и
  3. матрица имеет хотя бы одну строку, и индекс не выходит за пределы диапазона, в этом случае мы добавляем элемент первой строки для данного столбца и рекурсивно вызываем предикат, где мы сдвигаем столбец на один вправо или один слева.

Таким образом, мы можем реализовать это с помощью:

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/4 и right_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 и prediagonal/4 в одном предикате. Я оставляю это как упражнение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...