(3 + sqrt(5))^ nを正確に計算する


23

今日の目標は、次ような非負の整数nが与えられた整数aおよびbを見つけることです。

(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
→1479168 9、661504

回答:


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]41ではなく26バイトです。
orlp15年

3
@(n)[3 5;1 3]^n*[1;0](関数ハンドル)は5文字を節約します。
-flawr

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]

これは、入力として単一の整数を取り、解[a、b]に対応する整数の2要素ベクトルを返すラムダ関数を作成します。呼び出すには、名前を付けf=n->...ます。

掛けることから始めます

Initial expand

次に、この方程式の右辺を2列の行列に変換できます。最初の行列はaの係数に対応し、2番目はbの係数に対応します。

Matrix

この行列自体を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
algorithmshark

@algorithmsharkありがとう、なぜ(+/@:*&(3 5,.1 3)&1 0)機能し(+/@:*&1 0&(3 5,.1 3))ますか?2番目のものは正しく結合し、最初のものは交換されませんか?
randomra

思ったとおりに結合しますが、外部&は電源投入/ループを行うため、電源投入時に左側の入力を変更します(通常の右側の変更とは反対)。
randomra

7

Pyth、20バイト

u,+*3sGyeG+sGyeGQ,1Z

uこれは一般に削減されますが、ここでは繰り返し適用ループとして使用されます。更新関数はG-> ,+*3sGyeG+sGyeGG、2タプルです。その関数はに変換され3*sum(G) + 2*G[1], sum(G) + 2*G[1]ます。ssumyです*2


@randomraの回答をあなたよりも選んだのは、彼/彼女が16分早く投稿されたためです。ごめんなさい。
orlp

5

APL(22)

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

説明:

  • {... }⍣⎕⍨2↑1:数値を読み取り[1,0]、初期入力として使用して、次の関数を何度も実行します。
    • 2 2⍴3 5 1: マトリックス [[3,5],[1,3]]
    • ⍵+.×⍨:inの最初の数に3を掛け、2番目の数に5を掛けて合計します。これが新しい最初の数です。次に、inの最初の数に1を掛け、2番目に3を掛け、それらを合計します。これが新しい2番目の数です。

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.

いいえ、私はゼリーは、インターネットの作成前に長い時間を中心にしたかなり確信している:P
コナー・オブライエン

1
@Doᴡɴɢᴏᴀᴛ競合しない回答の場合、2行目のバイトカウントを保持することを好みます。これにより、回答がリーダーボードとユーザースクリプトでトップに上がらないようにします。
デニス


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はもうありません。
アレックスA.

数日前に紹介されたと思いますか?
flawr

ええ、しかしそれはスタックスニペットを台無しにしたので、無効にしなければなりませんでした。
アレックスA.

私は63をそのままカウントし、61に短縮できますF=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

1
これはすごい恐ろしいからです。
kirbyfan64sos

2

k2-22文字

1つの引数を取る関数。

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

_mul行列の乗算は、私たちが行列とそれをカレーようで(3 5;1 3)、その後、機能的なパワー副詞で叩い:f/[n;x]適用するfにはxn回。繰り返しますが、今回は開始ベクトルを使用し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)

何らかの理由f/[n;x]で正しく実装されていないため、これはコナでは機能しません。n f/x構文のみが機能するため、最短修正は{x _mul[(3 5;1 3)]/1 0}23文字です。


ワオ。このカレーの使用はとても賢いので、私のKの答えは馬鹿げているように感じます。とにかく、コナで見つかった問題をバグトラッカーで取り上げました。
kirbyfan64sos


2

ised、25バイト(20文字)

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

私はもっ​​と良いことを望んでいましたが、有能にするためにisedに必要なブレースが多すぎます。オペレーターの優先順位はゴルフには最適ではありません。

入力は$ 1のメモリスロットにあると想定されるため、これは機能します。

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

n = 0の場合、ゼロはスキップされます(1 0の代わりに出力1)。問題がある場合は、最終版1をに置き換え~[2]ます。


2

真剣に、32バイト、非競合

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

六角ダンプ:

2cbb34332f313260bd223b2940342af728362a2d229c6e2e58348df130606e7f

オンラインで試す

明らかに最短の競争相手ではありませんが、少なくともその方法は独創的です。(このような問題は、説明で述べたように、必ずルーカスシーケンスを示すことに注意してください。このプログラムは、再帰関係を使用してシーケンスの連続した用語を生成します

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

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

@orlp-それはあなたのためのCです。このソリューションは、括弧内の中間計算のために他のソリューションよりも早く失敗しますが、データ型を変更しない限り、とにかくいくつかの余分なステップを管理するだけです。サポートする予定の範囲を指定するために質問を明示的に変更する価値はありますか?おそらく今では遅すぎます。
アルキミスト

サポートする範囲はありません。どんな入力でも適切なソリューションが機能するはずです。Cでは、任意の幅の整数を実装する必要があります。申し訳ありません= /
orlp

提案するa[*a=1]=0代わりに*a=1,a[1]=0
ceilingcat

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.