Как работает это регулярное выражение?

От в этой статье,

/^1?$|^(11+?)\1+$/ проверяет, является ли число (его значение в унарном) простым или нет.

Используя это, perl -l -e '(1 x $_) !~ /^1?$|^(11+?)\1+$/ && print while ++$_;' возвращает список простых чисел.

У меня недостаточно опыта работы с Perl, но я понимаю, что регулярное выражение будет true для числа, которое не является простым. Итак, если мы напечатаем все числа, которые не выражают true с этим выражением, у нас есть список простых чисел. То, что пытается выполнить запрос perl.

О части регулярного выражения,

^1?$ часть предназначена для подсчета 1 как не просто

^(11+?)\1+$ предназначен для сопоставления не простых чисел, начиная с 4.


То, что я не понимаю, - это то, что ? в регулярном выражении вообще необходимо. По мне /^1$|^(11+)\1+$/ должно быть просто отлично и на самом деле

perl -l -e '(1 x $_) !~ /^1$|^(11+)\1+$/ && print while ++$_;' дает мне тот же набор простых чисел.

Есть ли недостаток в моем понимании регулярного выражения? Почему нужен ??

Не соответствует ли ? нулю или одному вхождению предшествующего ему выражения?

Ответ 1

Первый ? предназначен для сопоставления пустой строки (т.е. 0) как непростой. Если вам все равно, соответствует ли регулярное выражение 0, то это необязательно.

Второй ? предназначен только для эффективности. + обычно "жадный", что означает, что он соответствует количеству символов, доступных, а затем возвращается, если остальное регулярное выражение не соответствует. +? делает его неживым, поэтому он соответствует только 1 символу, а затем пытается сопоставить больше, если остальная часть регулярного выражения не соответствует. (См. раздел Quantifiers perlre для получения более подробной информации о жадных и нежелательных соответствиях.)

В этом конкретном регулярном выражении (11+?) означает, что он проверяет делимость на 2 ('11'), затем 3 ('111'), затем 4 и т.д. Если вы использовали (11+), он проверил делимость на N (само число), затем N-1, затем N-2 и т.д. Так как делитель должен быть не больше N/2, без ? он будет тратить время на тестирование множества "потенциальных" делителей, возможно, работает. Это все равно будет соответствовать нечетным числам, только медленнее. (Кроме того, $1 будет самым большим делителем, а не самым маленьким.)

Ответ 2

Первый ? сделает "" (пустая строка, унарный ноль) не будет простым числом. Нуль определяется как не простое.

Второе - другое; он останавливает регулярное выражение от жадного соответствия. Это должно значительно улучшить производительность матча, так как первая часть этого раздела ((11+)) не будет потреблять почти всю строку, прежде чем будет возвращаться. Если вы опускаете вопросительный знак, вы эффективно проверяете, делится ли нечетный n на n-1, и поэтому один вниз; если вы включите его, вы тестируете делимость на два первых и так далее. Очевидно, что числа, как правило, делятся на более мелкие факторы чаще, поэтому ваш матч будет быстрее.