Stadtnamen Spiel

16

Wenn Sie möchten, schreiben Sie ein Programm, das Städte nach den Regeln des Stadtnamensspiels sortiert.

  • Jeder Name der Stadt sollte mit dem letzten Buchstaben des vorherigen Städtenamens beginnen. Z.BLviv -> v -> Viden -> n -> Neapolis -> s -> Sidney -> y -> Yokogama -> a -> Amsterdam -> m -> Madrid -> d -> Denwer

  • In der sortierten Liste sollten der erste Buchstabe der ersten Stadt und der letzte Buchstabe der letzten nicht übereinstimmen. Es muss sich nicht um den gleichen Buchstaben handeln.

  • Sie können davon ausgehen, dass Städtenamen nur Buchstaben haben.
  • Die Programmausgabe sollte die gleiche Groß- und Kleinschreibung haben wie die Eingabe

Beispiel:

% ./script Neapolis Yokogama Sidney Amsterdam Madrid Lviv Viden Denwer
["Lviv", "Viden", "Neapolis", "Sidney", "Yokogama", "Amsterdam", "Madrid", "Denwer"]
defhlt
quelle
2
Können wir davon ausgehen, dass es immer eine gültige Lösung geben wird?
Gareth
@ Gareth ja, Sie können
defhlt
die zweite Regel - "[...] sollte nicht mit irgendetwas übereinstimmen" - ist es eine Anforderung oder nur eine Aussage, die besagt, dass es in Ordnung ist, zwischen dem ersten und dem letzten Buchstaben eine Abweichung zu haben? (Beispiel: ["Viden" ... "Lviv"]
Ist
@w0lf von "sollte nicht" Ich meinte es muss nicht, es ist nicht obligatorisch. Ihr Beispiel ist also gültig.
Defhlt
Tipp: Wenn Sie eine schöne Lösung wünschen , können Sie diese auf die Berechnung von Eulerschen Pfaden reduzieren, bei denen jeder Buchstabe ein Scheitelpunkt und jedes Wort eine Kante ist. ( Berlin ist zum Beispiel die Kante BN ) Dies ist lösbar in O (n), wobei n die Anzahl der Kanten ist.
FUZxxl

Antworten:

11

Ruby, 58 55 44 Zeichen

p$*.permutation.find{|i|i*?,!~/(.),(?!\1)/i}

Noch eine Ruby-Implementierung. Verwendet auch Regex ohne Berücksichtigung der Groß- / Kleinschreibung (wie die alte Lösung von Ventero ), aber der Test wird anders durchgeführt.

Vorherige Version:

p$*.permutation.find{|i|(i*?,).gsub(/(.),\1/i,"")!~/,/}
Howard
quelle
Sehr schön! Und ich denke, Sie können dies auf 55 reduzieren, wenn Sie !~den gesamten Ausdruck negieren, anstatt ihn zu verwenden.
Cristian Lupascu
Das ist smart regexp
defhlt
@w0lf Natürlich! Wie konnte ich nicht daran denken?
Howard
5

Python ( 162 141 124)

Brute Force für den Sieg.

from itertools import*
print[j for j in permutations(raw_input().split())if all(x[-1]==y[0].lower()for x,y in zip(j,j[1:]))]
beary605
quelle
1
Ich denke, Sie können die &(j[0][0]!=j[-1][-1])Bedingung entfernen ; Siehe die Fragenkommentare oben.
Cristian Lupascu
1
124 from itertools import*;print[j for j in permutations(raw_input().split())if all(x[-1]==y[0].lower()for x,y in zip(j,j[1:]))]
Ev_genus
Ich versuche meinen Kopf darum zu wickeln, was in dieser Funktion vor sich geht. Was genau sind j, x, y? Wie sind sie definiert? Es tut mir leid, wenn diese Fragen lahm sind, ich bin neu in Python und würde gerne noch mehr damit arbeiten.
Rob
@MikeDtrick: jEnthält eine Permutation der Städte, die mit dem permutationsBefehl generiert wird . Das große Zeichen ifam Ende bestätigt grundsätzlich, dass für alle Werte in jder Zeile der letzte Buchstabe eines Werts in jder Zeile der erste Buchstabe des nächsten Werts in der Zeile ist j. Ehrlich gesagt, weiß ich auch nicht, was der zipmacht, ziparbeitet auf mysteriöse Weise.
beary605
Okay, danke für die Erklärung! +1
Rob
5

Ruby 1.9, 63 54 Zeichen

Neue Lösung basiert auf Howard ‚s Lösung :

p$*.permutation.max_by{|i|(i*?,).scan(/(.),\1/i).size}

Dies nutzt die Tatsache, dass es immer eine gültige Lösung geben wird.

Alte Lösung, basierend auf w0lf ‚s Lösung :

p$*.permutation.find{|i|i.inject{|a,e|a&&e[0]=~/#{a[-1]}/i&&e}}
Ventero
quelle
Gute Idee mit dem max_by. Und Ihre neue Version hat mich zu einer noch neueren (und kürzeren) inspiriert.
Howard
@ Howard Danke! Ihre neue Lösung ist wirklich großartig, das wird schwer zu übertreffen sein. ;)
Ventero
4

Ruby 74 72 104 103 71 70

p$*.permutation.find{|i|i.inject{|a,e|a[-1].casecmp(e[0])==0?e:?,}>?,}

Demo: http://ideone.com/MDK5c (in der Demo habe ich verwendet gets().split()statt $*, ich weiß nicht , ob Ideone können Befehlszeilen args simulieren).

Cristian Lupascu
quelle
sieht meiner Variante ähnlich, $*.permutation{|p|p p if p.inject(p[0][0]){|m,e|m.casecmp(e[0])==0?e[-1]:?_}>?_}aber deine ist 9 Zeichen kürzer!
Defhlt
2
p$*.permutation.find{|i|i.inject{|a,e|a&&e[0]=~/#{a[-1]}/i&&e}}ist ziemlich viel kürzer. Eine Ruby 1.8 (!) Lösung, die noch kürzer ist:p$*.permutation.find{|i|i.inject{|a,e|a&&a[-1]-32==e[0]&&e}}
Ventero
@Ventero Die Verwendung von Regex ohne Berücksichtigung der Groß- und Kleinschreibung ist eine brillante Idee! Bitte posten Sie dies als Ihre eigene Antwort; Ich bin es nicht wert, das zu benutzen. :)
Cristian Lupascu
@Ventero die -32Lösung ist auch sehr genial, aber es beruht auf der Tatsache, dass Namen mit einem Großbuchstaben beginnen und mit einem Kleinbuchstaben enden, was möglicherweise nicht immer der Fall ist.
Cristian Lupascu
@w0lf Du hast recht, ich dachte, ich habe in den Spezifikationen gelesen, dass es der Fall sein würde, aber offensichtlich irre ich mich. ;)
Ventero
3

Python, 113

Sehr ähnlich der Antwort von @ beary605 und noch brutaler.

from random import*
l=raw_input().split()
while any(x[-1]!=y[0].lower()for x,y in zip(l,l[1:])):
 shuffle(l)
print l
Nolen Royalty
quelle
1
Woohoo, verdammter Stil!
beary605
3

Haskell , 94 74 Bytes

g[a]=[[a]]
g c=[b:r|b<-c,r<-g[x|x<-c,x/=b],last b==[r!!0!!0..]!!32]
head.g

Findet rekursiv alle Lösungen. -7 Bytes, wenn es in Ordnung ist, alle Lösungen anstelle der ersten auszugeben. Vielen Dank an @Lynn, der den lästigen Import beseitigt hat und 18 Bytes weniger hat!

Probieren Sie es online!

Angs
quelle
Sie können den Data.CharImport mit loswerden last b==[r!!0!!0..]!!32. Außerdem brauchen Sie keine Eltern ing[x|x<-c,x/=b]
Lynn
1
@Lynn nett, ich dachte irgendwie fromEnumwäre ein Muss. Komisch, ich habe diese Klammern schon einmal entfernt, aber ich muss von der falschen Registerkarte kopiert haben ...
Angs
2

GolfScript, 78 Zeichen

" ":s/.{1${1$=!},{:h.,{1$-1={1$0=^31&!{[1$1$]s*[\](\h\-c}*;}+/}{;.p}if}:c~;}/;

Eine erste Version in GolfScript. Es macht auch einen Brute-Force-Ansatz. Das Skript wird in der Online- Beispieleingabe ausgeführt .

Howard
quelle
2

Schale , 10 Bytes

←fΛ~=o_←→P

Probieren Sie es online!

Erläuterung

←fΛ~=(_←)→P  -- example input: ["Xbc","Abc","Cba"]
          P  -- all permutations: [["Xbc","Abc","Cba"],…,[Xbc","Cba","Abc"]]
 f           -- filter by the following (example with ["Xbc","Cba","Abc"])
  Λ          -- | all adjacent pairs ([("Xbc","Cba"),("Cba","Abc")])
   ~=        -- | | are they equal when..
     (_←)    -- | | .. taking the first character lower-cased
         →   -- | | .. taking the last character
             -- | : ['c'=='c','a'=='a'] -> 4
             -- : [["Xbc","Cba","Abc"]]
←            -- take the first element: ["Xbc","Cba","Abc"]

Alternativ 10 Bytes

Wir könnten auch die Anzahl benachbarter Paare zählen, die das Prädikat ( #) erfüllen , danach sortieren ( Ö) und das letzte Element ( ) für dieselbe Anzahl von Bytes nehmen:

→Ö#~=o_←→P

Probieren Sie es online!

ბიმო
quelle
2

Jelly , 25 18 bytes (Verbesserungen erwünscht!)

UżḢŒuE
ḲŒ!çƝẠ$ÐfḢK

Probieren Sie es online!

UżḢŒuE        dyadic (2-arg) "check two adjacent city names" function:
Uż            pair (żip) the letters of the reversed left argument with the right argument,
  Ḣ           get the Ḣead of that pairing to yield just the last letter of left and the first letter of right,
   Œu         capitalize both letters,
     E       and check that they're equal!
ḲŒ!çƝẠ$ÐfḢK    i/o and check / fold function:
ḲŒ!            split the input on spaces and get all permutations of it,
   çƝẠ$        run the above function on every adjacent pair (çƝ), and return true if Ȧll pairs are true
       Ðf      filter the permutations to only get the correct ones,
         ḢK    take the first of those, and join by spaces!

Vielen Dank an @Lynn für die meisten dieser Verbesserungen!

25-Byte-Lösung:

Uḣ1Œu=⁹ḣ1
çƝȦ
ḲŒ!©Ç€i1ị®K

Probieren Sie es online!

Uḣ1Œu=⁹ḣ1      dyadic (2-arg) "check two adjacent city names" function:
Uḣ1Œu          reverse the left arg, get the ḣead, and capitalize it (AKA capitalize the last letter),
     =⁹ḣ1      and check if it's equal to the head (first letter) of the right argument.
çƝȦ            run the above function on every adjacent pair (çƝ), and return true if Ȧll pairs are true
ḲŒ!©Ç€i1ị®K     main i/o function:
ḲŒ!©           split the input on spaces and get all its permutations, ©opy that to the register
    Ç€         run the above link on €ach permutation,
      i1       find the index of the first "successful" permutation,
        ị®K    and ®ecall the permutation list to get the actual ordering at that ịndex, separating output by spaces
Harry
quelle
2
Einige Verbesserungen: Probieren Sie es online! Ich habe ein kleines Changelog in das Feld "Input" geschrieben. (Oh, nachdem Ðfich Xeine zufällige Lösung anstelle der ersten gewählt habe, funktioniert das aber genauso gut.)
Lynn,
@Lynn Vielen Dank! Der Zip-Teil war sehr clever und ich denke, ich kann so Ðfschnell in vielen meiner anderen Programme etwas Platz sparen!
Harry
1

Mathematica 236 Zeichen

Definieren Sie die Liste der Städte:

d = {"Neapolis", "Yokogama", "Sidney", "Amsterdam", "Madrid", "Lviv", "Viden", "Denver"}

Suchen Sie den Pfad, der alle Städte enthält:

c = Characters; f = Flatten;
w = Outer[List, d, d]~f~1;
p = Graph[Cases[w, {x_, y_} /;x != y \[And] (ToUpperCase@c[x][[-1]]== c[y][[1]]) :> (x->y)]];
v = f[Cases[{#[[1]], #[[2]], GraphDistance[p, #[[1]], #[[2]]]} & /@  w, {_, _, Length[d] - 1}]];
FindShortestPath[p, v[[1]], v[[2]]]

Ausgabe:

{"Lviv", "Viden", "Neapolis", "Sidney", "Yokogama", "Amsterdam","Madrid", "Denver"}

Bei dem obigen Ansatz wird davon ausgegangen, dass die Städte als Pfaddiagramm angeordnet werden können.


Das Diagramm p ist unten dargestellt:

Graph

DavidC
quelle
1

C 225

#define S t=v[c];v[c]=v[i];v[i]=t
#define L(x)for(i=x;i<n;i++)
char*t;f;n=0;main(int c,char**v){int i;if(!n)n=c,c=1;if(c==n-1){f=1;L(2){for(t=v[i-1];t[1];t++);if(v[i][0]+32-*t)f=n;}L(f)puts(v[i]);}else L(c){S;main(c+1,v);S;}}

Führen Sie mit Ländernamen als Befehlszeilenargumente aus

Hinweis:

  • Brute-Force-Generierung von Permutationen
  • Bei der Überprüfung wird davon ausgegangen, dass die Ländernamen mit Großbuchstaben beginnen und mit Kleinbuchstaben enden.
  • geht davon aus, dass es nur eine Antwort gibt
  • In C wird davon ausgegangen, dass das Array ** v von main () beschreibbar ist
Baby-Kaninchen
quelle
Ich bin #define L(x)for(int i=x;i<n;i++)mir nicht sicher, ob es genau gültig ist, aber wenn Sie dies tun und izu Beginn nicht deklarieren main, sparen Sie 1 Byte.
Tsathoggua
1

J, 69 65 60 59 54 Zeichen

Etwas aus dem Tempo.

{.l\:+/2=/\|:tolower;"2({.,{:)@>l=.(i.@!@#A.]);:1!:1[1

Beispiel:

   {.l\:+/2=/\|:tolower;"2({.,{:)@>l=.(i.@!@#A.]);:1!:1[1
Neapolis Yokogama Sydney Amsterdam Madrid Lviv Viden Denwer
+----+-----+--------+------+--------+---------+------+------+
|Lviv|Viden|Neapolis|Sydney|Yokogama|Amsterdam|Madrid|Denwer|
+----+-----+--------+------+--------+---------+------+------+
Gareth
quelle
1

C # 398

Und hier ist C # mit Linq 5 Cent

IEnumerable<string>CityNameGame(string[]input){var cities=new List<string>(input);string lastCity=null;while(cities.Any()){var city=lastCity??cities.First();lastCity=cities.First(name=>string.Equals(city.Substring(city.Length-1),name.Substring(0,1),StringComparison.CurrentCultureIgnoreCase));cities.RemoveAll(name=>name==city||name==lastCity);yield return string.Format("{0}→{1}",city,lastCity);}}
Akim
quelle
0

K 96

{m@&{&/(~).'+(,_1_1#'x),,-1_-1#'x}@'$m:{$[x=1;y;,/.z.s[x-1;y]{x,/:{x@&~x in y}[y;x]}\:y]}[#x;x]}

.

k){m@&{&/(~).'+(,_1_1#'x),,-1_-1#'x}@'$m:{$[x=1;y;,/.z.s[x-1;y]{x,/:{x@&~x in y}[y;x]}\:y]}[#x;x]}`Neapolis`Yokogama`Sidney`Amsterdam`Madrid`Lviv`Viden`Denver
Lviv Viden Neapolis Sidney Yokogama Amsterdam Madrid Denver
tmartin
quelle
0

C # (.NET Core) , 297 Byte

using System;
using System.Linq;
var S="";int I=0,C=s.Count();for(;I<C;I++)S=Array.Find(s,x=>s[I].Substring(0,1).ToUpper()==x.Substring(x.Length-1).ToUpper())==null?s[I]:S;for(I=0;I<C;I++){Console.Write(S+" ");S=C>I?Array.Find(s,x=>S.Substring(S.Length-1).ToUpper()==x.Substring(0,1).ToUpper()):"";}

Probieren Sie es online!

using System;
using System.Linq;

var S = "";
int I = 0, C = s.Count();
for (; I < C; I++)
    S = Array.Find(
        s, x =>
        s[I].Substring(0, 1).ToUpper() == x.Substring(x.Length - 1).ToUpper()
    ) == null ?
    s[I] :
    S;
for (I = 0; I < C; I++) {
    Console.Write(S + " ");
    S = C > I ? Array.Find(s, x => S.Substring(S.Length - 1).ToUpper() == x.Substring(0, 1).ToUpper()) : "";
}
Hille
quelle