APL高尔夫技巧


28

我最近发起了一场代码高尔夫挑战赛,看来胜利者是GolfScript(惊喜,惊喜!)。有趣的是,还有另一个非常强大的竞争对手,有机会赢得GolfScript。它的名字叫APL。我在这里看到了许多用APL编写的答案。看来这种语言对于代码打高尔夫球相当有效,因此我决定询问您对APL程序了解的任何代码打高尔夫球技巧。随时发布一些代码示例。看到实际的语言通常非常有趣。

Answers:


23

编辑:对于人读这谁不知道APL的所有,但想利用它,掌握Dyalog APL是一种非常好的资源。

  1. 评估严格按照从右到左的顺序进行。这包括设置变量,因此请充分利用它。

    2+a, 1+a←1 -> 3 4

    a设置为1,1+a评估为2,a,2评估为1 2和2+1 2评估为3 4。

  2. 像C一样,←可以与一个函数(即)组合a +← 3。与C不同,这是通用的:foo F← bar设置foo为F bar。有点不直观,作为返回的表达式bar,不是F bar。

    它也可以使用匿名函数:

          a←0
          a+←3 ⋄ a
    3
          a+←3 ⋄ a
    6
          a { ⍵/'!' } ←4 ⋄ a
    !!!!
    
  3. 您可以A[3]←8像期望的那样分配给数组:。但是,您也可以同时分配多个项目:A[3 5 6]←9 1 4或什至A[3 5 6]←9,将它们全部设置为同一项目。当然,您也可以在←此处添加功能。然后,该函数将分别应用于每个元素,就像您所做的那样F¨。

  4. ⍨ 是你的朋友,即使他对此不太满意。

    1. 如果F为dyadic,则dyadic ⍨切换参数:a F b<-> b F⍨ a。打高尔夫球时这很方便,因为它可以避免使用牙套:

      (F G H x) K y      <->     y K⍨ F G H x
      

      确实会改变评估顺序,因为总是先评估右手,然后评估左手。

    2. 如果F为dyadic,则monadic ⍨将相同的参数应用于函数的两侧:

            5⍴5
      5 5 5 5 5
            ⍴⍨5
      5 5 5 5 5
      

      该参数仅计算一次。这尤其适用于外部乘积,即,可以将数组中的每个值与同一数组中的其他值进行比较,∘.=⍨而不必这样做x∘.=x←(whatever)。

    3. 如果F为monadic,则不⍨执行任何操作,但会将函数与参数分开。因此,如果函数很复杂,它仍然可以节省花括号:

            {⍵+3}⍣5 6
            ∇{⍵+3}              
           ∇ ⍣ 5 6              
            ({⍵+3}⍣5)6
      21
            {⍵+3}⍣5⍨6
      21
      
  5. 学习习语!然后打高尔夫球。例如:

    ((((1↑⍴X),⍴Y)↑X)^.=Y)⌿X
    

    可以机械地转换为:

    X⌿⍨Y^.=⍨X↑⍨(1↑⍴X),⍴Y
    

    然后进一步进入:

    X⌿⍨Y^.=⍨X↑⍨(⊃⍴X),⍴Y
    

    ⊃(第1↑一个)在这种情况下等于(取一个)。并且可能:

    X⌿⍨Y^.=⍨X↑⍨(≢X),⍴Y
    

    ≢(tally)⊃⍴除标量外,所有值均等于(形状的第一个元素)。


除了拥有树莓派版本外,还有没有办法获得免费许可证?
— Fabinout 2014年

显然,这是一种合法的获取方式。
— Fabinout 2014年

2
@Fabinout:在dyalog.com上,您可以下载免费的Windows版本。单击“下载区域”,然后单击“未注册的下载”。它将使您无法注册,但否则它将完全起作用并且免费合法。如果您是学生,则可以通过填写表格免费获得普通版。如果您不住在一个因盗版而毁了您的生活的国家,那么您就会知道该怎么做。
— marinus 2014年

还有Nars2000,这是一个开源实现,具有比Dyalog更多的功能(和一些错误)。它的某些功能在打高尔夫球时很方便,例如质数功能或多组功能。
— Tobia 2014年

1
有GNU APL。
— M. Alaggan

14

火车

A(f g h)B      ←→  (A f B)g A h B  ⍝ fork
 (f g h)B      ←→  (  f B)g   h B  ⍝ fork
A(  g h)B      ←→         g A h B  ⍝ atop
 (  g h)B      ←→         g   h B  ⍝ atop
 (A g h)       ←→  ({A} g h)       ⍝ "Agh" fork
 (f g h k)     ←→  (f (g h k))     ⍝ 4-train
 (f g h k l)   ←→  (f g (h k l))   ⍝ 5-train, etc
 (f g h k l m) ←→  (f(g h(k l m))) ⍝ groups of 3 from the right, last could be 2
  f∘g B        ←→    f g B         ⍝ "compose" operator, useful in trains
A f∘g B        ←→  A f g B

这是否意味着为了将来的读者,我们不应该告诉Oberon如何缩短它?
— 亚当

不,像平常在PPCG上一样。在表达式达到最短(我认为是最短)之后,我将删除该行。这很容易-我认为您个人不会从中受益。
— ngn

我可以将其降低到16,但是我没有使用您的任何提示,所以也许我走了。
— 亚当

@亚当好,您正在使用的列车:)我的是相似的,但较长时间,因为我没想到⎕ML的
— NGN

是不是“从右边开始的3组”?
— 亚当

7

火车上/和⌿火车上的技巧

当使用火车,你可能要使用的减少f/同样数目的钱+/,甚至重复减少//。但是,如果火车在减法项的左边有更多部分,则需要括号以创建一个顶。这里有一些保存字节的技巧。

使用1∊代替单子∨/或∨⌿布尔数组

任务:给定两个相等长度的字符串A和B,如果A和B的任何对应字符相等,则返回2,否则返回0。例如,A←'abc'与B←'def'赋予0和A←'abc'和B←'dec'给人2。

dfn解决方案可能是,A{2×∨/⍺=⍵}B但您想通过默认来缩短它。A(2×∨/=)B是不会工作,因为列车编组规则解析这个作为2 (× ∨/ =),但你想2 × (∨/=)。

观察∨/或∨⌿在布尔向量上(∨/,或∨⌿,对于较高秩的数组)询问是否存在1,即1∊,因此我们可以将火车写为2×1∊=。

请注意,∊它使用了正确的参数,因此不能使用它来分别减少每一行或每一列。

使用1⊥代替单子+/或+⌿

任务:给定一个列表L和一个索引N,返回第N个列表的和的三倍。例如L←(3 1 4)(2 7),N←1给出24。

dfn解决方案可能是,N{3×+/⍺⊃⍵}L但您想通过默认来缩短它。N(3×+/⊃)L是不会工作,因为列车编组规则解析这个作为3(× +/ ⊃),但你想3 × (+/⊃)。

观察到,评估一元数(以1为底)的数字列表等同于对该列表求和,因为∑ { a,b,c,d } =  a + b + c + d  =(a ×1³)+(b ×1² )+(c ×1¹)+(d ×1⁰)。因此+/a b c d与相同1⊥a b c d,我们可以将火车写成3×1⊥⊃。

请注意,在高级参数上,1⊥等效于+⌿。

使用f.g的,而不是f/g标量和/或向量参数

任务:给定一个列表L和一个数字N,当L的元素除以NEg L←31 41 59并N←7给出时,通过最小除法余数返回范围1 1 2 3。

dfn解决方案可能是,N{⍳⌊/⍺|⍵}L但您想通过默认来缩短它。N(⍳⌊/|)L是不会工作,因为列车编组规则解析这个作为⍳ (⌊/) |,但你想⍳ (⌊/|)。

A f.g B当参数是标量和/或向量时,标量两个函数的内积与f/ A g B它们都相同,因为它们都是(A[1] g B[1]) f (A[2] g B[2]) f (A[3] g B[3])等,所以我们可以将训练写为⍳⌊.|。

请注意,这不适用于更高级别的阵列。

使用∊⊆的,而不是/用布尔左,简单的矢量右参数

任务:给定列表L和数字N,请过滤列表,以便仅保留大于N的数字。例如L←3 1 4,N←1给出3 4。

dfn解决方案可能是,N{(⍺<⍵)/⍵}L但您想通过默认来缩短它。N(</⊢)L不会起作用,因为绑定规则会将其解析为,(</) ⊢但是您要/作为函数复制而不是运算符reduce。

⊆具有布尔型左引数的二元对数根据左引数中1的游程对右引数进行分区,删除由0表示的元素。这几乎是我们想要的,除了不必要的分区。但是,我们可以通过应用monadic摆脱分区∊。这样{(⍺<⍵)/⍵}就可以成为{∊(⍺<⍵)⊆⍵},因此我们可以将我们的火车写为∊<⊆⊢。

请注意,这不适用于更高级别的阵列。

使用0⊥代替数字参数⊢/或⊢⌿与数字参数一起使用

任务:给定一个列表L和多个N,乘法的N个与腿的最右边的元件L←3 1 4和N←2给出8。

dfn解决方案可能是,N{⍺×⊢/⍵}L但您想通过默认来缩短它。N(⊣×⊢/⊢)L是不会工作,因为列车编组规则解析这个作为⊣ (× ⊢/ ⊢),但你想⊣ × (⊢/⊢)。

观察到0⊥数值数组上的相同⊢⌿,因此我们可以将火车写为⊣×0⊥⊢。

请注意,这将选择较高级别数组的最后一个主要单元。


1
也许您可以将此聊天答案添加到此答案中?
— J.Sallé18年

1
@J.Sallé添加了。
— 亚当

7

用⊥乘法与加法结合

(a×b)+C  ->  a⊥b,C
(C)+a×b  ->  a⊥b,C
(a×b)-C  ->  a⊥b,-C

假设:

  • a并且b用作左引数时不需要进一步括号的术语

  • C 是用作左参数时可能需要括号的表达式

  • a b C 计算为数字标量


5

复数

通常会被忽略,它们提供了绝佳的机会来缩短处理网格,迷宫,分形或几何图形的表达式。

0j1⊥¨    0j1⊥   ⍝ pair(s) of reals -> complex
11 9∘○¨  11 9○  ⍝ complex -> pair(s) of reals
|z0-z1          ⍝ distance between two points
0j1×z   0j¯1×z  ⍝ rotate by ±90° around (0,0)
0j1*⍳4          ⍝ the four cardinal directions
+z       -+z    ⍝ reflect across x or y axis
+\0,z           ⍝ sequence of steps -> path
2-/z            ⍝ path -> sequence of steps
0j1⊥¨n-⍳2⍴1+2×n ⍝ lattice centred on (0,0)

4

标引模向量长度

⊃i⌽a通常比朴素⊃a[(≢a)|i]或a⊃⍨i|⍨≢a(在这里a是向量,i是整数,并且⎕io为0)短

关于此的一个有用的变化(感谢EriktheOutgolfer指出):I↑Y⌽⍨I×X其中哪里Y是一些长度I向量的串联,并且X是我们要选择的长度向量的索引,例如:3↑'JanFeb...Dec'⌽⍨3×month


3

常数函数

=⍨并≠⍨感谢ngn。

有时,您只需要为列表中的每个元素分配一个值。尽管您可能会想使用{value}¨,但使用起来却比较短,value⊣¨ 但对于某些常用值,您可以使用来更短⎕IO←0:

¯1与 ⍬⍸list

0与 ⍬⍳list

1与 ⍬⍷list

请注意,这些仅适用于列表(尽管它们可能是嵌套的)。对于更高级别的数组,可以使用以下命令获取全0和全1:

1与 =⍨ 

0与 ≠⍨

如果设置⎕ML←0,则可以使用以下方法将所有数字都设为零(就像0×):

∊

如果仅需要一个数字,则可以使用monadic ≡来获取1或0,而不是使用1⊣或0⊣。


“ 有时,列表的每个元素只需要一个值。 ”-可能值得注意:当该值是列表的第一个元素时,您可以使用⊣\
— ngn

@ngn我想说,⊣并⊢与/和⌿功绩自己的岗位。
— 亚当

2

使用 ⍨

避免括号

⍨(通勤)可以通过避免括号来节省字节。只要您有一个函数需要在左参数上加上括号,而右参数不需要上括号,则可以保存一个字节,例如(A<B)÷C→ C÷⍨A<B。

双数组

要将数组的副本附加到其末尾,请使用,⍨A或⍪⍨A。

双数

2∘×您可以使用而不是使用double,+⍨因为它将参数添加到自身:1+2∘×→ 1++⍨。

平方数

2*⍨Y您可以使用而不是平方,×⍨Y因为它会将参数与自身相乘:2*⍨A+B→ ×⍨A+B。

随机排列

?⍨N将为您提供长度的随机排列N。

自分类

找到每个主要像元第一次出现的索引 ⍳⍨A

计算布尔向量中的尾随1

不必+/∧\⌽B计算N可以使用多少个尾随的1 ⊥⍨。

反向组成

A f∘g B是A f g B,但如果需要(g A) f B,请使用f⍨∘g⍨。

反向减少

f/ a1 a2 a3是a1 f (a2 f a3)。如果需要(a1 f a2) f a3,请使用f⍨/⌽。

反向扫描

f\ A B C是
 A (A f B) (A f (B f C))。

f⍨/∘⌽¨,\ A B C是
 A (A f B) ((A f B) f C)。

f⍨\⌽ A B C是
 ((A f B) f C) (B f C) C。

⌽f/∘⌽¨,\⌽ A B C。是
 (A f (B f C)) (B f C) C。


2

枚举字符串中的字符,不带 ⍳≢

任务:给定两个字符串S和T,列出其串联索引。例如S←'abcd',T←'xyz'给出1 2 3 4 5 6 7。

dfn解决方案可能是,S{⍳≢⍺,⍵}T但您想通过默认来缩短它。⍳≢,是不会工作,因为火车解析规则解析此作为(⍳)≢(,),但你想(⍳≢),。

⍋左参数为空的Dyadic 根据其当前顺序对简单字符数组进行评分,该顺序与相同⍳≢。这样{⍳≢⍺,⍵} 就可以成为{⍬⍋⍺,⍵},因此我们可以将火车写成⍬⍋,。

请注意,这不适用于数字数组或混合数组。


哇,不知道那是一回事。
— 扎卡里
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.