Печатать значения макросов, не зная количества макросов

Решение

Можно проверить его с помощью regex - но вы должны предпочесть решение в коде, потому что оно будет намного быстрее. Этому регулярному выражению требуется много возврата. Единственное преимущество этого регулярного выражения состоит в том, что он работает для произвольной длины.

(?:^0+-\d+$)
|
(?:^(?>0*)(?\d+)-(?>0*)\k$)
|
(?:
    (?:^(?>0*)(?\d)+-(?>0*)(?<-length>\d)*(?(length)(?!))\d+$)
    |
    (
        (?=^(?>0*)(?\d)+-(?>0*)(?<-o>\d)*(?(o)(?!))$)
        ^
            (?>0*)
            (?\d*)
            (?:(?0)|(?1)|(?2)|(?3)|(?4)|(?5)|(?6)|(?7)|(?8)|(?9))
            \d*
        -
            (?>0*)
            \k
            (?(g0)[1-9]|(?(g1)[2-9]|(?(g2)[3-9]|(?(g3)[4-9]|(?(g4)[5-9]|(?(g5)[6-9]|(?(g6)[7-9]|(?(g7)[89]|(?(g8)9|(?!))))))))))
            \d*
        $
    )
)

Это соответствует для каждого x-y, где x <= y для положительных целых чисел, включая ледящие нули.

DEMO

Это не работает для символов.

Объяснение

Мне удалось создать регулярное выражение, которое соответствует x-y для всех x < y. Вопрос был x <= y. Поэтому я разделил вопрос на x = y | x < y.

Нам нужно обработать, что первое или оба числа содержат только нули, но это тривиально:

^0+-\d+$

Теперь случай x = y

^(?>0*)(?\d+)-(?>0*)\k$

Трудная часть - x < y.

  1. x меньше y, если x короче длины символа, чем y (фиксирующие нули захватываются атомной группой): ^(?>0*)(?\d)+-(?>0*)(?<-length>\d)*(?(length)(?!))\d+ Эта первая группа захватывает целое число на один захват за цифру. После разделителя определение балансирующей группы очищает стек захвата и заставляет по меньшей мере еще одну цифру.
  2. Оба числа имеют одинаковую длину (если первое число больше, оно также больше и не должно совпадать). Чтобы гарантировать, что оба числа имеют одинаковую длину, я начал с положительного взгляда на утверждение, которое обеспечивает его таким же образом, как я тестировал более длинное число на шаге 1: (?=^(?>0*)(?\d)+-(?>0*)(?<-o>\d)*(?(o)(?!))$). После этого алгоритм прост. Начните с начала. Если текущая цифра равна, перейдите к следующей цифре. Если текущий x -digit медленнее текущего y -digit, мы закончили и найдено совпадение. Если это медленнее, мы не должны совпадать. Это делается по этой схеме:
    ^
        (?>0*)   # cut out leeding zeros
        (?\d*)
        .*
    -
        (?>0*)   # cut out leeding zeros
        \k  # both numbers start with the same part
        .*
    $
    
    И теперь проверка на одну цифру. Есть только 10 возможностей [0-9]. Каждый из них захватывается одной группой: (?0)|(?1)|(?2)|(?3)|(?4)|(?5)|(?6)|(?7)|(?8)|(?9) Теперь мы можем использовать условия для проверки того, больше ли текущий y -digit, чем текущий x -digit. Отобразится для 0 и 1: (?0)|(?1): если для текущего x -digit соответствует 0, для текущего y -digit есть только [1-9]. Если 1 соответствует только [2-9], возможно. Это можно использовать в условии: (?(g0)[1-9]|...), что означает, что если g0 имеет захват [1-9], он должен совпадать, иначе остальное должно совпадать. Это комбинируется с: (?(g0)[1-9]|(?(g1)[2-9]|(?(g2)[3-9]|(?(g3)[4-9]|(?(g4)[5-9]|(?(g5)[6-9]|(?(g6)[7-9]|(?(g7)[89]|(?(g8)9|(?!)))))))))). Последний трюк заключается в том, что ни одна из групп g[0-8] не была сопоставлена ​​только g9, и нет большего количества цифр, и совпадение должно завершиться неудачно (?!).

Все это было объединено со всем регулярным выражением, которое соответствует x-y для всех x <= y.

30
задан Some programmer dude 23 November 2017 в 10:18
поделиться