문자열 X가 문자열 Y의 하위 시퀀스입니까?


23

주어진 문자열 X와 Y는 X가 Y의 서브 시퀀스 인지 여부를 판별합니다 . 빈 문자열은 모든 문자열의 서브 시퀀스로 간주됩니다. (예 '''anna'의 서브 시퀀스이다 'banana'.)

입력

  • X, 대소 문자를 구분하는 영숫자 문자열
  • 대소 문자를 구분하는 영숫자 문자열 인 Y

산출

  • X가 Y의 하위 시퀀스인지 여부를 올바르게 나타내는 True 또는 False (또는 동등한 항목)

I / O 예제

X      Y        output

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

기준

  • 소스 코드의 바이트 수에 따라 가장 짧은 프로그램이 승리합니다.

예제 프로그램

  • 관련 게시물 에 적용 할 수있는 여러 프로그램이 있습니다 .

1
왜 '안나'가 '바나나'의 기질입니까?
kaoD

4
@kaoD은 - annaA는 서브 (하지만 하지 문자열)의 banana. 스트링 X는 Y의 0 개 이상의 원소를 삭제함으로써 Y로부터 X를 얻을 수있는 경우에 스트링 Y의 서브 시퀀스이다; 예를 들어에서 b및 초 a를 삭제하면 bananagives anna.
res

2
이것은 모든 스크립트 언어에서 정규식을 제공하는 단일 솔루션에 관한 것입니다.
Joey

답변:


18

Perl 5 , 17 바이트 (+1?), 전체 프로그램

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

온라인으로 사용해보십시오!

에서와 같이 p펄 인터프리터에 플래그를 사용하여 호출하십시오 perl -pe 's//.*/g;$_=<>=~$_'. 당 이 문제가 처음 게시 된 기존의 채점 규칙 ,이 플래그를 하나 추가 바이트를 요한다. 에서 최근 규칙 , AFAICT, 그것은 무료로 할 수있다.

어느 쪽이든, 입력 문자열은 stdin에서 별도의 줄 바꿈으로 끝나는 줄에 제공되어야합니다. 1첫 번째 입력 문자열이 두 번째의 하위 문자열이거나 그렇지 않은 경우 아무것도 출력되지 않습니다 (stdout) .

참고 모두 입력 라인 끝에서 줄 바꿈이 있어야합니다, 또는 프로그램이 제대로 작동하지 않습니다. 또는l 펄이 개행을 제거하도록 명령 행 플래그를 호출에 . 유효한 점수 규칙에 따라 1 바이트의 추가 비용이 들거나 들지 않을 수 있습니다. 이 플래그를 사용하면 출력에 개행이 추가됩니다.

원본 버전 (스 니펫, 18 바이트 / 문자)

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

입력 값은 변수에 제공 $x되며 $y결과는 스칼라 컨텍스트의 표현식 값입니다. 참고 $x과정에서 수정됩니다. (예, $_대신 사용 하는 것을 알고 있습니다.$x 하면 네 개의 문자를 절약 할 수 있지만 약간 치즈 맛이 나는 스 니펫에서 그렇게하는 것이 좋습니다.)

어떻게 작동합니까?

첫 번째 부분 은의 각 문자 사이 $x=~s//.*/g에 문자열을 삽입합니다 . 두 번째 부분 은 정규 표현식으로 취급 하고 일치 합니다. Perl 정규식에서는 0 개 이상의 임의의 문자를 일치시키는 반면 모든 영숫자는 편리하게 일치합니다..*$x$y=~$x$x$y.*


(새로운?) 합의에 따르면, 제출은 스 니펫이 아닌 프로그램 또는 기능이어야합니다. 제출 한 내용이 만족스럽지 않으면 편집을 고려하십시오.
user202729

@ user202729 :이 과제는 해당 컨센서스보다 훨씬 오래되었으므로 소급 적용한다고 가정하지 않는 한이 스레드의 답변은 "할아버지"상태 여야합니다. 즉, 현재 규칙을 준수하는 버전을 추가했습니다. 명령 줄 스위치를 계산하는 방법에 따라 1 바이트 / 문자 길이가 더 짧을 수도 있습니다 (바이트 기반 카운팅은이 문제인 AFAIK보다 최신 버전입니다).
Ilmari Karonen

9

루비, 32 자

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

이 솔루션은 하위 시퀀스가 ​​아닌 nil경우 숫자를 반환하고 그렇지 않으면 숫자를 반환합니다 (예 : 및 루비에 해당 ). 예 :xyfalsetrue

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
나는 기본적으로 같은 일을했지만 너무 비슷해서 게시하지 않을 것입니다. 나는 람다를 떠나는 것이 허용된다고 생각합니다 y=~/#{[*x.chars]*".*"}/. (23 자). 건배!
Patrick Oscity

1
또는 짝수 y=~/#{x.split("")*".*"}/(21 자) :)
Patrick Oscity

@padde 분할 된 문자는 실제로 24 자입니다.
Howard

1
죄송합니다, y=~irb에서 이것을
다루는

내 버전 이 2 자 더 짧습니다.
Hauleth

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. 또한 연산자로 만들고 @대신-패턴을 사용하여 몇 가지를 더 절약 할 수 있습니다 (f:l). 이렇게하면 문자가 37 자로 줄어 듭니다.h@(f:l)%(g:m)=f==g&&l%m||h%m;x%y=x<=y
hammar

6

파이썬 (48 자)

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

Howard의 Ruby 답변과 동일한 접근 방식입니다. 파이썬이 정규식 패키지와 "verbose"를 가져와야한다는 점이 너무 나쁩니다 lambda. :-)


1
동의합니다. 람다는 장황합니다.
CalculatorFeline

4

파이썬, 59 자

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

내 대답이 파이썬으로 더 잘 표현 될 것이라고 생각했습니다.

편집 : 입술의 제안을 추가했습니다.


확실하게 부여 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=="". 주석에 올바르게 표시되지 않지만 의미하는 것을 볼 수 있다고 생각합니다. (또한 하나의 추가 공간이 들여 쓰기 레벨을 높이기에 충분합니다.)
res

@res 고마워, 파이썬은 내가 말할 수있는만큼 많이 사용하는 언어가 아니다. 좋은 골프. (Codegolf 사용자 스크립트에 따라 63 자-개행을 계산해야합니다).
Gareth

1
당신은 x에 대해 보호 ''하고 여러 문자를 저장 하여 확장 슬라이싱을 사용할 수 있습니다x=x[c==x[0:1]:]
Nolen Royalty

4

GolfScript (22 자)

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

입력은 두 개의 미리 정의 된 변수로 간주된다고 가정 X하고 Y그 GolfScript에서 다소 특이하지만,. 잎 1사실 또는 0스택에 거짓합니다.



4

해 학적 인 (6 자)

Burlesque의 6 문자 : R@\/~[ (x와 y가 스택에 있다고 가정합니다. 여기 에서 실제로 참조 하십시오 .)



3

PHP, 90 자

<?function s($x,$y){while($a<strlen($y))if($y[$a++]==$x[0])$x=substr($x,1);return $x=="";}

당신은 if진술을 제거 하고 단순화 할 수 있습니다 $x=substr($x,$y[$a++]==$x[0]): ideone.com/Ch9vK
mellamokb

또한 여기에 약간 짧은 82 문자 솔루션을 사용하여 재귀는 다음과 같습니다 ideone.com/IeBns
mellamokb은

3

스칼라 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

커피 스크립트 (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과 같은 일부 브라우저에서는 마우스 오른쪽 버튼을 클릭 한 다음 요소 검사를 통해 주석 코드가 올바르게 표시되는 것을 볼 수 있습니다.)
res

a.length당신은 대체하여 하나 개의 문자 더 절약 할 수 있도록 결코 부정 될 것하지 않습니다 if a==0와 함께 if a<1. CoffeeScript의 토큰 화가 어떻게 작동하는지 모르겠지만 if0두 개의 토큰으로 묶으면 두 가지 조건을 반대로하여 두 가지를 더 절약 할 수 있습니다 (예 :) if1>a.
피터 테일러

좋은 지적입니다. if1>a유효하지 않지만 if!a더 짧고 문자입니다! 나는 또한 변환 여분의 문자를 면도 할 수 실현 b+1b같은 만들고, 이전 라인에 그것을 증가 if는 0 / 0이 아닌 상황 처리 된 이후 트릭이 가능합니다.
Johno

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
Doesn't this search for a substring rather than a subsequence?
Gareth

yes, I misread. Should be fixed now.
mizer

1
As fun as Linq is, I think you can save 10% by using recursion instead.
Peter Taylor

Here's my best attempt. Still longer. 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

재귀 적을로 줄일 수는 x==""||y!=""&&S(...)있지만 여전히 업데이트 된 Linq 버전보다 깁니다. 의 좋은 사용 Any!
피터 테일러

3

Mathematica 19 17 27

LongestCommonSequence returns the longest non-contiguous subsequence of two strings. (Not to be confused with LongestCommonSubsequence, which returns the longest contiguous subsequence.

The following checks whether the longest contiguous subsequence is the first of the two strings. (So you must enter the shorter string followed by the larger string.)

LongestCommonSequence@##==#& 

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

True True True False

"애나"가 "바나나"에 비 연속적으로 포함되어 있기 때문에 중요한 테스트는 세 번째입니다.


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)

온라인으로 사용해보십시오!

파이썬 2 , 48 바이트

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

온라인으로 사용해보십시오!

Lynn의이 답변 에서 복사했습니다 . 는 >0단지 truthy / falsey 출력이 OK 인 경우 생략 될 수있다.

파이썬 2 , 50 바이트

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

온라인으로 사용해보십시오!

파이썬 2 , 50 바이트

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

온라인으로 사용해보십시오!


해마의 큰 사용.
Jonathan Allan

2

C- 74 71 64

이것은 피터 테일러의 솔루션을 능가하지는 않지만 꽤 재미 있다고 생각합니다 (또한 기능이 아니라 완전한 작업 프로그램입니다)

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

@GordonBailey 범프에 대해 죄송하지만 짧은 버전으로 약간 변경했습니다.
oldrinb

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하는 경우 인스턴스 a의 서브 순서 b또는nil otherwise.

하위 시퀀스 대신 하위 문자열을 찾는 이전 버전

루비 15

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

사용하여 String#[](str)반환하는 방법을 str경우 str의 문자열입니다 self!!반환하는 Boolean반환 값이 부울로 사용할 수 있습니다 (그리고 할 필요가없는 경우 true또는 false) 다음은 13 문자가 될 수 있습니다

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

의 하위 문자열이 아닌 nil경우 반환 됩니다 .ab


2
Nice, but the question asks for a subsequence rather than a substring.
Gareth

2

SWI-Prolog, SICStus

SICStus 의 내장 술어 서브 리스트 / 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 바이트

true로 1을 인쇄하고 false로 아무것도 인쇄하지 않습니다.

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

단어 1에서 단어 2까지만 삽입하면 실제 경우에는 카운트가 0입니다.

레 벤슈 테인

온라인으로 사용해보십시오!

PHP, 57 바이트

1은 true, 0은 false

정규식을 만듭니다.

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

온라인으로 사용해보십시오!


1
-2 bytes: leading .* is unnecessary. -2 bytes: don´t assign $argv to $a. +24 bytes: needs array_map(preg_quote()) for special characters (use parentheses as delimiters to avoid second preg_quote parameter.)
Titus

2
@Titus the leading .* is necessary for the input of an empty string and for the input I must only handle a possibly-empty case-sensitive alphanumeric string. You are right with the quote if there are special characters. Thank you for counting the assign. Copy and paste by an earlier solution and not think about it
Jörg Hülsermann

1
preg_match will not complain about an empty regex as long as the delimiters are there. It will just match anything. But preg_quote is only +22 bytes, not +24: array_map(preg_quote,str_split(...)).
Titus

1
But then, input is guaranteed to be alphanumeric :) But you still don´t need the leading .*.
Titus

2

Brachylog, 2 bytes

⊆ᵈ

Try it online!

As with this answer, is a built-in predicate that declares a relationship between the input and output variables, and is a meta-predicate that modifies it to declare that same relationship between the first and second elements of the input variable instead (and unify the output variable with the second element but as this is a decision problem that doesn't end up mattering here). X⊆Y is an assertion that X is a subsequence of Y, therefore so is [X,Y]⊆ᵈ.

This predicate (which of course outputs through success or failure which prints true. or false. when it's run as a program) takes input as a list of two strings. If input is a bit more flexible...

Brachylog, 1 byte

Try it online!

Takes string X as the input variable and string Y as the output variable. Outputs through success or failure, as before. If run as a full program, X is supplied as the input and Y is supplied as the first command line argument.


1

CoffeeScript 73

Here's an alternative CoffeeScript answer, using regexes instead of recursion:

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

If the haystack matches a very greedy regex constructed from the needle, it will be replaced with an empty string. If the haystack is shorter than it started, the needle was a subsequence.

Returns false when x and y are both empty strings. Think we need a philosopher to tell us if an empty string is a subsequence of itself!

(Posted as a separate answer from my previous because it feels different enough to justify it).


1

PowerShell, 38

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

Of course, any such regex- or pattern-matching-based solution has severe performance problems with longer strings. But since shortness is the criterion ...


1

A sort of anti-solution generating all subsequences of 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)

String handling is a bit lacking in APL.

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

usage:

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

1

Python 132

Similar to Daniero's. Not the easiest solution, but it was fun to try. I'm new to Python, so I'm sure I could make it shorter if I knew a little bit more.

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

Python - 72

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

1

Python (75 52)

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

Simple recursive solution. First time golfing, so any tips on whittling this down are much appreciated :)

Tested with the following:

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

Thanks to @lirtosiast for some clever boolean tricks.


1
You can get this down to 52 characters: s=lambda a,b:a==''or b>''and s(a[a[0]==b[0]:],b[1:])
lirtosiast

Thanks, that's clever, using the boolean as the 0/1 index into the splice :)
foslock

1

PHP, 75 65 64 bytes

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

takes input from command line arguments; prints 1 for true, empty string for false. Run with -r.

explanation:

  • strpos returns false if needle $c is not in the haystack $argv[2] (after position $p),
    causing the loop to break.
  • strpos also returns false for an empty needle, breaking the loop at the end of $argv[1].
  • If $argv[1] is a subsequence of $argv[2], $c will be empty when the loop breaks.
  • strpos needs @ to suppress Empty needle warning.

+$p instead of $p+1 after that ther is no need for the underscore
Jörg Hülsermann

@JörgHülsermann +1 is needed to advance in the haystack string; and the underscore avoids $p=-1 initialization. But ... I can avoid false!==.
Titus

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.