3フルーツのパイをいくつ作ることができますか?


32

3つのフルーツのパイは、3つの異なるフルーツでできています。あなたが持っている5つの果物の量から作ることができる最も3つの果物のパイは何ですか?

たとえば、

1 apple
1 banana
4 mangoes 
2 nectarines
0 peaches

あなたは2パイを作ることができます:

apple, mango, nectarine
banana, mango, nectarine

入力: 5つの非負整数、またはそれらのリスト。

出力:これらの量のフルーツから作成できる3フルーツパイの最大数。最少バイトが勝ちます。

テストケース:

1 1 4 2 0
2
2 2 2 2 2
3
0 6 0 6 0
0
12 5 3 2 1
5
1 14 14 3 2
6
0 0 1 0 50
0

リーダーボード:


あなたの例には、アップル、バナナ、マンゴーとアップル、バナナ、ネクタリンの2つの追加オプションが欠けていると思います。したがって、1 1 4 2 0テストケースは次の出力を生成する必要があります。4.
cobaltduck

@cobaltduckしかし、最初のパイ(Apple / Banana / Mango)でAppleとBananaを使用する場合、2番目のパイ(Apple / Banana / Nectarine)で使用するAppleまたはBananaはありません。
AdmBorkBork

2
@ティミーD:ああ、わかった。パイが同時に作られたかどうかは明らかではありませんでした。
コバルトダック

@cobaltduck同時に作られる必要はないと思いますが、最初に使った果物を再利用することでごまかすことはできません。
ミスターリスター

@氏。リスター:セマンティクス。(少なくとも1人の読者にとって)あいまいなルールがあり、それ以降に明確にされたルールがあれば十分です。
コバルトダック

回答:


34

Pyth、19 18 14バイト

@FryAmTheEggmanによる-1バイト

@isaacgによる14バイトのプログラム

昇順リストから作成できるパイの数[x1,x2,x3,x4,x5]は次のとおりです。

floor(min((x1+x2+x3+x4+x5)/3,(x1+x2+x3+x4)/2,x1+x2+x3))

またはコード内:

JSQhS/Ls~PJ_S3

[TI-BASICおよびAPLプログラムの改訂履歴を参照]

正当性の証明

させて

s3 = x1+x2+x3
s4 = x1+x2+x3+x4
s5 = x1+x2+x3+x4+x5

フルーツ1〜5の数のP(X)=floor(min(s5/3,s4/2,s3))リストに対して、常に最大数のパイであることを示したいと思いx1≤x2≤x3≤x4≤x5ます。

まず、3つの数値すべてが上限であることを示します。

  • あるのでs5、総果実、各パイ三個の果実を有し、⌊s5/3⌋上限です。

  • あるので、s4ある果物ではない果物5は、少なくとも2つの非5果物は、各円グラフで必要とされ、⌊s4/2⌋上限があります。

  • あるのでs3フルーツ4や果物5もない果実は、少なくとも1つのフルーツが各パイで必要とされ、s3上限があります。

第二に、3つの最大の山から果物をとる方法が常に限界を満たしていることを示します。これは帰納法で行います。

基本ケース:で有効なリストから0パイを形成できますP(X)>=0

帰納的ステップ:リストXがである場合P(X) > 0、1つのパイを焼き、リストX'をで残しP(X') >= P(X)-1ます。これを行うには、最大の3本の山から果物を採取し、3,4,5必要に応じて再利用します。私と一緒に耐えてください。いくつかのケースワークがあります。

  • の場合x2<x3、果物を削除した後にリストを並べ替える必要はありません。すでに有効ながありますX'P(X') = P(X)-1なぜならs5'、タイプ1〜5の3つの果物が削除されたため)3少ないため、s4'2少ない、s3'1少ないためです。そうP(X')、P(X)よりも正確に1つ小さくなります。
  • の場合x3<x4、同様に完了します。
  • 今、私たちはどこのケースを取りますx2=x3=x4。今回はリストを再配置する必要があります。

    • 場合はx5>x4、その後、私たちは山4と2を切り替えて、リストを並べ替えるs5's4'、それぞれまだ3と2の減少ですが、s3'=s3-2。if x2=x3=x4、then 2*x4<=s3-> 2*x4+s3 <= 2*s3-> ので、これは問題ではありません(x4 + s4)/2 <= s3。2つのサブケースがあります。
    • 等式、つまり(x4,x3,x2,x1)=(1,1,1,0)、この場合P(X)= 1と、山から明確にパイを作ることができます5,4,3、または:

    • (s4+1)/2 <= s3その場合、減少s4余分によっては1P(X)に余分の減少を意味するものではありません。

  • ここで、の場合が残っていますx1<x2=x3=x4=x5。今s3も1減少し、私たちが必要とされます(s5/3+1)ように<=s4/2。つまり8x5+2x1+2<=9x5+3x1、、またはx5+x1>=2。これより小さいケースはすべて手動で確認できます。

  • すべての数値が等しい場合、の境界を達成できることは明らかであり⌊s5/3⌋、これは常に他の2つよりも小さく、単純に数値を順番に調べます。

最後に完了しました。何かが足りない場合はコメントしてください。もっとエレガントな証拠に少額の賞金を差し上げます。


あなたの主張は@fryamtheeggmanの反復解と一致すると思います。
スパー

@Sparr fryamtheeggmanの方法を使用して、自分の限界に到達できることを証明しようとしています。
リルトシアスト

2
これは、ループに変えることで4バイトJSQhS/Ls~PJ_S3
ずつ

3
n材料とkパイごとの材料の証拠を見つけたと思いますが、このコメントボックスには長すぎます。これを証明できるように、見つけられる可能性のあるエラーを指摘してください。
メゴ

7

CJam、34

q~L{J2be!\f{\.-_W#){j)7}|;}0+:e>}j

オンラインで試す

説明:

q~          read and evaluate the input array
L{…}j       calculate with memoized recursion and no initial values
             using the input array as the argument
  J2b       convert 19 to base 2 (J=19), obtaining [1 0 0 1 1]
  e!        get permutations without duplicates
             these are all the combinations of three 1's and two 0's
             which represent the choices of fruit for one pie
  \         swap with the argument array
  f{…}      for each combination and the argument
    \       swap to bring the combination to the top
    .-      subtract from the argument array, item by item
    _       duplicate the resulting array
    W#)     does it contain the value -1? (calculate (index of W=-1) + 1)
    {…}|    if not
      j     recursively solve the problem for this array
      )7    increment the result, then push a dummy value
    ;       pop the last value (array containing -1 or dummy value)
  0+        add a 0 in case the resulting array is empty
             (if we couldn't make any pie from the argument)
  :e>       get the maximum value (best number of pies)

再帰のメモにはバイトがかかりますか?実行時の制限はありません。
xnor

2
@xnorここで実際に1バイト節約できると思います:)
aditsu

7

Haskell、62バイト

f x=maximum$0:[1+f y|y<-mapM(\a->a:[a-1|a>0])x,sum y==sum x-3]

これは関数を定義します f、フルーツリストを受け取るをxパイの最大数を返す。

説明

パイの数を再帰的に計算します。パーツmapM(\a->a:[a-1|a>0])xx、正のエントリをデクリメントすることで取得されたすべてのリストのリストに評価されます。の場合x = [0,1,2]、結果は

[[0,1,2],[0,1,1],[0,0,2],[0,0,1]]

外側の部分[]はリストの内包です:y上記のリストのすべてを反復処理し、合計がに等しくないものをフィルターで除外するsum(x)-3ため、3つの異なるフルーツがパイになっているすべてのリストを取得します。次にf、これらのリストを再帰的に評価し、1それぞれに追加し、それらの最大値を取得します0(パイを作成できない場合は基本ケース)。


7

C#、67

反復するたびに、あなたが最もなくなる果物を使い果たすまで、再帰的に1つのパイを作ります。

int f(List<int>p){p.Sort();p[3]--;p[4]--;return p[2]-->0?1+f(p):0;}

テストケースはこちら


C#に慣れていませんがp[2]--、チェックと同時に行うことができますp[2]>-1か?
xnor

良い点は、すぐに答えを更新します。
AXMIM

6

Pyth、29

Wtt=QS-Q0=Q+tPPQtM>3.<Q1=hZ;Z

テストスイート

入力リストをソートし、ゼロを削除します。次に、3つの果物がある限り、最初の要素と最後の2つの要素をデクリメントし、残りの要素をリストに追加してから、並べ替えて再びゼロを削除します。次に、カウンターを1増やします。

果物が5つしかない限り、これは実際にはかなり速く、非常に大きな果物のビン、つまり1000,1000,1000,1000,10001秒未満で解決できます。


それが正しいことを証明できますか?
-aditsu

@aditsu私はそれを証明していませんが、いくつかの追加の値についてあなたのものと照合しました。私は以前にこのようなことの証拠を実際に書いたことはありませんが、試してみます。今のところ、小さな果物を使い果たすまで、常に最大の果物の山からのみ摂取するので、それが機能するはずだと言います。貪欲な戦略は明らかに本質的に常に正しいわけではありませんが、なぜここでうまくいかないのか考えられません。
FryAmTheEggman

@FryAmTheEggman最も一般的な2つの果物と最も希少な果物を摂取していることを理解していますか?
xnor

@xnorはい、それは正しいです。それは機能しませんか?
FryAmTheEggman

1
@TimmyDいいえ、必要はありません(考えます)。ただし、この機能を削除するのにバイトはかかりません(実際にはもっとかかります)。それは私が期待する、と述べたレトKoradiのソリューションは、ほとんどの言語では短く、明らかトーマスさんは、はるかに簡潔です。再ソートする必要がない理由は、3つの小さな山のどれを使用するかに関係ないことに関係していると思います。
-FryAmTheEggman

6

Python、一般的なソリューション、128 92バイト

@xnorから-36バイト、本当のmvp

g=lambda l,k:0if k>sum(l)else-(-1in l)or-~g(map(sum,zip(sorted(l),[0]*(len(l)-k)+[-1]*k)),k))

def g(a,k):b=[i for i in a if i];return 0if len(b)<k;c=sorted(b,reverse=True);return 1+g([c[i]-(k-1>i)for i in range(len(c))],k)

これは私の証明が正しい限り機能します。そうでない場合は、その理由をお知らせください。修正を試みます。理解できない場合はお知らせください。コーヒーを数杯飲んだ後、攻撃します。


今はすべてがきついようです。
リトシアスト

@Megoこれに取り組んでくれてありがとう!SEの投稿に証拠を含めてください。数年後に読んでいる誰かが死んだリンクを見つけるかもしれないという一般的な懸念があります。LaTeXのフォーマットはほとんどがMathJaxで機能するはずです。
xnor

@Megoおっと、MathJaxがここで有効になっていないことを忘れました。うーん、私は何をすべきか尋ねます。
xnor

私はこの証明の賞金を授与しています。おめでとうございます!
-xnor

@Megoいや、MathCloudリンクが最高だと思う。
xnor

5

Python 2、78バイト

入力として5つの数字を使用: 91 89 88バイト

s=sorted([input()for x in[0]*5])
while s[2]:s[2]-=1;s[3]-=1;s[4]-=1;s.sort();x+=1
print x

編集:で変更するとs=sorted([input()for x in[0]*5])s=sorted(map(input,['']*5));x=01バイト保存されます。

入力として5つの数字を受け取り、作成可能なパイの数を出力します。Reto Koradiの答えと同じアプローチを取りますが、バイト数を改善することはできませんが、この質問にはPythonの答えが欠けているように感じました。

@ThomasKwaと@xsotにご提案いただきありがとうございます。

使い方

 s=sorted([input()for x in[0]*5]) takes 5 numbers as input, puts them in a list 
                                  and sorts it in ascending order. The result
                                  is then stored in s 

 while s[2]:                      While there are more than 3 types of fruit 
                                  we can still make pies. As the list is                     
                                  sorted this will not be true when s[2] is 0. 
                                  This takes advantage of 0 being equivalent to False.

 s[2]-=1;s[3]-=1;s[4]-=1          Decrement in one unit the types of fruit 
                                  that we have the most

 s.sort()                         Sort the resulting list

 x+=1                             Add one to the pie counter

 print x                          Print the result

変数xは決して定義されないことに注意してください。しかし、プログラムはpython 2.7が持っているいくつかのリークを事前に取ります。sリスト内包表記でリストを定義する場合、反復可能オブジェクトの最後の値([0]*5この場合)は、反復に使用される変数に格納されます。

物事を明確にするために:

>>>[x for x in range(10)]
>>>x
9

入力としてリストを取得する:78バイト

リストへの入力の変更を提案してくれた@xnor @xsotと@ThomasKwaに感謝します。

s=sorted(input());x=0
while s[2]:s[2]-=1;s[3]-=1;s[4]-=1;s.sort();x+=1
print x

使い方

上記のコードと同じように機能しますが、この場合、入力は既にリストであるため、作成する必要はなく、変数xを定義する必要があります。

免責事項:これはゴルフの私の最初の試みであり、それはまだゴルフをすることができると感じているので、バイト数を減らすために行うことができる変更を提案します。


1
リストに既に入力があることが許可されています。s[2]>0-> s[2]、パイル内の数値は常に非負であるため。
リトシアスト

トーマス・クワは、入力がすでにリストとして与えられていると仮定するかもしれないので、あなたはただやることができると指摘しましたs=sorted(input())。また、現在のバイト数は89です。改行は単一の文字としてカウントされます。
xnor

@ThomasKwaは、入力をリストとして受け入れることができることを既に指摘しましたが、複数行の入力を受け入れることを主張する場合は、最初の行を次の行に置き換えてバイトを保存しますs=sorted(map(input,['']*5));x=0
xsot

4

CJam、23バイト

0l~{\)\$2/~+:(+_2=)}g;(

オンラインで試す

これは、各反復で最大の3つの山から実を取り、反復回数をカウントします。

これが常に正しい結果を与えるという数学的な証明はありません。それは与えられたテスト例に対して行われ、誰かが私に反例を与えるまで、それはすべての場合に機能すると信じています。

私が自分を納得させるために使用した直感的な説明:パイの数を最大化するには、できるだけ多くの山を空にしないようにする必要があります。これは、空のパイルが3つ以上あるとすぐに、より多くのパイを作成する能力を失うためです。

これは、常に最大の山から果物をとることによって達成されます。小さい山から果物をとることが、大きい山から果物をとるよりも良い状況につながるというケースは考えられません。

私は頭の中で少し形式的な推論をしています。それを言葉/式に入れる方法を考えてみます。


私は誘導を使用しようとしています。アイデアを組み合わせて正式な証拠を見つけることができるかもしれません。
リトシアスト

@ThomasKwa私はそれを書き留めると納得できるような十分に明確なものを思いついていません。すべては、小さなスタックから大きなスタックよりも優れている理由がまったくないという事実に基づいています。明らかに、小さなスタックからの取得が悪い状況があります。また、私はいくつかのランダムで適度に大きい数を鉱山とaditsuの両方のソリューションに入力しましたが、それらは同じ結果をもたらしました。私の解決策は、私が試した例の式とも一致しています。
レトコラディ

3

> <>、76バイト

0&4\/~}&?!/
@:@<\!?:}$-1@@$!?&+&:)@:@
,:&:@(?$n;/++:&+::2%-2,:&:@(?$&~+:3%-3

> <>でのソートは簡単ではありません!このプログラムは、Thomas Kwaが提出した証拠が真実であることに依存していますが、これは確かにテストケースに当てはまるようです。

5つの入力番号は、プログラムの開始時にスタックに存在することが予想されます。

最初の2行はスタック上の数値をソートし、3行目はfloor(min((x1+x2+x3+x4+x5)/3,(x1+x2+x3+x4)/2,x1+x2+x3))Thomasの答えから取得した計算を実行します。


3/4要素のすべての合計とそれらの最小値を計算すると短くなりますか?
リトシアスト

@ThomasKwa私はそれが入力セットの順列を見つけ、それぞれの最上位の3要素と4要素を合計し、それらの最小値を取得することを伴うように見えますか?私は、特にスタックベースの言語で使用しているソート/計算のアプローチよりも、置換を見つけるのが短いとは思いません。もし私が見て興味があると思いスタックベースの言語で順列を生成するための任意の便利なアルゴリズムを知っている:O)
ソック

2

Python 2、59バイト

h=lambda l,k=3:k*'_'and min(h(sorted(l)[:-1],k-1),sum(l)/k)

nおよびに有効な一般的な方法k。これk=3により、パイごとの果物のデフォルトが3になりますが、別の値を渡すことができます。再帰では、文字列がPython 2の数値よりも大きいという事実を使用して、空の文字列が無限大の基本ケースを表すようにします。

この方法は、最も一般的な果物を常に摂取することが最適であるという事実を使用しているため、果物の各ランクを制限要因と見なします。以下にその事実を非難しました。


Megoの証明は、最も一般的な果物を繰り返し摂取することが最適であるというこのより直接的な証明を考えさせました。これはk果物のパイで述べられています。

定理:k最も一般的な果物を繰り返し摂取すると、最適な数のパイが得られます。

証明:Nパイが可能な場合、最も一般的なフルーツ戦略が少なくともNパイを生産することを示します。これを行うにはN、パイを有効な状態に保ちながら、パイ間で果物を切り替えて、この戦略によって生成されたものと一致させます。

最初のパイ(それを呼び出すp)に最も一般的な果物が含まれるようにしましょう。まだない場合は、フルーツiが含まれている必要がありますが、より一般的なフルーツは含まれていませんj。次に、残りのパイには、果物jよりも厳密に多くの果物が含まれているiため、他のパイにqは含まれている必要がありますjが、含まれていませんi。その後、私たちは果物を入れ替えることができますiパイからp果物とjパイからq続けて、N明確な果物を持っパイを。

最も一般的な果物になるまでp、このプロセスを繰り返しkます。

次に、パイをp脇に置き、次のパイについてもこのプロセスを繰り返して、最も一般的な残りの果物を作ります。パイが最も一般的な果物の状態によって生成されるシーケンスになるまで、これを繰り返してください。


1

PowerShell、92バイト

$a=($args|sort)-ne0;while($a.count-ge3){$a[0]--;$a[-1]--;$a[-2]--;$a=($a-ne0;$c++}($c,0)[!$c]

FryAmTheEggmanの答えと同じ貪欲ベースのアルゴリズムを使用します...

$a=($args|sort)-ne0  # Take input arguments, sort them, remove any 0's
while($a.count-ge3){ # So long as we have 3 or more fruit piles
  $a[0]--            # Remove one from the first element...
  $a[-1]--           # ... the last element ...
  $a[-2]--           # ... and the second-to-last.
  $a=$a-ne0          # Remove any 0's from our piles
  $c++               # Increment how many pies we've made
}                    #
($c,0)[!$c]          # Equivalent to if($c){$c}else{0}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.