Regex 🐝
(ECMAScript or better), 12 bytes
(x+)(?=\1+$)
Takes its input in unary, as a sequence of x
characters whose length represents the number. Returns its output as the number of matches.
This of course has already been done in Digital Trauma's Retina answer, but here it is demonstrated to work on a much wider variety of regex engines.
Try it online! - ECMAScript
Try it online! - Perl
Try it online! - Java
Try it online! - PCRE
Try it online! - Boost
Try it online! - Python
Try it online! - Ruby
Try it online! - .NET
(x+)(?=\2+$) # \2 = largest proper divisor of tail; tail -= \2;
# return \2 as a match
Try it online!
Regex 🐘
(.NET), 15 bytes
((x+)(?=\2+$))*
Try it online!
Returns its output as the capture count of group \1
.
# tail = input number; no need to anchor, as all inputs return a result
(
(x+)(?=\2+$) # \2 = largest proper divisor of tail; tail -= \2
)* # Loop the above as many times as possible, minimum zero, and push each
# match onto the \1 capture stack
Regex (Perl / Java / PCRE2 v10.34 or later), 26 bytes
((?=(\2?+(x*))x(x\3)+$)x)*
Returns its output as the length of the match.
Try it online! - Perl
Try it online! - Java
Attempt This Online! - PCRE2 v10.40+
We can't just do a direct port of the .NET version, because we need to subtract at least 1 from tail on each iteration (as a regex loop terminates after a zero-width match), and with most inputs, the iteration count exceeds the cumulative result of subtracting the largest divisor before the last iteration has finished. So instead, we let \2
be the sum of the subtracted divisors minus the iteration count:
# tail = input number; no need to anchor, as all inputs return a result
(
(?=
(\2?+(x*)) # \3 = {conjectured largest proper divisor of tail-\2} - 1;
# \2 = {\2, or 0 if \2 is unset} + \3; tail -= \2; note that the
# subtraction of 1 from this divisor compensates for the "tail -= 1"
# on each iteration (below)
x(x\3)+$ # assert tail - 1 is divisible by \3 + 1
)
x # head += 1; tail -=1
)* # Loop the above as many times as possible, minimum zero
(The PCRE version requirement is because PCRE2 v10.33 and earlier automatically makes any group containing a nested backreference atomic, thus \3
always captures the entire remaining tail, making the regex always return 0.)
Regex (.NET), 28 bytes
(?=((x+)(?=\2+$))*)(?<-1>x)*
Try it online!
A simple port of the 15 byte .NET version, that returns its output as the length of the match instead.
Regex (Perl / Java / PCRE2 v10.34 or later / .NET), 29 bytes
Obsoleted by the 29 byte regex below, which supports a superset of regex engines.
Regex (Perl / Java / PCRE / Pythonregex
/ Ruby / .NET), 33 29 bytes
((?=.*(?=\3$|^)(x+)(\2+$))x)*
Try it online! - Perl
Try it online! - Java
Try it online! - PCRE1
Try it online! - PCRE2 v10.33
Attempt This Online! - PCRE2 v10.40+
Try it online! - Python import regex
Try it online! - Ruby
Try it online! - .NET
For regex engines that lack nested backreferences but support forward-declared backreferences, we switch to a different approach. In this version, each iteration, while inside a lookahead, stores the new value of tail in the capture group \3
, so that the next iteration can then recall that value rather directly. Since this directly sets \3
instead of building it up incrementally, there's no need to emulate a nested backreference.
# tail = N = input number;
# no need to anchor, as all inputs return a result
(
(?=
.*(?=\3$|^) # tail = \3, or N if \3 is unset
(x+)(\2+$) # \2 = largest proper divisor of tail; \3 = tail - \2
)
x # Increment the return value
)* # Loop the above as many times as possible, minimum zero
Regex (Perl / PCRE / Pythonregex
), 63 bytes
(?=(xx+?)\1*(?=\1$)((?R)))(?=(x+)\3*(?=\3$)((?R)))\2\4|x\B(?R)|
This implements the recursive definition of the function:
\$a(1) = 0\$
\$a(p) = 1 + a(p-1)\$ if \$p\$ is prime
\$a(nm) = a(n) + a(m)\$ if \$m,n > 1\$
Try it online! - Perl
Try it online! - PCRE1
Try it online! - PCRE2 v10.33
Attempt This Online! - PCRE2 v10.40+
Try it online! - Python import regex
# tail = input number; no need to anchor, as all inputs return a result
(?=
(xx+?)\1*(?=\1$) # Assert tail isn't prime;
# tail = \1 = smallest prime factor of tail
((?R)) # \2 = recursive result of f(tail)
)
(?=
(x+)\3*(?=\3$) # tail = \3 = largest proper divisor of tail
((?R)) # \4 = recursive result of f(tail)
)
\2\4 # return \2 + \4 as the match
| # or if tail is prime:
x # tail -= 1; return result += 1
\B # Assert tail > 0
(?R) # return 1 + recursive result of f(tail)
| # or if tail == 1:
# return 0 at the match
Note that (?0)
could have been used as a synonym for (?R)
.
Regex (Perl / PCRE / Boost / Pythonregex
), 65 bytes
((?=(xx+?)\2*(?=\2$)((?1)))(?=(x+)\4*(?=\4$)((?1)))\3\5|x\B(?1)|)
The intent of the 63 byte version was to create a version that works under Boost, but as it turned out Boost has a bug (which I've reported) in which it ignores top-level alternatives in a top-level recursive call (i.e. (?R)
), trying only the first top-level alternative. The workaround is to nest the entire regex in a capture group, so that Boost sees the other alternatives. Either (?R)
or (?1)
would work, but the latter is used for slightly better efficiency.
Try it online! - Perl
Try it online! - PCRE2
Try it online! - Boost
Try it online! - Python import regex
Regex (Ruby), 76 71 bytes
(?=(xx+?)\1*(?=\1$)(\g<0>))(?=(x+)\3*(?=\3$)(\g<0>))\k<2+0>\4|x\B\g<0>|
Try it online!
This is a port to Ruby's style of recursion; (?R)
is replaced with \g<0>
. Also, the backreference \2
needs to be replaced with \k<2+0>
to get its value at the current level of recursion, rather than its global value which may have been overwritten at deeper levels of recursion.
2^32 - 1
. The rest is up to you and your system. Hope, this is what you meant with your question. \$\endgroup\$