字符串X是字符串Y的子序列吗?


23

给定字符串X和Y,请确定X是否为Y的子序列。空字符串被视为每个字符串的子序列。(例如'''anna'是的子序列'banana'。)

输入项

  • X,可能为空,区分大小写的字母数字字符串
  • Y,可能是空的区分大小写的字母数字字符串

输出量

  • True或False(或等效项),正确指示X是Y的子序列。

I / O实例

X      Y        output

''     'z00'    True
'z00'  'z00'    True 
'z00'  '00z0'   False
'aa'   'anna'   True
'anna' 'banana' True
'Anna' 'banana' False

标准

  • 最短的程序获胜,这取决于源代码的字节数。

示例程序


1
为什么“ anna”代替“ banana”?
kaoD 2012年

4
@kaoD- anna是的子序列(但不是子字符串)banana。字符串X是字符串Y的子序列,即使可以通过删除Y的零个或多个元素来从Y获得X的情况;例如,从Give中删除b和中的第二个。abananaanna
res 2012年

2
在提供正则表达式的每种脚本语言中,这只有一个解决方案,这既琐碎又难以实现。
2012年

Answers:


18

Perl 5、17个字节(+1?),完整程序

s//.*/g;$_=<>=~$_

在线尝试!

p标志一起调用到perl解释器,如中所示perl -pe 's//.*/g;$_=<>=~$_'。根据最初发布此挑战时已建立的评分规则,此标志会额外增加一个字节。根据最新的 AFAICT 规则,它可能是免费的。

无论哪种方式,输入字符串都应在stdin上以换行符结尾的单独行中提供。1如果第一个输入字符串是第二个输入字符串的子字符串,则输出(到stdout)将是输出,否则则根本不输出。

请注意,两个输入行的末尾必须换行,否则程序将无法正常运行。另外,您可以l在调用中添加命令行标志,以使perl去除换行符;根据有效的评分规则,这可能会或可能不会花费一个额外的字节。请注意,使用此标志还将在输出中添加换行符。

原始版本(代码段,18字节/字符)

$x=~s//.*/g,$y=~$x

输入是在变量$x和中给出的$y,结果是表达式的值(在标量上下文中)。请注意,$x在此过程中进行了修改。(是的,我知道使用$_代替$x可以让我节省四个字符,但是在一段对我来说太俗气的代码段中这样做。)

它是如何工作的?

第一部分在中的每个字符之间$x=~s//.*/g插入字符串。第二部分视为正则表达式并与其匹配。在Perl正则表达式中,匹配零个或多个任意字符,而所有字母数字字符都方便地匹配自己。.*$x$y=~$x$x$y.*


根据(新的?)共识,提交的内容必须是程序或功能,而不是摘要。如果您的提交不满足要求,请考虑对其进行编辑。
user202729 '18

@ user202729:这个挑战比共识要古老得多,因此,除非假定它具有追溯力,否则此线程中的答案可能应该是“祖父”。也就是说,我只是添加了一个符合当前规则的版本,并且甚至可能短一个字节/个字符(请注意,基于字节的计数也比这项挑战AFAIK更新),具体取决于您对命令行开关的计数方式。
Ilmari Karonen

9

Ruby,32个字符

s=->x,y{y=~/#{[*x.chars]*".*"}/}

nil如果x不是的子序列,则返回此解决方案,y否则返回一个数字(即与false和等效的红宝石true)。例子:

p s['','z00']        # => 0   (i.e. true)
p s['z00','z00']     # => 0   (i.e. true)
p s['z00','00z0']    # => nil (i.e. false)
p s['anna','banana'] # => 1   (i.e. true)
p s['Anna','banana'] # => nil (i.e. false)

1
我基本上做了相同的事情,但是太相似了,所以我不会发布。我认为离开lambda是可以接受的,这将使您剩下y=~/#{[*x.chars]*".*"}/(23个字符)。干杯!
Patrick Oscity

1
甚至y=~/#{x.split("")*".*"}/(21个字符):)
Patrick Oscity

@padde拆分的实际上是24个字符。
霍华德

1
抱歉,我想我y=~在irb摆弄这个东西的时候不小心离开了
Patrick Oscity 2012年

我的版本短了2个字符。
Hauleth 2012年

7

哈斯克尔, 51 37

h@(f:l)%(g:m)=f==g&&l%m||h%m;x%y=x<=y

感谢Hammar的实质性改进。现在它是一个infix函数,但似乎没有理由不这样做。

示范:

GHCi> :{
GHCi| zipWith (%) [""   , "z00", "z00" , "anna"  , "Anna"]
GHCi|             ["z00", "z00", "00z0", "banana", "banana"]
GHCi| :}
[True,True,False,True,False]

由于空列表小于任何其他列表,因此您可以将基本情况简化为s x y=x<=y。另外,您可以通过将其@设为运算符并使用-pattern代替来节省更多(f:l)。这样可以减少到37个字符:h@(f:l)%(g:m)=f==g&&l%m||h%m;x%y=x<=y
hammar 2012年

6

Python(48个字符)

import re;s=lambda x,y:re.search('.*'.join(x),y)

与Howard的Ruby回答相同的方法。对于Python是否需要导入regex软件包及其“详细”信息,这太糟糕了lambda。:-)


1
我同意,lambda很冗长。
CalculatorFeline

4

Python,59个字符

def s(x,y):
 for c in y:
  if x:x=x[c==x[0]:]
 return x==""

我想我的答案会更好地用Python表达。

编辑:添加了res的建议。


当然可以x="a"y="ab"您将退出循环y=="b"并返回false
彼得·泰勒

@PeterTaylor是啊,我当我发布后运行的实例作为测试,我已经注意到混合xy起来。在我的职能中y,必须是的子序列x。我认为我最好更改它们,以免造成任何混乱。
Gareth

您最多可以将其减少到59个字符:def s(x,y): for c in y: if x:x=x[c==x[0]:] return x==""。它无法在评论中正确显示,但是我想您可以理解我的意思。(另外,增加一个空间足以增加缩进级别。)
2012年

@res谢谢,您可能会说,Python不是我使用过多的语言。打高尔夫球不错。(根据Codegolf用户脚本显示63个字符-必须在计算换行符)。
Gareth 2012年

1
您可以使用扩展切片来防止出现x ''并通过写入来保存几个字符x=x[c==x[0:1]:]
Nolen Royalty

4

GolfScript(22个字符)

X[0]+Y{1$(@={\}*;}/0=!

假定将输入作为两个预定义变量XY,尽管这在GolfScript中是很不常见的。叶1为真或0堆栈上的虚假。



4

滑稽(6个字符)

Burlesque中的6个字符:( R@\/~[ 假设x和y在堆栈中。请参见此处的操作。)




3

Scala 106:

def m(a:String,b:String):Boolean=(a.size==0)||((b.size!=0)&&((a(0)==b(0)&&m(a.tail,b.tail))||m(a,b.tail)))

3

CoffeeScript 112 100 95 89

我第一次尝试打码高尔夫...希望我不要让我的家人感到羞耻!

z=(x,y)->a=x.length;return 1if!a;b=y.indexOf x[0];return 0if!++b;z x[1..a],y[b..y.length]

编辑:事实证明,Coffeescript比空白所想象的要宽容得多。

感谢res和Peter Taylor提供的一些技巧,使其变得更时尚


一些更多的字符可以如下消除(这不会权评论显示,但我认为你能明白我的意思)z=(x,y)-> a=x.length return 1if a==0 b=y.indexOf x[0] return 0if b<0 z x[1..a],y[b+1..y.length]。(在某些浏览器中,例如Chrome,右键单击然后检查元素,可以正确显示注释代码。)
2012年

a.length永远不会是负数,因此您可以通过替换if a==0为来多保存一个字符if a<1。我不知道CoffeeScript的令牌化如何工作,但是如果将它分解if0为两个令牌,则可以通过颠倒这两个条件(即if1>a)再节省两个。
彼得·泰勒

好点。if1>a无效,但是if!a并且字符短了!我还意识到,我可以刮掉一个额外的字符,将其转换b+1b前一行并在前一行进行递增,if因为处理0 /非0情况也使相同的技巧成为可能。
约翰诺2012年

3

C #, 70 113 107 90个字符

static bool S(string x,string y){return y.Any(c=>x==""||(x=x.Remove(0,c==x[0]?1:0))=="");}

6
这不是在寻找子字符串而不是子序列吗?
Gareth

是的,我读错了。现在应该修复。
mizer 2012年

1
与Linq一样有趣,我认为您可以通过使用递归来节省10%的费用。
彼得·泰勒

这是我的最佳尝试。还更长。 static bool S(string x,string y){if(x!=""&&y=="")return false;return x==""||S(y[0]==x[0]?x.Remove(0,1):x,y.Remove(0,1));}
mizer 2012年

您可以将递归代码减少为x==""||y!=""&&S(...),但仍比更新的Linq版本更长。很好用Any
彼得·泰勒

3

Mathematica 19 17 27

LongestCommonSequence返回两个字符串中最长的非连续子序列。(请勿与混淆LongestCommonSubsequence,它会返回最长的连续子序列。

下面检查最长的连续子序列是否是两个字符串中的第一个。(因此,您必须输入较短的字符串,然后输入较大的字符串。)

LongestCommonSequence@##==#& 

例子

LongestCommonSequence@## == # &["", "z00"]
LongestCommonSequence@## == # &["z00", "z00"]
LongestCommonSequence@## == # &["anna", "banana"]
LongestCommonSequence@## == # &["Anna", "banana"]

正确正确正确错误

关键测试是第三个测试,因为“香蕉”不连续地包含在“香蕉”中。


3

Python 3.8(预发布),42字节

lambda a,b:''in[a:=a[a[:1]==c:]for c in b]

在线尝试!

Python 3.8(预发布),48字节

lambda a,b,j=0:all((j:=1+b.find(c,j))for c in a)

在线尝试!

Python 2,48个字节

lambda a,b:re.search('.*'.join(a),b)>0
import re

在线尝试!

复制自 林恩的回答中>0如果只输出正确/错误,则可以省略。

Python 2个字节

f=lambda a,b:b and f(a[a[:1]==b[0]:],b[1:])or''==a

在线尝试!

Python 2个字节

lambda a,b:reduce(lambda s,c:s[c==s[:1]:],b,a)==''

在线尝试!


海象的大量使用。
乔纳森·艾伦

2

C - -74 71 64

这没有超越Peter Taylor的解决方案,但我认为这很有趣(而且,这是一个完整的工作程序,而不仅仅是一个功能)

main(int c,char**v){for(;*v[1]!=0;++v[1])v[2]+=*v[1]==*v[2];return*v[2];}

main(int c,char**v){for(;*v[1];++v[1])v[2]+=*v[1]==*v[2];return*v[2];}


main(c,v)char**v;{while(*v[1])v[2]+=*v[1]++==*v[2];return*v[2];}

和无高尔夫球场:

main(int argc, char** argv){
   char * input = argv[1];
   char * test  = argv[2];

   // advance through the input string. Each time the current input
   // character is equal to the current test character, increment
   // the position in the test string.

   for(; *input!='\0'; ++input) test += *input == *test;

   // return the character that we got to in the test string.
   // if it is '\0' then we got to the end of the test string which
   // means that it is a subsequence, and the 0 (EXIT_SUCCESS) value is returned
   // otherwise something non-zero is returned, indicating failure.
   return *test;
}

要测试它,您可以执行以下操作:

./is_subsequence banana anna && echo "yes" || echo "nope"    
# yes
./is_subsequence banana foobar && echo "yes" || echo "nope"    
# nope

!=0在某种情况下有点冗长...程序与功能是问题需要明确指定的东西,这里不是必须的,因此答案采用不同的选择。
彼得·泰勒

该死,这!='\0'是编写非高尔夫球代码的坏习惯(好吗?),我已经把它塞进了我的前两轮高尔夫比赛中,以后我将不得不更加小心。关于程序与功能,是的,您绝对正确。
Gordon Bailey 2012年

@GordonBailey很抱歉,但是我对较短的版本做了一些更改。
oldrinb 2012年

2

蟒蛇, 66 62 59 58个字符

一种有趣的解决方案,绝对是一个整洁的问题。

def f(n,h,r=0):
 for c in h:r+=n[r:r+1]==c
 return r==len(n)

2

红宝石32 30 28

f=->a,b{b.match a.tr'','.*'}

MatchData如果ab或的子序列,则将返回实例nil

查找子字符串而不是子序列的旧版本

红宝石15

f=->a,b{!!b[a]}

使用String#[](str)方法,该方法返回str,如果str是的子串self!!返回Boolean如果返回的值可以是可作为布尔型(和不需要是truefalse),那么它可以是只有13个字符:

f=->a,b{b[a]}

nil如果a不是的子字符串,它将返回b


2
很好,但是这个问题要求一个子序列而不是一个子串。
Gareth

2

SWI-Prolog,SICStus

SICStus 的内置谓词sublist / 2检查第一个列表中的所有项是否也出现在第二个列表中。该谓词也可通过兼容性库在SWI-Prolog中获得,该库可由查询加载[library(dialect/sicstus/lists)].

样品运行:

25 ?- sublist("","z00").
true.

26 ?- sublist("z00","z00").
true .

27 ?- sublist("z00","00z0").
false.

28 ?- sublist("aa","anna").
true .

29 ?- sublist("anna","banana").
true .

30 ?- sublist("Anna","banana").
false.

从技术上讲,字节数可以为0,因为我们在这里所做的只是查询,就像我们如何运行程序并为其提供输入一样。


2

PHP,41字节

打印1为真,否为假

<?=!levenshtein($argv[1],$argv[2],0,1,1);

如果仅从单词1到单词2进行插入,则对于真实情况,计数为零

莱文施泰因

在线尝试!

PHP,57字节

打印1表示true,0表示false

创建一个正则表达式

<?=preg_match(_.chunk_split($argv[1],1,".*")._,$argv[2]);

在线尝试!


1
-2个字节:.*不需要前导。-2个字节:不分配$argv$a。+24个字节:需要array_map(preg_quote())特殊字符(使用括号作为分隔符,以避免使用第二个preg_quote参数。)
Titus

2
@Titus前导。*对于输入空字符串是必需的,对于输入,我必须仅处理可能为空的区分大小写的字母数字字符串。如果有特殊字符,则您的报价正确。感谢您计算分配。复制并尽早解决粘贴,而不是去想
约尔格Hülsermann

1
preg_match只要分隔符在那里,就不会抱怨正则表达式为空。它将匹配任何东西。但是preg_quote只有+22字节,而不是+24: array_map(preg_quote,str_split(...))
泰特斯(Titus)

1
但是随后,输入保证是字母数字的:)但是您仍然不需要前导.*
泰特斯

2

Brachylog,2个字节

⊆ᵈ

在线尝试!

这个答案一样, 是一个内置谓词,声明输入和输出变量之间的关系,并且是一个元谓词,对其进行修改以声明输入变量的第一和第二元素之间的相同关系(并统一)。输出变量和第二个元素,但这是一个决策问题,在这里并没有关系。X⊆Y断言X是Y的子序列,因此也是如此[X,Y]⊆ᵈ

此谓词(当然,通过打印true.false.在程序运行时的)将输入作为两个字符串的列表。如果输入更灵活...

Brachylog,1个字节

在线尝试!

将字符串X作为输入变量,并将字符串Y作为输出变量。和以前一样,通过成功或失败输出。如果以完整程序运行,则将 X作为输入,并将Y作为第一个命令行参数。


1

CoffeeScript 73

这是一个替代的CoffeeScript答案,使用正则表达式而不是递归:

z=(x,y)->a='.*';a+=c+'.*'for c in x;b=eval('/'+a+'/');(y.replace b,'')<y

如果干草堆与用针构造的非常贪婪的正则表达式匹配,则将其替换为空字符串。如果干草堆比开始的时候要短,则说明针是一个子序列。

xy均为空字符串。想想我们需要一个哲学家来告诉我们一个空字符串是否是它本身的子序列!

(作为与我以前的答案分开发布的答案,因为感觉足以证明它的合理性)。


1

PowerShell,38岁

$args[1]-clike($args[0]-replace'','*')

当然,任何此类基于正则表达式或模式匹配的解决方案在使用更长的字符串时都存在严重的性能问题。但是由于短缺是标准...


1

一种产生Y的所有子序列的反解:

Python 93

l=len(y)
print x in[''.join(c for i,c in zip(bin(n)[2:].rjust(l,'0'),y)if i=='1')for n in range(2**l)]

1

APL(31)

APL中缺少字符串处理。

{(⊂'')∊N←⍵↓⍨¨1,⍨=/⊃¨⍵:~×⍴⊃N⋄∇N}

用法:

      {(⊂'')∊N←⍵↓⍨¨,⍨= /⊃¨⍵:〜×⍴⊃N⋄∇N}'anna''banana'
1个
      {(⊂'')∊N←⍵↓⍨¨,⍨= /⊃¨⍵:〜×⍴⊃N⋄∇N}'Anna''banana'
0
      {(⊂'')∊N←⍵↓⍨¨,⍨= /⊃¨⍵:〜×⍴⊃N⋄∇N}''香蕉'
1个

1

Python 132

类似于Daniero的。这不是最简单的解决方案,但是尝试很有趣。我是Python的新手,所以如果我知道更多一点,我敢肯定我可以缩短它的时间。

def f(i):
    s=x;j=0
    while j<len(s):t=~i%2;s=[s[:j]+s[j+1:],s][t];j+=t;i>>=1
    return s==y
print True in map(f,range(1,2**len(x)))

1

蟒蛇-72

def f(a,b):
 c=len(a)
 for i in b:a=a.replace(i,"",1)
 print len(a+b)==c

1

巨蟒(75 52)

s=lambda a,b:a==''or b>''and s(a[a[0]==b[0]:],b[1:])

简单的递归解决方案。第一次打高尔夫球,因此不胜感激的任何提示都值得赞赏:)

经过以下测试:

assert s('anna', 'banana') == True
assert s('oo0', 'oFopp0') == True
assert s 'this', 'this is a string') == True
assert s('that', 'this hat is large') == True
assert s('cba', 'abcdefg') == False

感谢@lirtosiast提供了一些聪明的布尔技巧。


1
您可以将其减少到52个字符:s=lambda a,b:a==''or b>''and s(a[a[0]==b[0]:],b[1:])
lirtosiast

谢谢,这很聪明,使用布尔值作为拼接的0/1索引:)
foslock 2016年

1

PHP,75 65 64字节

for(;$p=@strpos(_.$argv[2],$c=$argv[1][$i++],$p+1););echo""==$c;

从命令行参数获取输入;打印1为true的字符串,为false的空字符串。用运行-r

说明:

  • strposfalse如果针$c不在干草堆中$argv[2](在位置之后$p),则返回,
    从而导致循环中断。
  • strpos也返回false空针,在的末尾中断循环$argv[1]
  • 如果$argv[1]是的子序列$argv[2]$c则在循环中断时将为空。
  • strpos需要@抑制Empty needle警告。

+$p而不是$p+1之后疗法不需要下划线
约尔格Hülsermann

+1需要@JörgHülsermann 来推进大海捞针;下划线避免$p=-1初始化。但是...我可以避免false!==
泰特斯

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.