ベースを1-2-3-Tribonacciに、バイナリをベースに戻す


19

バックグラウンド

1-2-3-Tribonacciシーケンス

標準の反復式を次の式で置き換えることにより、フィボナッチ数列を作成できることを少し想像してください。

トリボナッチ

基本的に、最後の2つを合計して次を取得する代わりに、最後の3つを合計します。これが1-2-3-Tribonacciシーケンスの基礎です。

ブラウンの基準

ブラウンの基準では、次の条件があれば、シーケンスのメンバーの合計として整数値を表すことができます。

  1. x sub nは1に等しい

  2. n1より大きいすべての場合x sub nが2未満x sub n-1

これがチャレンジにとって何を意味するか

次の初期条件によって形成される1-2-3-Tribonacciシーケンスのメンバーの合計として、正の整数を記述できます。

初期条件

これは、このシーケンスのすべての値について、用語間の比率が2より大きくなることはありません(比率は約1.839で平均化されます)。

この数値表現システムでの書き方

リトルエンディアン表現を使用するとします。シーケンスのメンバーを次のように並べます。

1  2  3  6 11 20 37 68

次に、番号を表して(テストでは63)、指定された1-2-3-Tribonacciの値を求めます(合計値は63 (最初に最大値を使用)!)。数値が合計の一部である場合、その下に1を入れ、そうでない場合は0を入れます。

1  2  3  6 11 20 37 68
0  0  0  1  0  1  1  0

任意の整数に対してこれを行うことができます-最初に特定の入力以下の最大値を使用することを確認してください!

定義(最終的に)

n1からあなたの言語の最大値の間の(標準ベースで書かれた)正の整数入力が与えられた場合、以下を実行するプログラムまたは関数を作成します。

  1. 値を定義済みの1-2-3-Tribonacciの数値表現に変換します。
  2. このバイナリのような表現を使用し、それがバイナリであるかのように読み取ります。つまり、数字は同じままですが、意味は変わります。
  3. この2進数を取得し、元の数値の基数に変換します。
  4. この新しい番号を出力または返します。

ただし、出力が有効である限り、これらの手順に従う必要はありません。短い(および数学的に同等の)数式を魔法のように見つけた場合は、自由に使用してください。

関数をf定義で記述された関数とし、[](リトルエンディアンとして、それは重要ではありませんが)実行されたステップを表します(このプロセスに従う必要はありません、これは記述されたプロセスです):

>>> f(1)
[1]
[1]
[1]
1

>>> f(5)
[5]
[0, 1, 1]
[6]
6

>>> f(63)
[63]
[0, 0, 0, 1, 0, 1, 1]
[104]
104

短い時間ではないが、問題をより迅速に解決する別のプログラムを提出できますか?log(n)+ n時間ではなく、log(log(n))+ n時間。N番目のべき乗行列に進みます。
fənɛtɪk

@LliwTelracsソリューションの投稿を止めることはできません。その解決方法をできるだけ正確に知識に基づいてターゲットにして、正しい分野で競争していることを確認してください。
アディソンクランプ

まあ、少なくともこれはしません。この行列の高速累乗は途方もなく冗長です
fənɛtɪk

2
@LliwTelracsおそらく、それを補遺として既存の投稿に追加するだけかもしれません。
ジョナサンアラン

あなたの挑戦は、画像を表示できない人には判読できません。
マインドウィン

回答:


7

Javascript 117 111バイト

5バイトのゴルフを手伝ってくれた@theonlygustiに感謝

x=>{r=0;a=[1,2,3];i=1;while(a[++i]<x)a[i+1]=a[i]+a[i-1]+a[i-2];for(;x;i--)if(x>=a[i]){r+=1<<i;x-=a[i]}return r}

使い方

最初に、関数は入力よりも大きいものが見つかるまですべてのトリボナッチ数を生成します

a=[1,2,3];i=1;for(;a[++i]<x;)a[i+1]=a[i]+a[i-1]+a[i-2];

次に、数値のリストを逆検索します。数値が入力より小さい場合、2 ^(その数値のインデックス)を戻り値に追加し、その数値だけ入力を減らします。

for(;x;i--)if(x>=a[i]){r+=1<<i;x-=a[i]}

最後に結果を返します。

オンラインで試す


1
a[++i]<xバイトを保存するためのfor条件の内部はどうですか?
theonlygusti

1
また、あなたは置き換えることができx>0x。さらに2バイトを保存します。
theonlygusti

それはかなり良いアルゴリズムです。oo
アディソンクランプ

7

パイソン2110の 102バイト

-3(ブールを鋳造するための巧妙なトリックロッドのおかげバイトiとintに+iのreprのよう`+i`作品)

n=input()
x=[3,2,1]
r=''
while x[0]<n:x=[sum(x[:3])]+x
for v in x:i=n>=v;n-=v*i;r+=`+i`
print int(r,2)

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


1
あなたは置き換えることができ'01'[i]`+i`
ロッド

iintではなくブール値です。編集-ああ+i、すっきり。
ジョナサンアラン

3
@Rod Python 2のヒントとコツでそのトリックはありますか?
アディソンクランプ

@VoteToClose私はそうは思わない
ロッド

7

JavaScript(ES6)、97 93バイト

ここではreduce()、再帰関数で使用しています。出力は31ビットであると仮定します(これは、JSがビット単位の操作で簡単に処理できる符号なしの最大量です)。

n=>[...Array(x=31)].reduce(p=>(c=(F=k=>k<4?k:F(--k)+F(--k)+F(--k))(x--))>n?p:(n-=c,p|1<<x),0)

パフォーマンスに関しては、これは明らかにあまり効率的ではありません。

好奇心のために:

  • F()N + 1 reduce()回の反復とN回の反復の呼び出し回数の比率は、トリボナッチ定数(≈1.83929)に向かって急速に収束します。したがって、出力の追加ビットごとに、前のビットの約2倍の時間がかかります。
  • 31ビットでは、F()関数は1億2400万回と呼ばれます。

テスト

注意:これは完了するまでに1〜2秒かかる場合があります。


うわー、私がそれを使用するとき、それは私のブラウザより遅れます。xD
アディソンクランプ

@VoteToCloseパフォーマンスに関しては、これはひどく非効率的です。:-)ただし、テストコードは長すぎないはずです。私の箱では、Firefoxで約600ms、Chromeで900msを取得しています。あなたの側ではずっと遅いですか?
アーナウド

たとえば、5秒。xD
アディソンクランプ

@VoteToCloseはもう少し速くなるはずです。32回目の反復は無意味であったため、出力を符号なしの31ビット整数に制限しました。
アーナルド

6

Mathematica、78 74バイト

Fold[#+##&,#~NumberDecompose~Reverse@LinearRecurrence[{1,1,1},{1,2,3},#]]&

LinearRecurrence[{1,1,1},{1,2,3},#]入力と同じ長さの1-2-3トリボナッチ数のリストを生成します。({1,1,1}は、前の3つの用語の合計を表し、{1,2,3}初期値です。)次に#~NumberDecompose~、入力をリストの要素の合計として書き込む最も貪欲な方法を見つけます(これは、金額を倍数に分解するのと同じ関数です)利用可能な通貨など)。最後にFold[#+##&,...]、結果のバイナリリストを(ベース10)整数に変換します。

以前の提出:

Fold[#+##&,#~NumberDecompose~Reverse@Array[If[#<4,#,Tr[#0/@(#-Range@3)]]&,#]]&

よくあることですが(上記ではありませんが)、このゴルフバージョンは、20を超える入力では超低速です。最終結果を#より合理的な範囲に置き換えると、Round[2Log@#+1]パフォーマンスが大幅に向上します。


なんだ?Mathematicaには123Tribonacci[]組み込み機能がありませんか?
パルシュ

1
正確ではありませんが、ビルトインを使用すると少し役立つことがわかります。
グレッグマーティン

5

Haskell、95バイト

(a!b)c=a:(b!c)(a+b+c)
e#(r,c)|c-e<0=(2*r,c)|1<2=(2*r+1,c-e)
f n=fst$foldr(#)(0,n)$take n$(1!2)3

使用例:f 63-> 104オンラインでお試しください!

仕組み:!1-2-3-Tribonacciシーケンスを作成します。与えられた123起動パラメータとして、我々は最初に取るnシーケンスの要素を。その後、我々は右の関数から倍#次の要素を減算eからn、戻り値のビットをセットしrた場合にe必要に応じて、またはビットの設定を解除することができますされています。ビットを設定することは2倍にrなり、追加1されます。


4

ゼリー、31 バイト

S=³
3RUµḣ3S;µ<³Ạµ¿µŒPÇÐfṀe@ЀµḄ

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

Jellyでこれを達成するためのもっと短い方法があることはほぼ確実です。

どうやって?

S=³ - Link 1, compare sum to input: list
S   - sum
  ³ - 3rd command line argument which is 1st program argument.
 =  - equal?

3RUµḣ3S;µ<³Ạµ¿µŒPÇÐfṀe@ЀµḄ - Main link: n
3RU                         - range(3) upended -> [3,2,1]
   µ    µ   µ¿              - while
         <³                 - less than input (vectorises)
           Ạ                - all?
    ḣ3S;                    -     head(3), sum, and concatenate
                                  [3,2,1] -> [6,3,2,1] -> [11,6,3,2,1] -> ...
              µ             - monadic chain separation, call the result x
               ŒP           - power set of x - e.g. for [6,3,2,1] -> [[],[6],[3],[2],[1],[6,3],[6,2],[6,1],[3,2],[3,1],[2,1],[6,3,2],[6,3,1],[6,2,1],[3,2,1],[6,3,2,1]]
                  Ðf        - filter keep
                 Ç          -     last link (1) as a monad (those that sum to the input)
                    Ṁ       - maximum (e.g. an input of 63 would yield [[37,20,6],[37,20,3,2,1]], the maximum of which is [37,20,6], the one with the largest numbers used)
                         µ  - monadic chain separation (to have x as the right argument below)
                     e@Ѐ   - exists in with reversed arguments mapped over x (e.g. [37,20,6] with x = [68,37,20,11,6,3,2,1] yields [0,1,1,0,1,0,0,0])
                          Ḅ - convert from binary to integer.        

4

Perl 6の93の 91バイト

b2gillsのおかげで-2バイト

{my@f=1,2,3,*+*+*...*>$^n;sum @f».&{$_~~any first *.sum==$n,@f.combinations}Z*(2 X**^∞)}

使い方

  • 最初に、入力よりも大きい最初の要素まで1-2-3-Tribonacciシーケンスを生成します。

    my @f = 1, 2, 3, *+*+* ... * > $^n;
  • それに基づいて、入力に加算されるシーケンスのサブセットを見つけます。

    first *.sum==$n, @f.combinations
  • それに基づいて、シーケンスの各要素が合計の一部であるかどうかを指定するブール値のリストを作成します。

    @f».&{$_~~any ...}
  • 最後に、True = 1、False = 0の値のリストを基数2として解釈し、(基数10)数として返します。

    sum ... Z* (2 X** ^∞)

1
あなたは使用して、それを短縮することができます*>$^nし、.sum==$n。また、スペースが間に必要とされていないmy@f
ブラッド・ギルバートはb2gills

3

JavaScript(ES6)、61 60バイト

n=>(g=(x,y,z)=>(n>x&&g(y,z,x+y+z)*2)+!(n<x||![n-=x]))(1,2,3)

元の数値に達するまで1-2-3-Tribonacciの数値を計算し、再帰が解けると、それぞれを順番に減算して、結果を2倍にします。

編集:@Arnauldのおかげで1バイト保存されました。


うわー!非常に素晴らしい。n=>(g=(x,y,z)=>(n>x&&g(y,z,x+y+z)*2)+!(n<x||![n-=x]))(1,2,3)バイトを保存できますか?
アーナウド

@Arnauld私は何かを使用して探していましたn<x||が、それ![]はただ天才です。
ニール

2

バッチ、151 148 145バイト

@set/ar=0,n=%1
@call:c 3 2 1
@echo %r%
@exit/b
:c
@set/as=%1+%2+%3
@if %n% gtr %3 call:c %s% %*
@set/ar*=2
@if %n% geq %3 set/an-=%3,r+=1

JavaScript回答のポート。編集:サブルーチンの引数を逆順に渡すことで3バイトを節約@し、各行での代わりに個々のを使用して別の3バイトを節約しました@echo off


2

ゼリー19 18 17バイト

Ḣx3+
BÇL¡2ị
²Ç€»ċ

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

バックグラウンド

整数を1,2,3-Tribonacci基数に変換してからバイナリから整数に変換する代わりに、逆に整数をバイナリに変換してから、1,2,3-Trionacci基数から整数に変換して戻ります入力に一致する最高のもの。これは簡単に実現できます。

入力63のプロセス、特に104がテストされるステップを例示します。バイナリでは、最上位桁から最下位桁まで、104は次と等しい

 1  1  0  1  0  0  0
37 20 11  6  3  2  1

2番目の行は、これらの数字の位置の値を表します。

追加された数字が同じ再帰式に準拠していることを確認して、1,2,3-Tribonacciシーケンスを右に拡張できます。3 mre桁の場合、これにより

 1  1  0  1  0  0  0  0  0  0
37 20 11  6  3  2  1  0  1  0

ここで、ベース1,2,3-Tribonacci数の値を計算するために、再帰式を使用できます。各数値はその右側の3つの数値の合計であるため(上​​の表)、最初の数字を削除して、残りの配列の最初の3桁に追加できます。104の2進数の数に等しい7ステップの後、3桁しか残っていないことはまれです。

 1  1  0  1  0  0  0  0  0  0
37 20 11  6  3  2  1  0  1  0

    2  1  2  0  0  0  0  0  0
   20 11  6  3  2  1  0  1  0

       3  4  2  0  0  0  0  0
      11  6  3  2  1  0  1  0

          7  5  3  0  0  0  0
          6  3  2  1  0  1  0

            12 10  7  0  0  0
             3  2  1  0  1  0

               22 19 12  0  0
                2  1  0  1  0

                  41 34 22  0
                   1  0  1  0

                     75 63 41
                      0  1  0

現在、最初と最後の残りの数字は両方とも位置値0であるため、結果は中央の数字、つまり63です。

使い方

²Ç€»ċ   Main link. Argument: n

²       Yield n². Since 1.839² = 3.381921 > 2, the range [1, ..., n²] will contain
        the answer. Better bounds, at the cost of additional bytes are possible.
 Ç€     Map the the second helper link over [1, ..., n²].
   »    Take the maximum of n and each result.
    ċ   Count the occurrences of n.


BÇL¡2ị  Second helper link. Left argument: k. Right argument: n

B       Convert k to binary. Let's call the result A.
  L     Length; count the number of binary digits. Let's call the result l.
 Ç ¡    Apply the first helper link l times to A.
    2ị  Retrieve the second element.


Ḣ×3+    First helper link. Argument: A (array)

Ḣ       Head; pop and yield the first element of A.
 x3     Repeat it thrice.
   +    Add the result, component by component, to the beheaded A.

2

ゼリー(fork)、17 16バイト

ḣ3S;µ¡
3RṚdzæFṪḄ

実行さえせずにゴルフをしてくれた@Dennisに感謝します。

これは、Jellyのフォークに依存しています。ここでは、残念ながら効率的なFrobeniusソルバアトムの実装に取り​​組んでいます。興味がある人のために、私はMathematicaの速度に合わせたいと思います。FrobeniusSolve幸運なことに、ダニエル・リヒトブロウの論文「変化を起こし、レフィギットを見つける:ナップザックのバランス調整」でその方法の説明があります。

説明

ḣ3S;µ¡  Helper link. Input: a list
    µ   Create monadic chain
ḣ3        Take the first 3 items
  S       Sum
   ;      Prepend to the list
     ¡  Repeat it n (initial argument from main) times

3RṚdzæFṪḄ  Main link. Input: integer n
3          The constant 3
 R         Range. Makes [1, 2, 3]
  Ṛ        Reverse. Makes [3, 2, 1]
   Ç       Call the helper link on that list.
           Generates the first (n+3) 123-Tribonacci values in reverse
    ³      Get n
     æF    Frobenius solve for n using the first n 123-Tribonacci values in reverse
       Ṫ   Tail. Take the last value. The results of Frobenius solve are ordered
           where the last result uses the least
        Ḅ  Unbinary. Convert digits from base 2 to base 10

3
スーパーエソランのフォークを使用しているとき、コードゴルフの奥深くにいることを知っています。
アディソンクランプ

だろうḣ3S;µ¡¶3RṚdzæFṪḄ動作しますか?フォークがインストールされていないため、テストできません。
デニス

@Dennisそれは、引数ではなく標準入力から入力を取得しているのですか?引数の使用に問題があり、それが他の方法で機能していることに気付きました。
マイル

いいえ、それはまだ引数である必要があります。³最初の引数を参照します。
デニス

@Dennis Nvm、それは引数によって動作します、私のjelly.py最後のコミット後に他のいくつかのものがありました。
マイル

1

dc110 102バイト

?se1sa2sb3sc_1sf[laddSdlbdsalcdsb++sclf1+sfle>y]dsyx0sk[lk2lf^+skler-se]sr[Lddle!<rlf1-dsf0!>z]dszxlkp

まあ、偉大な心同じように考えているようだ。どうやら、制限を回避するために思いついたアルゴリズムdcは、偶然にも@LliwTelracの答えで使用されたものとまったく同じものです。面白い。

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



1

bash + BSDユーティリティ(OS Xなど)、53バイト

jot $[2#$1**4]|egrep -v '[2-9]|11(1|$)'|sed $[2#$1]!d

bash + GNUユーティリティ(BSDでも動作)、59バイト

seq -f2o%.fp $[2#$1**2]|dc|egrep -v '11(1|$)'|sed $[2#$1]!d

上記の両方の入力と出力はバイナリです。


TIOでGNUバージョンを試してください。 (リンク先の例は、111111の入力(バイナリで63)、および1101000の出力(バイナリで104)を示しています。)

TIOがBSDオプションを提供しているとは思いませんが、Macを利用できる場合は、両方を試してみることができます。(59バイトのプログラムは、53バ​​イトのプログラムよりもはるかに高速です。)


残念ながら、seq単にの代わりに、BSD溶液にドロップすることができないjotため、出力フォーマットするので、seq。999999を超える出力はが異なるためです(32 ^ 4> 1000000以降、32前後の入力では問題になります)。

jot上記をseq -f%.fGNUユーティリティで動作するように置き換えることができますが、同じ59バイトに対して、上記のGNUソリューションを使用できます。これははるかに高速です。

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