Game nama kota

16

Jika Anda suka, tulislah program yang mengurutkan kota-kota sesuai dengan aturan permainan nama kota.

  • Setiap nama kota harus dimulai dari huruf terakhir dalam nama kota sebelumnya. MisalnyaLviv -> v -> Viden -> n -> Neapolis -> s -> Sidney -> y -> Yokogama -> a -> Amsterdam -> m -> Madrid -> d -> Denwer

  • Dalam daftar yang diurutkan huruf pertama dari kota pertama dan huruf terakhir dari yang terakhir tidak boleh cocok dengan apa pun yang tidak harus menjadi huruf yang sama.

  • Anda dapat menganggap nama kota hanya memiliki huruf.
  • Output program harus memiliki kapitalisasi yang sama dengan input

Contoh:

% ./script Neapolis Yokogama Sidney Amsterdam Madrid Lviv Viden Denwer
["Lviv", "Viden", "Neapolis", "Sidney", "Yokogama", "Amsterdam", "Madrid", "Denwer"]
defhlt
sumber
2
Bisakah kita berasumsi bahwa akan selalu ada solusi yang valid?
Gareth
@ Gareth ya, Anda bisa
defhlt
aturan kedua - "[...] tidak boleh cocok dengan apa pun" - apakah itu persyaratan atau hanya pernyataan yang mengatakan bahwa tidak masalah memiliki ketidakcocokan antara huruf pertama dan terakhir? (mis: apakah daftar seperti ["Viden" ... "Lviv"]tidak valid?)
Cristian Lupascu
@ w0lf oleh "seharusnya" saya maksudnya tidak harus, itu tidak wajib. Jadi contoh Anda valid.
defhlt
Petunjuk: Jika Anda menginginkan solusi yang bagus , Anda bisa mengurangi ini ke perhitungan jalur euler, di mana setiap huruf adalah simpul dan setiap kata adalah ujung. (Misalnya, Berlin adalah tepi BN ) Ini dapat dipecahkan dalam O (n), di mana n adalah jumlah tepi.
FUZxxl

Jawaban:

11

Ruby, 58 55 44 karakter

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

Namun implementasi ruby ​​lain. Menggunakan juga case regens tidak sensitif (sebagai solusi lama Ventero ) tetapi tes dilakukan secara berbeda.

Versi sebelumnya:

p$*.permutation.find{|i|(i*?,).gsub(/(.),\1/i,"")!~/,/}
Howard
sumber
Sangat bagus! Dan saya pikir Anda bisa mendapatkan ini hingga 55 jika Anda menggunakan !~alih-alih meniadakan seluruh ekspresi.
Cristian Lupascu
Itu pintar regexp
defhlt
@ w0lf Tentu saja! Bagaimana mungkin aku tidak memikirkan itu?
Howard
5

Python ( 162 141) 124)

Kekuatan brutal untuk menang.

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
sumber
1
Saya pikir Anda dapat menghapus &(j[0][0]!=j[-1][-1])kondisinya; lihat komentar pertanyaan di atas.
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
Saya mencoba membungkus kepala saya dengan apa yang terjadi dalam fungsi ini. Apa sebenarnya yang j, x, y? Bagaimana mereka didefinisikan? Saya minta maaf jika pertanyaan-pertanyaan ini lemah, saya baru di Python dan ingin bekerja dengannya lagi.
Rob
@MikeDtrick: jberisi permutasi dari kota-kota, yang dihasilkan dengan permutationsperintah. Besar ifpada akhirnya pada dasarnya memvalidasi bahwa untuk semua nilai dalam j, huruf terakhir dari satu nilai dalam jadalah sama dengan huruf pertama dari nilai berikutnya dalam j. Jujur, saya juga tidak tahu apa yang zipdilakukannya, zipbekerja dengan cara yang misterius.
beary605
Oke, terima kasih atas penjelasannya! +1
Rob
5

Ruby 1.9, 63 54 karakter

Solusi baru didasarkan pada Howard 's solusi :

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

Ini menggunakan fakta bahwa akan selalu ada solusi yang valid.

Solusi tua, berdasarkan w0lf 's solusi :

p$*.permutation.find{|i|i.inject{|a,e|a&&e[0]=~/#{a[-1]}/i&&e}}
Ventero
sumber
Ide bagus dengan max_by. Dan versi baru Anda menginspirasi diri saya untuk versi yang lebih baru (dan lebih pendek).
Howard
@Howard, Terima kasih! Solusi baru Anda benar-benar luar biasa, akan sulit dikalahkan. ;)
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 (dalam demo yang saya gunakan gets().split()alih-alih $*; Saya tidak tahu apakah Ideone dapat mensimulasikan args baris perintah).

Cristian Lupascu
sumber
terlihat mirip dengan varian saya $*.permutation{|p|p p if p.inject(p[0][0]){|m,e|m.casecmp(e[0])==0?e[-1]:?_}>?_}tetapi milik Anda lebih pendek 9 karakter!
defhlt
2
p$*.permutation.find{|i|i.inject{|a,e|a&&e[0]=~/#{a[-1]}/i&&e}}sedikit lebih pendek. Solusi Ruby 1.8 (!) Yang bahkan lebih pendek:p$*.permutation.find{|i|i.inject{|a,e|a&&a[-1]-32==e[0]&&e}}
Ventero
@Ventero Menggunakan regex case-insensitive adalah ide cemerlang! Silakan posting ini sebagai jawaban Anda sendiri; Saya tidak layak menggunakannya. :)
Cristian Lupascu
@Ventero -32solusinya juga sangat cerdik, tetapi bergantung pada kenyataan bahwa nama dimulai dengan huruf besar dan diakhiri dengan huruf kecil, yang mungkin tidak selalu demikian.
Cristian Lupascu
@ w0lf Anda benar, saya pikir saya membaca dalam spesifikasi bahwa itu akan terjadi, tapi jelas saya salah. ;)
Ventero
3

Python, 113

Sangat mirip dengan jawaban @ beary605, dan bahkan lebih kasar.

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
Royalti yang Dicuri
sumber
1
Woohoo, gaya bogo-sort!
beary605
3

Haskell , 94 74 byte

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

Secara rekursif menemukan semua solusi. -7 byte jika tidak apa-apa untuk menampilkan semua solusi, bukan yang pertama. Terima kasih kepada @Lynn karena telah menyingkirkan impor sial, mengurangi nilai 18 byte!

Cobalah online!

Angs
sumber
Anda dapat menyingkirkan Data.Charimpor dengan last b==[r!!0!!0..]!!32. Juga, Anda tidak perlu orangtua dig[x|x<-c,x/=b]
Lynn
1
@ Lynn bagus, entah bagaimana saya pikir fromEnumakan menjadi suatu keharusan. Lucu, saya sudah mengambil tanda kurung itu sekali, tapi saya harus menyalin dari tab yang salah ...
Angs
2

GolfScript, 78 karakter

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

Versi pertama dalam GolfScript. Ini juga melakukan pendekatan brute force. Anda dapat melihat skrip berjalan pada input contoh online .

Howard
sumber
2

Sekam , 10 byte

←fΛ~=o_←→P

Cobalah online!

Penjelasan

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

Atau, 10 byte

Kita juga bisa menghitung jumlah pasangan yang berdekatan yang memenuhi predikat ( #), urutkan pada ( Ö) itu dan ambil elemen terakhir ( ) untuk jumlah byte yang sama:

→Ö#~=o_←→P

Cobalah online!

ბიმო
sumber
2

Jelly , 25 18 byte (Selamat datang di perbaikan!)

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

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

Terima kasih kepada @Lynn untuk sebagian besar peningkatan ini!

Solusi 25-byte:

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

Cobalah 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
sumber
2
Beberapa peningkatan: Cobalah online! Saya menulis log perubahan kecil di bidang "Input". (Oh, setelah Ðfsaya gunakan Xuntuk memilih solusi acak dan bukan yang pertama, tetapi berfungsi dengan baik.)
Lynn
@ Lynn Terima kasih banyak! Bagian zipnya sangat pintar, dan saya pikir saya bisa menggunakan itu dengan Ðfcepat di banyak program saya yang lain untuk menghemat ruang!
Harry
1

Mathematica 236 karakter

Tentukan daftar kota:

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

Temukan jalur yang mencakup semua kota:

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

Keluaran:

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

Pendekatan di atas mengasumsikan bahwa kota-kota dapat diatur sebagai grafik jalur.


Grafik p ditunjukkan di bawah ini:

grafik

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

Jalankan dengan nama negara sebagai argumen baris perintah

catatan:

  • generasi permutasi kasar
  • untuk memeriksanya mengasumsikan bahwa nama negara mulai dengan huruf besar dan berakhir dengan huruf kecil
  • menganggap hanya ada satu jawaban
  • Dalam C, mengasumsikan bahwa ** v array main () dapat ditulis
bayi-kelinci
sumber
Tidak yakin itu benar-benar valid, tetapi jika Anda melakukannya #define L(x)for(int i=x;i<n;i++)dan tidak menyatakan ipada awal mainAnda menghemat 1 byte.
Tsathoggua
1

J, 69 65 60 59 54 karakter

Agak melambat.

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

Contoh:

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

C #, 398

Dan di sini adalah C # dengan Linq 5 sen

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

Cobalah 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
sumber