並べ替えられたサブセットに基づいてマスターリストを並べ替える


19

最近、職場で解決すべき問題がありました。マスターリストと、マスターリスト内のアイテムのサブセットが異なる順序で含まれている可能性がある2つのリストがありました。リストにないアイテムの順序を変更せず、可能な限り同じ場所にアイテムを保持することなく、サブセット内のアイテムが同じ順序で表示されるように、マスターリストを並べ替える必要がありました。さて、それはおそらく混乱を招くように聞こえるので、私はそれを分解します:

  • マスターリストは、アイテムのデフォルトの順序を定義します。
  • サブセットリストは、特定のアイテムの相対的な順序を定義します。
  • マスターリストに2つの要素があり、サブセットリストに従って順序が狂っている場合、マスターリストの前の項目は、サブセットリスト内の他の項目に対して正しい位置にある最も早いインデックスに移動する必要があります。(つまり、後の項目の直後)

あなたの仕事は、この並べ替えアルゴリズムを実装することです。

テストケースの例

Master: [1, 2, 3]
Subset: []
Result: [1, 2, 3]

Master: [9001, 42, 69, 1337, 420]
Subset: [69]
Result: [9001, 42, 69, 1337, 420]

Master: [9001, 42, 69, 1337, 420, 99, 255]
Subset: [69, 9001, 1337]
Result: [42, 69, 9001, 1337, 420, 99, 255]

Master: [1, 2, 3, 4, 5]
Subset: [2, 5]
Result: [1, 2, 3, 4, 5]

Master: [apple, banana, carrot, duck, elephant]
Subset: [duck, apple]
Result: [banana, carrot, duck, apple, elephant]

Master: [Alice, Betty, Carol, Debbie, Elaine, Felicia, Georgia, Helen, Ilene, Julia]
Subset: [Betty, Felicia, Carol, Julia]
Result: [Alice, Betty, Debbie, Elaine, Felicia, Carol, Georgia, Helen, Ilene, Julia]

Master: [snake, lizard, frog, werewolf, vulture, dog, human]
Subset: [snake, werewolf, lizard, human, dog]
Result: [snake, frog, werewolf, lizard, vulture, human, dog]

Master: [Pete, Rob, Jeff, Stan, Chris, Doug, Reggie, Paul, Alex]
Subset: [Jeff, Stan, Pete, Paul]
Result: [Rob, Jeff, Stan, Pete, Chris, Doug, Reggie, Paul, Alex]

Master: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
Subset: [8, 1, 2, 12, 11, 10]
Result: [3, 4, 5, 6, 7, 8, 1, 2, 9, 12, 11, 10]

Master: [lol, rofl, lmao, roflmao, lqtm, smh, jk, wat]
Subset: [wat, lmao, rofl]
Result: [lol, roflmao, lqtm, smh, jk, wat, lmao, rofl]

ルール

  • 標準的な抜け穴、ヤッダ、ヤッダ、便利なI / O、なんとか。
  • 例では数値と​​文字列を使用しますが、整数、文字列、または言語で便利な場合は異種リストを含む明確に定義された等式セマンティクスを持つ他の何かであるかどうかにかかわらず、1つの要素タイプのみをサポートする必要があります。
  • マスターリストとサブセットリストの両方に重複がないと仮定できます
  • サブセットリストで見つかったすべてのアイテムがマスターリストで見つかったと想定できます。
  • どちらのリストも空かもしれません
  • 少なくとも、100要素までの配列をサポートする必要があります。
  • 並べ替えは、インプレースで、または新しいリスト/配列の作成を通じて実装できます。

ハッピーゴルフ!


1
素晴らしく、大きな問題。
ジョナ

8 1 3 4 5 6 7 2 9 12 11 10最後から2番目の1への有効な解決策は?
ヴェン

@Venいいえ。サブセットアイテムを同じ相対的な順序に保つという制約内に収まりますが、正しい答えが1つだけであることを確認したいので、以前の順序の悪いアイテムは、後の順不同のアイテム。
ビーフスター

複数の正解があることが重要なのはなぜですか?チャレンジのルールに制約を追加してください。
ヴェン

回答:


4

Retina 0.8.2、51バイト

+`(\b(\w+),(\w+)\b.*¶.*\b)\3,(.*\b\2\b)
$1$4,$3
1A`

オンラインでお試しください!入力を最初の行にあるサブワードのコンマ区切りリストとして、2行目にあるコンマ区切りの単語のマスターリストとして入力します。説明:

(\b(\w+),(\w+)\b.*¶.*\b)\3,(.*\b\2\b)

マスターリストで2番目の単語が最初の単語の前にある2つの隣接するサブワードを見つけます。

$1$4,$3

マスターリストの最初の単語の後に表示される2番目の単語を移動します。

+`

順不同の単語が表示されなくなるまで繰り返します。

1A`

サブワードを削除します。


4

JavaScript(ES6)、 96 89 74  71バイト

これはかさばった混乱として始まり、やがて簡潔でエレガントな形に縮小されました。感謝したい.splice()メソッドの実り多いコラボレーションにます。;)

入力をとして受け取ります(master)(subset)。マスターリストを更新して出力します。

m=>s=>s.map(p=x=>m.splice(p,0,...m.splice(i=m.indexOf(x),p>i||!(p=i))))

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

どうやって?

p

m.splice(p, 0, ...m.splice(i, condition))

1

  • 内側の.splice()は、位置の要素を削除して返します[element]
  • spread構文のおかげで、この要素は外側の.splice()の 3番目の引数として展開され、位置挿入されます。p

0

  • 内側の.splice()は何も削除せず、空の配列を返します
  • その結果、外側の.splice()は3番目の引数としてundefinedを受け取り、何も挿入されません

コメント済み

m => s =>                 // m[] = master list, s[] = subset list
  s.map(                  //
    p =                   // p = position in the master list of the last element from
                          //     the subset list (initialized to a non-numeric value)
    x =>                  // for each element x in the subset list:
    m.splice(             //   insert in the master list:
      p,                  //     at position p
      0,                  //     without removing any element
      ...m.splice(        //     remove from the master list and flatten:
        i = m.indexOf(x), //       i = position of x in the master list
        p > i             //       if p is greater than i, remove x from its current
                          //       position and insert it at position p
        || !(p = i)       //       otherwise, set p to i and don't remove/insert anything
      )                   //     end of inner splice()
    )                     //   end of outer splice()
  )                       // end of map()

1
.splice()メソッドに感謝します...」キューPPCGオスカーの音楽... :)
Chas Brown

より正確には、外側のスプライスコールはそれぞれ3つまたは2つの引数を受け取り、正しいことを行います。
ニール

2

Haskell、79バイト

(m:n)#u@(s:t)|m==s=m:n#t|all(/=m)u=m:n#u|(x,_:z)<-span(/=s)n=(x++s:m:z)#u
m#_=m

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

(m:n)#u@(s:t)                 -- m: head of master list
                              -- n: tail of master list
                              -- s: head of subset
                              -- t: tail of subset
                              -- u: whole subset
   |m==s                      -- if m==s
        =m:n#t                -- return 'm' and append a recursive call with 'n' and 't'
   |all(/=m)u                 -- if 'm' is not in 'u'
             =m:n#u           -- return 'm' and append a recursive call with 'n' and 'u'
   |                          -- else (note: 's' is element of 'n')
    (x,_:z)<-span(/=s)n       -- split 'n' into a list 'x' before element 's' and
                              -- a list 'z' after element 's' and
       = (x++s:m:z)#u         -- make a recursive call with
                              -- x++s:m:z as the new master list (i.e. 'm' inserted into 'n' after 's') 
                              -- and 'u'
m # _ = m                     -- if either list is emtpy, return the master list

2

ルビー73 68バイト

->a,b{0while b.zip(a&b).find{|m,n|m!=n&&a=a[0..a.index(m)]-[n]|a};a}

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

どうやって?

  • との交点にはa、のbすべての要素が含まれますbますが、a
  • したがって、b交差点を並行して繰り返し処理する場合、違いが見つかるとすぐに、単一の要素を再配置できます。
  • 再配置はa、私たちが見つけた要素の位置をカットすることで行われますb、次に交差点で見つかった要素を削除してから、aの残りを追加することます。
  • のすべての要素がb正しい順序になるまで、最初から繰り返しますa

0は何をしてい0whileますか?
ジョナ

それはただのNOPです。
GB

なぜ必要なのですか?
ヨナ

1
比較と操作は単一のブロックで行われるため、ループを開始する前に変数を宣言しないようにします。つまり、「操作がtrueを返している間は何もしない」、コードは「結果がtrueの間に操作を行う」より短い
GB


1

Perl 6、40バイト

{*.permutations.first(*.grep(.any)eq$_)}

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

カリー化された入力を受け取る匿名コードブロック(などf(subList)(masterList))、サブリストの要素が正しい順序にある​​マスターリストのインデックスの最初の辞書順列を見つけます。

直観的に、最初に満たされる置換は、正しく順序付けられた要素を元の順序のままにしますが、誤って配置された要素を正しい順序にするために必要最小限の距離だけ移動し、サブセット内の前の要素の直後に配置します。

説明:

{*                                     } # Anonymous code block that returns a lambda
  .permutations                          # In all permutations of the master list
               .first(                )  # Find the first permutation
                     (*.grep(.any)       # Where the order of the subset
                                  eq$_   # Is the same as the given order


1

ゼリー、9バイト

Œ!iⱮṢƑ¥ƇḢ

オンラインでお試しください!またはテストスイート

非効率的、特に大きなマスターリストの場合。可能なすべての順列を生成し、サブセットの順序が間違っている順列をフィルタリングして、最初の順列を返します。

説明

Œ!        | Generate all permutations of the master list
      ¥Ƈ  | Filter including only those where...
  iⱮ      |   the index of each sublist item in this permutation...
     Ƒ    |   is...
    Ṣ     |   in order. 
        Ḣ | Finally take the first item

これは、ルールに準拠していないようです。「サブセットリストによると、マスターリストに2つの要素の順序が狂っている場合、マスターリストの前の項目を、それが存在する最も早いインデックスに移動する必要があります。サブセットリスト内の他のアイテムに関連する正しい位置(つまり、後のアイテムの直後) "
Beefster

@Beefsterこれは今まで試したもので動作します。順列の順序はこれが正しい結果であると思います。反例がある場合、間違っていることが証明されてうれしいです。
ニックケネディ

@Beefster女性の名前と1..12を除くすべての例を試しましたが、結果の順序は正しいです。
ニックケネディ

2
@Beefster 私の答えは、なぜ、この作品のための部分的な説明がある
ジョー・キング

1

J、49バイト

[:(<@({:+i.@>:@-/)@i.~C.])^:(>/@i.~)&.>/]|.@;2<\[

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

説明

サブセットを左引数として、完全な入力を右引数として使用します。

明確にするために、特定の例を使用してコードを処理します。

5 2 4 f 1 2 3 4 5

サブセットのサイズ2のボックス化されたインフィックスを取得します。

2 <\ [

生産:

┌───┬───┐
│5 2│2 4│
└───┴───┘

それらを元の入力に追加し、全体を逆にします。

] |.@;

我々が得る:

┌───┬───┬─────────┐
│2 4│5 2│1 2 3 4 5│
└───┴───┴─────────┘

問題の解決は、上記の右から左への削減になります。/アイテム間に挿入するための正しい動詞を見つけるだけです。

縮約の各反復により、右端のボックス(変換中の完全な入力)が更新され、左のペアで表される順序制約に準拠します。縮小が完了すると、入力は完全なサブセットの順序を尊重します。

ペアの順序が入力の順序と同じ場合、以下は0と評価され、何もしません。

^:(>/@i.~)

それ以外の場合は1に評価され、動詞を左側に適用します ^:

   {: + i.@>:@-/)@i.~ C. ]

左のアイテムを右のアイテムの右に移動します。この移動は、問題の2つの要素間(およびそれらを含む)のすべての項目の単純な順列です。

Jには、このような巡回置換を適用するプリミティブがあります。

<cyclic permutation definition> C. ]

そして、動詞の残りの部分は、サイクルに必要なインデックスを選択するだけです。

{: + i.@>:@-/)@i.~

それは本来あるべきより長いように思えますが、私はそのフレーズをさらにゴルフすることができませんでした。

最後に結果を再ボックス化し、<@完了です。


0

ゼリー、24バイト

i@€MƤFṬœṗƲḊ;JḟF}W€ʋ@¥ṢFị

オンラインでお試しください!またはテストスイート

説明

サブセットを左引数として、マスターリストを右引数としてとるダイアディックリンク。以下の例では、9001、42、69、1337、420、99、255をマスターとして、69、9001、1337をサブセットとして使用しています。

i@€                      | Find the index of each subset item in the master list [3, 1, 4]
         Ʋ               | Previous 4 links as a monad
   MƤ                    | Find the index of the maximum for each prefix of this list [1, 1, 3]
     F                   | Flatten (because the previous result are actually each length one lists)
      Ṭ                  | Convert to a boolean list [1,0,1]
       œṗ                | Partition the [3, 1, 4] list before each 1 [[], [3, 1], [4]]
          Ḋ              | Remove the empty first list [[3, 1], [4]]
                    ¥    | Previous two links as a dyad
                  ʋ@     | Previous 4 links as a dyad with reversed arguments
            J            | Sequence along the master list [1, 2, 3, 4, 5, 6, 7]
             ḟF}         | Filter out items in the flattened [3, 1, 4] list
                W€       | Wrap each item as a list [[2], [5], [6], [7]]
           ;             | Concatenate rhis to the [[3, 1], [4]] list
                     Ṣ   | Sort (effectively by first item in each list) [[2], [3, 1], [4], [5], [6], [7]]
                      F  | Flatten
                       ị | Look up in original master list (and implicitly output)

0

C#(Visual C#Interactive Compiler)、118バイト

a=>b=>{for(int j;b.Any();)foreach(var e in b.Intersect(a.Take(j=a.IndexOf(b.Dequeue())))){a.Remove(e);a.Insert(j,e);}}

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

System.Collections.Generic名前空間の一部のクラスを活用します。マスターはList<T>で、サブセットはQueue<T>です。

// a: master
// b: subset
a=>b=>{
  // continue until b is empty
  for(int j;b.Any();)
    // iterate over values that are out of order in a
    // per the head of b using loop variable e
    foreach(var e in
      // the out of order values are determined by
      // intersecting remaining values in b with
      b.Intersect(
        // values in a occurring before the current head of b
        // save the position in a to variable j and remove the head of b
        a.Take(j=a.IndexOf(b.Dequeue()))
      )
    ){
      // push back the out of order element in a
      a.Remove(e);
      a.Insert(j,e);
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.