Spiele die Wortkette

15

Als ich jünger war, verwende ich ein Wortspiel spielen namens Word - Kette . Es war sehr einfach. Der erste Spieler wählt ein Wort; der nächste Spieler sagt ein anderes Wort, das mit demselben Buchstaben beginnt, mit dem das vorherige Wort geendet hat. Das geht ewig so weiter, bis jemand aufgibt! Der Trick ist, dass Sie nicht dasselbe Wort zweimal verwenden können (es sei denn, jeder hat vergessen, dass dieses Wort überhaupt verwendet wurde!). Normalerweise spielen wir mit einem bestimmten Thema, um es schwieriger zu machen. Aber jetzt möchte ich, dass Sie ein Programm erstellen, um dies für mich zu tun.

Herausforderung

Schreiben Sie ein vollständiges Programm oder eine vollständige Funktion, um mit einer bestimmten Menge von Wörtern möglichst lange Wortketten zu finden und das Wort zu beginnen.

Das ist , also gewinnt der kürzeste Code!

Eingang

Es gibt zwei Eingänge: eine Liste und ein Startwort. Das Startwort ist nicht in der Liste enthalten. Alle Eingaben sind ASCII-Kleinbuchstaben, und die Liste enthält keine doppelten Wörter.

Ausgabe

Alle Wortfolgen aus der Liste, so dass:

  • Das Startwort ist das erste Wort in der Sequenz.

  • Jedes nachfolgende Wort beginnt mit dem gleichen Buchstaben wie der letzte Buchstabe des vorherigen Wortes.

  • Die Länge der Sequenz ist so lang wie möglich .

Wenn es mehrere längste Sequenzen gibt, geben Sie alle aus.

Die Sequenz muss nicht unbedingt alle Listenwörter enthalten. Manchmal ist das nicht möglich (siehe Testfälle). Auch hier kann kein Wort zweimal verwendet werden!

Testfälle

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
quelle
4
@Downvoters Kannst du mir bitte erklären, wie ich meine Frage verbessern kann?
TanMath
@ user81655 sicher
TanMath
2
Können Sie einen Testfall mit mehreren Ausgabesequenzen hinzufügen?
Isaacg
@isaacg Sicher! Arbeiten daran
TanMath
@isaacg Hinzugefügt! (Beschränkung auf 15 Zeichen erfüllt ...)
TanMath

Antworten:

8

Pyth, 25 23 Bytes

.MlZfqhMtTeMPT+Lzs.pMyQ

Testsuite

Eine Brute-Force-Lösung. Für einige der größeren Testfälle viel zu langsam.

Eingabe in das Formular:

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

Ausgabe in der Form:

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

Erläuterung:

.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
quelle
2
Können Sie eine Erklärung hinzufügen?
TanMath
Ihr Code läuft für immer für das Beispiel mit mehreren Ausgabesequenzen
TanMath
3
@ TanMath Nein, es ist nur eine exponentielle Zeit, es ist also sehr langsam.
Isaacg
5
Code Golf: Die Kunst, ein ansonsten schnelles Programm in exponentieller Zeit ablaufen zu lassen, nur um ein paar Bytes zu sparen: P
Arcturus
1
@RikerW Ich denke, es lohnt sich auch, Martins Kommentar "Code Review: Code etwas weniger falsch machen / Code Golf: Code etwas weniger lang machen" aus dem Chat hier in Erinnerung zu rufen.
Arcturus
4

JavaScript (ES6), 164 Byte

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))

Erläuterung

Eine rekursive Funktion, die überprüft, wie lange die Ausgabeliste für alle möglichen Auswahlen gültig ist.

Gibt ein Array von Arrays von Wörtern zurück.

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

Prüfung

Der Standardparameter wird im Test nicht verwendet, um die Kompatibilität mit anderen Browsern zu verbessern.

user81655
quelle
Ich denke, Sie könnten Pop anstelle von Spleißen und o[r.length]?anstelle von verwenden o.length>r.length?.
Grc
@grc Danke, ich mag den o[r.length]Tipp wirklich ! Ich weiß allerdings nicht, wie ich es gebrauchen könnte pop.
user81655
Ah nvm - Ich dachte, Pop könnte einen Index als erstes Argument nehmen, wie in Python.
Grc
Diese Lösung ist für mehrere Ausgabesequenzen ungültig
TanMath
@TanMath Behoben, obwohl einer der Testfälle unterbrochen wurde.
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

Ich denke, es sollte jetzt funktionieren ...

Probieren Sie es online aus .

grc
quelle
1

Perl 5, 275 Bytes

Wahrscheinlich nicht so viel Golf gespielt wie es sein kann, aber es ist sowieso nicht siegreich, oder?

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}}}

Verwenden Sie es so:

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

Warnung! Die Verwendung dieses Skripts auf einer langen Liste erfordert viel Speicher! Bei sieben (sechs plus eins) hat es super geklappt, aber nicht bei dreizehn (zwölf plus eins).

Es entfernt die letzte Eingabe, generiert ein Array von Arrayrefs, wobei die Arrayrefs alle Permutationen sind, und fügt das Anfangswort am Anfang wieder ein. Dann schiebt es jede solche Permutation auf ein anderes Arrayref, das der Wert eines Hashs mit Schlüssel ist, der die Menge des Arrays angibt, das die gewünschte Verkettungseigenschaft hat. Es findet dann den maximalen solchen Schlüssel und druckt alle Arrays aus.

msh210
quelle
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(" ; ");}

Ich glaube, dass ich hier wahrscheinlich viel mehr Golf spielen könnte, also werde ich es wahrscheinlich aktualisieren.

De-Golf

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;
}

Ideone Link - Wenn ich das nicht richtig gemacht habe, lass es mich wissen: D

Danwakeem
quelle
könntest du einen ideone link zum testen hinzufügen ?
TanMath
Ja, ich werde meine Antwort damit aktualisieren
@
Der Link sollte den Golfcode enthalten, nicht die ungolfed Version. Auf diese Weise können wir die Golfversion bestätigen, die Sie für die Challenge-Arbeiten einreichen.
TanMath