Regex (.NET), 23 19 bytes
(\2?(\1)|x$|^x|\b)*
Try it online!
Takes its input in unary, as a string of x
characters whose length represents the number. Returns its output as the capture count of group \1
.
This is based on Martin Ender's .NET regex for matching Fibonacci numbers. The .NET feature of balanced groups is used to count the number of iterations taken by the loop.
- That regex is first initially translated to use
x
as its unary numeral, yielding ^$|^(^x|(?>\2?)(\1))*x$
.
- Then the
x$
at the end is moved inside as the extra alternative |x$
, incrementing the loop count by \$1\$ for all \$n>0\$. This also allows us to remove the ^$|
at the beginning, because ^(^x|(?>\2?)(\1)|x$)*$
will now match \$n=0\$ on its own. (It will also now match numbers that are \$0\$ or \$1\$ less than a Fibonacci number, but we don't care because as specified by the challenge, all inputs will be Fibonacci numbers.)
- Then the extra alternative
|\b
is added to increment the loop count again for all \$n>0\$; \b
cannot match on an input of \$n=0\$ because there is no word character ([0-9A-Za-z_]
) to form a boundary with the absense of a word character, but it will always match at the end of a string of one or more x
s. The match is zero-width, so the loop will then be terminated.
- Then we remove the
^
and $
anchors sandwiching the regex, because we don't need to return a non-match for non-Fibonacci numbers.
- Then an optimization for speed, moving the
^x
alternative as far to the end as possible, because it only has to match once, and would add a failed match to every subsequent iteration if ordered as the first alternative.
- The
\2?
can lose the (?>
...)
atomic group around it, because we don't need to determine if a number is Fibonacci or not. Due to the lack of any assertions following the loop, it will simply keep the first match it finds at each iteration, not having any reason to backtrack.
27 byte version that matches iff the input is a Fibonacci number:
^((?>\2?)(\1)\B|x$|^x|\b)*$
Try it online!
The \B
prevents numbers \$1\$ less than a Fibonacci number from being matched; in unary, \B
matches at every place except the beginning and end in a non-zero number (and matches "everywhere" in an input of zero).
Regex 🐇
(PCRE1 / PCRE2 v10.34 or earlier), 20 bytes
^(\2?(\1)|x$|^x)+|^x
Try it online! - PCRE1
Try it online! - PCRE2 v10.33
Takes its input in unary, as the length of a string of x
s. Returns its output as the number of ways the regex can match. (The rabbit emoji indicates this output method. It can yield outputs bigger than the input, and is really good at multiplying.)
This is a straight port of the .NET version to the 🐇
output format. It needs to be anchored, so that the only variation in how a match can happen is how many iterations the loop takes, not where in the string it starts. The *
is changed to +
because with the former, looping for 0 iterations would still be a match, and would result in a 1-indexed return value.
Moving the |\b
alternative to the end as |^x
is a minor speed optimization, at a zero-byte cost. As an added bonus, we can change this to |^xx
to return \$1\$ (instead of \$2\$) for an input of \$1\$.
For PCRE1, and PCRE2 before v10.35, the atomic group is not needed even with 🐇
-output, because those versions automatically atomicize groups that contain a nested backreference (in this case, \1
).
Regex 🐇
(Perl / PCRE), 23 bytes
^(\2?+(\1)|^x)+|^x|^xxx
Try it online! - Perl v5.28.2 / Attempt This Online! - Perl v5.36+
Try it online! - PCRE1
Try it online! - PCRE2 v10.33 / Attempt This Online! - PCRE2 v10.40+
Try it online! - PCRE2 - every Fibonacci number up to \$F_{46}\$ in under 20 seconds
Instead of atomicizing the whole loop, as ^((?>\2?(\1)|x$|^x|\b))+
, we move all choices out of the loop, so there's only one thing it can do at any iteration. This saves 1 byte.
As in the PCRE1 version, we can change |^x
to |^xx
to return \$1\$ (instead of \$2\$) for an input of \$1\$.
An alternative 23 byte option would be ^(\2?+(\1)|x$|^x)+|^xxx
, but that'd be ever-so-slightly slower due to having an extra choice inside the loop.
Regex (.NET), 33 29 bytes
(?=(^(x)|\3?(\1)|)*)(?<-1>x)*
Try it online!
Returns its output as the sum of the lengths of the match (group \0
) and group \2
. It is done as a sum because for inputs \$n=1,2,3\$ the Fibonacci index is \$n+1\$ and would not fit in a single capture group.
Group \2
, which is (x)
in this regex, is captured as \$1\$ iff the loop takes at least one iteration, which happens for all \$n>0\$. The loop count itself is also given an extra increment, as in the 23 byte version above, by the addition of an empty alternative |
inside the loop. This will result in a zero-width match being taken at the end, regardless of input; it even happens for \$n=0\$, but that doesn't matter, because the (?<-1>x)*
will not have room to pop its capture, and the return match will be \$0\$ anyway.
Note that this regex would actually not be made shorter by returning its output as the sum of the lengths of \0
, \3
, and \3
, as the shortest way I can think of to do that takes 34 bytes:
(?=((?>\2?)(\1)|^x)*(x))?(?<-1>x)*
Try it online!
38 byte version that matches iff the input is a Fibonacci number:
^(?=(^(x)|(?>\3?)(\1)|)*x$|$)(?<-1>x)*
Try it online!
Regex (Perl / PCRE), 31 bytes
((?=(\2?x))(^x|\4?+(\3)))*(x|^)
Try it online! - Perl
Try it online! - PCRE
Returns its output as the sum of the lengths of groups \2
, \5
, and \5
. The regex saves 3 bytes just by using a possessive quantifier, replacing (?>\4?)
with \4?+
.
The Fibonacci index minus \$2\$ is built up in \2
using the expression (?=(\2?x))
. The first time this is hit, the \2?
will evaluate to zero because \2
isn't set yet, and \2
will be given a value of \$1\$. On every subsequent iteration, it will be incremented. This is done in a lookahead to avoid influencing the running total Fibonacci match, and is safe because at every step, the index will be less than the amount added to the full match.
The (x|^)
at the end serves to let \5
\$=1\$ in all cases except \$n=0\$.
This regex does not work under Java; group \2
just captures \$1\$ and stays there. This may be due to a bug in Java's regex engine.
33 byte version that matches iff the input is a Fibonacci number:
^((?=(\2?x))(^x|\4?+(\3)))*(x|^)$
Try it online! - Perl
Try it online! - PCRE
If the output specification must be simplified to sum only two groups, this would be the shortest way I can think of doing it (39 bytes, output is the sum of the lengths of groups \0
and \5
):
(?=((?=(\2?x))(^x|\4?+(\3)))*(x))?\2?x?
Try it online! - Perl
Try it online! - PCRE
42 byte version that matches iff the input is a Fibonacci number:
^(?=((?=(\2?x))(^x|\4?+(\3)))*(x|^)$)\2?x?
Try it online! - Perl
Try it online! - PCRE