通常のフィボナッチチャレンジが非常に多いため、逆フィボナッチ定数、つまりフィボナッチシーケンスの逆数の合計を計算するのは興味深いことだと判断しました。
課題は、フィボナッチ数列を使用してフィボナッチ数の逆数を計算し、入力として指定された数字を使用することです。つまり、10の入力は、最初の10フィボナッチ数の逆数に基づいて計算することを意味します。おそらく同点の場合、最短のコードが優先されます。
優勝者は、標準のコードゴルフ規則により3週間で選ばれます。
通常のフィボナッチチャレンジが非常に多いため、逆フィボナッチ定数、つまりフィボナッチシーケンスの逆数の合計を計算するのは興味深いことだと判断しました。
課題は、フィボナッチ数列を使用してフィボナッチ数の逆数を計算し、入力として指定された数字を使用することです。つまり、10の入力は、最初の10フィボナッチ数の逆数に基づいて計算することを意味します。おそらく同点の場合、最短のコードが優先されます。
優勝者は、標準のコードゴルフ規則により3週間で選ばれます。
回答:
K(19)
(または、関数としての定義をスキップする場合は17)
f:{+/*+%x(|+\)\|!2}
コナでテスト済み。
基本的に、フィボナッチ数列の最初のx値を(組み込み関数を使用せずに)配列に生成し、配列全体の各値で1を割り、転置して合計します。
(より良い合計方法を提供してくれた@tmartinに感謝)
{+/*+%x(|+\)\|!2}
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桁(bとcの値はそれより大きくないため)であり、メインループの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倍よりも大幅に高速です。私は間違って表示されても大丈夫ですが、それ以上の調整はできないと思います。
{+/%(x(|+\)\1 1)[;1]}
おそらく専門家によって小さくすることができますが、私はまだ言語を学んでいます。
f 10
3.341705
f 3
2.8333
f 25
3.359872
f 400
3.359886
最後のものは実際には他のものよりも時間がかかりませんでした。
%
の逆数の関数としてではなく、やって1.%
- {+/%(x(|+\)\1 1)[;1]}
21文字のために
f 0
結果は1.0
、f 1 -> 2.0
などになります。
{+/÷{↑+\∘⌽⍣⍵⊢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バイトの長さと見なすことができます。
入力: n = 10
s=f=t=1;for(;n--;)t+=1/(s+=f=s-f)
Perlでの最初の投稿に基づいて、ここにGoogle Chromeコンソールからの直接の結果があります。
TI-84計算機で実行
1→Y:0→X`N4;N,1,N~1/X:Y→Z:X+Y→Y:Z→X&
1
内Y
と0
でX
N
入力としてFor
ループを初期化するX
Y
内Z
とX+Y
でY
Z
でX
For
ループを終了する$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
a=>{double r=1,x=1,y=1,i=0;for(;++i<a;y+=x,x=y-x)r+=1/y;return r;}
不正確なため、フロートを使用できません。
入力= 8の例:
未ゴルフ:
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
}
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バイトが得られました
まだ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
u.
。SBCSのトピックでは、ドキュメントに600を超えるコマンドまたはコマンドの組み合わせがリストされているため、問題が発生する可能性があります。SBCS言語は256バイトのシングルバイトコマンドしか持つことができません。一方で、役に立たない1対1の翻訳が多数あります...
RÆḞİS
RÆḞİS Main link (monad). Input: integer
R Range
ÆḞ nth Fibonacci number
İ Reciprocal
S Sum
;/b$
=1:Z+Y
; The sum of the first n terms of the sequence
/ which are 1 divided by
b$ the nth term in the sequence on the second line
=1:Z+Y Fibonacci with starting indexes 1,1
φ
、組み込みの言語は確かにあります。(変更のAPLではありません)