Jogue a cadeia de palavras

15

Quando eu era mais novo, costumava jogar um jogo de palavras chamado Word chain . Foi muito simples. O primeiro jogador escolhe uma palavra; o próximo jogador diz outra palavra que começa com a mesma letra que a palavra anterior terminou. Isso continua para sempre até que alguém desista! O truque é que você não pode usar a mesma palavra duas vezes (a menos que todos tenham esquecido que a palavra foi usada!). Geralmente brincamos com um determinado tópico para dificultar as coisas. Mas agora, quero que você faça um programa para fazer isso por mim.

Desafio

Escreva um programa ou função completa para encontrar todas as cadeias de palavras mais longas possíveis usando um determinado conjunto de palavras e inicie a palavra.

Isso é , então o código mais curto vence!

Entrada

Existem duas entradas: uma lista e uma palavra inicial. A palavra inicial não estará na lista. As entradas são todas ASCII em minúsculas e a lista não conterá palavras duplicadas.

Resultado

Todas as sequências de palavras da lista, tais como:

  • A palavra inicial é a primeira palavra na sequência.

  • Cada palavra subsequente começa com a mesma letra que a última letra da palavra anterior.

  • O comprimento da sequência é o maior possível .

Se houver várias seqüências mais longas, produza todas elas.

A sequência não precisa necessariamente conter todas as palavras da lista. Às vezes isso não é possível (consulte casos de teste). Novamente, nenhuma palavra pode ser usada duas vezes!

Casos de teste

In: [hello, turtle, eat, cat, people] artistic
Out:  [artistic, cat, turtle, eat]
In: [lemonade, meatball, egg, grape] ham 
Out: [ham, meatball, lemonade, egg, grape]
In: [cat, cute, ewok] attic
Out: [attic, cute, ewok]
In:[cat, cute, ewok, kilo, to, otter] attic
Out: [attic, cute, ewok, kilo, otter]
In:[cat, today, yoda, attic] ferret
Out: [ferret, today, yoda, attic, cat]
In: [cancel, loitering, gnocchi, improv, vivic, child, despair, rat, tragic, chimney, rex, xylophone] attic
Out: [[attic, child, despair, rat, tragic, cancel, loitering, gnocchi, improv, vivic, chimney], [attic, cancel, loitering, gnocchi, improv, vivic, child, despair, ra', tragic, chimney]]
In: [cat, today, yoda, artistic, cute, ewok, kilo, to, otter] attic
Out: [attic, cat, today, yoda, artistic, cute, ewok, kilo, otter]
TanMath
fonte
4
@downvoters, você pode explicar como posso melhorar minha pergunta?
precisa saber é o seguinte
@ user81655 certeza
TanMath
2
Você pode adicionar um caso de teste com várias seqüências de saída?
Isaacg
@isaacg Claro! trabalhando nisto
TanMath
@isaacg Adicionado! (15 limite de caracteres cumprida ...)
TanMath

Respostas:

8

Pitão, 25 23 bytes

.MlZfqhMtTeMPT+Lzs.pMyQ

Suíte de teste

Uma solução de força bruta. Muito lento para alguns dos casos de teste maiores.

Entrada no formulário:

attic
["cat", "today", "yoda", "to", "otter"] 

Saída no formulário:

[['attic', 'cat', 'today', 'yoda'], ['attic', 'cat', 'to', 'otter']]

Explicação:

.MlZfqhMtTeMPT+Lzs.pMyQ
                           Q = eval(input()) (The list of words)
                           z = input()       (The starting word)
                     yQ    All subsets of the input.
                  .pM      All permutations of the subsets.
                 s         Flatten.
              +Lz          Add the starting word to the front of each list.
                           This is all possible sequences.
    f                      Filter on
     q                     The equality of
      hMtT                 The first character of each word but the first
          eMPT             The last character of each word but the last
.MlZ                       Take only the lists of maximal length.
isaacg
fonte
2
Você pode adicionar uma explicação?
precisa saber é o seguinte
Seu código é executado sempre para o exemplo seqüência de saída múltipla
TanMath
3
@ TanMath não, é apenas tempo exponencial, por isso é muito lento.
Isaacg
5
Golf cupom: A arte de fazer um programa de corrida de outra forma rápida em tempo exponencial só para economizar alguns bytes: P
Arcturus
1
@RikerW Acho que também vale a pena relembrar o comentário de Martin "Code Review: tornando o código um pouco menos errado / Code Golf: tornando o código um pouco menos longo" do bate-papo aqui.
precisa
4

JavaScript (ES6), 164 bytes

f=(l,s,r=[[]])=>l.map((w,i)=>w[0]==s.slice(-1)&&(x=l.slice(),x.splice(i,1),o=f(x,w),a=o[0].length,b=r[0].length,r=a>b?o:a<b?r:r.concat(o)))&&r.map(q=>[s].concat(q))

Explicação

Uma função recursiva que verifica quanto tempo a lista de saída dura para todas as opções possíveis.

Retorna uma matriz de matrizes de palavras.

f=(l,s,r=[[]])=>            // l = list, s = starting word, r is not passed (it is
                            //     here so that it is not defined globally)
  l.map((w,i)=>             // for each word w at index i
    w[0]==s.slice(-1)&&(    // if the first letter is the same as the last letter:
      x=l.slice(),          // x = clone of the list of words
      x.splice(i,1),        // remove the current word
      o=f(x,w),             // get the list of words starting from the current word
      a=o[0].length,
      b=r[0].length,
      r=a>b?o:              // if o is longer, set r to o
        a<b?r:              // if o is shorter, keep r
        r.concat(o)         // if o is same, add it to r
    )
  )
  &&r.map(q=>[s].concat(q)) // return a list of longest lists with the starting word

Teste

Parâmetro padrão não usado no teste para torná-lo mais compatível com vários navegadores.

user81655
fonte
Eu acho que você poderia usar pop em vez de emenda e em o[r.length]?vez de o.length>r.length?.
grc
@grc Obrigado, eu realmente gosto da o[r.length]dica! Eu não sei como eu poderia usar pop.
precisa saber é o seguinte
Ah nvm - eu pensei que pop poderia pegar um índice como seu primeiro argumento, como em python.
grc 07/01
Esta solução é inválido para várias seqüências de saída
TanMath
@TanMath Corrigido, embora quebre um dos casos de teste.
user81655
3

Python, 104

def f(d,w):
 a=[[w]]
 while a:b=a;a=[x+[y]for x in a for y in set(d)-set(x)if x[-1][-1]==y[0]]
 return b

Eu acho que deveria funcionar agora ...

Experimente online .

grc
fonte
1

Perl 5, 275 bytes

Provavelmente não jogou golfe tanto quanto pode ser, mas, ei, de qualquer maneira, não é vencedor, certo?

use List::Util max;use List::MoreUtils uniq,before;use Algorithm::Permute permute;$i=pop;permute{push@c,[@ARGV]}@ARGV;for$c(@c){unshift@$c,$i;push @{$d{before{(substr$c->[$_],-1)ne(substr$c->[1+$_],0,1)}keys$c}},$c}for$m(max keys%d){say for uniq map{"@$_[0..$m+1]"}@{$d{$m}}}

Use-o assim:

$ perl -M5.010 chain.pl cat tin cot arc
arc cat tin
arc cot tin

Atenção! O uso desse script em uma lista longa requer muita memória! Funcionou muito bem para mim nos sete (seis mais o extra), mas não nos treze (doze mais um).

Ele remove a entrada final, gera uma matriz de arrayrefs, onde os arrayrefs são todas as permutações e adiciona a palavra inicial novamente no início. Em seguida, empurra cada uma dessas permutações para outra matrizref, que é o valor de um hash com a chave da quantidade da matriz que possui a propriedade de encadeamento desejada. Em seguida, encontra o máximo dessa chave e imprime todas as matrizes.

msh210
fonte
0

C, 373 bytes

g(char*y){printf("%s, ",y);}z(char*w){int i,k=-1,v=0,j=sizeof(c)/sizeof(c[0]);int m[j],b=0;for(i=0;i<j;i++){m[v++]=c[i][0]==w[strlen(w)-1]?2:1;if(u[i]==6)m[v-1]=1;if(strcmp(w,c[i]))k=i;}printf("%s",w);for(i=0;i<j;i++){if(m[i]!=1){if(v+i!=j){g(s);for(;b<j;b++){if(u[b]==6)g(c[b]);}}else printf(", ");u[i]=6;z(c[i]);u[i]=1;}else v+=-1;}if(k!=-1)u[k]=1;if(v==0)printf(" ; ");}

Eu acredito que provavelmente há muito mais golfe que eu poderia fazer aqui, então provavelmente o atualizarei.

De-golfe

char *c[9]={"cat","today","yoda","artistic","cute","ewok","kilo","to","otter"};
u[9]={-1};
char *s="attic";

g(char*y){printf("%s, ",y);}
z(char*w){
   int i,k=-1,v=0,j=sizeof(c)/sizeof(c[0]);
   int m[j],b=0;
   for(i=0;i<j;i++){
      m[v++]=c[i][0]==w[strlen(w)-1]?i:-1;
      if(u[i]==6)m[v-1]=-1;
      if(strcmp(w,c[i]))k=i;
   }
   printf("%s",w);
   for(i=0;i<j;i++){
      if(m[i]!=-1){
         if(v+i!=j){
            g(s);
            for(;b<j;b++){
                if(u[b]==6)g(c[b]);
             }
         }else printf(", ");
         u[i]=6;
         z(c[i]);
         u[i]=-1;
      } else v+=-1;
   }
   if(k!=-1)u[k]=-1;
   if(v==0)printf(" ; ");
}

main(){
   z(s);
   printf("\n");
   return 0;
}

Link Ideone - Se eu não fiz isso direito, avise-me: D

Danwakeem
fonte
você poderia adicionar um link ideone para teste?
precisa saber é o seguinte
Sim, vou atualizar minha resposta com ele @TanMath
Danwakeem
O link deve conter o código golfado, não a versão não-golfada. Dessa forma, podemos confirmar que a versão em golf que você está enviando para o desafio funciona.
TanMath