精确计算(3 + sqrt(5))^ n


23

今天,您的目标是找到给定非负整数n的整数ab,使得:

(3 + sqrt(5))^ n = a + b * sqrt(5)

您应该编写一个带有参数n并以您选择的格式输出ab的程序或函数。

有标准漏洞。另外,您打算自己使用基本算术来实现上述问题。因此,您可能不使用内置的精确代数功能,有理数或实现非平凡数学构造的函数(例如Lucas序列)。

以字节为单位的最短代码获胜。


输入/输出示例:

0→1,0
1→3,1
2→14,6
3→72 32
4→376,168
5→1968,880
6→10304,4608
7→53952,24128
8→282496,126336
9→1479168,661504

Answers:


3

Dyalog APL,18个字节

((3∘×+5 1×⌽)⍣⎕)1 0

这是一个通过输入的程序

 (         )         Monadic train:
  3∘×                3 times argument
     +               Plus
      5 1×⌽          (5 1) times the reverse
(           ⍣⎕)      Apply that function (input) times
               1 0   starting with (1 0)

此处使用的功能已在2015年4月之前实施,因此此答案有效。

在这里尝试。请注意,tryapl.org是Dyalog的有限子集,不支持


16

八度,26字节

[3 5;1 3]**input('')*[1;0]

因为(a + b * sqrt(5))*(3 + sqrt(5))=(3a + 5b)+(a + 3b)* sqrt(5),

输入向量相乘

| 1 |    /* a = 1 */
| 0 |    /* b = 0 */

通过矩阵代表1 =(3 + sqrt(5))^ 0

| 3 5 |
| 1 3 |

看起来很自然。而不是循环n时间,我们将矩阵提高到的幂,n然后乘以输入向量。


您卖空的[3 5;1 3]**input('')*[1;0]是26个字节,而不是41个字节
。– orlp

3
@(n)[3 5;1 3]^n*[1;0](功能手柄)将为您节省五个字符,这是个好主意!
瑕疵的

14

python 2,50

a=1;b=0
exec"a,b=3*a+5*b,3*b+a;"*input()
print a,b

乘以3+sqrt(5)多次受到其对对行动(a,b)代表a+b*sqrt(5)。等效于从列向量开始,[1,0]然后乘以n矩阵的左乘次数[[3,5],[1,3]]


12

朱莉娅,22 20字节

n->[3 5;1 3]^n*[1;0]

这将创建一个lambda函数,该函数将单个整数作为输入,并返回与解[a,b]对应的整数的2元素向量。要给它起个名字,例如f=n->...

从相乘开始

初始扩展

然后,我们可以此方程的右手侧转换成2列的矩阵,其中,所述第一对应的系数和第二对的系数b

矩阵

将此矩阵本身乘以n次,然后右乘以列向量(1、0)和POOF!Out弹出求解向量。

例子:

julia> println(f(0))
[1,0]

julia> println(f(5))
[1968,880]

8

J,20个字节

+/@:*(3 5,.1 3&)&1 0

将向量[1 0]与矩阵[[3 5] [1 3]] n时间相乘。

@algorithmshark节省了2个字节。

用法与测试:

   (+/@:*(3 5,.1 3&)&1 0) 5
1968 880

   (+/@:*(3 5,.1 3&)&1 0) every i.6
   1   0
   3   1
  14   6
  72  32
 376 168
1968 880

利用默认的副词解析,您可以降低到20 +/ .*(3 5,:1 3&)&1 0
algorithmhark

@algorithmshark谢谢,尽管为什么(+/@:*&(3 5,.1 3)&1 0)行得通(+/@:*&1 0&(3 5,.1 3))呢?第二个债券是否应正确结合而第一个债券不能互换?
randomra 2015年

知道了,它们按我的预期粘合,但是外部&进行供电/循环,因此您可以在供电期间修改左侧输入(与正常的右侧修改相反)。
randomra 2015年

7

Pyth,20个字节

u,+*3sGyeG+sGyeGQ,1Z

u通常减少的值在此处用作应用重复循环。更新功能是G-> ,+*3sGyeG+sGyeG,其中G是2个元组。该函数将转换为3*sum(G) + 2*G[1], sum(G) + 2*G[1]ssumy*2


我选择@randomra的答案是您的答案,因为抱歉,他/她的帖子早16分钟发布了。
orlp 2015年

5

APL(22)

{⍵+.×⍨2 2⍴3 5 1}⍣⎕⍨2↑1

说明:

  • {... }⍣⎕⍨2↑1:读取一个数字,并[1,0]作为初始输入多次运行以下功能。
    • 2 2⍴3 5 1: 矩阵 [[3,5],[1,3]]
    • ⍵+.×⍨:⍵中的第一个数字乘以3,第二个乘以5,然后将它们相加,这就是新的第一个数字;然后将in中的第一个数字乘以1,第二个乘以3,然后将这些数字相加,即新的第二个数字。

1
Awww yiss,APL。
Nit

5

果冻,13 个字节

5W×U++Ḥ
2Bdz¡

在线尝试!

怎么运行的

5W×U++Ḥ    Helper link. Argument: [a, b]

5W         Yield [5].
  ×U       Multiply it by the reverse of [a, b]. This yields [5b, a].
    +      Hook; add the argument to the result. This yields [a + 5b, a + b].
     +Ḥ    Fork; add the doubled argument ([2a, 2b]) to the result.
           This yields [3a + 5b, a + 3b].

2Bdz¡      Main link. Argument: n

2B         Convert 2 to binary, yielding [1, 0].
    ¡      Repeat:
  Ç            Apply the helper link...
   ³           n times.

不,我很确定Jelly在建立互联网之前已经很长时间了:P
Conor O'Brien

1
@Doᴡɴɢᴏᴀᴛ对于非竞争性答案,我更喜欢将字节数保留在第二行。这使答案无法在排行榜和用户脚本中排名靠前,这似乎是不公平的。
丹尼斯


3

CJam,21个字节

0X{_2$3*+@5*@3*+}li*p

在线尝试。

怎么运行的

0X       " Stack: [ 0 1 ]                                ";
li{      " Do int(input()) times:                        ";
  _2$    " Stack: [ a b ] -> [ a b b a ]                 ";
  3*+    " Stack: [ a b b a ] -> [ a b (b+3a) ]          ";
  @5*@3* " Stack: [ a b (b+3a) ] -> [ (b+3a) 5a 3b ]     ";
  +      " Stack: [ (b+3a) 5a 3b ] -> [ (b+3a) (5a+3b) ] ";
}*       "                                               ";
p        " Print topmost stack item plus linefeed.       ";
         " Print remaining stack item (implicit).        ";

3

Javascript,63 61字节

我正在对二项式进行递归求值:(x + y)^ n =(x + y)(x + y)^ {n-1}

新增(由于@ edc65)

F=n=>{for(i=y=0,x=1;i++<n;)[x,y]=[3*x+5*y,x+3*y];return[x,y]}

F=n=>{for(i=y=0,x=1;i<n;i++)[x,y]=[3*x+5*y,x+3*y];return [x,y]}

1
可能需要考虑编辑您的公式。我们不再有MathJax。
Alex A.

我以为是几天前才介绍的?
瑕疵的

是的,但是它弄乱了堆栈片段,因此必须禁用它。
Alex A.

我按原样算是63,可以缩短为61F=n=>{for(i=y=0,x=1;i++<n;)[x,y]=[3*x+5*y,x+3*y];return[x,y]}
edc65

n=>[...Array(n)].map(_=>[x,y]=[3*x+5*y,x+3*y],y=0,x=1)[n-1]相同长度
l4m2

2

C,114字节

g(n){int i,a[2]={1,0},b[2];for(i=0;i<n;i++)*b=*a*3+5*a[1],b[1]=*a+3*b[1],*a=*b,a[1]=b[1];printf("%d,%d",*a,a[1]);}

这无聊地实现了矩阵乘法。238字节解决方案提供了更多乐趣(引用:“超赞”),别无所求!

f(n){int p[2][n+3],i,j,k=0,a[2]={0};for(j=0;j<n+3;j++)p[0][j]=0;*p[1]=0;(*p)[1]=1;for(j=0;j<n;j++,k=!k)for(i=1;i<n+3;i++)p[!k][i]=p[k][i-1]+p[k][i];for(i=1;i<n+2;i++)a[!(i%2)]+=p[k][i]*pow(3,n+1-i)*pow(5,(i-1)/2);printf("%d,%d",*a,a[1]);}

拆解:

g(n){
    int i,a[2]={1,0},b[2];
    for(i=0;i<n;i++)
        *b=3**a+5*a[1],b[1]=*a+3*b[1],*a=*b,a[1]=b[1];
    printf("%d,%d",*a,a[1]);
}

这可能会缩短一点。在线尝试测试程序!


1
这是使用相当复杂的算法:P
orlp

@orlp我想不出这种语言的简短算法。我以为这个可以解决,但是有点失控,哈哈。手工实现矩阵乘法可能会更短。
BrainSteel 2015年

1
赞成,因为这太可怕了。
kirbyfan64sos 2015年

2

k2-22个字符

函数采用一个参数。

_mul[(3 5;1 3)]/[;1 0]

_mul是矩阵乘法,因此我们用矩阵对其进行咖喱处理(3 5;1 3),然后使用功能幂副词打它:f/[n;x]适用fxn时间。再次,我们用起始向量咖喱1 0

  _mul[2 2#3 5 1]/[;1 0] 5
1968 880
  f:_mul[2 2#3 5 1]/[;1 0]
  f'!8  /each result from 0 to 7 inclusive
(1 0
 3 1
 14 6
 72 32
 376 168
 1968 880
 10304 4608
 53952 24128)

这在Kona中不起作用,因为由于某些原因f/[n;x]未正确实现。仅n f/x语法有效,因此最短的修复为{x _mul[(3 5;1 3)]/1 0}23个字符。


哇。这种对curring的用法非常聪明,我觉得我的K答案很愚蠢。无论如何,我在他们的bug跟踪器上提出了您在Kona中发现的问题。
kirbyfan64sos 2015年


2

ised,25个字节(20个字符)

({:{2,4}·x±Σx:}$1)∘1

我希望能做得更好,但要使它能胜任,需要太多支撑,操作员的优先级并不是打高尔夫球的最佳选择。

它期望输入位于$ 1的内存插槽中,因此可以正常工作:

ised '@1{9};' '({:{2,4}·x±Σx:}$1)∘1'

对于n = 0,跳过零(输出1,而不是1 0)。如果这是一个问题,更换最后1~[2]


2

严重的是,32个字节,无竞争

,╗43/12`╜";)@4*≈(6*-"£n.X4ì±0`n

十六进制转储:

2cbb34332f313260bd223b2940342af728362a2d229c6e2e58348df130606e7f

在线试用

显然不是最短的竞争者,但至少该方法是原始的。(请注意,这样的问题必然表明Lucas序列,如说明书中所述,该程序使用递归关系生成序列的连续项

a_n = 6 * a_ {n-1}-4 * a_ {n-2}。)


1

Haskell,41个字节

(iterate(\(a,b)->(3*a+5*b,a+3*b))(1,0)!!)

用法示例:(iterate(\(a,b)->(3*a+5*b,a+3*b))(1,0)!!) 8-> (282496,126336)


1

C / C ++ 89字节

void g(int n,long&a,long&b){if(n){long j,k;g(n-1,j,k);a=3*j+5*k;b=j+3*k;}else{a=1;b=0;}}

格式:

    void g(int n, long&a, long&b) {
if (n) {
    long j, k;
    g(n - 1, j, k);
    a = 3 * j + 5 * k;
    b = j + 3 * k;
} else {
    a = 1;
    b = 0;
}}

相同的概念:

void get(int n, long &a, long& b) {
    if (n == 0) {
        a = 1;
        b = 0;
        return;
    }
    long j, k;
    get(n - 1, j, k);
    a = 3 * j + 5 * k;
    b = j + 3 * k;
}

测试台:

#include <iostream>
using namespace std;    
int main() {
    long a, b;
    for (int i = 0; i < 55; i++) {
        g(i, a, b);
        cout << i << "-> " << a << ' ' << b << endl;
    }
    return 0;
}

输出:

0-> 1 0
1-> 3 1
2-> 14 6
3-> 72 32
4-> 376 168
5-> 1968 880
6-> 10304 4608
7-> 53952 24128
8-> 282496 126336
9-> 1479168 661504
10-> 7745024 3463680
11-> 40553472 18136064
12-> 212340736 94961664
13-> 1111830528 497225728
14-> 5821620224 2603507712
15-> 30482399232 13632143360
16-> 159607914496 71378829312
17-> 835717890048 373744402432
18-> 4375875682304 1956951097344
19-> 22912382533632 10246728974336
20-> 119970792472576 53652569456640
21-> 628175224700928 280928500842496
22-> 3289168178315264 1470960727228416
23-> 17222308171087872 7702050360000512
24-> 90177176313266176 40328459251089408
25-> 472173825195245568 211162554066534400
26-> 2472334245918408704 1105661487394848768

欢迎来到该网站,并且是一个不错的第一答案!
DJMcMayhem

0

K,37个字节

f:{:[x;*(1;0)*_mul/x#,2 2#3 1 5;1 0]}

要么

f:{:[x;*(1;0)*_mul/x#,(3 1;5 3);1 0]}

他们都是同一回事。


0

Python 3,49个字节

w=5**0.5;a=(3+w)**int(input())//2+1;print(a,a//w)

尽管在我的机器上,这只能给出范围内输入的正确答案0 <= n <= 18

这实现了封闭式公式

w = 5 ** 0.5
u = 3 + w
v = 3 - w
a = (u ** n + v ** n) / 2
b = (u ** n - v ** n) / (2 * w)

并利用了v ** n零件很小的事实,并且可以通过舍入而不是直接计算来进行计算。


1
这不是一个有效的解决方案(您必须支持任何n),但是由于您距离最短的距离还很遥远,所以我看不出有任何不赞成的理由。这是一个很酷的解决方案。
orlp 2015年

0

方案,97字节

(define(r n)(let s([n n][a 1][b 0])(if(= 0 n)(cons a b)(s(- n 1)(+(* a 3)(* b 5))(+ a(* b 3))))))

0

C 71字节(带有预初始化变量的60个字节)

打高尔夫球的范围还可以,但是只是为了证明C不必“太可怕了”。

f(int n,int*a){for(*a=1,a[1]=0;n--;a[1]=*a+3*a[1],*a=(5*a[1]+4**a)/3);}

如果将a中的值初始化为{1,0},我们会做得更好。

f(int n,int*a){for(;n--;a[1]=*a+3*a[1],*a=(5*a[1]+4**a)/3);}

迭代地使用映射a-> 3a + 5b,b-> a + 3b,但通过从b的新值计算a来避免临时变量。


您的解决方案会为大型输入溢出整数:)
orlp 2015年

@orlp-这就是C。授予此解决方案比其他解决方案更早的失败是因为括号内的是临时计算,但是除非我更改数据类型,否则它只能管理几个额外的步骤。是否值得明确地更改问题以提供您希望支持的范围?不过现在可能为时已晚。
Alchymist 2015年

没有支持的范围,任何输入都应使用正确的解决方案。在C中,这意味着您必须实现任意宽度的整数,对不起= /
orlp

建议a[*a=1]=0而不是*a=1,a[1]=0
ceilingcat

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.