Ответ в теме: Отражение матрицы на Prolog

      Комментарии к записи Ответ в теме: Отражение матрицы на Prolog отключены
#2044

Отражение матрицы относительно главной диагонали эквивалентно ее транспонированию.

Для отражения относительно побочной диагонали нам придется определенным образом переставлять элементы. Для этого удобно сначала создать новую матрицу заданного размера, элементы которой не связаны (т.е. им не присвоено значение) — мы сможем присвоить им значения позже. Такой прием позволит нам значительно упростить алгоритм — мы будем выбирать элемент из старой матрицы и ставить ее на требуемую позицию в новой матрице.

new_list(0, []):-!.
new_list(Length, [_|Tail]):-
TailLength is Length - 1,
new_list(TailLength, Tail).
new_matr(0, _Width, []):-!.
new_matr(Height, Width, [Row|Tail]):-
new_list(Width, Row),
TailHeight is Height - 1,
new_matr(TailHeight, Width, Tail).

Функция new_list создает список из несвязанных переменных заданной длины. Если требуется создать список длины ноль — возвращается пустой список, иначе первым элементом списка записывается несвязанная переменная (символ подчеркивания), а остальные — вычисляются рекурсивно.
Функция new_matr создает матрицу, элементы которой не инициализированы. Если требуется создать матрицу из нуля строк — то вне зависимости от ширины функция вернет пустой список строк. В противном случае выполняется расчет первой строки матрицы при помощи функции new_list, а остальная часть получается рекурсивно.

Вспомогательная функция создает новую матрицу такого же размера как и старая, и запускает отражение. При отражении нам потребуется знать индексы каждого элемента, т.к. на их основе будет вычисляться новая позиция (в отраженной матрице), изначально индексы инициализируются нулями:

second_diag_mirror(Matrix, Mirror):-
length(Matrix, Size),
new_matr(Size, Size, Mirror),
second_diag_mirror(0, 0, Size, Matrix, Mirror).

Функция отражения матрицы завершает работу если номер текущей строки больше размера исходной матрицы — такая ситуация значит, что все элементы были обработаны. Если номер текущего столбца оказался больше размера — то функция переходит к обработке следующей строки. В остальных случаях функция:

  • извлекает элемент с заданными индексами;
  • рассчитывает новую позицию;
  • записывает элемент в матрицу-отражение;
  • остальные элементы обрабатывает рекурсивно

secondary_diagonal_mirror(RowIndex, _ColumnIndex, Size, _Matrix, _Mirror):-
RowIndex >= Size, !.
secondary_diagonal_mirror(RowIndex, ColumnIndex, Size, Matrix, Mirror):-
ColumnIndex >= Size, !, 
RowIndexRowIndex is RowIndex + 1, 
secondary_diagonal_mirror(RowIndexRowIndex, 0, Size, Matrix, Mirror).
secondary_diagonal_mirror(RowIndex, ColumnIndex, Size, Matrix, Mirror):-
% get element
get_matrix_element(Matrix, RowIndex, ColumnIndex, Element),
% calculate new indexes
MirrorRowIndex is Size - ColumnIndex - 1, 
MirrorColumnIndex is Size - RowIndex - 1,
% put element
get_matrix_element(Mirror, MirrorRowIndex, MirrorColumnIndex, Element),
% recursive call
TailColumnIndex is ColumnIndex + 1,
secondary_diagonal_mirror(RowIndex, TailColumnIndex, Size, Matrix, Mirror).

Для извлечения элемента списка с заданной парой индексов и записи значения в новую матрицу используется функция get_matrix_element.