Дьядик Транспонировать

9

Как и в случае большинства символов APL, при вызове с одним аргументом (транспонирование) имеет разные значения по сравнению с двумя аргументами (диадические измерения транспонирования / переупорядочения). Эта проблема касается последнего, который действует аналогично numpy.moveaxisPython или permuteMATLAB, но является более мощным.

order ⍉ Aкогда orderесть разные записи

Когда все члены orderразличны, order ⍉ Aэквивалентно:

  • numpy.moveaxis(A, tuple(range(len(A.shape)), order) в Python, или
  • permute(A,order)в MATLAB. Цитирование из документации последнего:

B = permute (A, order) переставляет размеры A так, чтобы они были в порядке, указанном векторным порядком. Результирующий массив B имеет те же значения, что и A, но порядок индексов, необходимых для доступа к какому-либо конкретному элементу, изменяется в соответствии с порядком.

Например, предположим, что Aэто трехмерный массив, и пусть B ← (2 0 1)⍉A. Тогда B таков, что B[x0,x1,x2] = A[x2,x0,x1]для всехx2,x0,x1

order ⍉ Aкогда orderповторил записи

Когда orderесть повторенные записи, мы берем диагональный срез массива. Например, пусть A будет массивом 2x3x4. B ← (0 0 1)⍉Aберет диагональный срез, Aчтобы создать Bтакое, что B[x0,x1] = A[x0,x0,x1]. Обратите внимание, что Bэто массив 2x4: если бы он был 3x4, нам нужно было бы установить, B[2, x1] = A[2, 2, x1]что было бы за пределами A. Вообще-то kизмерение Bбудет минимальным из всех A.shape[i]таких, что order[i] = k.

пример

Рассмотрим диадическое транспонирование, order⍉Aгде order = [2, 1, 0]A - 3x4x5

    A =
[[[ 0  1  2  3  4]
  [ 5  6  7  8  9]
  [10 11 12 13 14]
  [15 16 17 18 19]]

 [[20 21 22 23 24]
  [25 26 27 28 29]
  [30 31 32 33 34]
  [35 36 37 38 39]]

 [[40 41 42 43 44]
  [45 46 47 48 49]
  [50 51 52 53 54]
  [55 56 57 58 59]]]

В результате получается массив 5x4x3 B =

[[[ 0 20 40]
  [ 5 25 45]
  [10 30 50]
  [15 35 55]]

 [[ 1 21 41]
  [ 6 26 46]
  [11 31 51]
  [16 36 56]]

 [[ 2 22 42]
  [ 7 27 47]
  [12 32 52]
  [17 37 57]]

 [[ 3 23 43]
  [ 8 28 48]
  [13 33 53]
  [18 38 58]]

 [[ 4 24 44]
  [ 9 29 49]
  [14 34 54]
  [19 39 59]]]

Обратите внимание, что когда, например, (x0, x1, x2) = (4,1,2) мы имеем B[x0,x1,x2] = A[x2, x1, x0] = A[2,1,4] = 49.

Если вместо этого order = [0, 0, 0]и Aкак указано выше, мы получим B1-мерный массив size-3, B = [0, 26, 52]чтобыB[1] = B[x0] = A[x0,x0,x0] = A[1,1,1] = 26

вход

Здесь мы используем 0-индексирование, но вы также можете использовать 1-индексирование, как по умолчанию APL.

  • Многомерный или вложенный массив Aразмером n ≥ 1.

  • Список orderиз n натуральных чисел, состоящий из целых чисел {0,1, ..., k} (или {1, ..., k + 1} для 1-индекса) для некоторого k < n в любом порядке, возможно с повторениями.

Вывод

  • Многомерный или вложенный массив, представляющий результат применения двоичной транспонирования с этими аргументами. (Выход будет иметь размерность k + 1. )

Вы можете написать полную программу, функцию и т. Д. В соответствии с действующим стандартом meta.

Если ваш язык имеет встроенную функцию, рекомендуется также написать решение без встроенной функции ради интересного ответа.

Контрольные примеры

Тестовые случаи на TIO

Реализация ссылочной Python в ближайшее время.

Примечание для чтения тестовых случаев: в APL предпоследняя и конечная оси массива расположены вдоль столбцов и строк в указанном порядке.

lirtosiast
источник
4
APL, 1 байт:: P
Quintec
1
На самом деле, многие символы APL просто используют второй аргумент по умолчанию при вызове с одним аргументом. Это включает в себя, который использует индексы обращенной оси по умолчанию, так ⍉Aже, как (2 1 0)⍉Aесли Aэто 3-мерный массив и в целом ⍉Aэто (⌽⍳≢⍴A)⍉A.
Адам
@lirtosiast вопрос о вводе / выводе: можно ли представить многомерный массив в виде пары формы (список измерений) и содержимого (все элементы в лексикографическом порядке их индексов)?
НГН
@ngn Я бы сказал нет на данный момент, но вы должны спросить у мета , приемлем ли этот формат по умолчанию.
lirtosiast
@lirtosiast Анекдотично, Dyalog APL внутренне хранит массивы как [number-of-dimensions,first-dimension-length,second-dimension-length,…,last-dimension-length,first-element,second-element,…,last-element].
Адам

Ответы:

4

APL (Dyalog Unicode) , 34 байта SBCS

Это код моего коллеги (слегка измененный из Roger Hui : История APL в 50 функциях , глава 30 ), опубликованный с явного разрешения.

Лямбда анонимного молчаливого инфикса (может использоваться как дроп-ин ).

{⍵[(⊂⊂⍺)⌷¨,¨⍳⍺[⍋⍺]{⌊/⍵}⌸(⍴⍵)[⍋⍺]]}

Попробуйте онлайн!

{} Дфн; левый аргумент (оси), правый аргумент (массив),
например, [2,2,1]и[[[1,2],[3,4]]]

⍵[] Индексировать массив с помощью:

  (⍴⍵)[] Форма (длина осей) массива, проиндексированная:
  [1,2,2]

   ⍋⍺ вектор классификации (индексы, которые будут сортировать их) осей
   [3,1,2]
  [2,1,2]

  ⍺[⍋⍺]{... }⌸ использовать отсортированные оси в качестве ключей для группировки и для каждой группы:
  [1,2,2]{"1":[2],"2":[1,2]}

   {⌊/⍵} найти наименьшую длину оси
   {"1":2,"2":1}[2,1]

   генерировать индексы в декартовой системе этих измерений
  [[[1,1]],[[2,1]]]

   убедитесь, что индексы каждой координаты являются вектором (будут скалярными, если вектор)
  [[[1,1]],[[2,1]]]

  ()⌷¨ Индексировать в каждом из них следующее:

   ⊂⊂⍺ оси (дважды заключенные; один раз для выбора этих ячеек вдоль первой и единственной оси и один раз для ¨объединения каждого вектора справа со всем набором осей слева)
   2 1 2
  [[[1,1,1]],[[1,2,1]]]
[[1],[3]]

Адам
источник