⍋⍋ 到底是什么意思?
What does ⍋⍋ even mean? (2023)

原始链接: https://blog.wilsonb.com/posts/2023-08-04-what-does-grade-grade-even-mean.html

这篇帖子深入探讨了J语言中的`Grade Up` (⍋) 和 `Grade Down` (⍒) 运算符,起因于Paul Mansour提出的一个挑战。作者证明,这两个运算符不仅仅是逆置换,而是从根本上与数组中项目的排名有关。 “项目”被定义为沿着第一个轴的子数组(矩阵中的行,向量中的元素)。项目的*排名*是数组排序后的位置。`Grade Up` 返回给定排名的项目的索引,而 `Grade Down` 则以降序执行相同的操作。 作者建立了一种符号 `` 来表示项目原始索引 (i) 与其排名 (j) 之间的关系。通过这种方式,他们展示了如何将 `Grade Up` 和 `Grade Down` 结合起来产生四种不同的操作:升序/降序排名和升序/降序逆排名。本质上,前导 `Grade` 决定顺序(升序/降序),而尾随 `Grade` 决定是使用排名还是逆排名。 最后,帖子指出一个细微之处:当数组项目相等时,排名 + 逆排名不是常数,这突出了同时拥有这两个原语的效用,正如Mansour在AverageRank方面的工作所利用的那样。

A Hacker News discussion centers around the mysterious symbols “⍋⍋” found on a website. The initial guess points to **APL**, an obscure but powerful, matrix-centered programming language known for its unique symbolic notation. Many commenters confirm the symbols’ association with APL, with some playfully noting its reputation for being difficult to read – often described as “write-only.” This sparked debate, with some defending APL’s readability for those willing to learn its conventions. Others compared its complexity to Perl, another language notorious for its cryptic nature. A humorous side-thread references the “Twin Pines” (or “Lone Pine”) from *Back to the Future*. The conversation also briefly touches on the history of writing tools, reminiscing about ink and nibs. Ultimately, the discussion highlights APL’s niche status and its challenging, yet powerful, syntax.
相关文章

原文

Posted on August 4, 2023

A while back I was casually perusing the articles on Jo̊t Dọt Ti̽mes and fell in love with almost everything that Paul Mansour writes up. In his Grade Down of Grade Up, he shares a quote that just feels like a challenge:

So the conclusion is that if we are only dealing in permutations ⍒⍋ is worthless since it’s simply a slower ⌽, and if we are not dealing in permutations even Adám doesn’t know what ⍒⍋ does so it is probably equally worthless.

Mansour’s answer is a really nice special application, but it turns out that there’s actually a satisfying general answer! We will consider general arrays, but in the back of our mind let’s keep a concrete example in mind, something like this:

       ⊢Y←⎕UCS 97+?10⍴26
 lnpwbkmcxt
       ↑Y (⍋Y)
 l n p w b k m c x t
 4 7 5 0 6 1 2 9 3 8

Defining a couple terms up front will make our life much easier:

  • An item of an array is a sub-array along its first axis. In particular, for a vector, the items correspond with the elements of the array, and for a matrix the items are the rows; and

  • The rank of an item \(y \in Y\) is the index of \(y\) when you sort \(Y\) ascendingly. Specifically, this is TAO order. So if \(y\) has rank \(i\), then that just means that \(y\) is the \(i^{\rm th}\) smallest element of \(Y\).

Applying these to the definition of Grade Up, we can say that the \(i^{\rm th}\) element of ⍋Y simply indexes whichever item of \(Y\) has rank \(i\). With a little squinting, we also see that this is equivalent to the reference definition:

R is an integer vector being the permutation of ⍳1↑⍴Y that places the sub-arrays along the first axis in ascending order.

Let us add a little bit of notation. When the \(i^{\rm th}\) item of \(Y\) has rank \(j\), we write \(<i, j>\). Notice then that for ⍋Y the condition \(<j, i>\) holds—in other words, just swaps \(i\) and \(j\), meaning that ⍋⍋Y leaves \(<i, j>\) unchanged! When \(Y\) is a permutation vector, this makes ⍋⍋ the identity, but in general we can think of it as the function Rank, since it produces a vector of the item ranks.

Better yet, since is equal to ⌽⍋, we can say that \(<N-j, i>\) holds for its result, where N=¯1+≢Y (in ⎕IO←0), and if we think of \(i, j\) as living in \(\mathbb{Z}_N\), this becomes even nicer: \(<-j, i>\). Indeed,

       ↑Y (⍋⍋Y)
 l n p w b k m c x t
 3 5 6 8 0 2 4 1 9 7

Effectively, the negative sign in our \(<\cdot, \cdot>\) symbol just means that the corresponding field starts counting from the back of the array, which we can think of as the function ReverseRank. Armed with this little bit of algebra, we can now fully characterize the fourfold combinations of and :

Input Output Interpretation
\(<i, j>\) ⍋⍋ \(<i, j>\) Ascending Rank
\(<i, j>\) ⍋⍒ \(<i, -j>\) Ascending ReverseRank
\(<i, j>\) ⍒⍋ \(<-i, j>\) Descending Rank
\(<i, j>\) ⍒⍒ \(<-i, -j>\) Descending ReverseRank

Not bad! So the leading Grade chooses ascending or descending and the trailing Grade chooses Rank or ReverseRank. Applying to our example,

       ↑Y (⍋⍋Y) (⍋⍒Y) (⍒⍋Y) (⍒⍒Y)
 l n p w b k m c x t
 3 5 6 8 0 2 4 1 9 7
 6 4 3 1 9 7 5 8 0 2
 7 9 1 4 2 0 8 6 5 3
 2 0 8 5 7 9 1 3 4 6

As a sanity check, note that Rank + ReverseRank should be constant. Indeed, for each item \(y \in Y\), the number of items less than \(y\) plus the number of items greater than \(y\) should equal the total number of items in \(Y\), minus 1 for \(y\) itself:

       (⍋∘⍋+⍋∘⍒)Y
 9 9 9 9 9 9 9 9 9 9
       (⍒∘⍋+⍒∘⍒)Y
 9 9 9 9 9 9 9 9 9 9

Actually, there is a bit of nuance when items of \(Y\) are equal. Rank + ReverseRank will not be constant because both and rank equal items the same way, no directionality involved. This property makes having both primitives useful, otherwise (⍋≡⌽∘⍒)Y would always hold. This property is exactly what Paul Mansour exploits in his article above with the AverageRank function.

联系我们 contact @ memedata.com