Is string X a subsequence of string Y?

23

4

Given strings X and Y, determine whether X is a subsequence of Y. The empty string is regarded as a subsequence of every string. (E.g., '' and 'anna' are subsequences of 'banana'.)

Input

  • X, a possibly-empty case-sensitive alphanumeric string
  • Y, a possibly-empty case-sensitive alphanumeric string

Output

  • True or False (or equivalents), correctly indicating whether X is a subsequence of Y.

I/O examples

X      Y        output

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

Criteria

  • The shortest program wins, as determined by the number of bytes of source code.

Example programs

r.e.s.

Posted 2012-04-15T21:15:06.900

Reputation: 2 872

1Why is 'anna' substr of 'banana'? – kaoD – 2012-04-26T05:04:43.933

4@kaoD - anna is a subsequence (but *not* a substring) of banana. String X is a subsequence of string Y just if X can be obtained from Y by deleting zero or more of the elements of Y; e.g., deleting the b and the second a from banana gives anna. – r.e.s. – 2012-04-26T13:33:16.180

2This has about a single solution in every scripting language offering regex that's both trivial to see and impossible to golf further. – Joey – 2012-04-27T14:50:36.693

Answers

18

Perl 5, 17 bytes (+1?), full program

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

Try it online!

Invoke with the p flag to the perl interpreter, as in perl -pe 's//.*/g;$_=<>=~$_'. Per the established scoring rules when this challenge was originally posted, this flag costs one extra byte. Under more recent rules, AFAICT, it may be free.

Either way, the input strings should be supplied on separate newline-terminated lines on stdin. Output (to stdout) will be 1 if the first input string is a substring of the second, or nothing at all if it's not.

Note that both input lines must have a newline at the end, or the program won't work correctly. Alternatively, you can add the l command line flag to the invocation to make perl strip the newlines; depending on the scoring rules in effect, this may or may not cost one extra byte. Note that using this flag will also append a newline to the output.

Original version (snippet, 18 bytes / chars)

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

Input is given in the variables $x and $y, result is the value of the expression (in scalar context). Note that $x is modified in the process. (Yes, I know using $_ instead of $x would let me save four chars, but doing that in a snippet that feels a bit too cheesy for me.)

How does it work?

The first part, $x=~s//.*/g, inserts the string .* between each character in $x. The second part, $y=~$x, treats $x as a regexp and matches $y against it. In Perl regexps, .* matches zero or more arbitrary characters, while all alphanumeric characters conveniently match themselves.

Ilmari Karonen

Posted 2012-04-15T21:15:06.900

Reputation: 19 513

According to out (new?) consensus, submissions must be program or function, not snippet. If your submission doesn't satisfy that, consider editing it. – user202729 – 2018-03-26T06:21:16.713

@user202729: This challenge is a lot older than that consensus, so unless it's assumed to apply retroactively, the answers in this thread should probably be "grandfathered" in. That said, I did just add a version that complies with current rules, and may even be one byte / char shorter (note that byte-based counting is also newer than this challenge, AFAIK) depending on how you count command-line switches. – Ilmari Karonen – 2018-03-26T09:06:50.270

9

Ruby, 32 characters

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

This solution returns nil if x isn't a subsequence of y and a number otherwise (i.e. ruby equivalents to false and true). Examples:

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)

Howard

Posted 2012-04-15T21:15:06.900

Reputation: 23 109

1i did basically the same thing, but it's too similar so i won't post it. i think it is acceptable to leave off the lambda, which would leave you with y=~/#{[*x.chars]*".*"}/ (23 chars). cheers! – Patrick Oscity – 2012-04-26T12:46:11.440

1or even y=~/#{x.split("")*".*"}/ (21 chars) :) – Patrick Oscity – 2012-04-26T12:53:22.257

@padde The split one is actually 24 chars. – Howard – 2012-04-27T00:23:04.767

1sorry, i guess i accidentally left off the y=~ while fiddling with this in irb... – Patrick Oscity – 2012-04-27T13:27:15.047

My version is 2 char shorter. – Hauleth – 2012-09-12T09:47:26.267

7

Haskell, 51 37

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

Thanks to Hammar for the substantial improvement. It's now an infix function, but there seems to be no reason why it shouldn't.

Demonstration:

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

ceased to turn counterclockwis

Posted 2012-04-15T21:15:06.900

Reputation: 5 200

Since the empty list is smaller than any other list, you can simplify the base cases to s x y=x<=y. Also, you can save a few more by making it an operator and using an @-pattern instead of (f:l). This cuts it down to 37 characters: h@(f:l)%(g:m)=f==g&&l%m||h%m;x%y=x<=y – hammar – 2012-04-18T06:38:50.023

6

Python (48 chars)

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

Same approach as Howard's Ruby answer. Too bad about Python's need to import the regex package and its "verbose" lambda. :-)

Eric

Posted 2012-04-15T21:15:06.900

Reputation: 171

1I agree, lambda is verbose. – CalculatorFeline – 2016-03-09T19:31:58.923

4

Python, 59 characters

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

I figured my answer would be better expressed in Python.

Edit: Added r.e.s.'s suggestions.

Gareth

Posted 2012-04-15T21:15:06.900

Reputation: 11 678

Surely given x="a" and y="ab" you would exit the loop with y=="b" and return false? – Peter Taylor – 2012-04-15T22:29:35.357

@PeterTaylor Yeah, I noticed when I was running the examples as tests after posting that I've mixed x and y up. In my functions y needs to be a subsequence of x. I think I'd better change them to avoid any confusion. – Gareth – 2012-04-15T22:31:42.703

You can get this down to 59 chars: def s(x,y): for c in y: if x:x=x[c==x[0]:] return x=="". It doesn't display correctly in a comment, but I think you can see what I mean. (Also, one added space is enough to increase the indent level.) – r.e.s. – 2012-04-15T23:20:19.427

@r.e.s. Thanks, Python's not a language I use much as you can probably tell. Nice golfing. (63 characters according to the Codegolf userscript - it must be counting the newlines). – Gareth – 2012-04-15T23:26:24.710

The if statement can all go on one line, with no space after the colon, bringing the count down to 59. – r.e.s. – 2012-04-15T23:32:13.623

@r.e.s. Like I said - my Python-fu is weak. :-) – Gareth – 2012-04-15T23:33:55.230

you could probably save one more character on the third line if you follow this suggestion: http://codegolf.stackexchange.com/a/58/3527

– Cristian Lupascu – 2012-04-18T06:36:56.807

1You can use extending slicing to protect against x being '' and save several chars by writing x=x[c==x[0:1]:] – Nolen Royalty – 2012-09-10T07:57:03.317

4

GolfScript (22 chars)

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

Assumes that input is taken as two predefined variables X and Y, although that is rather unusual in GolfScript. Leaves 1 for true or 0 for false on the stack.

Peter Taylor

Posted 2012-04-15T21:15:06.900

Reputation: 41 901

4

C (52 chars)

s(char*x,char*y){return!*x||*y&&s(*x-*y?x:x+1,y+1);}

Test cases

Peter Taylor

Posted 2012-04-15T21:15:06.900

Reputation: 41 901

s(char*x,char*y){x=!*x||*y&&s(x+(*x==*y),y+1);} – l4m2 – 2018-03-26T17:11:54.823

4

Burlesque (6 chars)

6 chars in Burlesque: R@\/~[ (assuming x and y are on the stack. See here in action.)

mroman

Posted 2012-04-15T21:15:06.900

Reputation: 1 382

4

C, 23:

while(*y)*x-*y++?0:x++;

result in *x

http://ideone.com/BpITZ

olivecoder

Posted 2012-04-15T21:15:06.900

Reputation: 307

3

Python 3.8 (pre-release), 42 bytes

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

Try it online!

Python 3.8 (pre-release), 48 bytes

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

Try it online!

Python 2, 48 bytes

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

Try it online!

Copied from this answer of Lynn. The >0 can be omitted if just truthy/falsey output is OK.

Python 2, 50 bytes

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

Try it online!

Python 2, 50 bytes

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

Try it online!

xnor

Posted 2012-04-15T21:15:06.900

Reputation: 115 687

Great use of the walrus. – Jonathan Allan – 2019-08-20T18:03:55.663

3

PHP, 90 characters

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

Gareth

Posted 2012-04-15T21:15:06.900

Reputation: 11 678

You can remove the if statement and simplify to $x=substr($x,$y[$a++]==$x[0]): http://ideone.com/Ch9vK

– mellamokb – 2012-04-16T22:08:10.277

Also here is a slightly shorter 82-character solution using recursion: http://ideone.com/IeBns

– mellamokb – 2012-04-16T22:19:49.203

3

C #, 70 113 107 90 characters

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

mizer

Posted 2012-04-15T21:15:06.900

Reputation: 311

6Doesn't this search for a substring rather than a subsequence? – Gareth – 2012-04-15T23:17:16.420

yes, I misread. Should be fixed now. – mizer – 2012-04-18T01:41:47.177

1As fun as Linq is, I think you can save 10% by using recursion instead. – Peter Taylor – 2012-04-18T08:13:16.677

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 – 2012-04-26T02:15:12.210

You can reduce the recursive one to x==""||y!=""&&S(...), but it's still longer than the updated Linq version. Nice use of Any! – Peter Taylor – 2012-04-26T08:05:59.013

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

user unknown

Posted 2012-04-15T21:15:06.900

Reputation: 4 210

3

CoffeeScript 112 100 95 89

My first attempt at code golf... hope I don't shame my family!

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]

Edit: turns out Coffeescript is more forgiving than I thought with whitespace.

Thanks to r.e.s. and Peter Taylor for some tips for making it a bit sleeker

Johno

Posted 2012-04-15T21:15:06.900

Reputation: 301

A few more chars can be eliminated as follows (this won't display right in a comment, but I think you can see what I mean): 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]. (In some browsers, e.g. Chrome, you can see comment code properly displayed by right-clicking, then Inspect Element.) – r.e.s. – 2012-04-23T17:33:16.970

a.length is never going to be negative, so you can save one character more by replacing if a==0 with if a<1. I don't know how CoffeeScript's tokenisation works, but if it lexes if0 as two tokens you could save two more by reversing both conditions (i.e. if1>a). – Peter Taylor – 2012-04-23T21:42:10.060

Good points. if1>a isn't valid, but if!a is and is a character shorter! I also realised that I could shave an extra character converting b+1 to b and incrementing it on the previous line, also making the same if trick possible since it was dealing with a 0/non-0 situation. – Johno – 2012-04-24T09:59:56.507

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@##==#& 

Examples

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

True True True False

The critical test is the third one, because "anna" is contained non contiguously in "banana".

DavidC

Posted 2012-04-15T21:15:06.900

Reputation: 24 524

2

PHP, 41 Bytes

prints 1 for true and nothing for false

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

If only insertions from word 1 to word 2 done the count is zero for true cases

levenshtein

Try it online!

PHP, 57 Bytes

prints 1 for true and 0 for false

Creates a Regex

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

Try it online!

Jörg Hülsermann

Posted 2012-04-15T21:15:06.900

Reputation: 13 026

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 – 2017-03-14T15:28:41.607

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 – 2017-03-14T15:42:08.250

1preg_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 – 2017-03-14T16:02:46.140

1But then, input is guaranteed to be alphanumeric :) But you still don´t need the leading .*. – Titus – 2017-03-14T16:38:48.843

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.

Unrelated String

Posted 2012-04-15T21:15:06.900

Reputation: 5 300

2

SWI-Prolog, SICStus

The built-in predicate sublist/2 of SICStus checks whether all the items in the first list also appear in the second list. This predicate is also available in SWI-Prolog via compatibility library, which can be loaded by the query [library(dialect/sicstus/lists)]..

Sample run:

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.

The byte count can technically be 0, since all we are doing here is querying, much like how we run a program and supply input to it.

n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

Posted 2012-04-15T21:15:06.900

Reputation: 5 683

2

C - 74 71 64

This doesn't beat Peter Taylor's solution, but I think it's pretty fun (plus, this is a complete working program, not just a function)

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

And ungolfed:

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

To test it you can do something like:

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

Gordon Bailey

Posted 2012-04-15T21:15:06.900

Reputation: 708

!=0 in a condition is a bit verbose... Program vs function is something which the question needs to specify clearly, and here it doesn't, so the answers take different options. – Peter Taylor – 2012-04-24T13:32:31.717

Damn, that !='\0' is a bad (good?) habit from writing non-golf code, I've let that slip into my last two rounds of golf, I'll have to be more careful in the future. As to program vs. function, yes, you're absolutely right. – Gordon Bailey – 2012-04-24T17:55:51.843

@GordonBailey sorry for the bump, but I made a few changes into a shorter version. – oldrinb – 2012-09-09T14:54:29.583

2

Ruby 32 30 28

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

This will return MatchData instance if a is subsequence of b or nil otherwise.

Old version that find substring instead of subsequence

Ruby 15

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

Using String#[](str) method that returns str if str is a substring of self and !! to return Boolean if returned value can be usable as boolean (and don't need to be true or false) then it can be only 13 chars:

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

It will return nil if a is not a substring of b.

Hauleth

Posted 2012-04-15T21:15:06.900

Reputation: 1 472

2Nice, but the question asks for a subsequence rather than a substring. – Gareth – 2012-04-19T07:12:56.393

2

Python, 66 62 59 58 chars

Kind of a fun solution, definitely a neat problem.

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

Nolen Royalty

Posted 2012-04-15T21:15:06.900

Reputation: 330

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.

Titus

Posted 2012-04-15T21:15:06.900

Reputation: 13 814

+$p instead of $p+1 after that ther is no need for the underscore – Jörg Hülsermann – 2017-03-14T17:47:15.090

@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 – 2017-03-14T17:50:27.333

1

Swift, 27

print(Y.range(of:X) != nil)

Dimitrie-Toma Furdui

Posted 2012-04-15T21:15:06.900

Reputation: 139

Welcome to PPCG! – Martin Ender – 2017-05-19T21:13:59.197

1

APL(NARS), chars 46, bytes 92

{(⊂,⍺)∊(⊂''),↑¨,/¨{⍵⊂w}¨{⍵⊤⍨k⍴2}¨⍳¯1+2*k←≢w←⍵}

test:

  h←{(⊂,⍺)∊(⊂''),↑¨,/¨{⍵⊂w}¨{⍵⊤⍨k⍴2}¨⍳¯1+2*k←≢w←⍵}
  '' h 'z00'
1
  'z00' h 'z00'
1
  'z00' h '00z0'
0
  'aa' h 'anna'
1
  'anna' h 'banana'
1
  'Anna' h 'banana'
0

comment:

{(⊂,⍺)∊(⊂''),↑¨,/¨{⍵⊂w}¨{⍵⊤⍨k⍴2}¨⍳¯1+2*k←≢w←⍵}
 ⍳¯1+2*k←≢w←⍵    this assign to w the argument and k argument lenght, it return 1..(2^k)-1 range
 {⍵⊤⍨k⍴2}¨      for each element of 1..(2^k)-1 convert in base 2 with lenght k (as the arg lenght)
 {⍵⊂w}¨         use the binary array above calculation for all partition argument
 ,/¨            concatenate each element of partition
 ↑¨             get the firs element of each element because they are all enclosed
 (⊂''),         add to the array the element (⊂'')
 (⊂,⍺)∊         see if (⊂,⍺) is one element of the array, and return 1 true o 0 false

How all you can see the comments are +- superfluous all is easy...

I have to say not understand why the last instruction is not "(,⍺)∊" in the place of "(⊂,⍺)∊" because for example in code

  q←{↑¨,/¨{⍵⊂w}¨{⍵⊤⍨k⍴2}¨⍳¯1+2*k←≢w←⍵}
  o q '123'
┌7──────────────────────────────────────┐
│┌1─┐ ┌1─┐ ┌2──┐ ┌1─┐ ┌2──┐ ┌2──┐ ┌3───┐│
││ 3│ │ 2│ │ 23│ │ 1│ │ 13│ │ 12│ │ 123││
│└──┘ └──┘ └───┘ └──┘ └───┘ └───┘ └────┘2
└∊──────────────────────────────────────┘
  o (,'3')
┌1─┐
│ 3│
└──┘

all you see array of 1 element (,'3') is the element of the set of instruction q '123', but

  o (,'3')∊q '123'
┌1─┐
│ 0│
└~─┘

return one array of unclosed 0 instead of number 1... for workaround that one has to write:

  o (⊂,'3')∊q '123'
1
~

that is the right result even if the element seems different because :

  o (⊂,'3')
┌────┐
│┌1─┐│
││ 3││
│└──┘2
└∊───┘

It is sure i make some error because i am not so smart... where is my error?

RosLuP

Posted 2012-04-15T21:15:06.900

Reputation: 3 036

1

Perl 6, 34 28 bytes

-6 bytes thanks to nwellnhof

{$!=S:g/<(/.*/;&{?/<{$!}>/}}

Try it online!

Anonymous code block that takes input curried, like f(X)(Y). This does the familiar join by .* and evaluate as a regex as other answers, but takes a couple of shortcuts.

Explanation:

{                          }  # Anonymous code block
 $!=            # Assign to $!
    S:g/<(/.*/  # Inserting .* between every character
              ;&{         }   # And return an anonymous code block
                 ?/      /    # That returns if the input matches
                   <{$!}>     # The $! regex

Jo King

Posted 2012-04-15T21:15:06.900

Reputation: 38 234

1

Haskell, 36 bytes

(a:b)%(c:d)=([a|a/=c]++b)%d
s%t=s<=t

Try it online!


37 bytes

(.map concat.mapM(\c->["",[c]])).elem

Try it online!

I think mapM postdates this challenge. If we can assume the characters are printable, we can do

36 bytes

(.map(filter(>' ')).mapM(:" ")).elem

Try it online!


37 bytes

(null.).foldr(?)
c?(h:t)|c==h=t
c?s=s

Try it online!

xnor

Posted 2012-04-15T21:15:06.900

Reputation: 115 687

1

Python - 72

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

Coding man

Posted 2012-04-15T21:15:06.900

Reputation: 1 193

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).

Johno

Posted 2012-04-15T21:15:06.900

Reputation: 301

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

Joey

Posted 2012-04-15T21:15:06.900

Reputation: 12 260

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

daniero

Posted 2012-04-15T21:15:06.900

Reputation: 17 193

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

marinus

Posted 2012-04-15T21:15:06.900

Reputation: 30 224

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.

foslock

Posted 2012-04-15T21:15:06.900

Reputation: 111

1You can get this down to 52 characters: s=lambda a,b:a==''or b>''and s(a[a[0]==b[0]:],b[1:]) – lirtosiast – 2016-03-10T01:18:51.313

Thanks, that's clever, using the boolean as the 0/1 index into the splice :) – foslock – 2016-03-10T02:13:10.927

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

scleaver

Posted 2012-04-15T21:15:06.900

Reputation: 507

0

JavaScript (ES6), 42 bytes

Takes input n (needle) and h (haystack) in currying syntax (n)(h).

n=>h=>!!RegExp(n.split``.join`.*`).exec(h)

Test

let f =

n=>h=>!!RegExp(n.split``.join`.*`).exec(h)

console.log(f(''    )('z00'   )); // true
console.log(f('z00' )('z00'   )); // true 
console.log(f('z00' )('00z0'  )); // false
console.log(f('aa'  )('anna'  )); // true
console.log(f('anna')('banana')); // true
console.log(f('Anna')('banana')); // false

Arnauld

Posted 2012-04-15T21:15:06.900

Reputation: 111 334

What if n contains regex special characters? – Titus – 2017-03-14T16:11:25.813

@Titus Well, I assumed n is in [A-Za-z0-9] since the challenge mentions that both input strings are alphanumeric. – Arnauld – 2017-03-14T16:16:06.140

woops missed that. :) – Titus – 2017-03-14T16:36:03.347

0

Java 8, 163 162 38 bytes

a->b->b.matches(a.replaceAll("",".*"))

-124 bytes by converting to Java 8, and pasting my answer from the duplicated challenge.

Try it online.

Explanation:

a->b->         // Method with two String parameters and boolean return-type
  b.matches(   //  Check if the second input matches the regex:
   a           //   The first input,
    .replaceAll("",".*"))
               //   where every character is surrounded with ".*"

For example:

a="anna"
b="banana"

Will do the check:

"banana".matches("^.*a.*n.*n.*a.*$")

Kevin Cruijssen

Posted 2012-04-15T21:15:06.900

Reputation: 67 575

0

Pyth, 5 bytes (non-competing)

}hQye

Explanation

}hQye
 hQ       The first input...
}         ... is an element of...
   y      ... the power set...
    eQ    ... of the second input.

user48543

Posted 2012-04-15T21:15:06.900

Reputation:

0

REXX, 76 bytes

o=1
do while x>''
  parse var x a+1 x
  parse var y(a)b+1 y
  o=o&a=b
  end
return o

Note that x and y are consumed by this routine. Readability is impaired by skipping a lot of whitespace and parentheses.

idrougge

Posted 2012-04-15T21:15:06.900

Reputation: 641

0

APL (Dyalog Unicode), 18 bytesSBCS

Full program. Prompts for Y then for X.

×≢(∊'.*'∘,¨⍞)⎕S⍬⊢⍞

Try it online!

 prompt (for Y)

 yield that (separates from it)

()⎕S⍬ search for occurrences of the following, yielding one empty list for each match:

 prompt (for X)

'.*'∘,¨ prepend .* to each character

ϵnlist (flatten)

 tally the number of matches

× sign of that

Adám

Posted 2012-04-15T21:15:06.900

Reputation: 37 779

0

Python 2, 47 bytes

x,y=map(list,input())
while x:y.remove(x.pop())

Try it online!

Takes two quote-delimited strings via STDIN as input.

Output is by presence or absence of an error, which is allowed per meta consensus.

Explanation:

             # get arguments from STDIN
             input()
    # convert each argument to a list
    map(list,.......)
# split arguments into two variables
x,y=..................

# while x still has elements
while x:
                 # remove the final element of x and return its value
                 x.pop()
        # remove the first matching item in y
        # this will error if there is no matching element
        y.remove(.......)

# if the loop is exited without error, all elements in x were in y

Triggernometry

Posted 2012-04-15T21:15:06.900

Reputation: 765

This doesn't look like it checks that the removed letters are in the right order. – xnor – 2019-02-22T17:16:23.910

0

x86-16 Assembly, 11 bytes

Binary:

00000000: 41ac f2ae e303 4a75 f83b ca              A.....Ju.;.

Unassembled listing:

41          INC  CX                 ; Loop counter is 1 greater than string length 
        SCAN_LOOP: 
AC          LODSB                   ; load next char of acronym into AL 
F2/ AE      REPNZ SCASB             ; search until char AL is found 
E3 03       JCXZ DONE               ; stop if end of first string reached 
4A          DEC  DX                 ; decrement second string counter 
75 F8       JNZ  SCAN_LOOP          ; stop if end of second string reached 
        DONE: 
3B CA       CMP  CX, DX             ; which string ended first?

Input: Y string pointer in SI, length in CX. X string pointer in DI, length in DX. Output is Falsey if CF.

Example test program:

This test program uses additional PC DOS API I/O routines to take multi-line input from STDIN.

enter image description here

Download and test ACRON.COM.

640KB

Posted 2012-04-15T21:15:06.900

Reputation: 7 149

0

JavaScript, 32 bytes

Repost of a port of Kevin's Java solution to a duplicate challenge, modified in case my choices for I/O weren't standards at the time this challenge was posted.

x=>y=>!!y.match([...x].join`.*`)

Try it online! (will update with this challenge's test cases when I get back to a computer)

Shaggy

Posted 2012-04-15T21:15:06.900

Reputation: 24 623

0

Japt, 4 bytes

Repost from a duplicate challenge.

Takes input in reverse order (Y, then X).

à øV

Try it

Shaggy

Posted 2012-04-15T21:15:06.900

Reputation: 24 623

0

Red, 82 bytes

func[x y][parse/case y collect[foreach c x[keep reduce['to c 'skip]]keep[to end]]]

Try it online!

Galen Ivanov

Posted 2012-04-15T21:15:06.900

Reputation: 13 815

0

Charcoal, 18 bytes

Fη≔✂θ⁼ι∧θ§θ⁰Lθ¹θ¬θ

Try it online! Link is to verbose version of code. Uses Charcoal's default Boolean output of - for true, nothing for false. Explanation:

Fη

Loop over the characters of Y.

⁼ι∧θ§θ⁰

See if this character is the next character of X.

≔✂θ...Lθ¹θ

If so then remove that character from X.

¬θ

Were all the characters of X consumed?

Neil

Posted 2012-04-15T21:15:06.900

Reputation: 95 035

0

Julia 1.0, 53 bytes

f(x,y)=(x==""||[x=x[2:end] for c=y if c==x[1]];x=="")

Try it online!

user3263164

Posted 2012-04-15T21:15:06.900

Reputation: 381

0

05AB1E, 3 bytes

æQà

Try it online or verify all test cases.

Or alternatively:

æså

Try it online or verify all test cases.

With both programs the first input is \$Y\$ and the second input is \$X\$.

Explanation:

æ    # Get the powerset of the (implicit) input-string `Y`
 Q   # Check for each if it's equal to the (implicit) input-String `X`
  à  # And check if any are truthy by taking the maximum
     # (after which this result is output implicitly)

æ    # Get the powerset of the (implicit) input-String `Y`
 s   # Swap to take the (implicit) input-String `X`
     # (could also be `I` or `²` to simply take input)
  å  # Check if this string is in the powerset-list of strings
     # (after which this result is output implicitly)

Kevin Cruijssen

Posted 2012-04-15T21:15:06.900

Reputation: 67 575

0

J (20 chars)

(<x)e.(#:i.2^#y)<@#y

The input is given in the variables x and y. It makes a list of all subsequences of y, so don't use it for very big strings.

Omar

Posted 2012-04-15T21:15:06.900

Reputation: 1 154

0

Python (72)

import itertools as I;any(tuple(X)==Z for Z in I.permutations(Y,len(X)))

ɐɔıʇǝɥʇuʎs

Posted 2012-04-15T21:15:06.900

Reputation: 4 449

1No, that use of permutations ignores the required order of the elements; e.g., X='z00' and Y='00z0' should output False (whereas your program outputs True). – r.e.s. – 2014-03-17T22:42:23.900

0

C, 120

main(i,c){char x[99],y[99];c=0;gets(y),gets(x);for(i=0;y[i]!='\0';)c+=y[i++]==x[c]?1:0;puts(x[c]=='\0'?"True":"False");}

l0n3sh4rk

Posted 2012-04-15T21:15:06.900

Reputation: 1 387

You can save at least 15 chars by moving c=0 to the loop initialiser and eliminating every instance of == in favour of "non-zero is truthy" conditions. – Peter Taylor – 2012-04-16T16:36:58.073

0

Retina, 26 bytes (not competing)

The language is newer than the challenge. Byte count assumes ISO 8859-1 encoding. Input is taken on two lines with Y first.

+`^(.)(.*¶)(?(\1).|)
$2
¶$

Try it online

mbomb007

Posted 2012-04-15T21:15:06.900

Reputation: 21 944

0

Javascript, 104 chars

function _(x,y){f=true;for(c in x){if(y.indexOf(x[c])>-1)y=y.replace(x[c],"");else{f=!f;break}}return f}

Ungolfed

function _(x,y){
f=true;
    for(c in x)
    {
        if(y.indexOf(x[c])>-1)
           y=y.replace(x[c],"");
        else {
            f=!f;
            break;
        }
    }
    return f;
}

Clyde Lobo

Posted 2012-04-15T21:15:06.900

Reputation: 1 395

This appears to test whether x is a substring of y, but it's supposed to test whether x is a subsequence of y. E.g., 'anna' is a subsequence of 'banana', but 'banana'.indexOf('anna')>-1 evaluates to false. – r.e.s. – 2012-09-19T04:14:23.820

@r.e.s. : My bad dint read the question properly. Thanks – Clyde Lobo – 2012-09-19T08:57:36.843

@r.e.s. posted a altogether new answer – Clyde Lobo – 2012-09-19T09:17:38.917

What does the new answer do for _("ab", "ba")? – Peter Taylor – 2012-09-19T13:19:52.327

returns true. demo http://jsfiddle.net/yvAdT/

– Clyde Lobo – 2012-09-19T18:28:40.647