Kötü Haber, Birisi


10

Futurama bölümde Benda Tutsağı hiçbir çifti o yakalamak ile birbirleri ile mürettebat takas kuruluşlarının üyelerinin, organları akıllarını olabilir kereden fazla takas.

Meydan okuma

Zaten gerçekleşmiş geçerli bir zihin-beden swap koleksiyonunu kabul eden ve her zihni orijinal bedenine döndürecek yasal bir dizi swap veren bir program veya işlev yazın. Bu zihin-beden koleksiyonları için tanımlayıcılar, yeni satırlar içermeyen dizeler olmalıdır. Giriş grubuna önceden takasları olmayan en fazla iki (belirgin olarak adlandırılmış) kişi ekleyebilirsiniz. (Yalnızca en fazla 2 ek gövdeye ihtiyacınız olduğunu kanıtlayın) Ancak, sorunu çözmek için gereken minimum sayıda kişiyi eklemeniz gerekir.

Giriş ve çıkış herhangi bir net biçimde olabilir, ancak hiçbir ek bilgi saklanamaz. Her zaman geçerli olduğunu varsayabilirsiniz. Bu kod golf, yani kazanan en az bayt ile sunulmasıdır.

Örnekler

[('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"

Gösteriden:

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

Şovun aşağıda verilen çözümü geçersiz:

[("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")]

Bu geçersiz çünkü Ethan ve Clyde, Fry Phillip, Zoidberg John ve Hermes Hermes'in makineyi ne kadar az kullandıkları için gereksiz . Bu dava için geçerli bir çözüm aşağıda sunulmuştur:

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

Geçerli herhangi bir giriş için birçok olası cevabın açıkça bulunduğunu unutmayın. Herhangi biri geçerlidir.


Kullanılmayacağını varsayabileceğimiz bazı isimler var mı?
feersum

@feersum Hayır, mücadelenin bir parçası;)
FryAmTheEggman

1
@feersum Bütün girdiyi dize olarak aldıysanız mı demek istediniz? Ancak evet, ancak adların aralarında satırsonu olmadığını varsayabilirsiniz. (bunu şimdi düzenliyor)
FryAmTheEggman

1
Şovun girdisi için çözümünüz çalışmıyor. Amy ve Bender sonunda takas edilir. Doğru çözüm[('Nikolai', 'Phillip'), ('Nikolai', 'Hubert'), ('Nikolai', 'Turanga'), ('Nikolai', 'Bender'), ('Phillip', 'Amy'), ('John', 'Wash Bucket'), ('Nikolai', 'John'), ('Phillip', 'Wash Bucket'), ('Hubert', 'John'), ('Bender', 'Hermes')]
Jakube

1
@ Jakube Üzgünüz, şovun durumuna girerken yazım hatası yaptığım anlaşılıyor. Şimdi düzeltildiğine ve çözümün iyi olduğuna inanıyorum.
FryAmTheEggman

Yanıtlar:


3

Python 3: 328 karakter (yavaş), 470 karakter (hızlı)

Muhtemelen ciddi bir cevap için biraz uzun.

Yavaş ve kısa kod:

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)bir takas uygular siçin u. Ana yöntemde f(Q), önce nset işlemlerini kullanarak ve sonucu tekrar bir listeye dönüştürerek tüm kişilerin listesini oluşturuyorum. while 1-Loop ki değil bir sonsuzluk döngünün olduğunu. İçinde, problemi içinde bulunduğum kişileri kullanarak çözmeye çalışıyorum n. Başarılı olmazsa, tüm isimleri birleştirerek başka birini eklerim n+=[''.join(n)]. Bu nedenle while 1-loop en fazla 3 kez yürütülür (sorudaki ispatı inceleyin).

Sorunun çözümü kaba kuvvetle yapılır. Yasal olan tüm takasları oluşturur ve tüm permütasyonları denerim for t in permutations(i for i in combinations(n,2)if not set((i,i[::-1]))&set(Q)). Her insan kendi vücudundaysa, takas sırasını döndürürüm.

Kullanımı:

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

Futurama örneği çok uzun sürüyor. 9 kişi var, bu yüzden 36 olası takas var ve 28 tanesi yasal. Yani 26 tane var! yasal permütasyonlar.

Daha hızlı kod

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)

Fonksiyon f(Q)yinelemeli bir derinleşme yaklaşımına sahiptir. İlk önce derinlik = 0, sonra derinlik = 1, derinlik = (l * ll) // 2-len (Q) olana kadar çalışır; bu, maksimum yasal hareket sayısıdır. Yavaş kod gibi, başka bir kişi ekler ve tekrar dener.

Özyinelemeli fonksiyon r(n,u,Q,t,d)mevcut konumu çözmeye çalışır uile dtakası. nçözülmüş konumdur, Qgiriş hareket eder ve thareketler zaten yapılır. İlk önce mihtiyaç duyulan takas alt sınırını hesaplar (devleti yasal ve yasa dışı takaslarla çözerek). Eğer mbu çözüm basılır == 0, herkesin, doğru vücutta bulunmaktadır t. Aksi takdirde olası tüm takaslarını çalışırsa seğer, m<d(budama), d>1zaten dahil olan ( m<d, i//l<i%l(izin vermez gibi swap ('A','A')ya ('A','B')ve ('B','A')) ve not set([s,s[::-1]])&set(Q+t)( s) henüz yapılmamıştır.

Kullanımı:

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

Futurama problemi için en uygun swapları pypy kullanarak dizüstü bilgisayarımda yaklaşık 17 saniye içinde ve pypy olmadan yaklaşık 2 dakika içinde bulur. Her iki algoritmanın da aynı parametre ile çağrılırken farklı çözümler ürettiğine dikkat edin. Bunun nedeni, bir python'un hash algoritmasıdır set. nkişiyi her seferinde farklı bir sırada saklar. Bu nedenle algoritma her çalıştırmada daha hızlı veya daha yavaş olabilir.

Düzenleme: Orijinal futurama test durumu yanlıştı, düzeltilmiş test durumu 10 yerine 9'un en uygun çözümüne sahip ve bu nedenle daha hızlı. Pypy ile 2 saniye, 7 saniye olmadan.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.