在 APL 中生成没有循环或流控制的斐波那契数列
Generate a fibonacci series with no loops or flow control in APL
有没有一种方法可以在 APL 中使用不需要循环或流控制的单行创建斐波那契数列?
我已经通过使用 →
的函数和条件测试完成了它,但我觉得必须有一种更优雅、更声明的方式。 example 我发现声称在一行上完成它在 gnu-apl 上不起作用 - 它似乎在正确的轨道上,使用矩阵数学,但我很难跟上,并且无法调整它以使其正常工作。
我正在追求 APL 作为我的第一门真正的编程语言(我喜欢这些符号。我就是喜欢。)我现在正在使用 Project Euler 作为一种更好地熟悉的方式。
另一种方法是使用(相对较新的)幂运算符。 GNU APL 可能支持也可能不支持,它适用于 Dyalog(我使用的是 13.1)和 NGN APL。
尝试
({⍵,+/¯2↑⍵} ⍣ 20) (1 1)
与其他示例一样,迭代是隐藏的,此处使用幂运算符。
表达式
({⍵,+/¯2↑⍵} ⍣ 3) (1 1)
正在做
{⍵,+/¯2↑⍵} {⍵,+/¯2↑⍵} {⍵,+/¯2↑⍵} 1 1
在幕后。
1 1 是种子值,每个连续的 {⍵,+/¯2↑⍵} 只是连接最后两个元素的总和。
您在使用 Dyalog APL 吗?在这种情况下,您应该利用上一个答案所解释的 power
运算符(该答案中的第一段代码来自 Mastering Dyalog APL 一书,p . 416).
具有相同运算符的另一种解决方案是使用矩阵:
(+.×⍣10)⍨ 2 2⍴1 1 1 0
或作为直接函数:
{⊃(+.×⍣⍵)⍨2 2⍴1 1 1 0} 10
如果您不想使用 power
运算符,您仍然可以使用矩阵(下面的代码在 GNU APL 1.5 下测试):
{+.×/⍵⍴⊂2 2⍴1 1 1 0} 10
好吧,我想我已经找到了一种方法来生成长度为 N(而不是第 N 个数字)的 序列 在单个(虽然不是很漂亮的一行APL2):
+/¨(⊂0 0)⍉¨⊖¨(2/¨⍳N)↑¨⊂P←V∘.!V←⍳1+N←20
就像我说的:不太漂亮。
让我试着把它分解成成语:
这是 20 层的帕斯卡三角形:
P←V∘.!V←⍳1+N←20
然后取左上角前N个方格:
(2/¨⍳N)↑¨⊂P
这个成语returns矩阵的主对角线:
(⊂0 0)⍉
但是我们想要反对角线,所以在此之前我们将使用 ⊖
翻转所有方块。
最后一步只是将所有反对角线与 +/
求和。
我也喜欢 APL 的符号,以及它的数组编程能力。其他数组语言可能更强大,例如 J,但它们缺乏 APL 的符号之美和显式语法。
我刚刚在 GNU APL 中尝试了您 link 的示例,它工作正常:
↑0 1↓↑+.×/5/⊂2 2⍴1 1 1 0
5
↑0 1↓↑+.×/6/⊂2 2⍴1 1 1 0
8
↑0 1↓↑+.×/7/⊂2 2⍴1 1 1 0
13
如果您无法让它工作,请确保:
- 键入(或复制并粘贴)示例中显示的确切符号:特别是
×
是 U+00D7 MULTIPLICATION SIGN,而不是 X; ⍴
是 U+2374 APL FUNCTIONAL SYMBOL RHO,不是任何其他希腊 Rho,也绝对不是 P; ⊂
是 U+2282 的子集;等等;
- 测试 1 或 5 以外的一些数字,因为它们是唯一等于其斐波那契数的数字;
- 如果您没有用实际数字代替 N,请确保以正确的方式定义 N,例如在前一行中单独定义
N←7
。
如果您仍然无法使用它,请从右边开始一步一步地输入公式:
2 2⍴1 1 1 0
1 1
1 0
⊂2 2⍴1 1 1 0
1 1
1 0
7/⊂2 2⍴1 1 1 0
1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 1 0 1 0 1 0 1 0 1 0 1 0
+.×/7/⊂2 2⍴1 1 1 0
21 13
13 8
↑+.×/7/⊂2 2⍴1 1 1 0
21 13
13 8
0 1↓↑+.×/7/⊂2 2⍴1 1 1 0
13
8
↑0 1↓↑+.×/7/⊂2 2⍴1 1 1 0
13
至于问题标题,我认为这个矩阵公式很到位(太棒了@mappo!)
如果我是 golfing,我可能会使用更短的变体,但仅此而已:
2⌷∊+.×/7/⊂∘.∨⍨1 0
13
那里,从 24 到 17 个字符。看看你能不能想出来:-)
GNU APL 还不错,虽然它缺少一些现代功能,但请随身携带一份 Dyalog APL 程序员指南和语言参考,因为它是关于该语言的最全面的参考之一。
聚会迟到了,但这里有一个干净的解决方案,对 gnu-apl 是安全的,不使用幂运算符,并且稍微调整了 Lobachevsky 的 "neg-two take" 方法:
fib ← {{⍵, +/ ¯2↑ ⍵} / ⌽ ⍳⍵}
基本技巧是反转 iota 列表,因为压缩会向后读取它。示例输出:
fib 10
1 1 2 3 5 8 13 21 34 55
有没有一种方法可以在 APL 中使用不需要循环或流控制的单行创建斐波那契数列?
我已经通过使用 →
的函数和条件测试完成了它,但我觉得必须有一种更优雅、更声明的方式。 example 我发现声称在一行上完成它在 gnu-apl 上不起作用 - 它似乎在正确的轨道上,使用矩阵数学,但我很难跟上,并且无法调整它以使其正常工作。
我正在追求 APL 作为我的第一门真正的编程语言(我喜欢这些符号。我就是喜欢。)我现在正在使用 Project Euler 作为一种更好地熟悉的方式。
另一种方法是使用(相对较新的)幂运算符。 GNU APL 可能支持也可能不支持,它适用于 Dyalog(我使用的是 13.1)和 NGN APL。
尝试
({⍵,+/¯2↑⍵} ⍣ 20) (1 1)
与其他示例一样,迭代是隐藏的,此处使用幂运算符。
表达式
({⍵,+/¯2↑⍵} ⍣ 3) (1 1)
正在做
{⍵,+/¯2↑⍵} {⍵,+/¯2↑⍵} {⍵,+/¯2↑⍵} 1 1
在幕后。
1 1 是种子值,每个连续的 {⍵,+/¯2↑⍵} 只是连接最后两个元素的总和。
您在使用 Dyalog APL 吗?在这种情况下,您应该利用上一个答案所解释的 power
运算符(该答案中的第一段代码来自 Mastering Dyalog APL 一书,p . 416).
具有相同运算符的另一种解决方案是使用矩阵:
(+.×⍣10)⍨ 2 2⍴1 1 1 0
或作为直接函数:
{⊃(+.×⍣⍵)⍨2 2⍴1 1 1 0} 10
如果您不想使用 power
运算符,您仍然可以使用矩阵(下面的代码在 GNU APL 1.5 下测试):
{+.×/⍵⍴⊂2 2⍴1 1 1 0} 10
好吧,我想我已经找到了一种方法来生成长度为 N(而不是第 N 个数字)的 序列 在单个(虽然不是很漂亮的一行APL2):
+/¨(⊂0 0)⍉¨⊖¨(2/¨⍳N)↑¨⊂P←V∘.!V←⍳1+N←20
就像我说的:不太漂亮。 让我试着把它分解成成语:
这是 20 层的帕斯卡三角形:
P←V∘.!V←⍳1+N←20
然后取左上角前N个方格:
(2/¨⍳N)↑¨⊂P
这个成语returns矩阵的主对角线:
(⊂0 0)⍉
但是我们想要反对角线,所以在此之前我们将使用 ⊖
翻转所有方块。
最后一步只是将所有反对角线与 +/
求和。
我也喜欢 APL 的符号,以及它的数组编程能力。其他数组语言可能更强大,例如 J,但它们缺乏 APL 的符号之美和显式语法。
我刚刚在 GNU APL 中尝试了您 link 的示例,它工作正常:
↑0 1↓↑+.×/5/⊂2 2⍴1 1 1 0
5
↑0 1↓↑+.×/6/⊂2 2⍴1 1 1 0
8
↑0 1↓↑+.×/7/⊂2 2⍴1 1 1 0
13
如果您无法让它工作,请确保:
- 键入(或复制并粘贴)示例中显示的确切符号:特别是
×
是 U+00D7 MULTIPLICATION SIGN,而不是 X;⍴
是 U+2374 APL FUNCTIONAL SYMBOL RHO,不是任何其他希腊 Rho,也绝对不是 P;⊂
是 U+2282 的子集;等等; - 测试 1 或 5 以外的一些数字,因为它们是唯一等于其斐波那契数的数字;
- 如果您没有用实际数字代替 N,请确保以正确的方式定义 N,例如在前一行中单独定义
N←7
。
如果您仍然无法使用它,请从右边开始一步一步地输入公式:
2 2⍴1 1 1 0
1 1
1 0
⊂2 2⍴1 1 1 0
1 1
1 0
7/⊂2 2⍴1 1 1 0
1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 1 0 1 0 1 0 1 0 1 0 1 0
+.×/7/⊂2 2⍴1 1 1 0
21 13
13 8
↑+.×/7/⊂2 2⍴1 1 1 0
21 13
13 8
0 1↓↑+.×/7/⊂2 2⍴1 1 1 0
13
8
↑0 1↓↑+.×/7/⊂2 2⍴1 1 1 0
13
至于问题标题,我认为这个矩阵公式很到位(太棒了@mappo!)
如果我是 golfing,我可能会使用更短的变体,但仅此而已:
2⌷∊+.×/7/⊂∘.∨⍨1 0
13
那里,从 24 到 17 个字符。看看你能不能想出来:-)
GNU APL 还不错,虽然它缺少一些现代功能,但请随身携带一份 Dyalog APL 程序员指南和语言参考,因为它是关于该语言的最全面的参考之一。
聚会迟到了,但这里有一个干净的解决方案,对 gnu-apl 是安全的,不使用幂运算符,并且稍微调整了 Lobachevsky 的 "neg-two take" 方法:
fib ← {{⍵, +/ ¯2↑ ⍵} / ⌽ ⍳⍵}
基本技巧是反转 iota 列表,因为压缩会向后读取它。示例输出:
fib 10
1 1 2 3 5 8 13 21 34 55