Самый идиоматический способ создания идентификационной матрицы в 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
-с приземлится на главной диагонали.
Я не знаю, почему это должен быть лучший подход, чем тот, который использует внешний продукт. Либо кажется в порядке.