Разбираем олимпиадный пример и учимся базовой грамматике «регулярок»
8–9 классы • Подготовка к олимпиаде по кибербезопасности
Политики паролей описываются «масками» и регулярными выражениями.
Чтобы понять, какой пароль подходит, нужно уметь читать эти записи.
Вы научитесь:
Маска (в задачах): набор правил, иногда с собственной семантикой символов
Маска: ID[0-9][*|!]END
Regex (регулярное выражение): стандартный язык описания шаблонов строк
^ID0-9END$
Важно: в задачах олимпиад «маска» может отличаться от стандарта Regex.
Маска: SC[a-gA-S][*|!?]OL
Правила из условия:
- Вне [ ] — символы фиксированы (SC … OL)
- [a-gA-S] — один символ: a…g или A…S
- [*|!?] — альтернация:
- «*» = любая непустая подстрока из латинских букв/цифр
- «!» или «?» = ровно этот символ
Итого структура строки:
SC + (одна буква из диапазона) + (либо [A-Za-z0-9]+, либо !, либо ?) + OL
Варианты: SCHOOOL, SChоOL, SCHOO!L, SCHOOLOL, SCH*!OL, SCH?OL
Подумайте 30 секунд, какие подойдут.
Подсказка: проверьте позицию [a-gA-S] и затем альтернативу [*|!?].
Подходят:
Не подходят:
Маска → Regex:
^SC[a-gA-S](?:[A-Za-z0-9]+|[!?])OL$
Пояснения:
Строгое правило Regex:
Если вбить маску как есть: SC[a-gA-S][|!?]OL
Regex-движок поймёт: «один символ из {, |, !, ?}» — и признает только SCH?OL.
Поэтому вначале нужно перевести «маску задачи» в корректный Regex (см. предыдущий слайд).
Правило №1: внутри [ … ] пишем «один символ». Повторы — квантификаторами снаружи.
Лайфхак: когда видите «|» внутри [ … ], почти всегда это просто символ «|».
Жадность: по умолчанию берёт «как можно больше», но чтобы совпасть с остальным паттерном.
Ленивая форма: X+? и т.п. — «как можно меньше».
Похоже — не значит одинаково:
В задачах про пароли обычно подразумевается ASCII-латиница.
Проверяйте алфавит: [A-Za-z0-9] — только латинские буквы и цифры.
Начинается с AB,
затем одна цифра от 0 до 3,
затем ровно две латинские буквы,
заканчивается буквой Z.
Маска (олимпиадная семантика)
AB[0-3][A-Za-z][A-Za-z]Z
Регулярное выражение (стандартный Regex)
^AB[0-3][A-Za-z]{2}Z$
Какие строки подойдут?
AB2HiZ, AB3!Z, AB0abZ, AB1aZ
Подходят: AB2HiZ (2 и «Hi» — две буквы), AB0abZ (0 и «ab» — две буквы).
Не подходят:
AB3!Z — «!» не буква.
AB1aZ — только одна буква «a», требуется две.
Визуализация структуры: AB + [0–3] + [буква][буква] + Z
Ответ: ^X9[A-Za-z]{2,4}(?:\?|[0-9]{3})$
Пример: только цифры (A=10), длина 6 → H ≈ 6·log2(10) ≈ 19.9 бит
Латиница+цифры (A≈62), длина 8 → H ≈ 8·log2(62) ≈ 47.6 бит
Вывод: длина и алфавит сильно влияют на стойкость.
- Отметь фиксированные части (с учётом регистра)
- Явно распиши, что значит каждый [ … ] (диапазоны, 1 символ!)
- Пойми смысл «*», «|», «?» из условия (это может быть НЕ Regex)
- Сопоставляй всю строку (не подстроку): добавляй ^ и $
- Проверь крайние случаи (минимальная/максимальная длина)
- Следи за Unicode-двойниками (лат/кир)
- При сомнении — переведи в стандартный Regex и протестируй
import re
pat = re.compile(r'^SC[a-gA-S](?:[A-Za-z0-9]+|[!?])OL$')
tests = ["SCHOOOL","SChоOL","SCHOO!L","SCHOOLOL","SCH*!OL","SCH?OL"]
for s in tests:
print(s, bool(pat.fullmatch(s)))
Или используйте regex101, но только после перевода маски в корректный Regex.
Что не так с Regex: SC[a-gA-S][*|!?]OL?
Ответ: внутри [ … ] «|» и «*» — не альтернация и не квантификатор, это просто символы.
Нужно: ^SC[a-gA-S](?:[A-Za-z0-9]+|[!?])OL$
Домашка:
Главное правило: повторы задаются квантификаторами СНАРУЖИ от [ … ],
внутри [ … ] — всегда ровно один символ из набора.