Jogo de nomes de cidades

16

Se desejar, escreva um programa que classifique as cidades de acordo com as regras do jogo de nomes de cidades.

  • Cada nome da cidade deve começar com a última letra no nome da cidade anterior. Por exemploLviv -> v -> Viden -> n -> Neapolis -> s -> Sidney -> y -> Yokogama -> a -> Amsterdam -> m -> Madrid -> d -> Denwer

  • Na lista classificada, a primeira letra da primeira cidade e a última letra da última não devem corresponder a nada , não precisa ser a mesma letra.

  • Você pode assumir que os nomes das cidades tenham apenas letras.
  • A saída do programa deve ter a mesma capitalização que a entrada

Exemplo:

% ./script Neapolis Yokogama Sidney Amsterdam Madrid Lviv Viden Denwer
["Lviv", "Viden", "Neapolis", "Sidney", "Yokogama", "Amsterdam", "Madrid", "Denwer"]
defhlt
fonte
2
Podemos assumir que sempre haverá uma solução válida?
Gareth
@Gareth sim, você pode
defhlt
a segunda regra - "[...] não deve corresponder a nada" - é um requisito ou apenas uma declaração dizendo que não há problema em incompatibilidade entre a primeira e a última letra? (ex: é uma lista como ["Viden" ... "Lviv"]inválida?)
Cristian Lupascu
@ w0lf por "shouldn't" eu quis dizer que não precisa, não é obrigatório. Portanto, seu exemplo é válido.
Defhlt
Dica: Se você deseja uma boa solução, pode reduzi-la ao cálculo de caminhos eulerianos, onde cada letra é um vértice e cada palavra é uma aresta. (Por exemplo, Berlim é a aresta BN ) Isso é solucionável em O (n), onde n é o número de arestas.
FUZxxl 17/07/2012

Respostas:

11

Ruby, 58 55 44 caracteres

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

Mais uma implementação em ruby. Também usa regex que não diferencia maiúsculas de minúsculas (como a solução antiga de Ventero ), mas o teste é feito de maneira diferente.

Versão anterior:

p$*.permutation.find{|i|(i*?,).gsub(/(.),\1/i,"")!~/,/}
Howard
fonte
Muito agradável! E acho que você pode reduzir para 55 se usar em !~vez de negar toda a expressão.
18712 Cristian Lupascu
Isso é regexp inteligente
defhlt
@ w0lf Claro! Como eu não pude pensar nisso?
217 Howard
5

Python ( 162 141 124)

Força bruta para a vitória.

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
fonte
11
Eu acho que você pode remover a &(j[0][0]!=j[-1][-1])condição; veja os comentários da pergunta acima.
Cristian Lupascu 16/07/12
11
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 16/07/2012
Estou tentando entender o que está acontecendo nessa função. O que são exatamente j, x, y? Como eles são definidos? Sinto muito se essas perguntas são ruins, eu sou novo no Python e gostaria de trabalhar um pouco mais.
Rob
@MikeDtrick: jcontém uma permutação das cidades, gerada com o permutationscomando O valor iffinal basicamente valida que, para todos os valores em j, a última letra de um valor em jé igual à primeira letra do próximo valor em j. Honestamente, eu também não sei o que zipfaz, zipfunciona de maneiras misteriosas.
beary605
Ok, obrigado pela explicação! +1
Rob
5

Ruby 1.9, 63. 54 caracteres

Nova solução é baseada em Howard 's solução :

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

Isso usa o fato de que sempre haverá uma solução válida.

Solução antiga, baseado em w0lf 's solução :

p$*.permutation.find{|i|i.inject{|a,e|a&&e[0]=~/#{a[-1]}/i&&e}}
Ventero
fonte
Boa ideia com o max_by. E sua nova versão me inspirou para uma ainda mais nova (e mais curta).
Howard
@ Howard Obrigado! Sua nova solução é realmente incrível, será difícil superar isso. ;)
Ventero 17/07/2012
4

Rubi 74 72 104 103 71 70

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

Demonstração: http://ideone.com/MDK5c (na demonstração que usei em gets().split()vez de $*; não sei se o Ideone pode simular argumentos de linha de comando).

Cristian Lupascu
fonte
parece semelhante à minha variante, $*.permutation{|p|p p if p.inject(p[0][0]){|m,e|m.casecmp(e[0])==0?e[-1]:?_}>?_}mas a sua é 9 caracteres mais curta!
Defhlt
2
p$*.permutation.find{|i|i.inject{|a,e|a&&e[0]=~/#{a[-1]}/i&&e}}é um pouco mais curto. Uma solução Ruby 1.8 (!) Que é ainda mais curta:p$*.permutation.find{|i|i.inject{|a,e|a&&a[-1]-32==e[0]&&e}}
Ventero 17/07/2012
@Ventero Usar regex que não diferencia maiúsculas de minúsculas é uma idéia brilhante! Por favor, poste isso como sua própria resposta; Não sou digno de usar isso. :)
Cristian Lupascu
@Ventero, a -32solução também é muito engenhosa, mas se baseia no fato de que os nomes começam com uma letra maiúscula e terminam com uma minúscula, o que nem sempre pode ser o caso.
Cristian Lupascu 17/07/2012
@ w0lf Você está certo, pensei ter lido nas especificações que seria esse o caso, mas obviamente estou enganado. ;)
Ventero 17/07/2012
3

Python, 113

Muito parecido com a resposta de @ beary605 e ainda mais forçado.

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
Realeza Nolen
fonte
11
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

Encontra recursivamente todas as soluções. -7 bytes, se estiver correto, forneça todas as soluções em vez da primeira. Obrigado a @Lynn por se livrar da importação traquina, eliminando 18 bytes de pontuação!

Experimente online!

Angs
fonte
Você pode se livrar da Data.Charimportação com last b==[r!!0!!0..]!!32. Além disso, você não precisa parens emg[x|x<-c,x/=b]
Lynn
11
@ Lynn bom, de alguma forma pensei fromEnumque seria uma obrigação. Engraçado, eu já tirei esses parênteses uma vez, mas devo ter copiado da guia errada ...
Angs
2

GolfScript, 78 caracteres

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

Uma primeira versão no GolfScript. Ele também faz uma abordagem de força bruta. Você pode ver o script em execução na entrada de exemplo online .

Howard
fonte
2

Casca , 10 bytes

←fΛ~=o_←→P

Experimente online!

Explicação

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

Como alternativa, 10 bytes

Também podemos contar o número de pares adjacentes que satisfazem o predicado ( #), classificar em ( Ö) isso e pegar o último elemento ( ) para o mesmo número de bytes:

→Ö#~=o_←→P

Experimente online!

ბიმო
fonte
2

Geléia , 25 18 bytes (Melhoramentos bem-vindos!)

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

Experimente 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!

Obrigado a @Lynn pela maioria dessas melhorias!

Solução de 25 bytes:

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

Experimente 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
atormentar
fonte
2
Algumas melhorias: Experimente online! Eu escrevi um pequeno changelog no campo "Input". (Oh, depois Ðfque eu uso Xpara escolher uma solução aleatória em vez do primeiro, mas funciona tão bem.)
Lynn
@ Lynn Muito obrigado! A parte zip foi muito inteligente, e acho que posso usar isso Ðfrapidamente em muitos dos meus outros programas para economizar espaço!
Harry
1

Mathematica 236 caracteres

Defina a lista de cidades:

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

Encontre o caminho que inclui todas as cidades:

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

Resultado:

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

A abordagem acima pressupõe que as cidades podem ser organizadas como um gráfico de caminho.


O gráfico p é mostrado abaixo:

gráfico

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

Executar com nomes de países como argumentos da linha de comando

Nota:

  • geração de força bruta de permutações
  • para verificar, pressupõe que os nomes de países começam com maiúsculas e terminam com minúsculas.
  • assume que há apenas uma resposta
  • Em C, assume que a matriz ** v de main () é gravável
coelho bebê
fonte
Não tenho certeza se é exatamente válido, mas se você fizer #define L(x)for(int i=x;i<n;i++)e não declarar ino início, mainsalve 1 byte.
Tsathoggua
1

J, 69 65 60 59 54 caracteres

Um pouco fora do ritmo.

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

Exemplo:

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

C #, 398

E aqui está C # com 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
fonte
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
fonte
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()):"";}

Experimente 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
fonte