Dans l'épisode Futurama, le prisonnier de Benda, les membres de l'équipage échangent leurs corps les uns avec les autres, avec la capture qu'aucune paire de corps ne peut avoir leur esprit échangé plus d'une fois.
Défi
Écrivez un programme ou une fonction qui accepte une collection valide de permutations corps-esprit qui se sont déjà produites et génère un ensemble légal de permutations qui ramènera chaque esprit à son corps d'origine. Les identifiants de ces collections corps-esprit doivent être des chaînes qui ne contiennent pas de nouvelles lignes. Vous pouvez ajouter jusqu'à deux personnes (distinctement nommées) qui n'ont eu aucun échange préalable dans le groupe d'entrée. (Preuve que vous n'avez besoin que d'au plus 2 corps supplémentaires) Cependant, vous devez ajouter le nombre minimum de personnes nécessaires pour résoudre le problème.
L'entrée et la sortie peuvent prendre n'importe quelle forme claire, cependant, aucune information supplémentaire ne peut être stockée dans l'un ou l'autre. Vous pouvez supposer qu'il est toujours valide. C'est le golf de code, donc le gagnant est la soumission avec le moins d'octets.
Exemples
[('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"
Celui du spectacle:
[("Amy","Hubert"),("Bender","Amy"),("Hubert","Turanga"),("Amy","Wash Bucket"),("Wash Bucket","Nikolai"),("Phillip","John"),("Hermes","Turanga")]
La solution de l'émission, donnée ci-dessous, n'est pas valide:
[("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")]
Ceci n'est pas valide car Ethan et Clyde ne sont pas nécessaires en raison du peu de Fry Phillip, Zoidberg John et Hermes Hermes qui ont utilisé la machine. Une solution valable pour ce cas est fournie ci-dessous:
[("Philip","Hubert"),("John","Wash Bucket"),("Philip","Turanga"),("John","Nikolai"),("Philip","Hermes"),("John","Bender"),("Philip","Amy"),("John","Hubert"),("Philip","Wash Bucket")]
Notez qu'il existe clairement de nombreuses réponses possibles pour toute entrée valide. Tout est valide.
[('Nikolai', 'Phillip'), ('Nikolai', 'Hubert'), ('Nikolai', 'Turanga'), ('Nikolai', 'Bender'), ('Phillip', 'Amy'), ('John', 'Wash Bucket'), ('Nikolai', 'John'), ('Phillip', 'Wash Bucket'), ('Hubert', 'John'), ('Bender', 'Hermes')]
Réponses:
Python 3: 328 caractères (lent), 470 caractères (rapide)
Probablement un peu trop long pour une réponse sérieuse.
Code lent et court:
d(u,s)
applique un swaps
àu
. Dans la méthode principalef(Q)
, je génère d'abord la liste de toutes les personnesn
utilisant les opérations set et convertissant le résultat en liste. Lawhile 1
boucle n'est bien sûr pas une boucle infinie. Dans ce document, j'essaie aussi de résoudre le problème en utilisant les personnes que j'ain
. Si cela ne réussit pas, j'ajoute une autre personne en combinant tous les nomsn+=[''.join(n)]
. Par conséquent, lawhile 1
boucle est exécutée au plus 3 fois (voir la preuve dans la question).La résolution du problème se fait par bruteforce. Je génère tous les swaps légaux et essaie toutes les permutations
for t in permutations(i for i in combinations(n,2)if not set((i,i[::-1]))&set(Q))
. Si chaque personne est dans son propre corps, je retourne la séquence des échanges.Usage:
L'exemple de futurama prend beaucoup trop de temps. Il y a 9 personnes, il y a donc 36 swaps possibles et 28 d'entre eux sont légaux. Il y en a donc 26! permutations légales.
Code plus rapide
La fonction
f(Q)
a une approche d'approfondissement itérative. Il essaie d'abord profondeur = 0, puis profondeur = 1, jusqu'à profondeur = (l * ll) // 2-len (Q), qui est le nombre maximal de mouvements légaux. Comme le code plus lent, il ajoute ensuite une autre personne et réessaye.La fonction récursive
r(n,u,Q,t,d)
essaie de résoudre la position actuelleu
avec desd
swaps.n
est la position résolue,Q
l'entrée se déplace ett
les mouvements déjà effectués. Il calcule d'abord une limite inférieure des swapsm
nécessaires (en résolvant l'état avec des swaps légaux et illégaux). Sim
== 0, toutes les personnes sont dans le bon corps, donc il imprime la solutiont
. Sinon, il essaie tous les swaps possibless
, ifm<d
(élagage),d>1
(qui est déjà inclus dansm<d
,i//l<i%l
(ne pas autoriser les swaps comme('A','A')
ou('A','B')
et('B','A')
) etnot set([s,s[::-1]])&set(Q+t)
(s
n'a pas encore été effectué).Usage:
Il trouve les échanges optimaux pour le problème futurama en environ 17 secondes sur mon ordinateur portable en utilisant du pypy et environ 2 minutes sans pypy. Notez que les deux algorithmes génèrent des solutions différentes, lors de l'appel avec le même paramètre. C'est à cause de l'algorithme de hachage d'un python-
set
.n
stocke la personne à chaque fois dans un ordre différent. Par conséquent, l'algorithme peut être plus rapide ou plus lent à chaque exécution.Edit: le scénario de test futurama d'origine était faux, le scénario de test corrigé a une solution optimale de 9 au lieu de 10, et est donc plus rapide. 2 secondes avec pypy, 7 secondes sans.
la source