月曜日のミニゴルフ#1:逆フィボナッチソルバー


28

月曜日のミニゴルフ:毎週月曜日に(願わくば!)投稿された一連の短いチャレンジ。

A フィボナッチ様配列は、有名なのと同じ方法を用いて得られるフィボナッチ数列。つまり、各数値F(n)は、シーケンス内の前の2つの数値を加算する(F(n)= F(n-1)+ F(n-2))か、次の2つの数値を減算する(F (n)= F(n + 2)-F(n + 1))。主な違いは、これらのシーケンスは任意の2つの数字で開始できることです。これらのシーケンスのゼロインデックス付けは議論の余地がありますが、今のところ、このルールを使用します。

  • フィボナッチ数列の0番目の数字は、直前の数字よりも小さい最後の数字です。

例として、フィボナッチ数列はとして書くことができる1, 0, 1, 1, 2, 3, 5...ので、数列の0番目の数字はlone 0です。

チャレンジ

チャレンジの目標は、3つの整数を任意の形式で取り込むプログラムまたは関数を作成することです。

  • AおよびB、シーケンスの生成を開始する2つの数値。
  • N、出力する結果シーケンスの長さ。

そして、0番目から始まるシーケンスの最初のN個の数値を出力します。

詳細

  • AB、およびNは、視覚的に分離されている限り、任意の順序および形式で使用できます。別の順序/形式を使用する場合は、それが何であるかを指定してください。
  • AB、およびNは常に正の整数であると想定できます。
  • Nは100以下であり、結果のシーケンスにはが含まれないと想定できますx >= 2^31
  • 場合Aがより大きいB、次いでBは、シーケンス内の0番目の数です。
  • 出力は、スペース、コンマ、改行で区切る必要があります。
  • 末尾のスペースまたは改行は使用できますが、末尾のコンマは使用できません

テストケース

例1:

8 13 10

8 13前よりも大きい数が見つかるまで逆方向に作業すると、が得られ13 8 5 3 2 1 1 0 1ます。したがって、0このシーケンスの0番目の数値です。これから前進し0て、次の9人のメンバーを印刷します。

0 1 1 2 3 5 8 13 21 34

例2:

23 37 5

再び後方に移動して0番目の数を見つけます37 23 14 9 5 4 1 3。今回の0番目の数字は1ですので、次の4つのメンバーとともに出力します。

1 4 5 9 14

例3:

4 3 8

ので、この1で、我々は、0番目の番号を見つけるために、逆方向に働くことはありません3よりも小さくなっています4

3 7 10 17 27 44 71 115

例4:

29 47 11

結果:

1 3 4 7 11 18 29 47 76 123 199

得点

これはであるため、バイト単位の最短有効コードが優先されます。Tiebreakerは以前に投稿された投稿に移動します。勝者は9月28日の次の月曜日に選ばれます。頑張ってください!

編集:勝者の@Jakube、おめでとう、Pythを使って23バイトを驚かせてください


10
作成した[monday-mini-golf]タグを削除しました。多かれ少なかれ任意の課題グループに対してタグを作成する必要はないと思います。タグは実際にチャレンジについて何も伝えません。これらすべてを見つけたい場合は、検索バーでフレーズを検索するだけです。または、今後のすべてのインストールにこの最初のチャレンジへのリンクを含めると、それらはすべてサイドバーの「リンクされた質問」の下にリンクされます。
マーティンエンダー

@MartinBüttnerOK、ありがとう。ちゃんと覚えておきますよ。
ETHproductions

私が望むように入力を取ることができますか(Pythonリストリテラル[8, 13, 10])?
ブルー

3
現在の課題は、プログラムを書くことです。機能が許可されていないということですか?(CC @LuisMendo)
デニス

3
@デニス申し訳ありませんが、私の心を滑らせました。関数も使用できます。それを指摘してくれてありがとう!
-ETHproductions

回答:


12

Pyth、23バイト

AQWgHGA,-HGG)VvwHA,H+GH

オンラインで試す:デモンストレーションまたはテストスイート

Pythプログラミングの非常に珍しいスタイル。関数型プログラミングには欠点がある場合があります。

説明:

AQWgHGA,-HGG)VvwHA,H+GH  Q = input list of the two starting numbers
AQ                       G, H = Q (unpacking Q)
  WgHG                   while H >= G:
      A,-HGG                G, H = [H - G, G]
            )            end while
              vw         read a number from input
             V           for N in range(^):
                H           print H
                 A,H+GH     G, H = [H, G + H]

12

網膜65 54バイト

+`(1*),\1(1*)
$2,$1
+`(1*)(,1*);1\B
$1$2$2$1;
^1*,|;1
<empty>

ここで<empty>は、空の末尾の行を表します。-sフラグ付きの単一ファイルとしてコードを実行します。

入力形式は

A,B;N

ここで、数値は単項で表されます。出力はカンマ区切りのリストであり、単項です。例えば:

8 13 10

だろう

11111111,1111111111111;1111111111

と収量

,1,1,11,111,11111,11111111,1111111111111,111111111111111111111,1111111111111111111111111111111111

説明

+`(1*),\1(1*)
$2,$1

まず、我々は削減Aし、B0番目と-1の要素に。+いずれかの正規表現がマッチを停止または置換は文字列を変更しなくなるまで、この正規表現置換を繰り返し続けるために網膜を伝えます。正規表現のキャプチャAを持つグループ1に(1*)続いて、ことを確認しB、少なくとも同じくらい大きいようですAキャプチャ中B-A\1(1*)一度、このループが終了することをグループ2にこの性を保証しますA>B

置換は、単になりA,BB-A,Aに試合を設定することによって$2,$1

+`(1*)(,1*);1\B
$1$2$2$1;

これで、文字列に必要な出力の最初の番号が既にあります(その前の出力も同様です。後で削除する必要があります)。この置換により、1from を取得しながら、最後の2つの数値の合計として別の数値が追加されNます。すでに1つの番号があるので、これを発生させたいだけN-1です。これを行う\Bには、少なくとも;11文字列の最後にあることを確認します。シーケンスCとの最後の2つの値を呼び出すとD、正規表現はCグループ1と,Dグループ2にキャプチャします。それらをで書き戻し$1$2ます。次に、に$2$1変換するを書き,D+Cます。マッチしたシングルは書き戻さないことに注意してください1N、それにより減少します。

^1*,|;1
<empty>

最後に、シーケンスの-1番目の要素と、残りの;1from を削除する必要があります。これらの要素のNいずれかを一致させ、空の文字列で置き換えるだけです。


7

Python 2、93 87 67 61 60バイト

i,j,l=input()
while j/i:i,j=j-i,i
exec"i,j=j,i+j;print i;"*l

入力を取得します(リテラルPythonリストとして[8,10,13]

0期目

次に、長さに達するまで追加のシーケンスを出力します


1
いい方法。インデックスレスループのためにfor _ in[1]*l:、それはやって少し短いですexec"stuff;"*l
XNOR

@xnor:私にはかなり長く見えます。
再帰的

と比較for _ in[1]*l:stuffしてくださいexec"stuff;"*l。@xnorはforループのスタッフ部分を入れませんでした。またはfor _ in[1]*l:exec";"*l
ブルー

2
あなたは置き換えることができj>=ij/i。ちょうどそれを見つけました!(A、B、およびNは常に正の整数であると仮定することができるため)
mbomb007

6

CJam、26 23バイト

3バイトを節約してくれたDennisに感謝します。

q~{_@\-_g)}g\@{_@+_p}*t

入力を順番に受け取りますN B A(任意の種類の空白で区切られます)。結果を改行で区切られたリストとして出力し、エラーで終了します

ここでテストしてください。

説明

0番目の要素を見つけるとき、これはさらに一歩進みます。つまり、値の1つが負になると終了します。

q~      e# Read and evaluate input, pushing N, B and A on the stack.
{       e# do while...
  _@\-  e#   B, A = A, B-A
  _W>   e#   Check if A is still non-negative.
}g
\@      e# Reorder N B A into A B N.
{       e# Run the following N times...
  _@+   e#   A, B = B, A+B
  _p    e#   Print B.
}*
t       e# The last A, B are still on the stack. We remove them by trying to
        e# execute a ternary operator: it pops the first two values but then
        e# terminates the program with an error, because there is no third value.

q~{_@\-_g)}g\@{_@+_p}*tN B A)は3バイトを節約します。
デニス

CJamでこれを自分で解決しようとしていたときに、例1からの入力に問題がありました。今、この解決策でも期待される出力が得られないことがわかります。ここの欠陥はどこにありますか?私はB>Aそれをチェックする代わりにB not smaller than A何かをチェックする必要があると思いますが、CJamでそれを行う方法を理解することはできません。編集:デニスのソリューションは正しい出力を印刷します。
Cabbie407

まあ、私は自分のソリューションでそれを解決しました。
Cabbie407

@ Cabbie407あなたは正しい、私は<!代わりに使用する必要があり>ます。
マーティンエンダー

あ、そう。これをどこに置けばいいのか疑問に思い!ました。私は単にそれを機能させるために追加しました;)
Cabbie407

5

ラビリンス58 54 49 46 44バイト

2バイトを節約したビットごとの否定の使用を提案してくれたSp3000に感謝します。

??#"{=
  ;  -
@"~~:}
~""
?
"}}:=
(   +
{{\!:

入力形式はB A Nです。出力は、改行で区切られたリストです。

説明

(少し時代遅れ。基本的な考え方は同じですが、コードのレイアウトは今では異なります。)

これは私のCJamの答えと同じ考え方を使用します(したがって、クレジットはデニスに送られます)。次に、最初の値を出力する前にそれらの追加を開始します。

これは、いくつかの気の利いたラビリンスゴルフトリックを使用します。セクションのコードを見てみましょう。

?"
}

IPは?右に向かって開始します(読み取りA)。で"、それは行き止まりに当たる(ノー・オペレーション)、ので、実行、回る?(読んで再びB)。最後に、補助スタックに}移動Bします。行き止まりはナイーブよりもバイトを節約します

?
?
}

シーケンスの始まりを見つけるループ:

)(:{
"  -
" "`?...
=}""

)((インクリメント、デクリメント)は何もしませんが、それはスタックのトップが(IP東点灯するように)接合部に正であることを保証するために必要です。:複製A{移動B、バックメインスタックに、-計算しますA-BB-Aしかし、私たちが本当に欲しいのは`その値を否定します。

これは現在、4方向ジャンクションです。否定的な結果の場合、IPはに向かって左折し、プログラムの次の部分を?読んNで移動します。結果がゼロの場合、IPは南に移動し続け、角を曲がり、ループ内に残ります。結果が正の場合、IPは右折(西)して角を曲がり、さらに右折(再び西)してループ内に残ります。これは、負の値と負の値(または正の値と非正の値)を区別するための一般的なパターンになると思います。

                v
                "
               """>negative
non-negative <"""

少なくとも、このケースのよりコンパクトで便利なレイアウトを見つけることができませんでした。

とにかく、A負でない間、ループは継続し、補助スタックに}移動Aしておよびを=スワップABます。

一度A負になると、?読み取りN、2番目のループに移動します。

 }:=+:
 }   !
?"({{\

Nこれはポジティブであることがわかっているため、IPが左折(北)することに頼ることができます。ループ本体は単純になりました:

}}:=+:!\{{(

つまり、両方NA補助スタックに移動します。複製しB、コピーをに交換して、の別のコピーにA追加AしますB。再度複製して、現在の値を出力しBます。改行を印刷します。メインスタックに移動BしてN戻り、デクリメントしますN

一方でN正である、IPが右折(北)のループを続けるがかかります。一度Nに達するが、ゼロではなく、空想の方法でコードを終了します:

IPは直進(西)し続けます。?別の整数を読み取ろうとするが、それは実際にプッシュするように、我々はすでに、EOFに達した0代わりに。`それを否定しようとしますが、それはまだゼロです。そのため、IPは引き続き西に移動し、角を曲がり、さらに下に移動し続け@てプログラムを終了します。

私は置くことができるのだろうか@さえ安いの位置に3を回して(それは現在3つの空白文字がかかります)"周りの`化合物への無OPS(のような)()が、私はまだその仕事をすることができませんでした。


5

C、105の 102 100バイト

main(a,b,n,t){for(scanf("%d%d%d",&a,&b,&n);t=b-a,t>=0;a=t)b=a;for(;n--;b=t)t=a+b,printf("%d ",a=b);}

2バイトのゴルフをしてくれた@ C0deH4ckerに感謝します!

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


4

MATLAB /オクターブ、115の125バイト

function x=f(x,n)
while x(2)>=x(1)
x=[abs(x(1)-x(2)) x];end
x=x([2 1]);for k=1:n-1
x=[x(1)+x(2) x];end
x=x(n:-1:1);

関数はとして呼び出す必要がありますf([8 13],10)

例(Matlab):

>> f([8 13],10)
ans =
     0     1     1     2     3     5     8    13    21    34

または、オンライン(Octave)で試してください


ルールに従って、入力を変更できるため、f([a b],n)許可する必要があります。
ビーカー

@beakerありがとう!私はそれをしようとしていました...しかし、「入力と出力はスペース、コンマ、または改行で区切られる可能性がある」というルールを読んで混乱しました。説明をお願いします
ルイスメンドー

ええ、x=f(x,n)関数のヘッダーがカウントされているかどうかはわかりません
...-ビーカー

@AlexA。「入力と出力はスペース、コンマ、または改行で区切ることができます」というルールに関するルイスのコメントに応答し、OPの「A、B、およびNは、それらがあれば、任意の順序と形式で使用できます。目に見えて分離されました。」関数ヘッダーでAとBが目に見えて分離されなくなったため、2つの関数引数のみを使用できるかどうかを疑問視していました。
ビーカー

3

Haskell、67 65 56バイト

a#b|a>b=b:scanl(+)(a+b)(a#b)|1>0=(b-a)#a
n%a=take n.(a#)

提案してくれた@nimiに感謝

これは、たとえば次の%形式(n%a)bで呼び出される三項中置関数を定義します。

> (10%8)13
[0,1,1,2,3,5,8,13,21,34]

説明

#最初の行で定義されているバイナリ挿入関数は、2つの整数aを受け取りb、無限フィボナッチのようなシーケンスを返します。ab連続した要素として生じます。

a#b                                       -- Define a#b:
   |a>b=                                  -- if a>b, then a#b is
        b:                                -- the sequence that starts with b and
          scanl(+)     (a#b)              -- continues with the sums of prefixes of a#b
                  (a+b)                   -- plus the additional term a+b;
                            |1>0=(b-a)#a  -- otherwise, it's (b-a)#a.

関数は%単にの最初のn要素を取りますa#b


let f=a:scanl(+)(a+b)f in f(-> full #:でフィボナッチ数列を作成し、a#b|a>b=let f=a:scanl(+)(a+b)f in f|1>0=(b-a)#a2バイトを保存します。
nimi15年

@nimiありがとう。私はあなたのアイデアで走り、合計9バイトを節約しました。
ズガルブ

3

> <>、- v = 32バイトの場合は33 31 + 1

&:{:@(?v:}-$&
-1;!?:&<$+{oan::$&

10進数の解析は> <>で自明ではないため、入力は-vを使用してスタックにプッシュする必要があります。

説明 :

各(グループの)操作後のスタックを表します。[F(n)、F(n + 1)、N]で始まります

最初の行は、セリエをその第0項まで下げます。

& removes N from the stack to put it into a register. [F(n), F(n+1)]
:{:@ move the stack and duplicate items to get [F(n+1), F(n), F(n+1), F(n)]
(?v compares the two top items of the stack and branch to the second line if F(n+1) < F(n) [F(n+1), F(n)]
:} move the stack and duplicate its top to get [F(n), F(n+1), F(n)]
- substracts the two top items and put the result on top of the stack [F(n), F(n+1) - F(n)]
$ switchs the top two values of the stack. [F(n+1) - F(n), F(n)]
& retrieve the value from the register. iteration complete, since [F(n+1) - F(n), F(n), N] can also be read as [F(n-1), F(n), N]

2行目は、N個の用語を出力するまで、セリエを上に移動します。

< changes the code pointer direction to the left [F(0), F(-1)]
& retrieves the stored value back from the stack [F(0), F(-1), N]
:?!; copies N to compare it to 0, stops if it is [F(0), F(-1), N]
1- decreases it [F(0), F(-1), N-1]
& stores it back [F(0), F(-1)]
$:: makes the stack [F(-1), F(0), F(0), F(0)]
n{ prints the top of the stack then left shifts it [F(0), F(0), F(-1)]
ao displays a line feed (ascii character 0x0a) [F(0), F(0), F(-1)]
+ adds the two top values [F(0), F(-1) + F(0)]
$ switch the two top values. iteration complete since [F(-1) + F(0), F(0)] which can be read as [F(1), F(0)]

00.最初の行をに変更することにより、バイト数を2減らすことができるはず&です。理論的に!は動作するはずですが、行の幅を最も長いものの幅に合わせて> <>で埋めると思います(編集:00.そもそもあなたが持っていたと思う理由です)。
コール

ええ、私はそれについてあまり知りません、私はここの人々が使用するのを見ました!スペースを無視する方法で。fishlanguage.comのオンラインインタープリターがそのように機能しないことは知っていますが、Pythonインタープリターはおそらく機能します。とにかくうまくやる、ありがとう!
アーロン

オンラインインタープリターは、!または?(行の最後で)最長の行にある場合に動作します。のようなものを試してみると1n!エラーになりますが、下にそれよりも長いものがある場合(のように)はエラーlorumipsumになりません。
コール

「出力はスペース、カンマ、改行で区切る必要があります。」申し訳ありませんが、他のバージョンを使用する必要があります。いい仕事だ!
-ETHproductions

それを修正し、スペースの代わりに\ nを使用して2バイトを節約しました
アーロン

2

Java、113 78 76バイト

この回答で使用したアルゴリズムを提供した功績はETHproductionにあります。

(a,b,n)->{for(;a<=b;b-=a)a=b-a;for(;n-->0;b+=a,a=b-a)System.out.println(b);}

こちらをお試しください

説明:

(a,b,n)->{
    for (;a<=b;b=b-a)a=b-a;  //Compute previous terms while a <= b
    for (;n-->0;b=a+b,a=b-a) //Compute and print next terms while n > 0
    System.out.println(b);   //Print term
}

元のアプローチ、113 93バイト

よりゴルフらしい;)

String a(int a,int b,int n){return n<0?a+" "+a(b,a+b,n+1):n>0?a>b?a(b,a+b,-n):a(b-a,a,n):"";}

ここで試してみてください

説明:

String a(int a, int b, int n){
    return 
    n < 0 ?                           //If n < 0
        a + " " + a(b, a + b, n + 1)  //Return a + next terms and increment n.
    :                                 //Else
        n > 0 ?                       //If n > 0
            a > b ?                   //If a > b
                a(b, a + b, -n)       //Negate n and return terms.
            :                         //If a <= b
                a(b - a, a, n)        //Generate previous term.
        :                             //If n == 0
            ""                        //Return nothing.
    ;
}

3
何?JavaはJSより短い?!?そこのお奨めは、私が間違ってやっている何か....も
ETHproductions

@ETHproductions私は実際にあなたのアルゴリズムをコピーしました(そしてそれをゴルフしました):P
TheNumberOne

私はそれでいいです、私はあなたの改善のいくつかを取りました;)私は各アイテムを別々に印刷するのを忘れていましたJSで有効でした。
ETHproductions

あなたは短縮することができますb=b-ab-=a、そして同じa=b+a。2バイトを節約します
ハビエル・ディアス

冗長な言語の提出を非常に短くするための+1。通常、Javaの提出は最長です!
DankMemes

2

Javascript(ES6)、83 73 63バイト

これは最大限にゴルフされたかもしれません。表示します。

(a,b,n)=>{while(a<=b)b-=a=b-a;for(;n--;console.log(a=b-a))b+=a}

ゴルフをしていない:

function f(a,b,n) {
  // repeat until we find the 0th item...
  while (a <= b) {  // if a = 5, b = 8:
    a = b - a;      // a = (8 - 5) = 3
    b = b - a;      // b = (8 - 3) = 5
  }
  // repeat n times...
  while (n-- > 0) { // if a = 5, b = 8:
    b += a;         // b = (8 + 5) = 13
    a = b - a;      // a = (13 - 5) = 8
    console.log(a); // print out each item
  }
}

1

Mathematica 112

最終的にゴルフします

z[a_, b_, n_] := (
  f[0] := Min[a, b];
  f[1] := Max[a, b];
  f[x_] := f[x - 1] + f[x - 2];
  f /@ Range[n]
  )

1

CJam、40バイト

l~:A;{_@_@)<}{_@\-\}w\{A(:A0>}{_p_@+}w\;

赤ちゃんのステップ。これは私の最初のCJamプログラムであるため、このプログラムが機能することを誇りに思っています。

例と同じ形式で入力を受け取ります。

これで、{ ... }*コンストラクトを使用して33バイトに削減できることがわかりました。

l~:A;{_@_@)<}{_@-z\}w\A{_p_@+}*;;

そして、三項演算子を使用してスタックをクリーンアップし、エラーを生成することで、さらに1つ減らすこともできます。


1

Ruby、141バイト

def u a,b,n,z=""
n<1 ? z.chop : u(b,a+b,n-1,z+"#{a} ")
end 
def d a,b,z=0
a.abs>b ? z : d(b-a,a,[a,b]) 
end 
def f a,b,n
x,y=d a,b 
u x,y,n
end 

実行

f関数は目的の出力を生成し、引数名は質問の変数名と一致します

f(8,13,10) # returns => "0 1 1 2 3 5 8 13 21 34"

賢いものは何もありません:

  • u(up)関数は、再帰を使用してa、bで始まるフィボナッチ数列のn個の要素を計算します
  • d(down)関数は、再帰を使用して2つの終了要素を指定して、0番目と1番目の要素を見つけます
  • f(fibonacci)関数は2つをまとめます


0

ルビー、81 75 73

a,b,n=23,37,5;while(c=b-a)<a;b,a=a,c;end;p a;[*2..n].map{b=c+a;c,a=a,b;p b}

for-loopをrange.mapに置き換えると6バイト短縮されます。

a,b,n=23,37,5;while(c=b-a)<a;b,a=a,c;end;p a;[*2..n].map{p b=c+a;c,a=a,b}

printステートメントを移動してさらに2バイトを保存しました




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