Самый идиоматический способ создания идентификационной матрицы в APL

Согласно Rosetta Code, есть два идиоматических способа создания идентификационной матрицы в APL:

1. ID←{∘.=/⍳¨ ⍵ ⍵}
2. ID←{⍵ ⍵ ρ 1, ⍵ρ0}

Как работает (2)? Почему это лучше, чем (1), который использует внешний продукт, который считается идиоматическим подходом в APL?

3 ответа

Решение

Если вы сравните производительность двух выражений, 2 явно выиграет:

cmpx'{∘.=/⍳¨ ⍵ ⍵}1000'  '{⍵ ⍵ ⍴ 1, ⍵⍴0}1000'       
  {∘.=/⍳¨ ⍵ ⍵}1000   → 2.4E¯3 |   0% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
* {⍵ ⍵ ⍴ 1, ⍵⍴0}1000 → 5.7E¯5 | -98% ⎕                                       

Если вы учитываете, что должен делать интерпретатор при обработке двух выражений, (2) также гораздо менее трудоемкий: преобразовать скаляр в вектор и изменить форму результата, тогда как в (1) он должен создать два вектора, построить внешний продукт с равным сравнением. Плюс к этому относится "каждый", который (некоторыми) не считается "чистым APL"... И, очевидно, если подумать об идеях, реализованных двумя алгоритмами, (2) гораздо приятнее и элегантнее. Но это только мое мнение;)

1,⍵⍴0 создает вектор, который состоит из 1 с последующим нули. Итак, длина этого вектора ⍵+1,

⍵ ⍵ ⍴ покрывает -от- матрица. Копии вектора будут помещаться слева направо и сверху вниз. Первая копия будет покрывать всю первую строку и переполняться на второй ряд, например, для ⍵=5:

1 0 0 0 0
0 . . . .
. . . . .
. . . . .
. . . . .

Теперь вторая копия появится с небольшим отступом во втором ряду:

. . . . .
. 1 0 0 0
0 0 . . .
. . . . .
. . . . .

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

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

{⍵ ⍵⍴(⍵+1)↑1} ... быстро

{∘.=⍨⍳⍵} ... хорошо

;)

Другие вопросы по тегам