ネックレス分割問題


19

バックグラウンド

3Blue1Brownネックレス分割問題(または盗難ネックレス問題)とBorsuk-Ulam定理との関係に関する最近のビデオに触発されました

この問題では、2人の泥棒がいくつかの異なる種類の宝石で構成される貴重なネックレスを盗みました。各タイプの宝石は偶数個あり、泥棒はそれぞれのタイプの宝石を2つに均等に分割したいと考えています。キャッチは、ネックレスをいくつかの連続したセグメントに分割し、それらの2つの間にセグメントを分配することによってそうしなければならないということです。

ここで示される4つの宝石の種類の一例でありSED、およびR(それぞれ、サファイア、エメラルド、ダイヤモンド、ルビーのために)。ネックレスは次のようだとしましょう:

[S,S,S,E,S,D,E,R,S,R,E,S,S,S,D,R,E,E,R,E,D,E,R,R,D,E,E,E]

あり8サファイヤ、10エメラルド、4ダイヤモンド、そして6ルビーは。ネックレスは次のように分割できます。

[[S],[S],[S,E,S,D,E,R,S],[R,E,S,S,S,D,R,E,E,R,E,D,E],[R,R,D,E,E,E]]

次に、1番目の泥棒に1番目、3番目、5番目のセグメントを、もう1つの泥棒に2番目と4番目のセグメントを与えると、それぞれが4サファイア、5エメラルド、2ダイヤモンド、3ルビーになります。

[S],    [S,E,S,D,E,R,S],                            [R,R,D,E,E,E]
    [S],                [R,E,S,S,S,D,R,E,E,R,E,D,E],

0-indexing を使用すると、これらのカットはインデックスで発生します[1,2,9,22]

ゴール

そのような公正な分割は、多くのn場合、常にn宝石の種類の数であるカットを使用して行うことができます。あなたの仕事は、入力としてネックレスを取り、最小のそのような分割(最少のカット数)を出力する完全なプログラムまたは関数を書くことです。

入力

入力は任意の便利な形式にすることができます。ネックレスは一連の宝石である必要があります。たとえば、整数のリスト、宝石の種類を表すキーを持つ辞書、およびインデックスのリストである値。必要に応じて、ネックレスの長さや宝石の種類の数を含めることもできますが、他の入力を行わないでください。

入力ネックレスが有効であるとみなすことができます。特定の種類の宝石の数が奇数である場合や、ネックレスが空の場合に対処する必要はありません。

出力

繰り返しますが、出力は任意の便利な形式にすることができます。たとえば、セグメントのリスト、カット位置のリスト、2つの泥棒を表すキーを持つ辞書、セグメントのリストである値など。セグメントは、開始インデックス、終了インデックス、連続インデックスのリスト、宝石のリスト、それらの長さ、などあなたは使用することができます0-または1-インデックスを。順序がフォーマットにとって重要でない場合、出力は任意の順序になります。上記の出力をいくつかの異なる形式で示します。

list of segments: [[S],[S],[S,E,S,D,E,R,S],[R,E,S,S,S,D,R,E,E,R,E,D,E],[R,R,D,E,E,E]]
list of cuts:     [1,2,9,22]
list of lengths:  [1,1,7,13,6]
dictionary:       {'thief1' : [(R,R,D,E,E,E),(S),(S,E,S,D,E,R,S)], 'thief2' : [(S),(R,E,S,S,S,D,R,E,E,R,E,D,E)]}

セグメントのリスト(泥棒の間で交互になっているセグメント)と長さのリスト(セグメントを識別するため)では順序が重要ですが、カットのリストや辞書では重要ではありません。編集:グレッグ・マーティンは、2つのカットで公正な分割が得られるため、これらは有効な出力ではないと指摘した。

テストケース

[1,2,1,2,1,3,1,3,3,2,2,3] -> [[1,2,1],[2,1,3,1],[3,3,2],[2,3]]
[1,1,1,1,2,2,3,3,3,3,3,3] -> [[1,1],[1,1,2],[2,3,3,3],[3,3,3]]
[1,1,1,1,1,1,1,1,1,1,1,1] -> [[1,1,1,1,1,1],[1,1,1,1,1,1]]
[1,1,1,1,2,3,4,2,3,4,2,2] -> [[1,1],[1,1,2,3,4,2],[3,4,2,2]]

ノート

  1. 標準的な抜け穴は禁止されています。
  2. これはです。最短回答(バイト単位)が勝ちます。

2
ネックレスは円形ですか?
デニス

1
@Dennisいいえ、ネックレスは線形です。
ngenisis

1
入力を整数ではなく、異なる宝石タイプを示す文字/トークンとして受け取ることはできますか?
グレッグマーティン

3
セグメントの順序が変更されない場合、断片はif Aとtheif Bの間で交互に切り替わります。そのため、出力にその情報を含めることは冗長です。答えが宝石の順序を変えない場合、theif表示を省略できますか?テストケースはありますか?
ルーク

2
あなた例えば[S,S,S,E,S,D,E,R,S,R,E,S,S,S,D,R,E,E,R,E,D,E,R,R,D,E,E,E]、出力があるべきと思われる[[S,S,S,E,S,D,E,R],[S,R,E,S,S,S,D,R,E,E,R,E,D,E],[R,R,D,E,E,E]]ことがより少ないカットを有しているので、[[S],[S],[S,E,S,D,E,R,S],[R,E,S,S,S,D,R,E,E,R,E,D,E],[R,R,D,E,E,E]]。仕様を正しく理解していますか?
グレッグマーティン

回答:


3

ブラキログ、13バイト

~c.ġ₂z₁Ċcᵐoᵛ∧

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

注:メタ述語はこのチャレンジよりも新しいです。

説明

~c.ġ₂z₁Ċcᵐoᵛ∧  Input is a list, say L = [1,2,2,2,1,2,3,3]
~c.            Output is a partition of the input: [[1,2,2],[2,1,2],[3],[3]]
  .ġ₂          Split the output into chunks of length 2: [[[1,2,2],[2,1,2]],[[3],[3]]]
     z₁        Zip (transpose) the chunks: [[[1,2,2],[3]],[[2,1,2],[3]]]
       Ċ       This is a 2-element list (forbid the trivial partition).
        cᵐ     Concatenate both: [[1,2,2,3],[2,1,2,3]]
          oᵛ   If you sort both lists, they are equal.
            ∧  Don't unify with the output.

パーティションはブロック数の昇順で列挙されるため、結果のブロック数は可能な限り少なくなります。


3

ゼリー、18 バイト

s2ZFṢ$€E¬,L
ŒṖṖÇÞḢ

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

効率的ではありません- この実装には28個の宝石がありますが、この実装の最初のステップは2つの27可能なパーティションの。

リストのリストを返します-交互の泥棒の間でそれらを分配する順序でセグメント。(TIOの出力について:リストに単一の項目しかない場合、暗黙の印刷は角括弧に煩わされず、[]

どうやって?

s2ZFṢ$€E¬,L - Link 1, get (isUnfair, Slices): A possible partition
s2          - split into slices of length 2 (any odd one on it's own at the end)
  Z         - transpose (first item is one thief's slices, second is the others)
     $€     - last two links as a monad for €ach
   F        -     flatten
    Ṣ       -     sort
       E    - equal? (theif1's jewels == theif2's jewels)
        ¬   - not
          L - length (number of slices in the partition)
         ,  - pair

ŒṖṖÇÞḢ - Main link: necklace
ŒṖ     - all partitions
  Ṗ    - pop, we must remove the rightmost one...
              because Link 1 will say it is fair, and it will have length 1!
              (a list of one thing has all entries equal)
    Þ  - sort by
   Ç   -     last link (1) as a monad
     Ḣ - head (get the first one, i.e. minimal isUnfair, then minimal length)

3

Mathematica、118バイト

ほとんどゼリーを打つ...わずか1オフ;)

SelectFirst[l_±c_:=Append[-#±Most@c,#2]&@@l~TakeDrop~Last@c;l_±{}:={l};i=#;(i±#)&/@Range@#2~Subsets~#3,Tr[Tr/@#]==0&]&

3つの引数を取る純粋な関数:ネックレス、{A, A, A, A, B, C, D, B, C, D, B, B}; などのトークンのリスト。ネックレスの長さ; ジュエルタイムの数。サブリストのリストをの形式で返します{{A, A}, {-A, -A, -B, -C, -D, -B}, {C, D, B, B}}。ここでは、マイナス記号のないトークンは1つの泥棒に行き、マイナス記号のあるトークンはもう1つの泥棒に行きます。(これは冗長な情報ですが、アルゴリズムはこの表現につながり、負の符号を削除すると数バイトかかります。)

最初に、リストとnカットプレースのセットを取り、n+1それらのnカットプレースで入力リストをカットすることによって取得されたサブリストのリストを返す関数を実装する必要があります。二項中置演算子±はこの目的に使用され、を通じて再帰的に定義されl_±c_:=Append[-#±Most@c,#2]&@@l~TakeDrop~Last@c;l_±{}:={l};ます。直後のマイナス記号のためAppend、結果として、サブリストは各トークンに負符号を交互に付けたり付けたりしません。

次に、を使用して長さが最大で宝石タイプの数であるすべての可能なカットプレースセットを生成しRange@#2~Subsets~#3、を使用i=#;(i±#)&/@して±演算子を(宝石の入力リストとともに)これらのカットプレースセットのそれぞれに順番に適用します。

最後に、SelectFirst[...,Tr[Tr/@#]==0&]&結果として得られる最初の公正なネックレス部門を選択します。これは、すべてのサブリスト内のすべての要素を文字通り加算することにより行われます。Mathematicaは各トークンの正と負のコピーを明白な方法でキャンセルするのに十分賢明です。


3

Pyth、16バイト

hfqFSMsM.TcT2t./

オンラインで試す:デモンストレーションまたはテストスイート

説明:

hfqFSMsM.TcT2t./Q   implicit Q (=input) at the end
              ./Q   create all partitions of the input list 
                    (they are already sorted by number of cuts)
             t      remove the partition with zero splits
 f                  filter for partitions T, which satisfy:
          cT2          chop into pieces of length 2
        .T             transpose to get the pieces of each thieve
    SMsM               combine all pieces for each thieve and sort the results
  qF                   check if they got the same jewels
h                   print the first such partition

1

05AB1E、14 バイト

.œ¨ʒ2ôζε˜{}Ë}¤

オンラインそれを試してみたり、すべてのテストケースを検証します

説明:

                # All partitions of the (implicit) input
                  #  i.e. [2,3,2,1,3,1]
                  #   → [[[2],[3],[2],[1],[3],[1]],[[2],[3],[2],[1],[3,1]],
                  #      ...,[[2,3,2,1,3,1]]]
  ¨               # Remove the last one
   ʒ        }     # Filter this list by:
    2ô            # Split it into parts of 2
                  #  i.e. [[2,3],[2],[1],[3,1]] → [[[2,3],[2]],[[1],[3,1]]]
                  #  i.e. [[2,3,2],[1,3],[1]] → [[[2,3,2],[1,3]],[[1]]]
      ζ           # Swap rows and columns (using space as filler if necessary)
                  #  i.e. [[[2,3],[2]],[[1],[3,1]]] → [[[2,3],[1]],[[2],[3,1]]]
                  #  i.e. [[[2,3,2],[1,3]],[[1]]] → [[[2,3,2],[1]],[[1,3]," "]]
       ε  }       # Map each inner list to:
        ˜         # Flatten the list
                  #  i.e. [[2,3],[1]] → [2,3,1]
                  #  i.e. [[1,3]," "] → [1,3," "]
         {        # Sort the list
                  #  i.e. [2,3,1] → [1,2,3]
                  #  i.e. [1,3," "] → [1,3," "]
           Ë      # Check if both sorted lists are equal
                  # (if not, remove them from the partitions)
             ¤    # After filtering, take the last one as result (and output implicitly)
                  #  i.e. [[[2],[3,2],[1,3],[1]],[[2,3],[2],[1],[3,1]]]
                  #   → [[2,3],[2],[1],[3,1]]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.