Regex (PCRE), 65 bytes
^((?=(.))(?!(.*?\2(?=.*
(\4?+.*?\2)))*+.*\2)(?=.*
(\5?+.)).)*
\5$
Try it online! - test cases
Try it on regex101 - try it on your own
Takes the input strings delimited by newline.
This asserts that both:
- For each character in the first string, the second string contains that character at least as many times as it occurs in the first string
- The second string is equal in length to the first
^ # Assert that we're starting at the beginning of the first word.
(
(?=(.)) # Match and capture a character in \2, without consuming it.
# Assert that the second has at least as many occurrences of \2 as there
# are subsequent occurrences of it in the first word (including the one we
# just captured above).
(?! # Negative lookahead - assert the following can't match, and also
# conveniently erase whatever capture groups it creates when finished.
(
.*?\2 # Match up to the next occurrence of \2 in the first word
# (which will be the first one when this loop starts)
(?=
.*¶ # Skip to the second word.
( # \4 = the following:
\4?+ # previous value of \4, if any
.*?\2 # Match up to the first subsequent occurrence of
# \2 in the second word (which will be the first
# occurrence when this loop starts)
)
)
)*+ # Loop the above possessively, locking in each iteration
# atomically as it matches.
.*\2 # Assert \2 occurs again in the first word.
)
# Append one more character from the second word onto \5, building up \5
# to have the same number of characters of the second word as characters
# we have finished processing in the first word.
(?=
.*¶ # Skip to the second word.
( # \5 = the following:
\5?+ # Previous value of \5, if any
. # One additional character
)
)
. # Skip over the \2 just processed in the first word.
)* # Iterate the above as many times as possible.
¶ # Assert we've reached a newline, meaning we've processed the
# entire first word, and advance to the second word.
\5$ # Assert that the second word is of equal length to the first.
It only takes +1 byte (66 bytes) to add support for zero-length words:
^((?=(.))(?!(.*?\2(?=.*
(\4?+.*?\2)))*+.*\2)(?=.*
(\5?+.)).)*
\5?$
Try it online! - test cases
Try it on regex101 - try it on your own
Regex (.NET), 70 66 62 bytes
^(((.))(?=(?>(?<2>\2)|.)*
((?<-2>\2)|.)*$(?(2)^)))*
(?<-3>.)*$
Try it online! - test cases
Try it on regex101 - try it on your own
This asserts that both:
- For each character in the first string, the second string contains that character at least as many times as it occurs in the first string
- The second string is not longer than the first
Although it is not required, this works even with zero-length words (for free; there is no golf sacrifice in doing so).
^ # Assert that we're starting at the beginning of the first word.
(
((.)) # Consume a character and capture it in both \2 and \3.
# Assert that the second word has at least as many occurrences of \2 as
# there are subsequent occurrences of it in the first word (including the
# occurrence we just consumed). This only needs to be asserted for the first
# occurrence of each character in the first word (because on each subsequent
# occurrence, the count of subsequent occurrences will be one fewer than
# before) but for golf reasons, it's harmless to do it for every occurrence.
(?= # Atomic lookahead
# Step 1: Push every subsequent occurrence of \2 onto the \2 stack.
(?> # Atomic group - prevent backtracking from changing what's
# done inside it once it's been done.
# For each subsequent character in the first word:
(?<2>\2) # If it matches \2, push another copy of it onto the
# \2 stack, and consume the character.
| # or
. # Consume the character.
)* # Iterate the above as many times as possible.
¶ # Consume the newline to begin reading the second word,
# preventing the number of loop iterations in the above
# loop from being backtracked.
# Step 2: Assert that the second word has at least as many occurrences
# of \2 as were counted above.
( # For each character in the second word:
(?<-2>\2) # If it matches \2, pop it off the \2 stack, and consume
# the character.
| # or
. # Consume the character.
)*$ # Iterate the above until reaching end of string.
(?(2)^) # Assert that the \2 stack is empty.
)
)* # Iterate the above as many times as possible.
¶ # Assert we've reached a newline; advance to the second word.
(?<-3>.)*$ # Assert that this word is not longer than the first word, by
# popping every capture from the \3 stack and matching one
# character of the second word (it doesn't have to match \3)
# for each.
Regex (Perl / PCRE), 71 bytes
^((?=(.))(?4)(?=.*
(\3?+.)).)*
\3$((?!(.*?\2(?=.*
(\6?+.*?\2)))*+.*\2))
Try it online! - Perl
Try it online! - PCRE2
Perl doesn't erase capture groups upon exiting from a negative lookahead. For compatibility with it, this version uses a subroutine call (?4)
instead of a negative lookahead to erase the necessary capture group. The subroutine is then executed again, harmlessly, after the regex finishes and reaches the end of the string (for golf reasons, it is not hidden in a (?(DEFINE)
...)
block or similar construct).
Regex (PCRE / .NET), 74 bytes
^((?=(.))(?!(?>(.*?\2(?=.*
((?>\4?).*?\2)))*).*\2)(?=.*
((?>\5?).)).)*
\5$
Try it online! - PCRE2
Try it online! - .NET
This is the PCRE version ported to be compatible with .NET, replacing possessive quantifiers with atomic groups.
Regex (PCRE / Ruby), 87 bytes
^((?=(.))(?!(.*?\2(?=.*
(\5?+.*?\2))(?=.*
(\4)))*+.*\2)(?=.*
(\7?+.))(?=.*
(\6)).)*
\6?$
Try it online! - PCRE
Try it online! - Ruby
This is a port of the 65 byte PCRE version, using back-and-forth copying of \4
↔\5
and \6
↔\7
to avoid use of nested backreferences, which aren't supported by Ruby.
For a reason I have yet to determine, this doesn't work on Pythonregex
, even its latest version.
Regex (Perl / PCRE / Ruby / .NET), 147 bytes
^((?=(.))(?!(?>(.*?\2(?=((?!.*\2)|.))(?=.*
((?!.*$\4)(?>\6?).*?\2|(?=.*$\4)(?=(?>\6?).*?\2)))(?=.*
(\5)))*).*\2)(?=.*
((?>\8?).))(?=.*
(\7)).)*
\7$
Try it online! - Perl
Try it online! - PCRE2
Try it online! - Ruby
Try it online! - .NET
This is a rather interesting challenge for writing a regex polyglot.
Supporting both Perl and Ruby/.NET is rather difficult. The problem is finding a way to erase the capture group that is created inside a negative lookahead in the PCRE version. Erasing capture groups in situations like this can be a challenge, and to support this combination of regex engines, we can't use negative lookahead (Perl doesn't erase it), a subroutine call (because Ruby's syntax is incompatible with Perl, and .NET doesn't have them), a branch reset group (neither Ruby nor .NET support them), or capture group aliasing or explicit erasure (only .NET has those).
So we must signal to the place where the capture is normally made, to erase it when it needs to be erased. The method I settled upon here is rather convoluted, but it works. (It would be shorter with a lookaround conditional, but we can't use one, as Ruby doesn't have them, and .NET's syntax for them is different.) This post is already pretty long, so here's a link to the commented version.
aaab, bbba = false
\$\endgroup\$