Juego de nombres de ciudades

16

Si lo desea, escriba un programa que clasifique las ciudades de acuerdo con las reglas del juego de nombres de ciudades.

  • Cada nombre de la ciudad debe comenzar desde la última letra del nombre de la ciudad anterior. P.ejLviv -> v -> Viden -> n -> Neapolis -> s -> Sidney -> y -> Yokogama -> a -> Amsterdam -> m -> Madrid -> d -> Denwer

  • En la lista ordenada, la primera letra de la primera ciudad y la última letra de la última no deben coincidir con nada , no tiene que ser la misma letra.

  • Puede suponer que los nombres de ciudades solo tienen letras.
  • La salida del programa debe tener la misma capitalización que la entrada

Ejemplo:

% ./script Neapolis Yokogama Sidney Amsterdam Madrid Lviv Viden Denwer
["Lviv", "Viden", "Neapolis", "Sidney", "Yokogama", "Amsterdam", "Madrid", "Denwer"]
defhlt
fuente
2
¿Podemos suponer que siempre habrá una solución válida?
Gareth
@Gareth sí, puedes
defhlt
la segunda regla, "[...] no debe coincidir con nada", ¿es un requisito o simplemente una declaración que dice que está bien que no coincidan entre la primera y la última letra? (ej .: ¿es una lista como ["Viden" ... "Lviv"]inválida?)
Cristian Lupascu
@ w0lf por "no debería" quise decir que no tiene que hacerlo, no es obligatorio. Entonces su ejemplo es válido.
defhlt
Sugerencia: si desea una buena solución, puede reducir esto al cálculo de rutas eulerianas, donde cada letra es un vértice y cada palabra es un borde. (Por ejemplo, Berlín es el borde BN ) Esto se puede resolver en O (n), donde n es el número de bordes.
FUZxxl

Respuestas:

11

Ruby, 58 55 44 caracteres

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

Otra implementación más de rubí. También utiliza expresiones regulares sin distinción entre mayúsculas y minúsculas (como la antigua solución de Ventero ), pero la prueba se realiza de manera diferente.

Versión previa:

p$*.permutation.find{|i|(i*?,).gsub(/(.),\1/i,"")!~/,/}
Howard
fuente
¡Muy agradable! Y creo que puede reducir esto a 55 si usa en !~lugar de negar toda la expresión.
Cristian Lupascu
Esa es una
expresión
@ w0lf ¡Por supuesto! ¿Cómo podría no pensar en eso?
Howard
5

Python ( 162 141 124)

Fuerza bruta para la victoria.

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
fuente
1
Creo que puedes eliminar la &(j[0][0]!=j[-1][-1])condición; ver los comentarios de la pregunta arriba.
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
Estoy tratando de entender qué está pasando en esta función. ¿Cuáles son exactamente j, x, y? ¿Cómo se definen? Lo siento si estas preguntas son tontas, soy nuevo en Python y me gustaría trabajar con él un poco más.
Rob
@MikeDtrick: jcontiene una permutación de las ciudades, que se genera con el permutationscomando. La letra grande ifal final básicamente valida que para todos los valores en j, la última letra de un valor en jes la misma letra que la primera letra del siguiente valor en j. Honestamente, tampoco sé qué ziphace, zipfunciona de manera misteriosa.
beary605
Bien, gracias por la explicación! +1
Rob
5

Ruby 1.9, 63 54 caracteres

La nueva solución se basa en la solución de Howard :

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

Esto utiliza el hecho de que siempre habrá una solución válida.

Solución anterior, basada en la solución de w0lf :

p$*.permutation.find{|i|i.inject{|a,e|a&&e[0]=~/#{a[-1]}/i&&e}}
Ventero
fuente
Buena idea con el max_by. Y su nueva versión me inspiró para una aún más nueva (y más corta).
Howard
@Howard Gracias! Su nueva solución es realmente increíble, será difícil de superar. ;)
Ventero
4

Rubí 74 72104103 71 70

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

Demostración: http://ideone.com/MDK5c (en la demostración que he usado en gets().split()lugar de $*; No sé si Ideone puede simular argumentos de línea de comandos).

Cristian Lupascu
fuente
¡Se parece a mi variante $*.permutation{|p|p p if p.inject(p[0][0]){|m,e|m.casecmp(e[0])==0?e[-1]:?_}>?_}pero la tuya es 9 caracteres más corta!
defhlt
2
p$*.permutation.find{|i|i.inject{|a,e|a&&e[0]=~/#{a[-1]}/i&&e}}es bastante más corto Una solución Ruby 1.8 (!) Que es aún más corta:p$*.permutation.find{|i|i.inject{|a,e|a&&a[-1]-32==e[0]&&e}}
Ventero
@Ventero ¡Usar expresiones regulares sin distinción entre mayúsculas y minúsculas es una idea brillante! Por favor publique esto como su propia respuesta; No soy digno de usar eso. :)
Cristian Lupascu
@Ventero, la -32solución también es muy ingeniosa, pero se basa en el hecho de que los nombres comienzan con una letra mayúscula y terminan en minúscula, lo que puede no ser siempre el caso.
Cristian Lupascu
@ w0lf Tienes razón, pensé que había leído en las especificaciones que sería el caso, pero obviamente estoy equivocado. ;)
Ventero
3

Python, 113

Muy similar a la respuesta de @ beary605, e incluso más forzada.

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
fuente
1
Woohoo, estilo bogo-sort!
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

Recurrentemente encuentra todas las soluciones. -7 bytes si está bien generar todas las soluciones en lugar de la primera. ¡Gracias a @Lynn por deshacerse de la molesta importación, eliminando 18 bytes de la puntuación!

Pruébalo en línea!

Angs
fuente
Puede deshacerse de la Data.Charimportación con last b==[r!!0!!0..]!!32. Además, no necesita padresg[x|x<-c,x/=b]
Lynn
1
@ Lynn agradable, de alguna manera pensé fromEnumque sería imprescindible. Es curioso, ya me quité esos paréntesis una vez, pero debo haber copiado de la pestaña incorrecta ...
Angs
2

GolfScript, 78 caracteres

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

Una primera versión en GolfScript. También hace un enfoque de fuerza bruta. Puede ver el script que se ejecuta en la entrada de ejemplo en línea .

Howard
fuente
2

Casco , 10 bytes

←fΛ~=o_←→P

Pruébalo en línea!

Explicación

←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"]

Alternativamente, 10 bytes

También podríamos contar el número de pares adyacentes que satisfacen el predicado ( #), ordenar en ( Ö) eso y tomar el último elemento ( ) para el mismo número de bytes:

→Ö#~=o_←→P

Pruébalo en línea!

ბიმო
fuente
2

Jelly , 25 18 bytes (¡Se aceptan mejoras!)

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

Pruébalo en línea!

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!

¡Gracias a @Lynn por la mayoría de estas mejoras!

Solución de 25 bytes:

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

Pruébalo en línea!

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
fuente
2
Algunas mejoras: ¡ Pruébelo en línea! Escribí un pequeño registro de cambios en el campo "Entrada". (Oh, después de Ðfque solía Xelegir una solución aleatoria en lugar de la primera, pero funciona igual de bien.)
Lynn
@ Lynn ¡Muchas gracias! ¡La parte zip fue muy inteligente, y creo que puedo usar eso Ðfrápidamente en muchos de mis otros programas para ahorrar espacio!
Harry
1

Mathematica 236 caracteres

Defina la lista de ciudades:

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

Encuentra el camino que incluye todas las ciudades:

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

Salida:

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

El enfoque anterior supone que las ciudades se pueden organizar como un gráfico de ruta.


El gráfico p se muestra a continuación:

grafico

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

Ejecutar con nombres de países como argumentos de línea de comando

Nota:

  • generación de fuerza bruta de permutaciones
  • para verificarlo, se supone que los nombres de países comienzan con mayúsculas y terminan en minúsculas.
  • asume que solo hay una respuesta
  • En C, se supone que la matriz ** v de main () se puede escribir
conejo bebé
fuente
No estoy seguro de que sea exactamente válido, pero si lo hace #define L(x)for(int i=x;i<n;i++)y no declara ial principio main, ahorrará 1 byte.
Tsathoggua
1

J, 69 65 60 59 54 caracteres

Algo fuera del ritmo.

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

Ejemplo:

   {.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
fuente
1

C #, 398

Y aquí está C # con Linq 5 centavos

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
fuente
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
fuente
0

C # (.NET Core) , 297 bytes

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

Pruébalo en línea!

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
fuente