Générez un Portmantout!

16

Contexte

Il y a trois ans, ce type Tom Murphy s'est mis en tête d'étendre l'idée d'un portemanteau à tous les mots dans une langue et a appelé cela un portmantout ( portmanteau plus tout [français pour tous ]). Définissant l'anglais comme une liste de 108 709 mots, il a réussi à trouver une séquence de 611 820 lettres avec les deux propriétés suivantes:

  • Chaque mot anglais est contenu dans la chaîne.
  • Un quartier contenant deux lettres adjacentes dans la chaîne est un mot anglais.

Voici un lien vers une page sur laquelle ce portmantout peut être trouvé (avec une explication vidéo).

Un portemantout

La première des deux propriétés d'un portmantout est facile à comprendre. La seconde peut nécessiter quelques explications.

Fondamentalement, les mots doivent se chevaucher. "golfcode" n'apparaîtra jamais dans un portmantout de l'anglais, car il n'y a aucun mot qui contient le "fc". Cependant, vous pouvez trouver "codegolf" dans un portmantout, car "ego" comble l'écart (et toutes les autres paires de lettres sont soit en "code" soit en "golf").

Ta tâche:

Écrivez un programme ou une fonction qui prend une liste de chaînes et renvoie tout portmantout de la liste.

Ce code Python 3 vérifiera un portmantout.

Cas de test

Toutes les listes ne sont pas ordonnées; C'est,

{"code", "ego", "golf"} -> "codegolf"
{"more", "elm", "maniac"} -> "morelmaniac" or "morelmorelmaniac" or "morelmorelmorelmaniac" or...
    Would a morelmaniac be some sort of mycologist?
{"ab", "bc", "cd", "de", "ef", "fg", "gh", "hi", "ij", "jk", "kl", "lm", "mn", "no", "op", "pq", "qr", "rs", "st", "tu", "uv", "vw", "wx", "xy", "yz", "za"} -> "abcdefghijklmnopqrstuvwxyza" or "rstuvwxyzabcdefghijklmnopqrstuvwxyzabcdef" or any 27+ letters in order

Et pourquoi pas? L'énorme sur le site de Murphy, si votre code s'exécute dans un délai raisonnable.

Règles

  • Votre code doit s'arrêter.
  • Vous n'avez pas besoin de renvoyer le même portmantout à chaque exécution.
  • Vous pouvez prendre toutes les chaînes se composent de lettres minuscules seulement apar z.
  • Si aucun portmantout n'est possible, votre programme peut faire n'importe quoi. Ex:{"most", "short", "lists"}
  • Les règles standard pour les E / S et les failles s'appliquent.

Il s'agit de , donc la solution la plus courte (en octets) dans chaque langue gagne! Bon golf!

Khuldraeseth na'Barya
la source
Sandbox
Khuldraeseth na'Barya
1
Peut-être quelques cas de test?
Adám
{"sic", "bar", "rabbits", "cradle"} -> "barabbitsicradle" {"mauve", "elated", "cast", "electric", "tame"} -> "mauvelectricastamelated"(plus de cas de test)
Sundar
2
Ouais, peut-être un testcase où un mot doit être utilisé deux fois
ASCII uniquement
2
Aurons-nous jamais des mots d'une lettre?

Réponses:

3

Python 2 , 204 202 octets

def f(l,s=''):
 if all(w in s for w in l):return s
 for i,w in enumerate(l):
	a=next((s+w[i:]for i in range(len(w)-1,0,-1)if s[-i:]==w[:i]),0)if s else w;x=a and f(l[:i]+l[i+1:]+[l[i]],a)
	if x:return x

Essayez-le en ligne!


Enregistré

  • -2 octets, grâce à récursif
TFeld
la source
Vous pouvez utiliser des onglets sur les deux dernières lignes pour enregistrer 2 octets.
récursif
200 octets .
Jonathan Frech
Cela ne produit pas la sortie correcte pour ["ab", "ba", "ca"]. Ma solution a le même bug.
récursif
1

Pyth, 39 octets

JQW}_1mxbdQ=+J|=b*qKOQ<=T+OP._KOJlKTY)b

Essayez-le ici

Explication

JQW}_1mxbdQ=+J|=b*qKOQ<=T+OP._KOJlKTY)b
JQ                                        Get a copy of the input.
  W}_1mxbdQ                          )    While there are words in the input
                                          that aren't in b (initially space)...
                   KOQ    OP._KOJ         ... get a random input word, a random
                                          prefix, and a random joined word...
                       =T+                ... stick them together...
                  q   <          lKT      ... and check if joining them together
                                          is valid...
               =b*                        ... then update b accordingly...
           =+J|                     Y     ... and stick the new word into J.
                                      b   Output the final result.

la source
1

Stax , 39 36 octets

ä▬│•.k=╠lƒ☺╜00║¿~,▓╕╠7ÉΔB<e┼>☼Θ²└ô┴\

Exécuter et déboguer

Exécute tous les cas de test de manière déterministe en environ une seconde.

Il s'agit d'un algorithme récursif.

  • Commencez par chaque mot d'entrée en tant que candidat
  • À chaque étape, triez les mots par le nombre de fois où ils apparaissent comme sous-chaînes du candidat.
  • Pour chaque mot compatible avec la fin du candidat actuel, joignez le mot pour former un nouveau candidat et effectuez un appel récursif.

Voici le programme décompressé, non golfé et commenté.

FG              for each word in input, call target block
}               unbalanced closing brace represents call target
  x{[#o         sort input words by their number of occurrences in the current candidate
  Y             store it in register Y
  h[#{,}M       if all of the words occur at least once, pop from input stack
                input stack is empty, so this causes immediate termination,
                followed by implicitly printing the top of the main stack
  yF            for each word in register y, do the following
    [n|]_1T|[|& intersect the suffixes of the candidate with prefixes of the current word
    z]+h        get the first fragment in the intersection, or a blank array
    Y           store it in register Y
    %t+         join the candidate with the current word, eliminating the duplicate fragment
    y{G}M       if the fragment was non-blank, recursively call to the call target
    d           pop the top of stack

Exécutez celui-ci

Modifier: cela échoue pour une classe d'entrées qui a une boucle, comme la ["ab", "ba", "ca"]plupart des autres réponses publiées.

récursif
la source
0

JavaScript (ES6), 138 130 octets

f=a=>a[1]?a.map((c,i)=>a.map((w,j,[...b])=>i!=j&&!/0/.test(m=(c+0+w).split(/(.+)0\1/).join``)?t=f(b,b[i]=m,b.splice(j,1)):0))&&t:a

Renvoie une erreur pour les listes qui ne peuvent pas être complètement portées.

Non golfé:

f = a =>
  a[1] ?                                        //if more than one element ...
    a.map((c, i)=>                              // for each element
      a.map((w, j, [...b])=>                    //  for each element
        i != j &&                               //   if not the same element
        !/0/.test(m=(c+0+w).split(/(.+)0\1/).join``) &&  //   and the elements overlap
        (t = f(b,                               //   and f recursed is true when
               b[i] = m,    //    replacing the ith element with the 2-element portmanteau
               b.splice(j, 1)                   //    and removing the jth element
              )
        )
      )
    ) &&
    t :                                         //return the recursed function value
    a                                           //else return a

Le code est atrocement lent sur l'exemple de l'alphabet complet (non inclus pour cette raison dans l'extrait ci-dessus).

Cela est résolu en changeant le maps en somes, pour la perte de 2 octets:

f=a=>a[1]?a.some((c,i)=>a.((w,j,[...b])=>i!=j&&!/0/.test(m=(c+0+w).split(/(.+)0\1/).join``)?t=f(b,b[i]=m,b.splice(j,1)):0))&&t:a

Rick Hitchcock
la source
1
Il semble que j'ai fait une erreur. Je ne peux pas reproduire le comportement que je pensais avoir vu hier. Désolé pour ma confusion et perdre votre temps. Je vais supprimer mes commentaires sur le sujet, car ils sont tous faux et trompeurs.
récursif