悪いニュース、誰か


10

フューチュラマエピソードでは、乗組員のベンダの囚人のメンバーが遺体を交換しましたが、遺体のペアが2度以上心を交換することはできません。

チャレンジ

既に発生している心身のスワップの有効なコレクションを受け入れ、それぞれの心を元の体に戻す正当なスワップのセットを出力するプログラムまたは関数を記述します。これらの心身のコレクションの識別子は、改行を含まない文字列である必要があります。入力グループには、以前にスワップしたことがない2人まで(明確に名前が付けられた)人を追加できます。(必要な証明は、追加のボディが2つだけであること)ただし、問題を解決するために必要な最小限の人数を追加する必要があります。

入力と出力はどのような形式でもかまいませんが、追加の情報を格納することはできません。常に有効であると考えるかもしれません。これはコードゴルフなので、バイト数が最も少ない送信が勝者です。

[('A','B'),('C','D')] -> [('A','C'),('B','D'),('A','D'),('B','C')]

['A','B'] -> ['C','D','A','C','B','D','A','D','B','C']

[('A','B'),('C','D'),('A','C'),('A','D')] -> [('B', 'E'), ('A', 'E'), ('C', 'B'), ('C', 'E')]

"A\nB\nC\nD\n" -> "A\nC\nB\nD\nA\nD\nB\nC\n"

ショーからのもの:

[("Amy","Hubert"),("Bender","Amy"),("Hubert","Turanga"),("Amy","Wash Bucket"),("Wash Bucket","Nikolai"),("Phillip","John"),("Hermes","Turanga")]

以下に示すショーのソリューションは無効です。

[("Clyde","Phillip"),("Ethan","John"),("Clyde","John"),("Ethan",Phillip"),("Clyde","Hubert"),("Ethan","Wash Bucket"),("Clyde","Leela"),("Ethan","Nikolai"),("Clyde","Hermes"),("Ethan","Bender"),("Clyde","Amy"),("Ethan","Hubert"),("Clyde","Wash Bucket")]

イーサンとクライドはフライフィリップ、ゾイドバーグジョン、ヘルメスヘルメスがマシンをほとんど使用しなかったので不要なので、これは無効です。この場合の有効な解決策を以下に示します。

[("Philip","Hubert"),("John","Wash Bucket"),("Philip","Turanga"),("John","Nikolai"),("Philip","Hermes"),("John","Bender"),("Philip","Amy"),("John","Hubert"),("Philip","Wash Bucket")]

有効な入力には、明らかに多くの回答が考えられることに注意してください。いずれも有効です。


使用しないと想定できる名前はありますか?
feersum

@feersum Nope、チャレンジの一部;)
FryAmTheEggman

1
@feersum入力全体を文字列として受け取ったかどうか。そうであれば、ただし、名前の間に改行がないと仮定できます。(これを今編集しています)
FryAmTheEggman

1
番組の入力に対するソリューションが機能しません。エイミーとベンダーは最後に入れ替えられます。正しい解決策は次のようになります[('Nikolai', 'Phillip'), ('Nikolai', 'Hubert'), ('Nikolai', 'Turanga'), ('Nikolai', 'Bender'), ('Phillip', 'Amy'), ('John', 'Wash Bucket'), ('Nikolai', 'John'), ('Phillip', 'Wash Bucket'), ('Hubert', 'John'), ('Bender', 'Hermes')]
ジャクベ2015年

1
@Jakube申し訳ありませんが、ショーのシチュエーションに参加する際に入力ミスをしたようです。私はそれが今修正されたと信じており、解決策は大丈夫です。
FryAmTheEggman 2015年

回答:


3

Python 3:328文字(遅い)、470文字(速い)

真剣な答えにはおそらく長すぎます。

遅くて短いコード:

from itertools import*
def d(u,s):i,j=map(u.index,s);u[i],u[j]=u[j],u[i]
def f(Q):
 n=set()
 for s in Q:n|=set(s)
 n=list(n)
 while 1:
  for t in permutations(i for i in combinations(n,2)if not set((i,i[::-1]))&set(Q)):
   u=n[:];j=0
   for s in Q:d(u,s)
   for s in t:
    j+=1;d(u,s)
    if n==u:return t[:j]
  n+=[''.join(n)]

d(u,s)にスワップsを適用しuます。メインの方法ではf(Q)、最初にn集合演算を使用してすべての人物のリストを生成し、結果をリストに変換します。while 1-loopはもちろんない無限ループです。その中で、私もの人たちを使って問題を解決しようとしていnます。うまくいかない場合は、すべての名前を組み合わせて別の人を追加しますn+=[''.join(n)]。したがって、while 1-loopは最大3回実行されます(質問の証明を参照)。

問題の解決は総当たりです。正当なすべてのスワップを生成し、すべての順列を試しますfor t in permutations(i for i in combinations(n,2)if not set((i,i[::-1]))&set(Q))。各人が自分の体の中にいる場合は、スワップのシーケンスを返します。

使用法:

print(f([('A','B'),('C','D')]))
print(f([('A','B')]))
print(f([('A','B'),('C','D'),('A','C'),('A','D')]))

futuramaの例は時間がかかりすぎます。9人がいるので、36の可能なスワップがあり、そのうち28が合法です。26個あります!法的順列。

より高速なコード

def w(u,s):i,j=map(u.index,s);u[i],u[j]=u[j],u[i]
def f(Q):
 n=set()
 for s in Q:n|=set(s)
 while 1:
  n=list(n);u=n[:];l=len(n)
  for s in Q:w(u,s)
  for d in range((l*l-l)//2-len(Q)+1):r(n,u,Q,[],d)
  n+=[''.join(n)]
def r(n,u,Q,t,d):
 m=0;v=u[:];l=len(u)
 for i in range(l):
  if n[i]!=v[i]:m+=1;w(v,(n[i],v[i]))
 if m<1:print(t);exit()
 for i in range(l*l):
  s=n[i//l],n[i%l]
  if m<=d and i//l<i%l and not set([s,s[::-1]])&set(Q+t):v=u[:];w(v,s);r(n,v,Q,t+[s],d-1)

関数f(Q)には反復的な深化アプローチがあります。最初にdepth = 0を試行し、次にdepth = 1を試行します。これは、正当な移動の最大数であるdepth =(l * ll)// 2-len(Q)までです。遅いコードと同様に、別の人を追加して再試行します。

再帰関数r(n,u,Q,t,d)は現在の位置udスワップで解決しようとします。n解決された位置です。Q入力は移動しt、移動はすでに完了しています。まず、m必要なスワップの下限を計算します(合法的および不法なスワップで状態を解決することにより)。m== 0の場合、すべての人が正しい身体にいるので、解が出力されますt。それ以外の場合sは、m<d(プルーニング)、d>1(既にに含まれているm<di//l<i%l('A','A')or ('A','B')およびandのようなスワップを許可しない('B','A'))、およびnot set([s,s[::-1]])&set(Q+t)sまだ実行されていない)場合に、可能なすべてのスワップを試行します。

使用法:

f([("Amy","Hubert"),("Bender","Amy"),("Hubert","Turanga"),("Amy","Wash Bucket"),("Wash Bucket","Nikolai"),("Philip","John"),("Hermes","Turanga")])

pypyを使用している私のラップトップでは約17秒、pypyなしでは約2分でフューチュラマ問題の最適なスワップが見つかります。同じパラメーターで呼び出すと、両方のアルゴリズムが異なるソリューションを出力することに注意してください。これは、python-のハッシュアルゴリズムが原因setです。nその人を毎回異なる順序で保管します。したがって、アルゴリズムは実行ごとに速くなったり遅くなったりします。

編集:元のフューチュラマテストケースは間違っていました。修正されたテストケースの最適解は10ではなく9であるため、より高速です。pypyで2秒、なしで7秒。

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