Genera un Portmantout!


16

sfondo

Tre anni fa, questo ragazzo Tom Murphy si è messo in testa per estendere l'idea di un portmanteau a tutte le parole in una lingua e lo ha definito un portmantout ( portmanteau plus tout [francese per tutti ]). Definendo l'inglese come un elenco di 108.709 parole, è riuscito a trovare una sequenza di 611.820 lettere con le seguenti due proprietà:

  • Ogni parola inglese è contenuta nella stringa.
  • Un quartiere che contiene due lettere adiacenti nella stringa è una parola inglese.

Ecco un link a una pagina in cui è possibile trovare questo portmantout (insieme a una spiegazione video).

Un portmantout

La prima delle due proprietà di un portmantout è di facile comprensione. Il secondo potrebbe richiedere alcune spiegazioni.

Fondamentalmente, le parole devono sovrapporsi. "golfcode" non apparirà mai in un portmantout di inglese, in quanto non vi è alcuna parola che contenga "fc". Tuttavia, potresti trovare "codegolf" in un portmantout, poiché "ego" colma il divario (e tutte le altre coppie di lettere sono in "codice" o "golf").

Il tuo compito:

Scrivi un programma o una funzione che accetta un elenco di stringhe e restituisce qualsiasi portmantout dell'elenco.

Questo codice Python 3 verificherà un portmantout.

Casi test

Tutti gli elenchi non sono ordinati; questo è,

{"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

E perchè no? Quello massiccio sul sito di Murphy, se il tuo codice viene eseguito in tempi ragionevoli.

Regole

  • Il tuo codice deve arrestarsi.
  • Non è necessario restituire lo stesso portmantout ad ogni esecuzione.
  • Si può assumere tutte le stringhe sono costituite da solo lettere minuscole aattraverso z.
  • Se non è possibile effettuare il portmantout, il programma potrebbe fare qualsiasi cosa. Ex:{"most", "short", "lists"}
  • Si applicano le norme standard per I / O e scappatoie .

Questo è , quindi vince la soluzione più breve (in byte) in ogni lingua! Buon golf!



1
Forse alcuni casi di test?
Adám,

{"sic", "bar", "rabbits", "cradle"} -> "barabbitsicradle" {"mauve", "elated", "cast", "electric", "tame"} -> "mauvelectricastamelated"(altri casi di test)
Sundar - Ripristina Monica il

2
Sì, forse un banco di prova in cui una parola deve essere usata due volte
solo ASCII il

2
Avremo mai parole di 1 lettera?

Risposte:


3

Python 2 , 204 202 byte

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

Provalo online!


Salvato

  • -2 byte, grazie a ricorsivo

È possibile utilizzare le schede nelle ultime due righe per salvare 2 byte.
ricorsivo


Questo non produce l'output corretto per ["ab", "ba", "ca"]. La mia soluzione ha lo stesso bug.
ricorsivo il

1

Pyth, 39 byte

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

Provalo qui

Spiegazione

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.

1

Stax , 39 36 byte

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

Esegui ed esegui il debug

Esegue tutti i casi di test in modo deterministico in circa un secondo.

Questo è un algoritmo ricorsivo.

  • Inizia con ogni parola di input come candidato
  • Ad ogni passo, ordina le parole per il numero di volte in cui si presentano come sottostringhe del candidato.
  • Per ogni parola compatibile con la fine dell'attuale candidato, unisciti alla parola per formare un nuovo candidato ed effettua una chiamata ricorsiva.

Ecco il programma decompresso, ungolf e commentato.

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

Esegui questo

Modifica: questo non riesce per una classe di input che ha un ciclo, come ["ab", "ba", "ca"], come la maggior parte delle altre risposte postate.


0

JavaScript (ES6), 138 130 byte

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

Restituisce un errore per gli elenchi che non possono essere portmantouted completamente.

Ungolfed:

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

Il codice è estremamente lento nell'esempio di alfabeto completo (non incluso per tale motivo nello snippet sopra).

Ciò viene risolto modificando la maps in somes, per la perdita di 2 byte:

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


1
Sembra che abbia fatto un errore. Non riesco a riprodurre il comportamento che pensavo di aver visto ieri. Ci scusiamo per la mia confusione e spreco di tempo. Eliminerò i miei commenti sull'argomento, poiché sono tutti sbagliati e fuorvianti.
ricorsivo il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.