Задание по регулярным выражениям от Егора

Эту задачку придумал мой коллега Егор Симонов. Она используется для обучения стажеров. Одно из условий испытательного срока тестировщика — сдать Егору это задание. А это не так то легко! Егора не проведешь, сдать «ну вот тут не сработает, конечно, зато остальное норм» не пройдет ))

Хорошая задачка с подколками. Сможете ее решить?

Есть набор строк с адресами. Нам эти адреса нужно «почистить», убрать лишнее. Как именно? Смотри в таблице ниже.

Мы должны написать правила замены. Каждое правило замены содержит два обязательных и один опциональный параметр:

  • regexp — шаблон, регулярное выражение;

  • replacement — замена, применяется если входная строка удовлетворяет шаблону

  • exception (опциональный) — запрещающий шаблон, тоже регулярное выражение. Если входная строка подходит по шаблону и одновременно подходит по запрещающему шаблону, замена не применяется;

Правила замены применяются последовательно для входных данных, в том порядке, в котором они указаны.
Делается попытка применить все правила замены для каждой строки, нельзя остановиться в каком-то месте.

Для отладки регулярных выражений можно воспользоваться, например, плагинами Regex или Regex Tester в IDEA, онлайн-проверщиком регулярных выражений (http://myregexp.com, https://regex101.com/) или плагином для eclipse (для фанатов оного) с того же сайта http://myregexp.com (рекомендую попробовать несколько вариантов).

Входной адрес

Что надо получить

Комментарий

Входной адрес

Что надо получить

Комментарий

140002 ЛЮБЕРЦЫ 2 ОКТЯБРЬСКИЙ ПР 123/4-115

140002 ЛЮБЕРЦЫ ОКТЯБРЬСКИЙ ПР 123/4-115

После названия города может идти цифра, совпадающая с концом индекса. Это номер почтового отделения. Это не адресная информация, надо убрать.

636450 636450, Г. ТОГУР, УЛ. БЕЛИНСКОГО Д. 6 КВ 2

636450, Г. ТОГУР, УЛ. БЕЛИНСКОГО Д. 6 КВ 2

Дублирование индексов - не смертельно, но нехорошо. Убрать.

423571 423571 НИЖНЕКАМСК 1 ТАТАРСТАН ВАХИТОВА 51-171

423571 НИЖНЕКАМСК ТАТАРСТАН ВАХИТОВА 51-171

Комбинация первых двух случаев.

658219 РУБЦОВСК 19 УЛ. ЖЕЛЕЗНОДОРОЖНАЯ 194

658219 РУБЦОВСК УЛ. ЖЕЛЕЗНОДОРОЖНАЯ 194

Номер отделения может состоять из двух цифр.

622049 НИЖНИЙ ТАГИЛ 49 УРАЛЬСКИЙ ПР 54-252

622049 НИЖНИЙ ТАГИЛ УРАЛЬСКИЙ ПР 54-252

Город - не обязательно одно слово.

344112 РОСТОВ-НА-ДОНУ 112 УЛ КИЗИТИРИНОВСКАЯ Д 37 3

344112 РОСТОВ-НА-ДОНУ УЛ КИЗИТИРИНОВСКАЯ Д 37 3

Или даже так.

127543 МОСКВА 543,МОСКВА 543,КОНЕНКОВА 12-32

127543 МОСКВА,КОНЕНКОВА 12-32

Часть с номером отделения может повторяться.

391112 РЫБНОВСКИЙ РАЙОН, РЫБНОЕ 2 БОЛЬШАЯ 18-33

391112 РЫБНОВСКИЙ РАЙОН, РЫБНОЕ БОЛЬШАЯ 18-33

Может и район быть.

622049 НИЖНИЙ ТАГИЛ, УРАЛЬСКИЙ ПР 49 252

622049 НИЖНИЙ ТАГИЛ, УРАЛЬСКИЙ ПР 49 252

А тут 49 - номер дома, терять нельзя

420098 420098 КАЗАНЬ 98 ТАТАРСТАН ЛЕСНАЯ 18

420098 КАЗАНЬ ТАТАРСТАН ЛЕСНАЯ 18

Что-то такое-же уже было. =)

644103 ОМСК 103 3 МАТЕРИАЛЬНЫЙ ПЕР 45

644103 ОМСК 3 МАТЕРИАЛЬНЫЙ ПЕР 45

Нельзя потерять 3, она относится к улице

431451 РУЗАЕВКА 11 ШКОЛЬНЫЙ БУЛЬВАР Д 2 Б КВ 27

431451 РУЗАЕВКА ШКОЛЬНЫЙ БУЛЬВАР Д 2 Б КВ 27

Есть и хитрые номера отделений, они состоят из двух цифр (всегда), причём последняя совпадает с последней цифрой индекса, а первая с предпоследней не совпадает.

666793 УСТЬ-КУТ 13 ИРКУТСКАЯ ОБЛ УЛ ПУШКИНА 113 КВ 65

666793 УСТЬ-КУТ ИРКУТСКАЯ ОБЛ УЛ ПУШКИНА 113 КВ 65

Аналогично.

347042 БЕЛАЯ КАЛИТВА 2 ЭНГЕЛЬСА 42 КВ. 20

347042 БЕЛАЯ КАЛИТВА ЭНГЕЛЬСА 42 КВ. 20

Нельзя потерять 42

344079 РОСТОВ-НА-ДОНУ 79 ПРОФИНТЕРНА 79 КВ,60

344079 РОСТОВ-НА-ДОНУ ПРОФИНТЕРНА 79 КВ,60

Нельзя потерять 79

344079 РОСТОВ-НА-ДОНУ 39 ПРОФИНТЕРНА 79 КВ,60

344079 РОСТОВ-НА-ДОНУ ПРОФИНТЕРНА 79 КВ,60

Нельзя потерять 79

644011 ПРОЕЗД 7 ТЮКАЛИНСКИЙ, ДОМ 7,ГОРОД ОМСК, 644011

644011 ПРОЕЗД 7 ТЮКАЛИНСКИЙ, ДОМ 7,ГОРОД ОМСК

В конце может стоять копия индекса

141006 МЫТИЩИ 6 ОЛИМПИЙСКИЙ ПР-Т 18, 1410

141006 МЫТИЩИ ОЛИМПИЙСКИЙ ПР-Т 18

Копия может быть не полной, а содержать, например, 4 первых цифры индекса

141006 МЫТИЩИ 6 ОЛИМПИЙСКИЙ ПР-Т 18, 141

141006 МЫТИЩИ ОЛИМПИЙСКИЙ ПР-Т 18

...или даже три

141006 МЫТИЩИ 6 ОЛИМПИЙСКИЙ ПР-Т 18, КВ. 141

141006 МЫТИЩИ ОЛИМПИЙСКИЙ ПР-Т 18, КВ. 141

Но если перед конечной цифрой стоит "КВ.", это квартира

141006 МЫТИЩИ 6 ОЛИМПИЙСКИЙ ПР-Т 18, КВ 141

141006 МЫТИЩИ ОЛИМПИЙСКИЙ ПР-Т 18, КВ 141

...или "КВ"

141006 МЫТИЩИ 6 ОЛИМПИЙСКИЙ ПР-Т 18, КВД 141

141006 МЫТИЩИ ОЛИМПИЙСКИЙ ПР-Т 18, КВД

...а КВД - не квартира =)

Результирующие адреса могут отличаться от требуемых в таблице, но незначительно. То есть если в эталоне один пробел, а получилось два - это нормально. А вот терять точки и запятые - неправильно. Можно добавлять запятые, но только в правильных местах.

В таблице приведены, скажем так, шаблоны косяков. Не надо закладываться на конкретные цифры. Если при изменении какой-нибудь циферки в адресе, которое подходит по шаблону, правило перестанет работать, это неправильно.

Во избежание дополнительных вопросов будем считать, что нормальные адреса не могут быть похожи на те, которые приведены в задаче. =)

Пример оформления

1. Заменить слово ПЛОХО на слово ХОРОШО, если не содержится подстрока НЕ ТРОГАТЬ или ТАК НАДО:

regexp — ^(.)ПЛОХО(.)$ replacement — $1ХОРОШО$ exception — ^.(НЕ ТРОГАТЬ|ТАК НАДО).$

2. Заменить …

Как проверять себя

  1. Написали список правил

  2. Взяли список исходных адресов, скопировали себе куда-то, в блокнот, например

  3. Применили ко всему списку правило 1

  4. Применили ко всему списку правило 2

  5. ...

  6. Применили последнее правило (ко всему списку, уже N раз измененному)

  7. Сверили результат с колонкой «Что надо получить», обращая внимание на комментарии. Ничего не потерялось?

  8. Если потерялось / испортилось, то находим баг в регулярках, исправляем, и повторяем все шаги с самого начала =)