Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Match increasing/decreasing sequences using regex

Tags:

c#

regex

I'd like to match any string that contains only digits that are increasing or decreasing. This means that these strings would be matched:

123, 234567, 0123456789, 87654, 321

And these would not:

7891011, 1234566789, 987865, 134

I was looking for an answer and all I found was that this is not possible to be done using regex. However, I would like to do it in regex, otherwise it'd make a mess in the code.

Thanks for answers.

like image 462
leopik Avatar asked Apr 02 '26 18:04

leopik


2 Answers

Technically it is possible with the use of lookaheads, but it won't look nice.

Logic for ascending pattern:

  1. Start from the beginning of string
  2. Match current digit only in case if it is followed by next digit or end of string. Move to next position.
  3. Repeat 2 until we reach end of string.

Example for 123:

  1. Start from the beginning of string
  2. Current symbol is 0? No. Ok, skip.
  3. Current symbol is 1? Yes. Is it followed by 2 or end of string? Yes. Ok, go to next symbol.
  4. Current symbol is 2? Yes. Is it followed by 3 or end of string? Yes. Ok, go to next symbol.
  5. Current symbol is 3? Yes. Is it followed by 4 or end of string? Yes. Ok, go to next symbol.
  6. Current symbol is 4? No. Current symbol is 5? No. ... Is it end of string? Yes.

Example for 134:

  1. Start from the beginning of string
  2. Current symbol is 0? No. Ok, skip.
  3. Current symbol is 1? Yes. Is it followed by 2 or end of string? No. Error, no match.

Regex to match ascending patterns:

^(?:0(?=1|$))?(?:1(?=2|$))?(?:2(?=3|$))?(?:3(?=4|$))?(?:4(?=5|$))?(?:5(?=6|$))?(?:6(?=7|$))?(?:7(?=8|$))?(?:8(?=9|$))?9?$

Regular expression visualization

Debuggex Demo

Regex to match descending patterns:

^(?:9(?=8|$))?(?:8(?=7|$))?(?:7(?=6|$))?(?:6(?=5|$))?(?:5(?=4|$))?(?:4(?=3|$))?(?:3(?=2|$))?(?:2(?=1|$))?(?:1(?=0|$))?0?$

Regular expression visualization

Debuggex Demo

Combined together:

^((?:0(?=1|$))?(?:1(?=2|$))?(?:2(?=3|$))?(?:3(?=4|$))?(?:4(?=5|$))?(?:5(?=6|$))?(?:6(?=7|$))?(?:7(?=8|$))?(?:8(?=9|$))?9?|(?:9(?=8|$))?(?:8(?=7|$))?(?:7(?=6|$))?(?:6(?=5|$))?(?:5(?=4|$))?(?:4(?=3|$))?(?:3(?=2|$))?(?:2(?=1|$))?(?:1(?=0|$))?0?)$

Regular expression visualization

Debuggex Demo

Regex101 Demo

like image 104
Ulugbek Umirov Avatar answered Apr 04 '26 07:04

Ulugbek Umirov


The code wouldn't be more of a mess than the regex to do this. Regular expressions are bad at math.

Something like this will do it:

bool IsSequentiallyIncreasing(string input)
{
    char? lastDigit = null;

    foreach (char c in input)
    {
        if (!c.IsDigit || (lastDigit != null && c != lastDigit + 1))
        {
            return false;
        }

        lastDigit = c;
    }

    return true;
}

So you walk over all characters in the string, and as soon as you encounter a non-digit or a digit that isn't the last digit + 1, you return false.

And do the same for decreasing, and you can simply call IsSequentiallyIncreasing(input) || IsSequentiallyDecreasing(input). I'll leave it up to you to add error handling and merge the two methods into one.

like image 28
CodeCaster Avatar answered Apr 04 '26 07:04

CodeCaster



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!