最短加算チェーン


23

加算チェーンは、1から始まる整数のシーケンスで、最初の1以外のすべての整数は、2つの前の整数の合計です。

たとえば、追加チェーンは次のとおりです。

[1, 2, 3, 4, 7, 8, 16, 32, 39, 71]

加算チェーンにする合計は次のとおりです。

1 + 1 = 2
1 + 2 = 3
1 + 3 = 4
3 + 4 = 7
1 + 7 = 8
8 + 8 = 16
16 + 16 = 32
7 + 32 = 39
32 + 39 = 71

このチャレンジでは、正の整数が与えられ、nで終わる最短の加算チェーンの1つを出力する必要がありますn

例-多くの可能な出力があることに注意してください、あなたが見つけるために必要なのは、同じくらい短い追加チェーンです:

1: [1]
2: [1, 2]
3: [1, 2, 3]
4: [1, 2, 4]
5: [1, 2, 3, 5]
6: [1, 2, 3, 6]
7: [1, 2, 3, 4, 7]
11: [1, 2, 3, 4, 7, 11]
15: [1, 2, 3, 5, 10, 15]
19: [1, 2, 3, 4, 8, 11, 19]
29: [1, 2, 3, 4, 7, 11, 18, 29]
47: [1, 2, 3, 4, 7, 10, 20, 27, 47]
71: [1, 2, 3, 4, 7, 8, 16, 32, 39, 71]

標準I / Oルールなど。標準の抜け穴は禁止されています。コードゴルフ:最少バイト数が勝ちます。




1
チェーンを逆順で出力することはできますか?
アーナウド

@Arnauldいいえ、この特定の順序。
isaacg

回答:


6

Haskell、57バイト

c=[1]:[x++[a+b]|x<-c,a<-x,b<-x]
f n=[x|x<-c,last x==n]!!0

ブルートフォースソリューション。 オンラインでお試しください!

説明

無限リストにcは、すべての追加チェーンが長さ順に並べられています。リストxからcと2つの要素を取り、xそれらの合計をに追加することにより、それ自体に関して帰納的に定義されxます。関数fは、c目的の番号で終わる最初のリストを見つけます。

c=            -- c is the list of lists
 [1]:         -- containing [1] and
 [x           -- each list x
  ++[a+b]     -- extended with a+b
 |x<-c,       -- where x is drawn from c,
  a<-x,       -- a is drawn from x and
  b<-x]       -- b is drawn from x.
f n=          -- f on input n is:
 [x           -- take list of those lists x
 |x<-c,       -- where x is drawn from c and
  last x==n]  -- x ends with n,
 !!0          -- return its first element.

4

Brachylog、14バイト

∧≜;1{j⊇Ċ+}ᵃ⁽?∋

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

反復的深化を使用して可能なすべての追加チェーンを構築し、正しい引数を含むチェーンが見つかったときに停止するブルートフォースサブミッション。ほとんどのBrachylogサブミッションとは異なり、これは、右引数(従来は出力と呼ばれる)を介して入力し、左引数(従来は入力と呼ばれる)を介して出力する関数サブミッションです。これを行うことは幾分議論の余地がありますが、主題に関する最高の投票のメタの答えはそれが合法であると言います(そしてそうすることは関数の通常のI / Oデフォルトと一致します)。入力と出力をより一般的な方法で使用した場合、これは16バイト(∧≜;1{j⊇Ċ+}ᵃ⁽.∋?∧)、プログラムの右側では暗黙的な制約を使用できないため(2バイトのコストで、無効にした新しい明示的な制約を指定する必要があります)。

説明

∧≜;1{j⊇Ċ+}ᵃ⁽?∋
∧               Disable implicit constraint to read the left argument
 ≜;        ⁽    Evaluation order hint: minimize number of iterations
    {    }ᵃ     Repeatedly run the following:
   1      ᵃ       From {1 on the first iteration, results seen so far otherwise}
     j            Make {two} copies of each list element
      ⊇           Find a subset of the elements
       Ċ          which has size 2
        +         and which sums to {the new result for the next iteration}
             ∋    If the list of results seen so far contains {the right argument}
            ?     Output it via the left argument {then terminate}

ここで興味深い微妙な点は、最初の反復で起こることです。入力は、他の反復のようなリストではなく数値です。数字の1から始めて、すべての数字の2つのコピーを作成し(数字11を作成)、その数字の2桁のサブシーケンス(数字11も)を見つけます。次に、その数字の合計(2)を取得します。そのため、シーケンス[1,2]は希望どおりに開始されます。将来の反復では、我々のようなリストを開始している[1,2]にそれを倍増、[1,2,1,2](2つの要素のサブシーケンスを取って、[1,1][1,2][2,1]、または[2,2])。明らかに、これらのそれぞれの合計は、加算チェーンの有効な次の要素になります。

ここでは、評価順序のヒント、特にコンポーネント(ここでは、デフォルトでは外部からはなく内部から評価順序のヒントを取得するように見えるため、問題を強制するためにかなり粗雑な使用が必要です)が少しイライラします。


私はこの挑戦をするための短い方法を見つけるために約30分間試みました。私の解決策はこれよりずっと長かった。
致命的

1
@Fatalize:めったに表示されないビルトインの1つですが、他の制御構造を使用して簡単に実装する方法がないため、必要な場合は本当に必要です。これが挑戦だと気づいたら、残りはそこからかなり直接やって来ました。

2

ゼリー、17バイト

’ŒP;€µ+þ;1Fḟ@µÐḟḢ

指数時間で辞書式に最初の解を出力します。

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

使い方

’ŒP;€µ+þ;1Fḟ@µÐḟḢ  Main link. Argument: n (integer)

’                  Decrement; n-1.
 ŒP                Powerset; generate all subarrays of [1, ..., n-1], sorted first
                   by length, then lexicographically.
   ;€              Append n to all generate subarrays.
     µ       µÐḟ   Filterfalse; keep only subarrays for which the chain between the
                   two chain separators (µ) returns a falsy value.
     µ             Monadic chain. Argument: A (array of integers)
      +þ               Add table; compute the sums of all pairs of elements in x,
                       grouping the results by the right addend.
        ;1             Append 1 to the resulting 2D array.
          F            Flatten the result.
           ḟ@          Filterfalse swapped; remove all elements of A that appear in
                       the result. This yields an empty list for addition chains.
                Ḣ  Head; select the first result.

2

JavaScript(ES6)、83 86バイト

編集:リストを非逆順で出力するように修正

n=>(g=(s,a=[1])=>s-n?s>n||a.map(v=>g(v+=s,a.concat(v))):r=1/r|r[a.length]?a:r)(r=1)&&r

デモ


2

PHP、195バイト

function p($a){global$argn,$r;if(!$r||$a<$r)if(end($a)==$argn)$r=$a;else foreach($a as$x)foreach($a as$y)in_array($w=$x+$y,$a)||$w>$argn||$w<=max($a)?:p(array_merge($a,[$w]));}p([1]);print_r($r);

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


残念ながら、このアルゴリズムでは最適な答えが得られません。たとえば、15。-
ニール

@Neilは現在より長くなっていますが、動作します。どちらの方法が正しいかを判断する方法は、現時点ではわかりません。おそらく素数のカウントが役割を果たしている
ヨルクヒュルサーマン

このコードは149テストに合格しません。長さは11ではなく10
J42161217

@Jenny_mathy修正済み
ヨルクヒュルサーマン

1

Mathematica、140バイト

t={};s={1};(Do[While[Last@s!=#,s={1};While[Last@s<#,AppendTo[s,RandomChoice@s+Last@s]]];t~AppendTo~s;s={1},10^4];First@SortBy[t,Length@#&])&

実行するたびに異なる最短加算チェーンを生成します

オンラインで試す
ctrl + vでコードを貼り付け、コードの最後に入力(例:[71])を置き、shift + enterを押す


私はMathematicaにアクセスできないので、15の入力に対してどのくらいの長さのチェーンを与えますか?
ニール

正しいもの{
1、2、3、5、10、15

3
入力149について、プログラムから長さ11のチェーンを取得しましたが、長さ10([1,2,4,5,9,18,36,72,77,149])のチェーンが存在します。あなたのプログラムはランダムサンプリングを使用しており、最適なソリューションを見つけることを保証されていないようです。
-Zgarb

一定!時間がかかります
-J42161217

1

Pyth、13バイト

h-DsM^N2/#QyS

テストスイート

辞書編集上最初の最短チェーンを提供します。かなり遅いですが、それほど悪くはありません19-pypyを使用して約30秒で完了します。

@Dennisのソリューションからのアイデア。

私はこれが本当に好きです-巧妙なトリックがたくさんあります。

説明:

h-DsM^N2/#QyS
h-DsM^N2/#QySQ    Implicit variable introduction
            SQ    Inclusive range, 1 to input.
           y      Subsets - all subsets of the input, sorted by length then lexicographically
                  Only sorted subsets will be generated.
                  Our addition chain will be one of these.
        /#Q       Filter for presence of the input.
  D               Order by
 -                What's left after we remove
     ^N2          All pairs of numbers in the input
   sM             Summed
h                 Output the list that got sorted to the front.

これはまだ理解するのが少し難しいですが、もう少し詳しく説明してみましょう。

から始めます。これは、サイズの昇順ySQ[1, 2, ... Q]、のすべての可能な順序付きサブセットを提供します。最短の加算チェーンは間違いなくこれらの1つですが、見つける必要があります。

最初に行うことは、リストをフィルタリングして、を含むリストのみを保持することQです。これはで行い/#Qます。

次に、特定の関数の結果を削除した後に残っているものでリストを並べ替えます。-D何かを削除した後、残りの人が注文します。

削除するのはでsM^N2、ここで削除するのはNリストです。^N2のデカルト積、Nそれ自体の2つの要素のすべての可能なペアを与えNます。sM次に、各ペアを合計します。

この削除を行った後、可能な最小の結果は何ですか?すべての数値が正であるため、入力リストの最小要素は間違いなく残ります。したがって、2つの数値の合計は最小数より大きくなります。リストに入力が存在することを確認したため、少なくとも1つの数字があります。したがって、可能な最小の結果は、最小数を除くすべての数がリスト内の他の2つの数の合計であり、リスト内の最小数が1の場合になります[1]。この場合、ソートキーはになります。これらの要件は、リストが追加チェーンでなければならないことを意味します。

そのため、追加チェーンを前面に並べ替えます。それは覚えておいてくださいy前にソートされたリストは、最短加えチェーンのいずれかでなければなりませんので、サイズの昇順でそのサブセットを提供します。hそのリストを選択します。

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