在APL中由X指示的累积最大值

时间:2013-07-03 12:11:30

标签: algorithm sorting apl

FinnAPL Library中的第三项称为“由X表示的Y的子向量的累积最大值(⌈)”,其中X是二进制向量,Y是数字向量。以下是其用法示例:

X←1 0 0 0 1 0 0 0
Y←9 78 3 2 50 7 69 22
Y[A⍳⌈\A←⍋A[⍋(+\X)[A←⍋Y]]]       ⍝ output 9 78 78 78 50 50 69 69

你可以看到从X数组的开头或任何1个值开始,找到Y中所有相应数字的累积最大值,直到在X中找到另一个数字。在给出的例子中,X正在对数组为两个相等的部分,每个部分包含4个数在第一部分中,9是最大值,直到遇到78,而在第二部分50是最大值,直到遇到69.

这很容易理解,我可以盲目地使用它,但我想了解它是如何工作的,因为APL习语本质上是由运算符和函数组成的算法。为了更好地理解APL,重要的是要了解大师如何能够将它们编织成如此紧凑和优雅的代码行。

我发现这个特殊的习惯用法特别难以理解,因为索引嵌套了两层深层。所以我的问题是,是什么让这个成语嘀嗒?

2 个答案:

答案 0 :(得分:2)

这个成语可以分解为较小的习语,最重要的是,它包含来自FinnAPL图书馆的成语#11,标题为:

升级(⍋),用于排序由X表示的Y的子向量

使用问题中给出的X和Y的相同值,这是它的用法示例:

X←1 0 0 0 1 0 0 0
Y←9 78 3 2 50 7 69 22
A[⍋(+\X)[A←⍋Y]]             ⍝ output 4 3 1 2 6 8 5 7

和以前一样,X将矢量分成两半,输出表明,对于每个位置,需要Y的哪个数字来对每一半进行排序。所以,输出中的4表示它需要第1位的Y(2)的第4位数; 3表示第2位的第3位(3); 1表示第三位的第一位数字(9);因此,如果我们将此索引应用于Y,我们得到:

Y[A[⍋(+\X)[A←⍋Y]]]          ⍝ output 2 3 9 78 7 22 50 69

为了理解这个升级成语中的索引,请考虑以下内容:

(+\X)[A←⍋Y]                 ⍝ Sorted Cumulative Addition

一步一步地打破它:

A←⍋Y                        ⍝ 4 3 6 1 8 5 7 2
+\X                         ⍝ 1 1 1 1 2 2 2 2
(+\X)[A←⍋Y]                 ⍝ 1 1 2 1 2 2 2 1 SCA
A[⍋(+\X)[A←⍋Y]]             ⍝ 4 3 1 2 6 8 5 7

您可以看到应用于A的X 1 1 2 1 2 2 2 1的已排序累积加法( SCA )充当左侧压缩和右侧压缩的组合。排列为1的A的所有值都向左移动,排列为2的A向右移动。当然,如果X有更多的1,它将按照 SCA 结果的值指示的顺序压缩和定位压缩包。例如,如果X的 SCA 类似于3 3 2 1 2 2 1 1 1,那么最终会得到与1相对应的4位数,然后是与2相对应的3位数,最后是2位对应3s。

您可能已经注意到我跳过了显示评分效果的步骤

(+\X)[A←⍋Y]                 ⍝ 1 1 2 1 2 2 2 1 SCA
⍋(+\X)[A←⍋Y]                ⍝ 1 2 4 8 3 5 6 7 Grade up
A[⍋(+\X)[A←⍋Y]]             ⍝ 4 3 1 2 6 8 5 7

单独使用 SCA 无法实现压缩和重排的效果。正如我在另一篇post中所讨论的那样,它实际上充当了排名。同样在那篇文章中,我谈到了排名和索引基本上是同一枚硬币的两面,你可以使用等级来在两者之间切换。因此,这就是这里发生的事情: SCA 正在转换为应用于A的索引,效果是按等级划分的子向量,如X所示。

从排序子向量到累积最大值

如前所述,对子向量进行排序的结果是一个索引,当应用于Y时,将数据压缩为数据包并根据X排列这些数据包。重点是它是一个索引,再一次,等级应用了up,它将索引转换为rank:

⍋A[⍋(+\X)[A←⍋Y]]            ⍝ 3 4 2 1 7 5 8 6

这里的问题是,为什么?那么,下一步是应用累积最大值,并且只有当它应用于表示每个数据包内相对幅度的秩值时才真正有意义。查看这些值,您可以看到4是第一组4的最大值,8是第二组的最大值。这些值对应于78和69的输入值,这正是我们想要的。将最大值应用于表示位置的索引值是没有意义的(至少在这种情况下),因此转换为排名是必要的。应用累积最大值得出:

⌈\A←⍋A[⍋(+\X)[A←⍋Y]]        ⍝ 3 4 4 4 7 7 8 8

这是完成索引的最后一步。在执行累积最大值操作后,矢量值仍然表示排名,因此需要将它们转换回索引值。为此,使用index-of运算符。它接受右参数中的值并返回它们在左参数中找到的位置:

A⍳⌈\A←⍋A[⍋(+\X)[A←⍋Y]]      ⍝ 1 2 2 2 5 5 7 7

为了更容易看到:

3 4 2 1 7 5 8 6             left argument
3 4 4 4 7 7 8 8             right argument
1 2 2 2 5 5 7 7             result

4位于左参数的第2个位置,因此结果显示右参数中每4个为2。索引已完成,因此将其应用于Y,我们得到预期的结果:

Y[A⍳⌈\A←⍋A[⍋(+\X)[A←⍋Y]]]    ⍝ 9 78 78 78 50 50 69 69

答案 1 :(得分:0)

我的实施:

      X←1 0 0 0 1 0 0 0
      Y←9 78 3 2 50 7 69 22

      ¯1+X/⍳⍴X ⍝ position
0 4 
      (,¨¯1+X/⍳⍴X)↓¨⊂Y
 9 78 3 2 50 7 69 22  50 7 69 22

      (1↓(X,1)/⍳⍴X,1)-X/⍳⍴X ⍝ length
4 4 
      (,¨(1↓(X,1)/⍳⍴X,1)-X/⍳⍴X)↑¨(,¨¯1+X/⍳⍴X)↓¨⊂Y
 9 78 3 2  50 7 69 22

      ⌈\¨(,¨(1↓(X,1)/⍳⍴X,1)-X/⍳⍴X)↑¨(,¨¯1+X/⍳⍴X)↓¨⊂Y
 9 78 78 78  50 50 69 69
      ∊⌈\¨(,¨(1↓(X,1)/⍳⍴X,1)-X/⍳⍴X)↑¨(,¨¯1+X/⍳⍴X)↓¨⊂Y
9 78 78 78 50 50 69 69

度过愉快的一天。