ブックスタックソート


21

本を積み重ねるときは、通常、一番大きいものを一番下に、一番小さいものを一番上に置きます。しかし、潜在的なOCDのおかげで、2冊の本があり、一方の本の高さは短く、他方の本よりも幅が広い場合、非常に不安になります。どの順序で配置しても、一番上の本は一番下の本を超えて一面に広がります。

例として、ある本には次元が(10,15)あり、別の本には次元があるとしましょう(11,14)。どのように配置しても、オーバーハングが発生します。ただし、寸法が(4,3)、の書籍がある場合は(5,6)、前者の下に後者を配置することで張り出しを回避できます。

この挑戦の目的のために、私たちはすぐ下の本に関してオーバーハングを考えるでしょう。例えば、私は、スタックを持っている場合は(5,5)(3,3)(4,4)(まともな人はそれを行うだろうということではない)、オーバーハングなどのトップ帳の数は、それが下の本を超えて拡張しませんが。同様に、スタックは(3,3)(3,3)(4,4)また、下の1を越えて延びるトップ帳にもかかわらず、唯一のオーバーハングを有します。

チャレンジ

ブックの寸法の整数ペアのリストが与えられたら、オーバーハングの数が最小になるようにそれらのペア/ブックをソートします。本を回転させてはいけません-すべてのスパインを同じ方向に向けてください。オーバーハングの数が同じソリューションが複数ある場合は、そのような順序を選択できます。ソートアルゴリズムは安定している必要はありません。実装では、ブックの寸法がそれぞれ2 16未満であると想定する場合があります。

時間の複雑さ:これをもう少し面白くするには、アルゴリズムの漸近的な最悪の複雑さをスタックのサイズの多項式にする必要があります。そのため、可能なすべての順列をテストすることはできません。アルゴリズムの最適性と複雑さの簡単な証明と、オプションで大きなランダム入力のスケーリングを示すプロットを含めてください。もちろん、O(1)でコードを実行する引数として入力の最大サイズを使用することはできません。

プログラムまたは関数を作成し、STDIN、ARGV、または関数引数を介して任意の便利な(前処理されていない)リスト形式で入力し、結果を出力または返すことができます。

これはコードゴルフなので、最短の回答(バイト単位)が勝ちです。

多項式解が存在すると確信していますが、間違いを証明できる場合は、ゴルフの提出の代わりにそのような証明を提出できます。この場合、P≠NPと仮定できます。私は最初の正しいそのような証明を受け入れ、それに賞金を授与します。

In:  [[1, 1], [10, 10], [4, 5], [7, 5], [7, 7], [10, 10], [9, 8], [7, 5], [7, 5], [3, 1]]
Out: [[10, 10], [10, 10], [9, 8], [7, 7], [7, 5], [7, 5], [7, 5], [4, 5], [3, 1], [1, 1]]

In:  [[4, 5], [5, 4], [5, 4], [5, 4], [5, 4], [4, 5], [4, 5], [4, 5], [5, 4], [4, 5]]
Out: [[4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [5, 4], [5, 4], [5, 4], [5, 4], [5, 4]]
  or [[5, 4], [5, 4], [5, 4], [5, 4], [5, 4], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5]]

In:  [[2, 3], [1, 1], [5, 5], [7, 1]]
Out: [[5, 5], [2, 3], [7, 1], [1, 1]]
 or  [[5, 5], [2, 3], [1, 1], [7, 1]]
 or  [[7, 1], [5, 5], [2, 3], [1, 1]]
 or  [[7, 1], [1, 1], [5, 5], [2, 3]]

これらは手作業で作成したので、間違いを見つけたら教えてください。


3
オーバーハングの最小数を持つ解を見つけることは、多項式時間で解決できると確信していますか?
COTO 14年

@COTOはい、かなり自信があります。
マーティンエンダー14年

うーん 通常は貪欲なアルゴリズムでそれに取り組みますが、私が思いつく「欲」の基準(たとえば、面積、1つの次元の最大化、最小の次元の最大化など)に対して準最適な出力につながる入力を簡単に調達できます。私が考えることができる他の唯一のアプローチは、本をクリークに分割することを含み、それらはすべて指数関数的な最悪の場合の複雑さを持っています。どんな答えが出てくるか興味があります。また、仕様の一部としてソートの最適性の簡単な証明を要求することもできます。
COTO 14年

@COTO実際に間違っている場合に備えて、これに関する段落を追加しましたが、それを期待しないでください。;)
マーティンエンダー14年

念のため、多項式時間アルゴリズムが存在しないという潜在的な証拠は、PがNPに等しくないと仮定することを許可する必要があります。
xnor 14年

回答:


2

ピス、30

FN_SQFbYIgeeYeb~b]NB)E~Y]]N;sY

これは、grcの素晴らしいアルゴリズムの直接的なゴルフです。これは、コンパイル済みのpythonコードで、上記のpythプログラムとまったく同じです。

Q = eval(input())
Y = []
for N in sorted(Q)[::-1]:
     for b in Y:
         if Y[-1][-1] >= b[-1]:
             b += [N]
             break
     else:
         Y += [[N]]
print(Psum(Y))

このコンテキストでは、Psum(Y)関数はpythonと同等sum(Y,[])です。

実際のコンパイルされ実行されたコード(からpyth -d):

Y=[]
Q=copy(eval(input()))
for N in neg(Psorted(Q)):
 for b in Y:
  if gte(end(end(Y)),end(b)):
   b+=[N]
   break
 else:
  Y+=[[N]]
Pprint("\n",Psum(Y))

1
Pythonの翻訳には「Y = []」が必要で、Python 2を使用している場合はevalを削除し、合計には2番目の引数が必要sum(Y,[])です。これはすべてPythで動作するはずで、翻訳には自動的に含まれません。
xnor 14年

@xnor最後の行は実際に読み取りますPprint("\n",Psum(Y))。私は彼がすべてのとともに、利便性のためにそれを単純化しているかもしれないと思う-1のなどPsum実際にはより多くのように実行しますreduce(lambda x,y:x+y, Y[1:], Y[0])
FryAmTheEggman 14年

20

Python、113

P=[]
for n in sorted(input())[::-1]:
 for p in P:
  if p[-1][1]>=n[1]:p+=[n];break
 else:P+=[[n]]
print sum(P,[])

書籍のリストを降順(最初に幅、次に高さ)に並べ替えた後、これにより、書籍が重なり合うことなく山に分割されます。各本の配置場所を決定するために、その高さは各パイルの一番上の本の高さと比較されます。可能な最初のパイルに配置されるか、新しいパイルが作成されます。

時間の複雑さはあまり得意ではありませんが、ON 2)の最悪の場合があると思います。2つのループがあり、それぞれ最大でN回の繰り返しがあります。また、Pythonの組み込みソートであるOn log n)も使用しています。


このアルゴリズムが最適なソリューションを生成するという私の最初の証拠は、間違っていることが判明しました。@xnorと@ Sp3000に感謝します。これを証明するためのチャットでの素晴らしい議論(これはここから読むことができます)。正しい証明を作成した後、@ xnorはその一部がすでに行われていることを発見しました(ディルワースの定理)。

とにかく証拠の概要は次のとおりです(@xnorおよび@ Sp3000の功績)。

まず、アンチパイルまたはアンチチェーンの概念を定義します(@xnorから引用):

antipileは高さが減少するが、幅の増加の本のシーケンスである
ので、それぞれの連続した書籍は、厳密に背が高いが、厳密に小さい幅である
。なお、antipile内の他の書物を超えるantipileオーバーハングのいずれかの本は
antipile缶内だから、何も2冊ありません同じパイル内に
ある結果として、x本の反パイルを見つけることができる場合、それらの本は異なるパイルにある必要があります。
したがって、最大のパイルのサイズはパイルの数の下限です

次に、幅(1番目)と高さ(2番目)*で降順に並べ替えます。

Bごとに、次のようにします。

  1. Bが最初のパイルに収まる場合は、そこに配置して先に進みます。
  2. そうでなければ、我々は早い*パイル見つけるX Bはの上に配置することができます。これは、必要に応じて新しい山にすることができます。
  3. 次に、BPにリンクします。ここで、Pは前のパイルx-1のトップブックです。
  4. 私たちは今、それを知っています:
    • 本は幅で降順でソートされているため、Bは厳密に* Pよりも幅が小さい
    • Bの高さはPよりも厳密に大きいか、Pの上にBを配置します

これで、すべての本(最初の山の本を除く)から、幅が大きく高さが低い前の山の本へのリンクが作成されました。

@ Sp3000の優れた図は、これをよく示しています。

最後のパイル(右側)から最初のパイル(左側)までの任意のパスをたどることにより、アンチパイルが得られます。重要なのは、この対抗杭の長さが杭の数に等しいことです。したがって、使用される杭の数は最小限です。

最後に、オーバーラップのない最小数のパイルに本を整理したので、オーバーラップを最小限に抑えて1つのパイルを得るためにそれらを積み重ねることができます。

* この役立つコメントはいくつかのことを説明しています


3
明確な証拠と議論へのリンクのために+1。xnor等への小道具。
COTO 14年

ディルワースの定理は証明全体を網羅するものではなく、最小数のパイルが最大サイズの反パイルに等しいという事実だけを明確にする必要があります。
xnor 14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.