城市名称游戏


16

如果愿意,可以编写一个根据城市名称游戏规则对城市进行排序的程序。

  • 城市的每个名称应从前一个城市名称的最后一个字母开始。例如Lviv -> v -> Viden -> n -> Neapolis -> s -> Sidney -> y -> Yokogama -> a -> Amsterdam -> m -> Madrid -> d -> Denwer

  • 在排序列表中,第一个城市的第一个字母和最后一个城市的最后一个字母不应该匹配,不必是相同的字母。

  • 您可以假设城市名称只有字母。
  • 程序输出应与输入大写相同

例:

% ./script Neapolis Yokogama Sidney Amsterdam Madrid Lviv Viden Denwer
["Lviv", "Viden", "Neapolis", "Sidney", "Yokogama", "Amsterdam", "Madrid", "Denwer"]

2
我们可以假设总会有一个有效的解决方案吗?
Gareth 2012年

@Gareth是的,您可以
2011年

第二个规则-[[...]不应匹配任何内容”-是一项要求还是只是一个声明,说第一个字母与最后一个字母不匹配是可以的?(例如:列表是否["Viden" ... "Lviv"]无效?)
Cristian Lupascu 2012年

@ w0lf by“ should't not”我的意思是不必这样做,这不是强制性的。所以你的例子是有效的。
2012年

提示:如果您想要一个好的解决方案,可以将其简化为欧拉路径的计算,其中每个字母是一个顶点,每个单词是一个边。(例如,柏林是边BN)。这在O(n)中是可解的,其中n是边数。
FUZxxl 2012年

Answers:


11

Ruby,58 55 44个字符

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

红宝石的另一个实现。还使用不区分大小写的正则表达式(作为Ventero的旧解决方案),但是测试的方式有所不同。

先前版本:

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

非常好!而且我认为如果使用!~而不是否定整个表达式,则可以将其降低到55 。
克里斯蒂安·卢帕斯库

那是明智的regexp
2012年

@ w0lf当然!我怎么会想到呢?
霍华德

5

蟒(162 141 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:]))]

1
我认为您可以消除这种&(j[0][0]!=j[-1][-1])情况;请参阅上面的问题评论。
克里斯蒂安·卢帕斯库

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

我正在努力解决此功能中发生的一切。究竟是什么jxy?如何定义它们?很抱歉,如果这些问题很la脚,我是Python的新手,并且想多使用一些它。
罗布

@MikeDtrick:j包含使用permutations命令生成的城市排列。if末尾的big 基本上验证了in中的所有值,in中j的一个值的最后一个字母与in j中的下一个值的第一个字母相同j。老实说,我也不知道它是做什么的zipzip以神秘的方式起作用。
beary605

好的,谢谢您的解释!+1
Rob

5

Ruby 1.9, 63 54个字符

新的解决方案基于霍华德解决方案

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

这利用了永远存在有效解决方案的事实。

基于w0lf解决方案的旧解决方案

p$*.permutation.find{|i|i.inject{|a,e|a&&e[0]=~/#{a[-1]}/i&&e}}

不错的主意max_by。您的新版本激发了我自己的灵感,希望购买一个更新(或更短)的产品。
霍华德

@霍华德谢谢!您的新解决方案确实很棒,将很难克服。;)
Ventero 2012年

4

红宝石74 72 104 103 71 70

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

演示: http : //ideone.com/MDK5c(在我使用的演示中,gets().split()而不是$*;我不知道Ideone是否可以模拟命令行参数)。


看起来与我的变体相似,$*.permutation{|p|p p if p.inject(p[0][0]){|m,e|m.casecmp(e[0])==0?e[-1]:?_}>?_}但您的变体短了9个字符!
2012年

2
p$*.permutation.find{|i|i.inject{|a,e|a&&e[0]=~/#{a[-1]}/i&&e}}短很多。一个甚至更短的Ruby 1.8(!)解决方案:p$*.permutation.find{|i|i.inject{|a,e|a&&a[-1]-32==e[0]&&e}}
Ventero 2012年

@Ventero使用不区分大小写的正则表达式是一个绝妙的主意!请将此作为您自己的答案发布;我不值得使用。:)
克里斯蒂安·卢帕斯库

@Ventero的-32解决方案也非常巧妙,但是它依赖于名称以大写字母开头和以小写字母结尾的事实,但情况并非总是如此。
克里斯蒂安·卢帕斯库

@ w0lf是的,我以为我在规格书中读到了这种情况,但显然我弄错了。;)
Ventero

3

Python,113

与@ beary605的答案非常相似,甚至更加残酷。

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

1
哇,波哥大排序风格!
beary605

3

Haskell94 74字节

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

递归找到所有解决方案。如果可以输出所有解决方案而不是第一个解决方案,则为-7个字节。感谢@Lynn摆脱了讨厌的导入,比分减少了18个字节!

在线尝试!


您可以使用摆脱Data.Char导入last b==[r!!0!!0..]!!32。另外,您不需要旁白g[x|x<-c,x/=b]
Lynn

1
@Lynn很好,我以某种方式认为fromEnum是必须的。有趣的是,我已经删除了一次括号,但是我肯定是从错误的选项卡中复制的……
Angs,

2

GolfScript,78个字符

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

GolfScript中的第一个版本。它也采用暴力手段。你可以看到的例子输入运行脚本在线


2

外壳,10字节

←fΛ~=o_←→P

在线尝试!

说明

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

或者,10个字节

我们还可以计算满足谓词(#)的相邻对的数量,对()进行排序Ö,并以相同的字节数获取最后一个元素():

→Ö#~=o_←→P

在线尝试!


2

Jelly25个 18字节(欢迎改进!)

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

在线尝试!

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!

感谢@Lynn所做的大部分改进!

25字节解决方案:

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

在线尝试!

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

2
一些改进:在线尝试!我在“输入”字段中写了一些变更日志。(哦,在ÐfX用来选择一个随机解而不是第一个解之后,但效果也不错。)
Lynn

@Lynn非常感谢!zip部分非常聪明,我认为我可以Ðf在很多其他程序中快速使用该压缩程序,以节省一些空间!
哈利

1

Mathematica 236个字符

定义城市列表:

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

查找包含所有城市的路径:

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

输出:

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

上述方法假定可以将城市安排为路径图。


图形p如下所示:

图形


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

使用国家/地区名称作为命令行参数运行

注意:

  • 暴力产生排列
  • 为了进行检查,假设国家/地区名称以大写字母开头,以小写字母结尾。
  • 假设只有一个答案
  • 在C中,假设main()的** v数组可写

不确定它是否完全正确,但是如果您在开始时#define L(x)for(int i=x;i<n;i++)声明并且不声明i,则main保存1个字节。
沙吞瓜

1

J,69 65 60 59 54个字符

有点不合时宜。

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

例:

   {.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|
+----+-----+--------+------+--------+---------+------+------+

1

C#,398

这是C#和Linq 5美分

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

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

0

C#(.NET Core),297字节

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

在线尝试!

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()) : "";
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.