搜索库的代码行进方式


15

挑战:

我的音乐收藏中有成千上万首歌曲,幸运的是,我最喜欢的播放器具有搜索功能。我也有一个美好的回忆-我可以记住收藏中每首歌曲的标题。但是,我很懒惰,不喜欢打字-每次额外的按键操作都很麻烦!

  • 要隔离一首歌曲,我必须搜索的最短字符串是什么?帮我记住一个列表,以便在搜索时尽量减少键入!

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


规则:

给定一个歌曲标题的输入列表,请生成一个受以下限制的搜索关键字列表:

  1. 每个歌曲标题都应有一个搜索键。
  2. 输出列表中的字符总数必须尽可能少。
  3. 我最喜欢的音乐播放器是foob​​ar2000
    • 搜索功能不区分大小写。(appleaPpLE)。
    • 每个搜索关键字必须由一个或多个“单词”组成,并且以任意顺序且以空格分隔:
      • 每个单词必须是相应歌曲标题的子字符串
      • 如果多次指定相同的子字符串,则其相应的歌曲标题中必须出现多次。
      • 如果子字符串本身包含空格,则该子字符串必须用引号引起来。

提示:

  • 通常,对于某些歌曲标题,有多个符合规则2的搜索键。在这种情况下,任何一个键都可以,但是您会获得布朗尼点,以列出所有键。
  • 您可以假设输入列表将仅使用ASCII字符,但是由于UTF-8兼容性而获得了布朗尼点。
  • 规则3难以遵循吗?运作方式如下:


例:

如果我的音乐收藏只包括两张专辑,迈克尔·杰克逊的《离墙》和《颤栗》

您可以使用上面的列表来测试您的程序。这是第二个列表的原始版本:

["Don't Stop 'Til You Get Enough","Rock with You","Working Day and Night","Get on the Floor","Off the Wall","Girlfriend","She's out of My Life","I Can't Help It","It's the Falling in Love","Burn This Disco Out","Wanna Be Startin' Somethin'","Baby Be Mine","The Girl Is Mine","Thriller","Beat It","Billie Jean","Human Nature","P.Y.T. (Pretty Young Thing)"]

1
您是否有一个示例,要求一个键包含多个字符串?
乔纳森·艾伦

1
怎么["Wanta Be A Wanna B","Wanta Bea A Wanna B","Wanna Be A Wanna Bea"]
乔纳森·艾伦

...但是如果子字符串本身不允许有空格,它们应该/应该是什么?请注意,所有整个单词都会发生冲突。
乔纳森·艾伦

为什么原始版本在剧透中?
Leaky Nun

Answers:


4

Python 2,556字节

在线尝试。

-10个字节,感谢@ Riker,@ ovs

花了我几个晚上使一切正常。
输出歌曲名称,搜索键数组和组合的搜索键长度(包括空格和引号)

import re
S=map(str.lower,input())
T=len
for s in S:
 y=s;n=T(s)
 def R(r,t):
    global n,y
    l=T(' '.join(t))+2*sum(map(lambda x:' 'in x,t))
    if l>n:return
    if(lambda K:T([s for s in S if T(s)-T(reduce(lambda x,y:re.sub(re.escape(y),'',x,1),K,s))==T(''.join(K))])==1)(t)and l<n:y=t;n=l
    u=[(lambda s,n:n and[''.join(y) for y in eval('zip(s%s)'%(''.join(',s[%s:]'%-~x for x in range(n))))]or list(s))(r,i)for i in range(T(r))]
    for i in range(T(r)):
     for j in range(T(r)-i):R(r[j+T(u[i][j]):],t+[u[i][j]])
 R(s,[])
 print[' 'in x and'"%s"'%x or x for x in y]

一些解释:

T=len

该函数len()在这里经常使用,因此重命名可以节省字节


L=lambda s,n:n and[''.join(y) for y in eval('zip(s%s)'%(''.join(',s[%s:]'%-~x for x in range(n))))]or list(s)

计算字符串s长度n的所有可能的子字符串。
eval(...)创建命令如果可能的话,zip(s,s[1:],s[2:],...,s[n:])
它将n从每个索引创建长度的子字符串s。因此,对于s='budd'n='2'会产生BU,UD,DD


F=lambda K:len([s for s in S if len(s)-len(reduce(lambda x,y:re.sub(re.escape(y),'',x,1),K,s))==len(''.join(K))])==1

进行过滤以检查提供的键(K)是否具有唯一的歌曲名称。
re.sub需要多个相同的键,例如示例中的['nn','nn']。


内部函数def R(r,t)是一种递归函数,用于创建子串的所有可能组合,以描述歌曲名称。
将每个组合与当前最短的组合(如果有)进行比较,以减少创建的组合的数量-如果组合较大,则将不接受所有组合,因为它是所有组合的派生形式。
函数使用2个变量跟踪状态:n当前最短键组合的长度以及y组合本身


l=T(' '.join(t))+2*sum(map(lambda x:' 'in x,t))

这将计算组合键的长度。' '.join在键之间添加空格,并2*sum(...)计算带空格的键所需的引号数量。


u=[L(r,i)for i in range(0,T(r))]

使用第一个lambda函数获取当前字符串的所有可能的键组合(每个可能的长度)。


两个for循环可浏览所有生成的键,并将它们分别传递给下一个递归步骤。j要在字符串末尾正确切分字符串,需要键位()r[j+T(u[i][j]):]
Slice提供了字符串,该字符串从当前键结束处开始,因此不会有任何重叠。
如果位置未知,则相等的键会使所有内容混乱。


[' 'in x and'"%s"'%x or x for x in y]

比更长的时间y,但是带空格的键应该用引号引起来。


这真太了不起了。您是第一个正确制定规则3的人!
艾y(Ayane)'17

1
顺便说一句,您应该能够通过删除以下0,范围之一来删除两个字节:u=[L(r,i)for i in range(0,T(r))]=> u=[L(r,i)for i in range(T(r))]
notjagan

1
您可以再保存几个字节:在输出中,不必显示输入字符串和输出字符串的大小。
艾y(Ayane)

@彩音M谢谢!我从范围和输出中修剪了这几个字节。
死负鼠宝

1
S=map(str.lower,input())-5字节
ovs
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.