Regex (ECMAScript or better), 48 35 29 28 bytes
-20 bytes thanks to H.PWiz
^(xx)?(?!(xx(x*))\3?\2+$)xxx
Try it online! - ECMAScript
Try it online! - Perl
Try it online! - Java
Try it online! - Python
Try it online! - Ruby
Try it online! - PCRE
Try it online! - .NET
Takes its input in unary, as a string of x
characters whose length represents the number.
Commented and indented:
^ # tail = N = input number
# Assert either that N-2 and N are prime, or that N and N+2 are prime.
(xx)? # tail -= 2, optionally
# Assert that neither tail nor tail+2 are composite. For testing that they are both prime,
# this has false positives for tail=0, tail=1, and tail=2.
(?! # Assert that the following can't match:
(xx(x*)) # \2 = any number >= 2; \3 = \2 - 2
\3? # tail -= \3, optionally; if this is done, we're asserting that tail+2 is
# composite (divisible by \2 with a quotient >= 3), otherwise
# we're asserting tail is composite (quotient >= 2).
\2+$ # Assert that tail is positive and divisible by \2
)
xxx # Assert that tail >= 3, preventing the false positives.
# The "quotient >= 3" requirement above is why tail=2 can be one of them,
# as it prevents 2+2 from being seen as composite.
29 bytes
^ # tail = N = input number
# Assert either that N-2 and N are prime, or that N and N+2 are prime.
(xx)? # tail -= 2, optionally
# Assert that neither tail nor tail+2 are composite. For testing that they are both prime,
# this has false positives for tail=0 and tail=1.
(?! # Assert that the following can't match:
(xx)? # tail -= 2, optionally; if this is done, we're asserting that tail is
# composite, otherwise we're asserting tail+2 is composite.
(x*) # \3 = S-2, where S is a potential divisor to test against M = tail+2;
# tail -= \3
(\3xx)+$ # assert that tail is positive and divisible by \3+2, which is
# equivalent to asserting M is divisible by S with a quotient >= 2
)
xx # Assert that tail >= 2, preventing the false positives.
48 bytes
This misses the fact that we can switch between testing N-2 and N or testing N and N+2. Instead, this regex switches between testing N and N-2 or testing N and N+2, which results in tests not having enough in common to be collapsed together.
^ # tail = N = input number
(
# Assert that neither N nor N-2 are composite. But we want N and N-2 to be prime, so
# this gives false positives for 0, 1, and 2.
(?! # Assert that the following can't match:
(xx)? # tail -= 2, optionally
(xx+) # \3 = any number >= 2
\3+$ # Assert that tail is positive and divisible by \3
)
| # or...
# Assert that neither N nor N+2 are composite. But we want N and N+2 to be prime, so
# this gives false positives for 0 and 1.
(?! # Assert that the following can't match:
(xx(x*)) # \4 = any number >= 2; \5 = \4 - 2
\4*(xx)?\5$ # Assert that either tail or tail+2 is positive and divisible by \4
)
)
xxx # Block the false positives on every number less than 3
51 bytes (not golfed at all)
^ # tail = N = input number
(?!(xx+)\1+$) # Assert that N is not composite. But we want N to be prime,
# so this gives false positives for 0 and 1.
(
(?!xx(xx+)\3+$) # Assert that N-2 is not composite. But we want N-2 to be prime, so this
# gives false positives for 0, 1, and 2.
| # or...
(?!(x*)(xx\4)+$) # Assert that N+2 is not composite. Has no false positives for primality.
)
xxx # Block the false positives on every number less than 3
Regex (ECMAScript), 67 bytes
Just for kicks, here is a port of Dennis's Jelly algorithm:
^(?!(xx+)\1+$)(?=(x{6})*(x*))xxx(?!(xx+)(?=\4*(x*)).*(?=\5\3$)\4+$)
Try it online!
^ # tail = N = input number
(?!(xx+)\1+$) # Assert N is not composite
(?=(x{6})*(x*)) # \3 = N % 6
xxx # assert N>=3; tail -= 3
# Assert tail + \3 is not composite
(?! # Assert the following can't match:
(xx+) # \4 cycles through all values such that 2 <= \4 <= tail,
# and is tested as a possible divisor of tail + \3
(?=\4*(x*)) # \5 = tail % \4
.*(?=\5\3$) # tail = \5 + \3
\4+$ # Assert that tail is positive and divisible by \4
)
\$\large\textit{Anonymous functions}\$
JavaScript (ES6), 50 bytes
n=>/^(..)?(?!(..(.*))\3?\2+$).../.test(Array(n+1))
Try it online!
Ruby, 41 bytes
->n{?x*n=~/^(xx)?(?!(xx(x*))\3?\2+$)xxx/}
Try it online!
Try it online! - test cases only
\$\large\textit{Full programs}\$
.*
$*
^(11)?(?!(11(1*))\3?\2+$)111
Try it online! - test cases only