Last active
June 6, 2022 10:39
-
-
Save kobi/b126088b26dacba2719e49045e0b79f9 to your computer and use it in GitHub Desktop.
A version of https://github.com/kobi/RecreationalRegex/blob/master/RecreationalRegex/Rectangles/SmallRectangles.cs with no rotations, fewer groups, Nx1 size rectangles, for this issue: https://github.com/dotnet/runtime/issues/69381
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Text.RegularExpressions; | |
using System; | |
const string smallRectangles = "1\n\n2\n\n~~\n\n"; | |
Regex normal = new Regex(Rect.RectanglesPatternShorter, RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace); | |
Regex compiled = new Regex(Rect.RectanglesPatternShorter, RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace); | |
Console.WriteLine("normal: " + normal.IsMatch(smallRectangles)); | |
Console.WriteLine("compiled: " + compiled.IsMatch(smallRectangles)); | |
public static class Rect { | |
public const string RectanglesPatternShorter = @" | |
\A | |
(?=(?<NextPos>[^~]*)) # \k<NextPos> always matches the position *before* the next free tilde. | |
(?: | |
(?: | |
(?<IndexLength>.)+? # Match n characters. We will use rectangle number n in position <Index>. | |
# 0 is not an option - we need some shape to be first, second, third, etc. | |
(?<=\A(?=(?<Index>(?<-IndexLength>.)+)).*) # Capture into <Index> the first n characters. | |
(?<=\A(?<CurrentIndex>\k<Index>).*) # Copy Index into CurrentIndex | |
(?=.*\Z # Ensure <Index> is unique. We cannot use the same rectangle twice | |
(?<!(?=\A\k<Index>(?<=\A\k<CurrentIndex>))\A.*(?<-Index>.)+) | |
) | |
#Copy the shape of rectangle <Index> to the target area. | |
#Find rectangle number <Index> | |
(?<=(?=.(?<IndexLength>.)*?(?<=\A\k<Index>))\A.*) # Populate <IndexLength> again. | |
# ^-- we are skipping over one character. We want to reach rectangle number <IndexLength>, | |
# so we're skiping over <IndexLength>-1 rectangles | |
(?<=(?=\s*(?<-IndexLength>(?:\w+\r?\n)+\r?\n)*(?<=(?<RectangleStart>.*))\w)\A.*) # Capture starting position of this rectangle. | |
(?(IndexLength)(?!)) | |
(?<=(?=\k<NextPos>(?<=(?<X>~*)))\A.*) # Init <X> with the number of tildes to the left of the starting position. | |
# Basically `(?:\w+\n)+\n` to match the whole rectangle. | |
(?<=(?=\k<RectangleStart> # Go to the position before the first character in the current rectangle. | |
\w+ | |
\r?\n | |
\r?\n # Match until we reach the end of this rectangle. | |
)\A.*) | |
# Try to fit the rectangle into empty positions in the target rectangle. | |
(?<=(?=\k<NextPos> | |
(?: # Match tildes | |
~ | |
(?<=(?<Filled>\A.*)) # Push the current position to <Filled> | |
)+? | |
(?<=^\k<X>~) # Match exactly <Width> tildes. | |
)\A.*) | |
# Find the next free position - <NextPos>. | |
(?<=(?=.*? | |
(?<=(?<NextPos>\A.*)) # <NextPos> is the position before the next free tilde. | |
~ | |
(?<=(?<TempNextPos>\A.*)) # We compare it to <Filled>, which is the position including the tilde. | |
(?=.*\Z | |
(?<!(?=\A\k<Filled>(?<=\A\k<TempNextPos>))\A.*(?<-Filled>.)*) | |
) | |
| | |
.*\r?\n\Z (?<Done>) # If we cannot find more empty positions it means we are done. Set the <Done> flag. | |
)\A.*) | |
) | |
)+ | |
(?(Done)|(?!)) | |
"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment