公正な王のための8つのコイン


22

これは別のパズルの「カウンターパート」です。Puzzling.SEの公正な王のための8つのコインです

上記のパズルの背景を読むことができます。このパズルの詳細は次のとおりです。

異なる値の8種類のコインのセットが作成されます。王は、0からNまでの任意の数の価格が8コイン以下の組み合わせで無料で支払われるように、最大​​Nを見つけることを望んでいます。

たとえば、(Glorfindelの回答から引用)。値1、2、5、13、34、89、233、610のコインのセットが与えられた場合、プログラムは1596を出力する必要があります。与えられたリストから8個以上の数字(数字は繰り返される可能性があります)、1597はそのようには表現できません。

数学的には、入力が8つの正の整数で構成される集合Sである場合、望ましい出力Nは、0からNまでの任意の数nに対して、x1、x2、x3、...、x8が存在することを満たします。

バツ1+バツ2++バツ8=nそしてバツ1バツ2バツ8{0}S

あなたの目標は、入力として8つの数字を受け取り、上記のように最大Nを出力するプログラム、関数、またはスニペットを作成することです。

ルール:

  • 柔軟なI / Oが許可されているため、プログラムは最適な形式で入力を取得できます。入力番号は、プログラムに最適な方法でソートされていると想定できます。
    • プログラムが入力順序に依存している場合は、回答にそれを明記してください
  • 入力は、8つの異なる正の整数(ゼロなし)のセットです。出力は、1つの非負整数です。
    • 入力セットに1がない場合、0〜0の任意の数が要件を満たすため、プログラムは0を出力する必要があります。
    • 無効な入力(セットにゼロ、負の数、または重複する数が含まれる)の場合、プログラムは何でもできます。
  • 標準的な抜け穴は禁止されています。
  • プログラムは、最新のコンピューターで数分以内に実行されるはずです。

テストケース(主にPuzzlingのリンクされた質問の下の回答から取得):

[1, 2, 3, 4, 5, 6, 7, 8] => 64
[2, 3, 4, 5, 6, 7, 8, 9] => 0
[1, 3, 4, 5, 6, 7, 8, 9] => 72
[1, 2, 5, 13, 34, 89, 233, 610] => 1596
[1, 5, 16, 51, 130, 332, 471, 1082] => 2721
[1, 6, 20, 75, 175, 474, 756, 785] => 3356

これはであるため、各言語で最も短いプログラムまたはスニペットが優先されます。


1
いいパズルですが、私は個人的に、提出物をテストするために、さらにいくつかのテストケースが役立つと思います。
Mr. Xcoder

入力サイズをパラメータにする方が良いと思いませんか?ブルートフォースアプローチは8で苦労します
ルイスメンドー

1
@iBugそうすると、通常のルールは「現代のコンピューターで1分以内に実行される送信」のようなものです。ブルートフォースと効率的なアプローチの違いが非常に大きいので、ファジー、通常は良い十分です
ルイスMendo

1
「数分」の制限時間でブルートフォースは可能です。私の答えを少し修正したバージョンでは、7歳のラップトップで1分20秒で最後のテストケースを実行します。
nimi

1
@Arnauldが明確化
iBug

回答:


14

Pythonの3113の 62バイト

for i in[1]*3:x|={a+b for a in x for b in x}
while{i+1}&x:i+=1

これxは、intのセットとしての入力でiあり、出力です。

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

(ありがとう:エリック・ザ・アウトゴルファー、ミスター・エクスコーダー、リン)



x=0,*x1バイト節約します。いっそのこと、x+=0,2。は、節約
氏Xcoder

Python 2では78バイト
Lynn

9

ゼリー、12 バイト

œċⱮ8Ẏ§ṢQJƑƤS

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

携帯電話でTIOですべてのテストケースを実行するのに平均で約3.7秒かかります。そのため、驚くほど高速です。

説明

œċⱮ8Ẏ§ṢQJƑƤS     Monadic link / Full program.
  Ɱ8             Promote 8 to [1 ... 8] and for each value k:
œċ                    Generate all combinations of k elements from the list.
    Ẏ§           Tighten, then sum. Flatten to a 2D list then sum each.
      ṢQ         Sort the result and remove equal entries.
        JƑƤ      For each prefix of this list, return 1 if it is equal to its length range, 0 otherwise.
           S     Finally, sum the result (counts the 1's which is equivalent to what is being asked).

7

Haskell、56 50バイト

g c=[x|x<-[1..],all((/=x).sum)$mapM(0:)$c<$c]!!0-1

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

総当たりアプローチ。0コインのリストに追加して、8つのピックのすべての組み合わせを試してください。nピックとリターンの合計と等しくない最初の数を見つけますn-1

[1, 2, 5, 13, 34, 89, 233, 610]私の7歳のラップトップハードウェアで約5分30秒かかります。

編集:@ØrjanJohansenのおかげで-6バイト

さらに短いバージョン(-2バイト、再び@ØrjanJohansenのおかげ)は

Haskell、48バイト

g c=[x|x<-[1..],all((/=x).sum)$mapM(:0:c)c]!!0-1

しかし、かなり多くのメモリを使用し、マシン上で重いページングを実行し、「数分以内」に終了しません。


1
を使用できますmapM(0:)$c<$c。(実際にmapM(:0:c)cは動作するはずですが、指定されたテストケースのTIOでタイムアウトします。)
ØrjanJohansen

4

ゼリー、9バイト

Żœċ8§ḟ’$Ṃ

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

使い方

Żœċ8§ḟ’$Ṃ  Main link. Argument: A (array)

Ż          Prepend a 0 to A.
 œċ8       Take all combinations of length 8, with repetitions.
    §      Take the sum of each combination.
       $   Combine the two links to the left into a monadic chain.
      ’      Decrement all sums.
     ḟ       Filterfalse; keep only sums that do not appear in the decremented sums.
        Ṃ  Take the minimum.

2
Żṗ8§ḟ’$Ṃ1つのバイトが保存されますが、8.5分としてカウントされている場合、私はわからないいくつか
デニス


4

JavaScript(ES6)、 100 88 80  76バイト

これは基本的にブルートフォース検索ですが、速度を上げるためにプルーニングで強化されています。テストケースの平均実行時間は、TIOで1秒に近いです。

入力配列が最高から最低にソートされていると仮定します。

a=>[...Array(a[0]*9)].findIndex(g=(i=8,s)=>s*i>0?a.every(x=>g(i-1,s-x)):s)-1

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

コメント済み

a =>                      // a[] = input array
  [...Array(a[0] * 9)]    // create an array of 9 * max(a) entries
  .findIndex(             // find the position of the first truthy result
    g = (i = 8, s) =>     // g = recursive function taking a counter i, initialized to 8
                          //     and a sum s, initialized to the position in the above array
      s * i > 0 ?         //   if s is positive and i is not equal to 0:
        a.every(x =>      //     for each value x in a[]:
          g(i - 1, s - x) //       do a recursive call with i - 1 and s - x
        )                 //     end of every()
      :                   //   else:
        s                 //     yield s (s = 0 means success and makes findIndex go on)
  ) - 1                   // end of findIndex(); decrement the result


3

パリ/ GP、57バイト

a->n=-1;while(polcoeff((1+sum(i=1,8,x^a[i]))^8,n++),);n-1

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


これは生成関数を使用していますか?
明るい

1
@donbrightはい。
alephalpha

1
それはすごい..ソリューションを総当たり攻撃しない数少ない答えの1つです。おそらく多くの言語は、多項式シンボリック機能を組み込んでいないでしょう。パリGPはクールです。
明るい

2

パイソン2125の 115 111バイト

lambda c:sum(i==j for i,j in enumerate(sorted(set(map(sum,product([0]+c,repeat=8))))))-1
from itertools import*

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

入力として整数のリストが必要です。

説明:

# an anonymous function
lambda c:
                                                          # get all length-8 combinations of values, from (0,0,0,0,0,0,0,0) to (8,8,8,8,8,8,8,8)
                                                          # zero is added to ensure that combinations of fewer than 8 coins are represented Ex:(1,0,0,0,0,0,0,0)
                                                          product([0]+c,repeat=8)
                                                  # for each combination, sum the values
                                                  map(sum,.......................)
                                       # get unique values, then sort them smallest to largest
                                       sorted(set(................................))
             # for each index, value pair, return if the index is equal to the value
             i==j for i,j in enumerate(.............................................)
         # in Python arithmetic, False is 0 and True is 1. So, count how many items match their index.
         # Since zero was added to the list, there will always be one extra match (0==0). So offset by one.
         sum(........................................................................)-1
from itertools import*

2

Perl6の、65 63 41バイト(39 37文字)

{@_=(0,|@_)X+(0,|@_)for ^3;($_ if $_==$++for @_.sort.unique)-1}

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

これは、データを配列として渡す匿名ブロックです。(0,|@_)追加する簡単な方法です0@_、それは二回行うのにもかかわらず、それはよりもまだ少し短いです@_.push: 0;、その後の後のスペースを必要とすることになります_。これはブルートフォースアプローチであり、8つの組み合わせであるという事実に少し触れています。相互追加後、連続値の匿名リストが作成されます。算術演算子を使用すると、リストはその長さに評価されるため、-1は2つの義務を果たします。0を考慮して、Intに強制します。

これには甘い時間がかかりますが、一方または両方(0,|@_)(0,|@_.unique)最初の前に変更forすることにより、かなり高速化できます。最初のスコアが遅すぎると感じる場合、スコアに+7(ランタイム<60 秒)または+14(ランタイム<10秒)を追加します(60秒後のタイムアウトを回避するために、リンクされたコードでこれを行いました)。

編集:コメントのJoKingは、驚異的な39文字(41バイト)にそれを改善しました(同じアイデア、クロス追加、そして最後の連続した結果を返します):

{(@_=@_ X+0,|@_)xx 3;first *+1@_,^∞}

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

最終的な集計には0は必要ありません。一度に0を追加するだけで数バイトを節約できます。xx 3forループを模倣する(2の累乗である硬貨に依然としてチーズ)。firstサブ無限リストの最初の番号を返す0..*^Infすぎる可能であるが、スペース保存しない)、その+1クロス添加リストのメンバーではありません。私のように、それは遅いので、ガイドラインに対して遅すぎると感じるなら、最初のイコールの後に+7を追加uniqueします。


1
48バイト。技術的には、これuniqueは必要ありませんが、大幅に高速化されます
ジョーキング

@JoKingいいですね、なぜ使用することを考えなかったのかわかりませんxx。セット関数を使用して、はるかに短い方法で最終的な集計を行う方法が必要であることは知っていましたが、私の脳は機能していませんでした。
user0721090601

xx 1必要がありますxx 3
ジョーキング

@JoKingが修正されました。また、私は2つの文字(ただしバイトなし)を使用して保存できることに気付きました^∞
user0721090601を

実際(1...*∉@_)-1には、使用する代わりに、いくつかのバイトを節約できますfirst(これは、私がここで使用したのと同じ方法です
Jo King



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