玩单词链


15

在我小的时候,我经常玩一个叫做Word chain的文字游戏。这很简单。第一个玩家选择一个单词;下一位玩家说另一个单词,该单词以与上一个单词结尾相同的字母开头。这将一直持续下去,直到有人放弃!诀窍是,您不能两次使用相同的单词(除非每个人都忘记了甚至使用过该单词!)。通常,我们会讨论一个特定的主题,以使其难度更大。但是现在,我希望您编写一个程序来为我执行此操作。

挑战

编写完整的程序或函数,以使用给定的一组单词和起始单词查找所有最长的单词链。

这是,因此最短的代码获胜!

输入值

有两个输入:一个列表和一个起始词。起始词将不在列表中。输入全部为小写ASCII,并且列表中将不包含重复的单词。

输出量

列表中的所有单词序列,使得:

  • 起始单词是序列中的第一个单词。

  • 每个后续单词均以与前一个单词的最后一个字母相同的字母开头。

  • 序列的长度是最长的

如果有多个最长的序列,请全部输出。

该序列不一定需要包含所有列表单词。有时这是不可能的(请参见测试用例)。同样,任何单词都不能使用两次!

测试用例

In: [hello, turtle, eat, cat, people] artistic
Out:  [artistic, cat, turtle, eat]
In: [lemonade, meatball, egg, grape] ham 
Out: [ham, meatball, lemonade, egg, grape]
In: [cat, cute, ewok] attic
Out: [attic, cute, ewok]
In:[cat, cute, ewok, kilo, to, otter] attic
Out: [attic, cute, ewok, kilo, otter]
In:[cat, today, yoda, attic] ferret
Out: [ferret, today, yoda, attic, cat]
In: [cancel, loitering, gnocchi, improv, vivic, child, despair, rat, tragic, chimney, rex, xylophone] attic
Out: [[attic, child, despair, rat, tragic, cancel, loitering, gnocchi, improv, vivic, chimney], [attic, cancel, loitering, gnocchi, improv, vivic, child, despair, ra', tragic, chimney]]
In: [cat, today, yoda, artistic, cute, ewok, kilo, to, otter] attic
Out: [attic, cat, today, yoda, artistic, cute, ewok, kilo, otter]

4
@downvoters能否请您解释一下我如何改善我的问题?
TanMath '16

@ user81655确定
TanMath '16

2
您可以添加具有多个输出序列的测试用例吗?
isaacg

@isaacg好!正在
为此

@isaacg添加了!(已达到15个字符的限制...)
TanMath '16

Answers:


8

Pyth,25 23字节

.MlZfqhMtTeMPT+Lzs.pMyQ

测试套件

蛮力解决方案。对于某些较大的测试用例而言,速度太慢了。

输入形式:

attic
["cat", "today", "yoda", "to", "otter"] 

输出形式:

[['attic', 'cat', 'today', 'yoda'], ['attic', 'cat', 'to', 'otter']]

说明:

.MlZfqhMtTeMPT+Lzs.pMyQ
                           Q = eval(input()) (The list of words)
                           z = input()       (The starting word)
                     yQ    All subsets of the input.
                  .pM      All permutations of the subsets.
                 s         Flatten.
              +Lz          Add the starting word to the front of each list.
                           This is all possible sequences.
    f                      Filter on
     q                     The equality of
      hMtT                 The first character of each word but the first
          eMPT             The last character of each word but the last
.MlZ                       Take only the lists of maximal length.

2
你能补充说明吗?
TanMath

对于多个输出序列示例,您的代码将永远运行
TanMath 2016年

3
@TanMath不,这只是指数时间,所以非常慢。
isaacg

5
代码高尔夫:制作一个本来可以快速运行的程序以指数方式运行的艺术只是为了节省几个字节:P
Arcturus,2016年

1
@RikerW我认为还值得回想一下Martin在这里聊天时发表的“代码审查:使代码错误少一些/代码高尔夫:使代码长度少一些”。
Arcturus

4

JavaScript(ES6),164个字节

f=(l,s,r=[[]])=>l.map((w,i)=>w[0]==s.slice(-1)&&(x=l.slice(),x.splice(i,1),o=f(x,w),a=o[0].length,b=r[0].length,r=a>b?o:a<b?r:r.concat(o)))&&r.map(q=>[s].concat(q))

说明

递归函数,用于检查所有可能选择的输出列表将持续多长时间。

返回单词数组。

f=(l,s,r=[[]])=>            // l = list, s = starting word, r is not passed (it is
                            //     here so that it is not defined globally)
  l.map((w,i)=>             // for each word w at index i
    w[0]==s.slice(-1)&&(    // if the first letter is the same as the last letter:
      x=l.slice(),          // x = clone of the list of words
      x.splice(i,1),        // remove the current word
      o=f(x,w),             // get the list of words starting from the current word
      a=o[0].length,
      b=r[0].length,
      r=a>b?o:              // if o is longer, set r to o
        a<b?r:              // if o is shorter, keep r
        r.concat(o)         // if o is same, add it to r
    )
  )
  &&r.map(q=>[s].concat(q)) // return a list of longest lists with the starting word

测试

测试中未使用默认参数,以使其更加兼容跨浏览器。


我想你可以使用弹出,而不是拼接和o[r.length]?替代的o.length>r.length?
grc

@grc谢谢,我真的很喜欢o[r.length]小费!我不知道该怎么用pop
user81655'1

嗯,nvm-我认为pop可以像python一样将索引作为其第一个参数。
grc

此解决方案对于多个输出序列无效
TanMath '16

@TanMath已修复,尽管它破坏了测试用例之一。
user81655

3

巨蟒,104

def f(d,w):
 a=[[w]]
 while a:b=a;a=[x+[y]for x in a for y in set(d)-set(x)if x[-1][-1]==y[0]]
 return b

我认为它现在应该可以工作...

在线尝试


1

Perl 5,275个字节

可能没有尽可能多地打高尔夫球,但是,嘿,无论如何它是不赢的,对吧?

use List::Util max;use List::MoreUtils uniq,before;use Algorithm::Permute permute;$i=pop;permute{push@c,[@ARGV]}@ARGV;for$c(@c){unshift@$c,$i;push @{$d{before{(substr$c->[$_],-1)ne(substr$c->[1+$_],0,1)}keys$c}},$c}for$m(max keys%d){say for uniq map{"@$_[0..$m+1]"}@{$d{$m}}}

因此使用它:

$ perl -M5.010 chain.pl cat tin cot arc
arc cat tin
arc cot tin

警告!在长列表中使用此脚本需要大量内存!它对我来说很好(七个(六个加一个)),但对十三个(十二个加一个)却不起作用。

它删除最终输入,生成arrayrefs数组,其中arrayrefs是所有排列,并在开头重新添加初始单词。然后,它将每个这样的置换推送到另一个arrayref上,该ref是具有键的哈希值,该哈希值是具有所需链接属性的数组的数量。然后,它找到最大的此类密钥并打印出所有阵列。


0

C,373字节

g(char*y){printf("%s, ",y);}z(char*w){int i,k=-1,v=0,j=sizeof(c)/sizeof(c[0]);int m[j],b=0;for(i=0;i<j;i++){m[v++]=c[i][0]==w[strlen(w)-1]?2:1;if(u[i]==6)m[v-1]=1;if(strcmp(w,c[i]))k=i;}printf("%s",w);for(i=0;i<j;i++){if(m[i]!=1){if(v+i!=j){g(s);for(;b<j;b++){if(u[b]==6)g(c[b]);}}else printf(", ");u[i]=6;z(c[i]);u[i]=1;}else v+=-1;}if(k!=-1)u[k]=1;if(v==0)printf(" ; ");}

我相信在这里我可以打更多的高尔夫球,所以我可能会对其进行更新。

去高尔夫

char *c[9]={"cat","today","yoda","artistic","cute","ewok","kilo","to","otter"};
u[9]={-1};
char *s="attic";

g(char*y){printf("%s, ",y);}
z(char*w){
   int i,k=-1,v=0,j=sizeof(c)/sizeof(c[0]);
   int m[j],b=0;
   for(i=0;i<j;i++){
      m[v++]=c[i][0]==w[strlen(w)-1]?i:-1;
      if(u[i]==6)m[v-1]=-1;
      if(strcmp(w,c[i]))k=i;
   }
   printf("%s",w);
   for(i=0;i<j;i++){
      if(m[i]!=-1){
         if(v+i!=j){
            g(s);
            for(;b<j;b++){
                if(u[b]==6)g(c[b]);
             }
         }else printf(", ");
         u[i]=6;
         z(c[i]);
         u[i]=-1;
      } else v+=-1;
   }
   if(k!=-1)u[k]=-1;
   if(v==0)printf(" ; ");
}

main(){
   z(s);
   printf("\n");
   return 0;
}

Ideone链接 -如果我没有正确执行操作,请告诉我:D


您可以添加一个ideone链接进行测试吗?
TanMath

是的,我将使用@TanMath更新它的答案
Danwakeem '16

链接应包含高尔夫代码,而不是非高尔夫版本。这样,我们可以确认您为挑战赛提交的高尔夫球版本。
TanMath
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.