22
\$\begingroup\$

Your task here is to write two regular expressions, each of which matches the other one but does not match itself.

Both regular expressions should have this form:

/pattern/optional-flags

This is also the form in which they should be matched.

The shortest solution wins. The solution length is counted as the sum of characters in both regular expressions including slashes and flags.

Use a regex syntax standard of your choice, or specify a programming language, when it makes a difference.

Have fun!

\$\endgroup\$
9
  • \$\begingroup\$ Does the regex also have to match the slashes and flags of the other regex? \$\endgroup\$
    – ProgramFOX
    Mar 2, 2014 at 15:30
  • \$\begingroup\$ @ProgramFOX yes, I added a line to make it clear. \$\endgroup\$
    – GOTO 0
    Mar 2, 2014 at 15:35
  • \$\begingroup\$ Can you define match? i.e. does the regex /a/ match abc? \$\endgroup\$ Mar 2, 2014 at 20:05
  • 2
    \$\begingroup\$ @TheGuywithTheHat well, I think so, unless you choose a language that imposes certain restrictions, like the need to match the whole string. Does this address your concern? \$\endgroup\$
    – GOTO 0
    Mar 2, 2014 at 20:21
  • 1
    \$\begingroup\$ To be clear: I assume that the use of different delimiters (as permitted by e.g. PHP PCRE) is not permitted? (I.e. no submitting /^%/ and %^/%) \$\endgroup\$ Mar 3, 2014 at 9:27

11 Answers 11

18
\$\begingroup\$

4+6=score of 10

First regex:

/i$/

Second regex:

/^.i/i

Hooray for flag abuse! :-P

The first one matches anything that ends with i (therefore, any regex with the i flag).

The second one matches anything with a second character of i.

Alternative version: /i$/g and /g$/i.

\$\endgroup\$
3
  • 3
    \$\begingroup\$ Another variation would be /x.$/ and /^.x/ for a bunch of x \$\endgroup\$
    – shiona
    Mar 2, 2014 at 21:52
  • \$\begingroup\$ Or /i$/ and /\/$/i \$\endgroup\$ Mar 2, 2014 at 23:29
  • \$\begingroup\$ Or /i$/ and /i\$/i \$\endgroup\$ Mar 3, 2014 at 8:16
7
\$\begingroup\$

PRCE with the A modifier: 9 chars

/A$/
/.A/A

Although this is a variant on Doorknob's /modifier$/ answer, I think this innovation qualifies it as a separate answer rather than a comment on his: the modifier does double-duty. Rather than being there solely for the other regex to match, it anchors.

The first regex matches any string ending in a literal A. The second regex matches any string whose second character is a literal A, using an anchor-to-start flag.

Online demo

\$\endgroup\$
1
  • 3
    \$\begingroup\$ To beat this requires only four non-delimiter chars, and since // matches anything that means that each of the regexes can have at most three non-delimiter chars. Using PHP PCRE there are 73339 non-self-matching regexes within that constraint, and exhaustive checking of the pairs whose length is less than 10 (on the order of 32Mpairs rather than 5.7Gpairs because most of them are 5 chars including delimiters) turns up this solution and no others. I therefore claim that it is optimal for that particular regex engine. \$\endgroup\$ Mar 3, 2014 at 16:11
6
\$\begingroup\$

JavaScript regexes, score: 18

First regex:

/^[^a]+$/

Second regex:

/^[^b]+$/

JavaScript test:

var regex1 = "/^[^a]+$/";
var regex2 = "/^[^b]+$/";
alert(/^[^a]+$/.test(regex2)); // true: regex1 matches regex2
alert(/^[^b]+$/.test(regex1)); // true: regex2 matches regex1
alert(/^[^a]+$/.test(regex1)); // false: regex1 doesn't match regex1
alert(/^[^b]+$/.test(regex2)); // false: regex2 doesn't match regex2

Test online: http://jsfiddle.net/99Sx6/

\$\endgroup\$
5
\$\begingroup\$

Ruby regex, 15

Regular expressions:

/.{9}/
/^.{06}$/

Just counting characters...

Online version

r1 = '/.{9}/'
r2 = '/^.{06}$/'

p r1 =~ /^.{06}$/ #0:   r2 matches r1
p r2 =~ /.{9}/    #0:   r1 matches r2
p r1 =~ /.{9}/    #nil: r1 doesn't match r1
p r2 =~ /^.{06}$/ #nil: r2 doesn't match r2
\$\endgroup\$
5
\$\begingroup\$

4 + 6 = 10

First regex:

/i$/

Second regex:

/\/$/i

i$ matches something that ends with i, the second one. /$ matches something that ends with /, the first one.

\$\endgroup\$
3
  • 2
    \$\begingroup\$ Dupe of a comment I posted to Doorknob's answer. \$\endgroup\$ Mar 3, 2014 at 8:09
  • \$\begingroup\$ @PeterTaylor Didn't notice the comments until now. These were independent discoveries. \$\endgroup\$
    – Justin
    Mar 3, 2014 at 18:11
  • \$\begingroup\$ Yeah, I independently discovered shiona's version too. \$\endgroup\$ Mar 3, 2014 at 19:09
4
\$\begingroup\$

5 + 5 = 10

Regex #1:

/0.$/

Regex #2:

/^.0/

The 0s in both regexes can be replaced with any non-metacharacter and the regex still works.

0.$ matches anything whose second last character is 0, and ^.0 matches anything whose second character is 0.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ The first pair aren't valid regexes: you need to escape the /es. The alternative is a dupe of a comment on Doorknob's answer. \$\endgroup\$ Mar 3, 2014 at 8:13
3
\$\begingroup\$

Score: 5 + 5 = 10

Took me half-an-hour to figure out but I am really happy that I did :)

1st is: /j.$/

2nd is: /^.j/

The 1st matched a j occurring in the second position starting from the right. The 2nd matches a j occurring at the second-position starting from left.

I haven't tested but I think that these RegExs are really versatile as the j can be replaced with any \w character (or more?) and still should work fine.

P.S. This should (hopefully) work in any language. Though, if it does not work in any, please inform in the comments below :)

Test

\$\endgroup\$
1
  • \$\begingroup\$ And I figure out now that @Quiccunx has already posted the same version as mine. I am really sorry Quiccunx and if it shall please any, I shall delete my answer. \$\endgroup\$ Mar 4, 2014 at 13:07
2
\$\begingroup\$

JavaScript regexes, score: 13

First regex:

/\d/

Second regex:

/^[^0]+$/

Explanation: the first regex matches everything that contains a digit, and the second regex matches everything that doesn't contain a 0.

JavaScript test:

var regex1 = "/\d/";
var regex2 = "/^[^0]+$/";
alert(/\d/.test(regex2)); // true: regex1 matches regex2
alert(/^[^0]+$/.test(regex1)); // true: regex2 matches regex1
alert(/\d/.test(regex1)); // false: regex1 doesn't match regex1
alert(/^[^0]+$/.test(regex2)); // false: regex2 doesn't math regex2

Test online: http://jsfiddle.net/5VYjC/1/

\$\endgroup\$
2
\$\begingroup\$

12 chars ;) JS regex

/\d/
/0?\/$/g
\$\endgroup\$
1
\$\begingroup\$

PCRE using modifier x: 11 chars

/\s/
/ s.$/x

The first matches any string with a whitespace character, but doesn't contain whitespace. The second contains whitespace, but it's ignored because of the x modifier; it matches any string whose penultimate character is s.

PCRE and other engines using character classes: 11 chars

/\w+w/
/\Ww/

The first matches any string with a "word" character (letter, digit, underscore) followed by a literal w; the second matches any string with a non-word character followed by a literal w.

PCRE and other engines using character classes and word boundary anchor: 11 chars

/\w\w/
/\bw/

The first matches any string with two consecutive "word" characters; the second any string with a non-word character or start of string followed by a literal w.

\$\endgroup\$
-1
\$\begingroup\$

ECMAScript (11 bytes):

/^\1?d/
/\d/

Other REGEXP Engines (14 bytes):

/^\\\\1?d/
/\d/

The 1st matches \d[..] or \1d[..].

The second matches any string with a number.

EDIT:

Originally, this answer was posted as being compatible with all engines, but it was proven to be wrong.

There was a problem with references to the capturing groups (for example, in php).

\$\endgroup\$
9
  • \$\begingroup\$ Many regex engines take the regex without surrounding slashes, but the question is quite clear in requiring them to be counted. \$\endgroup\$ Mar 2, 2014 at 23:43
  • \$\begingroup\$ I am not counting it as an answer. Let me add the note for that. \$\endgroup\$ Mar 2, 2014 at 23:45
  • 1
    \$\begingroup\$ @PeterTaylor I added the note. The Apache version is there just because. \$\endgroup\$ Mar 2, 2014 at 23:50
  • \$\begingroup\$ Hang on: in what engines does the first one parse with \1 not interpreted as a back-reference? \$\endgroup\$ Mar 2, 2014 at 23:51
  • \$\begingroup\$ Depending on the way you use it. In php, for example, if you put inside "/^\1?d/" you will have trouble, but if you do '/^\1?d/', then it's fine. The quotes make a huge difference when the code is interpreted. \$\endgroup\$ Mar 2, 2014 at 23:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.