Regex (Perl / PCRE2 / Boost / Pythonregex
), 35 bytes
^(([018])((?1)\2|)|6(?1)9|9(?1)6|)$
Takes its input in decimal.
Try it online! - Perl
Try it online! - PCRE2
Try it online! - Boost
Attempt This Online! - Python import regex
^ # Assert this is the start of the string
( # Define (?1) recursive subroutine call
([018]) # \2 = match a 0, 1, or 8
((?1)\2|) # Optionally match (?1) followed by \2
| # or
6(?1)9
| # or
9(?1)6
| # or
# Match an empty string
)
$ # Assert this is the end of the string
Regex (Ruby), 43 bytes
^(([018])(\g<1>\k<2+0>|)|6\g<1>9|9\g<1>6|)$
Try it online!
This is a direct port of the Perl/PCRE2/Boost version to Ruby's subroutine call syntax and behavior; (?1)
has been changed to \g<1>
, and \2
to \k<2+0>
.
In Perl, PCRE, and Boost, the contents of capture groups are passed to deeper recursion levels, but upon return from a subroutine call, all captures are returned to the state they were in before the subroutine was called, i.e. there is no way to pass captures done within a subroutine call back to its caller. But in Ruby, captures are passed to the caller. So \2
will refer to whatever it captured at the deepest recursion level, and so would \k<2>
. It is possible, however, to refer to a capture's value at a specific recursion level; that is why \k<2+0>
is used here to refer to its value at the current level.
Regex (.NET), 94 77 66 53 bytes
^((?=([018]|6.*9|9.*6)(?<=(.))).?)+(?<-3>\3)*(?(3)^)$
Try it online!
Implementing this using .NET's Balancing Groups feature turns out to provide an edge over the 57 byte .NET-compatible version that doesn't use any .NET-specific features.
^ # Assert we're at the beginning of the string
(
(?=
# Depending on what the next left-edge digit is, push its corresponding
# right-edge digit onto the Group 3 stack.
(
[018]
|
6.*9
|
9.*6
)
(?<=(.)) # \3 = the right-edge digit (push it onto the Group 3 stack)
)
.?
)+
(?<-3>\3)* # Match all right-edge digits in reverse order as they're
# popped from the stack.
(?(3)^) # Assert that the Group 3 stack is now empty (literally: if
# its stack is not empty, assert something impossible, that
# we're at the beginning of the string).
$ # Assert we've reached the end of the string, having matched
# all of its characters.
Regex (Perl / PCRE / .NET), 106 62 57 bytes
^((?=([018]|6.*9|9.*6)(?<=(.))).?(?=.*(\3(?(4)\4))))*\4?$
Try it online! - Perl
Try it online! - PCRE1
Try it online! - PCRE2
Try it online! - .NET
In PCRE1, subroutine calls are atomic, which prevents the Perl/PCRE2/Boost version (which requires backtracking to extend into nested subroutine calls) from working. As for .NET (and Java), subroutine calls are not supported.
In this version, instead of using recursion, we read inward from the left and right edges, one pair of characters at a time, remembering the right-edge position using capture group \4
. A set of alternatives followed by a lookbehind is used to set the required right-edge digit based on whether the left-edge digit was [018]
, 6
, or 9
.
^
(
# Depending on the next left digit, capture the required right digit in \3
(?=
(
[018]
|
6.*9
|
9.*6
)
(?<=(.)) # Capture the previous character (the right digit) in \3
)
.?
(?=
.*
( # Capture \4 as the following:
\3
# Match \4 iff it has been captured (i.e., iff this is not the
# first iteration). As such, \4 will be prepended with the current
# right digit.
(?(4)\4)
)
)
)*
\4?
$
Regex (Perl / PCRE / Java / .NET), 113 76 69 64 bytes
^((?=([018]|6.*9|9.*6)(?<=(.))).?(?=.*(\3(\6\4|(?!\6))())))*\4?$
Try it online! - Perl
Try it online! - PCRE1
Try it online! - PCRE2
Try it online! - Java
Try it online! - .NET
This is a port of the Perl/PCRE/.NET version, removing the use of the conditional due to their lack in Java, and emulating it with an empty capture whose set/unset status can be detected. Only the modified portion is shown below:
# Match \4 iff it has been captured (i.e., iff this is not the
# first iteration). As such, \4 will be prepended with the current
# right digit.
(
\6\4
|
(?!\6)
)
() # \6 = set and empty, to signal \4 is captured
raw_input
, the user entered an integer, which would become a string behind the scenes. That's fine. \$\endgroup\$lol
is an ambigram,dad
isn't \$\endgroup\$