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

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

В этой теме 2 ответа, 2 участника, последнее обновление  Васильев Владимир Сергеевич 2 года/лет назад.

  • Автор
    Сообщения
  • #2022

    questioner
    Участник

    Помогите на языке Пролог написать функции, выполняющие:

    • горизонтальное отражение матрицы;
    • вертикальное отражение матрицы;
    • отражение матрицы относительно главной диагонали;
    • отражение матрицы относительно побочной диагонали.
  • #2042

    Матрица представлена списком строк, поэтому чтобы выполнить вертикальное отражение — достаточно выполнить реверс соответствующего списка:

    vertical_mirror(Matrix, Mirror):-
      reverse(Matrix, Mirror).

    Для реверса списка используется встроенная функция reverse.

    Для горизонтального отражения матрицы достаточно перевернуть каждую ее строку:

    horizontal_mirror([], []):-!.
    horizontal_mirror([Row|Tail], [ReverseRow|ReverseTail]):-
      reverse(Row, ReverseRow), 
      horizontal_mirror(Tail, ReverseTail).

    Если матрица пустая — то результатом является также матрица, не содержащая ни одной строки.
    В противном случае от матрицы отделяется первая строка, выполняется ее реверс, а остальная часть матрицы обрабатывается рекурсивно.

  • #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.

Для ответа в этой теме необходимо авторизоваться.