逆フィボナッチ定数


8

通常のフィボナッチチャレンジが非常に多いため、逆フィボナッチ定数、つまりフィボナッチシーケンスの逆数の合計を計算するのは興味深いことだと判断しました。

課題は、フィボナッチ数列を使用してフィボナッチ数の逆数を計算し、入力として指定された数字を使用することです。つまり、10の入力は、最初の10フィボナッチ数の逆数に基づいて計算することを意味します。おそらく同点の場合、最短のコードが優先されます。

優勝者は、標準のコードゴルフ規則により3週間で選ばれます。


2
これは(私が正しく理解していれば)1 /φ(黄金比の逆数)と同じです。フィボナッチ数列を実際に計算に使用する場合は、指定する必要があります。そうでない場合φ、組み込みの言語は確かにあります。(変更のAPLではありません)
マリナス2014年

@marinus変更されました。

1
@marinus、それは1 / phiとは異なります。それは閉じた形をしていますが、かなりトリッキーです。Mathematicaはおそらく組み込まれているでしょうが、他の多くの言語が持っているとは思えません。
Peter Taylor

@OP、「可能な限り最高の精度」は無意味な勝利基準です。任意の10進精度をサポートする言語を持っている人、またはそのサポートを作成するのが面倒な人は、precisionパラメーターを使用して実装を行い、編集戦争に参加してそのパラメーターを増やすことができます。精度をパラメーターとして取る関数を要求する方が理にかなっています。速度の判断は、多くの要因(CPUモデル、使用可能なRAM、システム負荷など)に依存するため、注意が必要です。
Peter Taylor

@PeterTaylorこれはいいですか?

回答:


5

K(19)

(または、関数としての定義をスキップする場合は17)

f:{+/*+%x(|+\)\|!2}

コナでテスト済み。

基本的に、フィボナッチ数列の最初のx値を(組み込み関数を使用せずに)配列に生成し、配列全体の各値で1を割り、転置して合計します。

(より良い合計方法を提供してくれた@tmartinに感謝)


17文字でわずかに変化します–{+/*+%x(|+\)\|!2}
tmartin 2014年

@tmartinありがとう、そうです、それほど複雑ではない合計方法でした:)
Joachim Isaksson

9

Perl-35バイト

print!map$\-=1/($%+=$.=$%-$.),0..<>

使用例:

$ echo 10 | perl inv-fib-sum.pl
3.34170499581934

さらなる分析

合計が

収束しています。数千桁程度を計算したいと仮定すると、単純なアプローチでほぼ十分です。収束は最初はかなり遅いですが、急速にスピードアップするため、1000桁は約4800項しかかかりません。Pythonの実装例は次のとおりです。

a=[1,1]
for i in range(4800):a=[a[0]+a[1]]+a
z=10**1000
print sum(map(lambda i:z/i,a))

これは1秒程度で出力されます。

33598856662431775531720113029189271796889051337319684864955538153251303189966833836154162164567900872970453429288539133041367890171008836795913517330771190785803335503325077531875998504871797778970060395645092153758927752656733540240331694417992939346109926262579646476518686594497102165589843608814726932495910794738736733785233268774997627277579468536769185419814676687429987673820969139012177220244052081510942649349513745416672789553444707777758478025963407690748474155579104200675015203410705335285129792635242062267537568055761955669720848843854407983324292851368070827522662579751188646464096737461572387236295562053612203024635409252678424224347036310363201466298040249015578724456176000319551987905969942029178866949174808096746523682654086938399069873211752166957063859411814553647364268782462926166650100098903804823359519893146150108288726392887669917149304053057745574321561167298985617729731395370735291966884327898022165047585028091806291002444277017460241040417786069190065037142832933

(最後の4桁は収束していませんが、ここでは無視します。)

収束を少し高速化してみましょう。標準的なトリックは、オイラーの変換を使用することです。拡張と単純化の後、これはより良い結果を生み出します:

これがより早く収束する理由はかなり明白です。各項には、分母に1つだけではなく3つの項があります。1000桁を計算するには、1600(1/3の数)の項しか必要ありません。

a=[1,1]
for i in range(1601):a=[a[0]+a[1]]+a
z=10**1000
print sum(map(lambda i:(-1)**i*z/(a[i]*a[i+1]*a[i+2]),range(1601)))

出力:

3598856662431775531720113029189271796889051337319684864955538153251303189966833836154162164567900872970453429288539133041367890171008836795913517330771190785803335503325077531875998504871797778970060395645092153758927752656733540240331694417992939346109926262579646476518686594497102165589843608814726932495910794738736733785233268774997627277579468536769185419814676687429987673820969139012177220244052081510942649349513745416672789553444707777758478025963407690748474155579104200675015203410705335285129792635242062267537568055761955669720848843854407983324292851368070827522662579751188646464096737461572387236295562053612203024635409252678424224347036310363201466298040249015578724456176000319551987905969942029178866949174808096746523682654086938399069873211752166957063859411814553647364268782462926166650100098903804823359519893146150108288726392887669917149304053057745574321561167298985617729731395370735291966884327898022165047585028091806291002444277017460241040417786069190065037142834500

(ここでも、最後の4桁は収束しません。)

まだ完了していません。隣接する用語を組み合わせると、次のようになります。

残りの合計から各項を除外すると、ネストされた式が得られます。

今、私たちはどこかに着いています。の分子はOEIS A206351に準拠していることに注意してください(最初の項は2倍になります)。

そして、分母はOEIS A081016に従います(1項シフト):

これらのそれぞれには、非常に単純な繰り返し関係があります。

そして

それぞれ。すべてをまとめると、1000桁に対して800回の反復のみが必要であることがわかります。

b,c=[16,3,1],[273,40,3]
for i in range(800):b,c=[7*b[0]-b[1]-4]+b,[7*c[0]-c[1]-1]+c
s=z=10**1000
for x,y in zip(b,c):s=(z+s)*x/y
print s

出力:

3598856662431775531720113029189271796889051337319684864955538153251303189966833836154162164567900872970453429288539133041367890171008836795913517330771190785803335503325077531875998504871797778970060395645092153758927752656733540240331694417992939346109926262579646476518686594497102165589843608814726932495910794738736733785233268774997627277579468536769185419814676687429987673820969139012177220244052081510942649349513745416672789553444707777758478025963407690748474155579104200675015203410705335285129792635242062267537568055761955669720848843854407983324292851368070827522662579751188646464096737461572387236295562053612203024635409252678424224347036310363201466298040249015578724456176000319551987905969942029178866949174808096746523682654086938399069873211752166957063859411814553647364268782462926166650100098903804823359519893146150108288726392887669917149304053057745574321561167298985617729731395370735291966884327898022165047585028091806291002444277017460241040417786069190065037142835294

(ここで、最後に、最後の4桁が正しく収束します。)

しかし、それはまだすべてではありません。sの中間値を観察すると、実際の収束点に収束する前に、それが完全に異なる値に収束していることがわかります。この理由は次のとおりです。

安定したsを解くと、次のことがわかります。

これは単純なルートであるため、ニュートン法を使用してほとんどの方法を取得し、反復のずっと後の時点にジャンプできます。必要な精度は約400桁(bcの値はそれより大きくないため)であり、メインループの320回の繰り返しを節約しながら、わずか7回の繰り返しで実現できます。

b,c=[16,3,1],[273,40,3]
for i in range(480):b,c=[7*b[0]-b[1]-4]+b,[7*c[0]-c[1]-1]+c
z=10**1000;s=z/17
for i in range(7):s-=(s*s+s*z-z*z/16)/(2*s+z)
for x,y in zip(b,c):s=(z+s)*x/y
print s

出力は以前と同じですが、ランタイムはPyPy v2.1を使用している私のシステムでは約0.02秒です。元の数の1/10の反復回数が必要ですが、非常に小さい項で乗算および除算を行うため、10倍よりも大幅に高速です。私は間違って表示されても大丈夫ですが、それ以上の調整はできないと思います。


6

Mathematica(フィボナッチが組み込まれていない32文字)

Tr[1/⌈(.5+√5/2)^Range@#/√5-.5⌉]&

ここに画像の説明を入力してください

ここではフィボナッチ数の丸め式を使用しました

ここに画像の説明を入力してください

φ黄金比はどこですか。


5

コナ(25 21)

{+/%(x(|+\)\1 1)[;1]}

おそらく専門家によって小さくすることができますが、私はまだ言語を学んでいます。

  f 10
3.341705
  f 3
2.8333
  f 25
3.359872
  f 400
3.359886

最後のものは実際には他のものよりも時間がかかりませんでした。


私はいくつかの言語でそれらの課題を完了することによって学習しています。私だけではないのは嬉しいです。

名前付き関数ではなくラムダとして関数を呼び出すだけで、2つの文字を節約できます。次に使用することによって、さらに2を救う%の逆数の関数としてではなく、やって1.%- {+/%(x(|+\)\1 1)[;1]}21文字のために
tmartin

@tmartin:奇数...私は逆数を試してみて、整数除算のために0になっていたと思いましたが、それは現在私のために働いています。回答を更新しています。ありがとうございました。
カイルKanos

正しい金額を計算していますか?たとえば、n = 4の場合、3ではなく2.833333333になります。私たちの1人は間違っています!
トビア2014年

@Tobia:0と1のインデックス付けの違い。f 0結果は1.0f 1 -> 2.0などになります。
カイルカノス2014年

4

Mathematica 30 24

ybeltukovのおかげで6文字が保存されました。

 Tr[1/Fibonacci@Range@#]&

用語を追加する前に:

1/Fibonacci@Range@#&[20]

画像1


追加が含まれています:

 Tr[1/Fibonacci@Range@#]&[20]

画像2


Fibonacciis Listable:)に削減できますTr[1/Fibonacci@Range@#]&
ybeltukov

4

APL、21文字/バイト*

{+/÷{↑+\∘⌽⍣⍵⊢0 1}¨⍳⍵}

      {+/÷{↑+\∘⌽⍣⍵⊢0 1}¨⍳⍵} 10
3.330469041
      ⍪{+/÷{↑+\∘⌽⍣⍵⊢0 1}¨⍳⍵}¨⍳10
1          
2          
2.5        
2.833333333
3.033333333
3.158333333
3.23525641 
3.282875458
3.312287223
3.330469041
      {+/÷{↑+\∘⌽⍣⍵⊢0 1}¨⍳⍵} 100
3.359885666

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
*:APLは、APLシンボルを上位128バイトの値にマップする独自の(レガシー)シングルバイト文字セットで記述できます。したがって、スコアリングの目的で、ASCII文字とAPL記号のみを使用する N文字のプログラムは、Nバイトの長さと見なすことができます。


3

JavaScript、33

入力: n = 10

s=f=t=1;for(;n--;)t+=1/(s+=f=s-f)

Perlでの最初の投稿に基づいて、ここにGoogle Chromeコンソールからの直接の結果があります

ここに画像の説明を入力してください



2

GTB、35

TI-84計算機で実行

1→Y:0→X`N4;N,1,N~1/X:Y→Z:X+Y→Y:Z→X&
  • ストア1Y0X
  • テイクN入力として
  • Forループを初期化する
  • 表示 X
  • ストアYZX+YY
  • ストアZX
  • Forループを終了する

うまくいくと思いますが、説明はありますか?

1つ追加しました。
Timtech 2014年

2

BC-116

define f(n){if(n < 2){return n;}else{return f(n-1)+f(n-2);}}
define r(n){for(i=1;i<n;++i){m=m+(1/f(i));};return m;}

解決するにはnを指定してr(n)を呼び出します。精度は任意に設定できるため、これが最も正確なソリューションです。


2

PERL、62 43

$s=$t=1;$t+=1/($a=$f+$s),$f=$s,$s=$a,for 0..<>;say $t

編集:

私のコードをもう少し見てみると、19文字節約できました。

$s=1;$t+=1/($s+=$f=$s-$f)for 0..<>;say $t+2

入力:10
> 3.35294128575734


2

フォース、64

: r 1 1 rot 1e 0 do 2dup - nip tuck + dup s>f 1/f f+ swap loop ;

使用法:

10 r f. 3.34170499581934  ok
100 r f. 3.35988566624318  ok
1000 r f. 3.35988566624318  ok

2

パイソン(55 51)

i,r=p=1,1
while i<n+1:r+=1./p[-1];p=p[1],sum(p);i+=1
r

i,r,a,b=[1]*4
while i<n+1:r+=1./b;a,b=b,b+a;i+=1
r

インタラクティブモードの場合:

n=10
3.341704995819338

n=100

3.3598856429940778

3.359885666243178

n=400

3.3598855578800064

3.359885666243178



1

C#(.NET Core)、66バイト

a=>{double r=1,x=1,y=1,i=0;for(;++i<a;y+=x,x=y-x)r+=1/y;return r;}

オンラインでお試しください!

不正確なため、フロートを使用できません。

入力= 8の例:

  • double:3.28287545787546(3.282875に丸める)
  • float:3.282876(0.000001オフ)

未ゴルフ:

a => {
    double r = 1,                       // initialize r (sum of reciprocals) - start at 1 to save one byte in for loop
            x = 1, y = 1,                   // initialize x (2nd largest Fibonacci) and y (largest Fibonacci)
            i = 0;                          // initialize i (loop counter)
    for(; ++i < a; y += x, x = y - x)   // from 1 to a, while incrementing the Fibonacci numbers
        r += 1 / y;                         // increment the reciprocal Fibonacci
    return r;                           // return the reciprocal Fibonacci
}

1

RPL(HP 49G / G + / 50g)、50バイト

« 0. 1. DUP2 5. ROLL
  START SWAP OVER + ROT OVER INV + UNROT
  NEXT DROP2
»

例:

10-> 3.33046904076

11-> 3.34170499582

30-> 3.35988372158

55-> 3.35988566622

理論的には、最初の55桁の合計は12桁の正しい数字になります。最後の数字は「2」ではなく「4」でなければなりません。これは、用語を逆に追加することで修正されますが、コードは少し長くなります。

定義を使用して定数を小数点以下1000桁で計算する場合、合計は少なくとも最初の4790項まで実行する必要があります。これは、HP 50gで可能な限り時間がかかりすぎます。このタスクには、次のRPLプログラムで使用される方法(464バイト、チェックサム#207Eh)のように、引数が小数点以下の桁数であるような、より効率的な方法が必要です。

%%HP: T(3)A(R)F(.);
\<< PUSH RAD -105 CF -3 CF R\->I DUP 1 + 2 INV SWAP 100 LN * 5 LN + OVER ASINH / \v/ * CEIL DUP 2 MOD + DUP 0 ROT
[[ 1 1 ]
 [ 1 0 ]] SWAP DUP2 ^ 3 GETI UNROT GET 4 ROLLD 4 ROLLD DUP + ^ 1 GETI UNROT GET 1 + 0 1 8 ROLL 2 /
  START PICK3 + DUP PICK3 * NEG 6 PICK SQ + / 4 PICK SQ * EXPAND ROT PICK3 - ROT OVER - ROT 6 ROLL 6 ROLL 6 ROLL + LASTARG * LASTARG 5 ROLLD 5 ROLLD / + ROT PICK3 - ROT OVER - 6 ROLL 6 ROLL 6 ROLL
  NEXT ROT + INV 5 ROLL + EXPAND 4 ROLLD 3 DROPN FXND PICK3 ALOG OVER - PICK3 * SWAP IQUOT + \->STR DUP HEAD -51 FC? { "." } { "," } IFTE + SWAP TAIL + 1 ROT 2 + SUB POP
\>>

'RFC' STO

1000 RFC->

3。3598856662431775531720113029189271796889051337319684864955538153251303189966833836154162164567900872970453429288539133041367890171008836795913517330771190785803335503325077531875998504871797778970060395645092153758927752656733540240331694417992939346109926262579646476518686594497102165589843608814726932495910794738736733785233268774997627277579468536769185419814676687429987673820969139012177220244052081510942649349513745416672789553444707777758478025963407690748474155579104200675015203410705335285129792635242062267537568055761955669720848843854407983324292851368070827522662579751188646464096737461572387236295562053612203024635409252678424224347036310363201466298040249015578724456176000319551987905969942029178866949174808096746523682654086938399069873211752166957063859411814553647364268782462926166650100098903804823359519893146150108288726392887669917149304053057745574321561167298985617729731395370735291966884327898022165047585028091806291002444277017460241040417786069190065037142835294

(22分23秒、実際のHP 50gで)


1000桁の場合、系列の最初の50項と継続分数の別の50項が評価され、一度に2つずつ、25回の反復でのみ実行されます(ただし、それぞれ48項で十分です)。私のコンピューター(Intel(R)Core(TM)Duo CPU E4700 @ 2.6 GHz)では、同等のDECIMAL BASICプログラムはわずか10ミリ秒かかります。


1

JAEL、9 7バイト

分音記号をある文字から別の文字に変更すると、1バイトが得られました

まだSBCSエンコーディングに取り組んでいます。

#`&@uȦ

説明(自動生成):

./jael -u explain '#`&@uȦ'

ORIGINAL CODE:
#`&@uȦ

EXPANDING EXPLANATION:
Ȧ => .a!

EXPANDED CODE:
#`&@u.a!

COMPLETED CODE:
#`&@u.a!,


#       ,               repeat (p1) times:
 `                              stack 1
  &                             push number of iterations of this loop
   @                            push nth fibonacci number
    u                           push p2 / p1
     .                          push the value under the tape head
      a                         push p1 + p2
       !                        write p1 to the tapehead
         ␄              print machine state

はい、あなたが正しい。私はそれを間違って数えました。
Eduardo Hoefel

言語が文字用に最適化されていることは知っていますが、このサイトはバイト単位でスコア付けするため、文字数を含めるのは誤解を招きやすい
Jo King

圧縮しない場合は8バイトを取得できますu.。SBCSのトピックでは、ドキュメントに600を超えるコマンドまたはコマンドの組み合わせがリストされているため、問題が発生する可能性があります。SBCS言語は256バイトのシングルバイトコマンドしか持つことができません。一方で、役に立たない1対1の翻訳が多数あります...
Jo King

はい@JoKing、あなたは正しいです。私は少し前にアイデア全体を始めましたが、それがバイトサイズに影響を与えるとは考えていませんでした。現在、私はJAELの上に学部論文を書いています。いくつかの決定を再考するには遅すぎます(11月末までに発表します)。コマンドリストについて:はい、それは自動的に生成され、十分な注意を払っていませんでした。これはこの分野での最初のプロジェクトなので、経験を積み、悪い決定から学ぼうとします。ご意見をお寄せいただきありがとうございます。
Eduardo Hoefel


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