Gere um Portmantout!


16

fundo

Três anos atrás, esse cara, Tom Murphy, pensou em estender a idéia de um portmanteau a todas as palavras em um idioma e chamou isso de portmantout ( portmanteau plus tout [francês para todos ]). Definindo inglês como uma lista de 108.709 palavras, ele conseguiu encontrar uma sequência de 611.820 letras com as duas propriedades a seguir:

  • Cada palavra em inglês está contida na string.
  • Alguma vizinhança contendo duas letras adjacentes na sequência é uma palavra em inglês.

Aqui está um link para uma página na qual essa saída pode ser encontrada (junto com uma explicação em vídeo).

Um portmantout

A primeira das duas propriedades de um portmantout é fácil de entender. O segundo pode exigir alguma explicação.

Basicamente, as palavras devem se sobrepor. "golfcode" nunca aparecerá em um portmantout em inglês, pois não há nenhuma palavra que contenha o "fc". No entanto, você pode encontrar "codegolf" em um portmantout, pois "ego" preenche a lacuna (e todos os outros pares de letras estão em "code" ou "golf").

Sua tarefa:

Escreva um programa ou função que pegue uma lista de cadeias e retorne qualquer porta da lista.

Este código Python 3 verificará um portmantout.

Casos de teste

Todas as listas são desordenadas; isso é,

{"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 porque não? O massivo no site de Murphy, se o seu código for executado dentro de um prazo razoável.

Regras

  • Seu código deve parar.
  • Você não precisa retornar o mesmo portmantout a cada execução.
  • Você pode assumir todas as cadeias consistem em apenas letras minúsculas aatravés z.
  • Se nenhuma portmantout for possível, seu programa poderá fazer qualquer coisa. Ex:{"most", "short", "lists"}
  • Aplicam-se regras padrão para E / S e brechas .

Isso é , então a solução mais curta (em bytes) em cada idioma vence! Feliz golfe!



1
Talvez alguns casos de teste?
Adám 06/06/19

{"sic", "bar", "rabbits", "cradle"} -> "barabbitsicradle" {"mauve", "elated", "cast", "electric", "tame"} -> "mauvelectricastamelated"(mais casos de teste)
sundar - Restabelece Monica

2
Sim, talvez um testcase onde uma palavra precisa para ser usado duas vezes
ASCII-only

2
Será que vamos conseguir palavras de uma letra?

Respostas:


3

Python 2 , 204 202 bytes

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

Experimente online!


Salvou

  • -2 bytes, graças ao recurso recursivo

Você pode usar as guias nas duas últimas linhas para salvar 2 bytes.
recursivo


Isso não produz a saída correta para ["ab", "ba", "ca"]. Minha solução tem o mesmo bug.
recursivo

1

Pitão, 39 bytes

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

Experimente aqui

Explicação

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 bytes

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

Execute e depure

Executa todos os casos de teste deterministicamente em cerca de um segundo.

Este é um algoritmo recursivo.

  • Comece com cada palavra de entrada como candidato
  • Em cada etapa, ordene as palavras pelo número de vezes que ocorrem como substrings do candidato.
  • Para cada palavra compatível com o final do candidato atual, junte-se à palavra para formar um novo candidato e faça uma chamada recursiva.

Aqui está o programa descompactado, não destruído e comentado.

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

Execute este

Editar: Isso falha para uma classe de entradas que possui um loop, como a ["ab", "ba", "ca"]maioria das outras respostas postadas.


0

JavaScript (ES6), 138 130 bytes

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

Retorna um erro para listas que não podem ser completamente desmanteladas.

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

O código é terrivelmente lento no exemplo completo do alfabeto (não incluído por esse motivo no snippet acima).

Isso é corrigido alterando maps para somes, para a perda de 2 bytes:

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
Parece que cometi um erro. Não consigo reproduzir o comportamento que pensei ter visto ontem. Desculpe pela minha confusão e desperdiçando seu tempo. Excluirei meus comentários sobre o assunto, pois todos estão errados e enganosos.
recursivo
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.