Подходим перестановки!


15

Ваша задача - создать регулярное выражение, соответствующее каждой перестановке строк, и ничего больше. Соответствие также должно учитывать регистр.

Так, например, если ваше регулярное выражение:

ABC

Он должен соответствовать (и только соответствовать) этим строкам:

ABC
ACB
BAC
BCA
CAB
CBA

Это не должно соответствовать вещам как:

AABC (contains an extra A)
ABCD (contains an extra D)
AC   (no B)
AAA  (no B and C, extra 2 A's)
abc  (case-sensitive)

Правила:

  • Вам разрешено использовать любой вкус регулярных выражений, который вам нравится.
  • Применяются стандартные лазейки.
  • В вашем коде должно быть как минимум два разных символа. Это означает, что такие решения 1являются недействительными.
  • Регулярное выражение должно содержать только печатный ASCII и ничего больше.


Также связано:
Количество

Я думал, (ABC|ACB|BAC|BCA|CAB|CBA)но вы хотели обобщенный ответ.
Стивен Куан

Ответы:


11

JavaScript, 64 57 байт

4 байта удалено благодаря Мартину Эндеру.

^(?!.*([^])(.*\1){3}]?)[$$[-^?!!.'''-*11{33}5577\\-]{57}$

Попробуй это здесь.

Пояснения (устаревшие)

^                                  # Beginning of the string.
(?!.*                              # Match only the strings that don't contain...
  (.)(.*\1){4}                     #     5 occurrences of the same character.
  [^1]?[^1]?                       #     Something that doesn't matter.
)
[]zzz^(?!!!.**[)\\1{{44}}666]{64}  # 64 occurrences of these 16 characters.
                                   # Some are duplicated to make sure the regex
                                   # contains 4 occurrences of each character.
\z                                 # End of the string.

2
Я думаю, что это работает для 60: ^(?!.*(\S)(.*\1){3}[^1]?)[]zzSS[-^?!!.'''-*1{33}0066-]{60}\z regex101
Мартин Эндер

Это почти работает в .NET:^(?'4'(?!(.*\4){3})[]$$[\\^^?!!..'-*{}33-5-]){54}$[5]*
jimmy23013

Что не работает? Трейлинг перевода строки?
Мартин Эндер

@MartinEnder Да.
jimmy23013

2

Регулярные выражения Perl и PCRE, 280 байт

^(?=(.*z){2})(?=(.*\(){43})(?=(.*\)){43})(?=(.*\*){22})(?=(.*\.){23})(?=(.*0){2})(?=(.*1){6})(?=(.*2){16})(?=(.*3){7})(?=(.*4){4})(?=(.*5){1})(?=(.*6){3})(?=(.*7){2})(?=(.*8){2})(?=(.*9){1})(?=(.*=){22})(?=(.*\?){22})(?=(.*\\){11})(?=(.*\^){2})(?=(.*\{){23})(?=(.*\}){23}).{280}\z

(Чуть) более читабельно:

^
(?=(.*z){2})
(?=(.*\(){43})
(?=(.*\)){43})
(?=(.*\*){22})
(?=(.*\.){23})
(?=(.*0){2})
(?=(.*1){6})
(?=(.*2){16})
(?=(.*3){7})
(?=(.*4){4})
(?=(.*5){1})
(?=(.*6){3})
(?=(.*7){2})
(?=(.*8){2})
(?=(.*9){1})
(?=(.*=){22})
(?=(.*\?){22})
(?=(.*\\){11})
(?=(.*\^){2})
(?=(.*\{){23})
(?=(.*\}){23})
.{280}\z

Это выполняется за O (2 ^ n) времени, как написано, поэтому невероятно неэффективно. Самый простой способ проверить это, чтобы заменить каждое вхождение .*с .*?, что вызывает тот случай , когда он соответствует , чтобы проверить первое ( что означает , что он соответствует в линейное время, но по- прежнему занимает экспоненциальное время , если оно не совпадает).

Основная идея состоит в том, что мы устанавливаем длину регулярного выражения равной 280, и используем косвенные утверждения, чтобы каждый символ в регулярном выражении появлялся по крайней мере определенное количество раз, например, (?=(.*z){2})заставляет zсимвол появляться по крайней мере дважды. 2+43+43+22+23+2+6+16+7+4+1+3+2+2+1+22+22+11+2+23+23равно 280, поэтому у нас не может быть никаких «лишних» вхождений каких-либо символов.

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

Perl и PCRE regex, 253 байта, в сотрудничестве с Мартином Эндером

Я предположил, что могут быть более короткие решения, в которых пропущены некоторые цифры (скорее всего, 9, 8 или 7). Мартин Эндер нашел один, показанный ниже:

^(?=(.*z){2})(?=(.*\(){39})(?=(.*\)){39})(?=(.*\*){20})(?=(.*\.){21})(?=(.*0){4})(?=(.*1){6})(?=(.*2){11})(?=(.*3){6})(?=(.*4){3})(?=(.*5){2})(?=(.*6){3})(?=(.*9){4})(?=(.*=){20})(?=(.*\?){20})(?=(.*\\){9})(?=(.*\^){2})(?=(.*{){21})(?=(.*}){21}).{253}\z

Читаемая версия:

^
(? = (. * Г) {2})
(? = (. * \ () {39})
(? = (. * \)) {39})
(? = (. * \ *) {20})
(? = (. * \.) {21})
(? = (. * 0) {4})
(? = (. * 1) {6})
(? = (. * 2) {11})
(? = (. * 3) {6})
(? = (. * 4) {3})
(? = (. * 5) {2})
(? = (. * 6) {3})
(? = (. * 9) {4})
(? = (. * =) {20})
(? = (. * \?) {20})
(? = (. * \\) {9})
(? = (. * \ ^) {2})
(? = (. * {) {21})
(? = (. *}) {21})
. {253} \ г

Я не думаю, что вам нужно избегать тех, кто {}в последних двух взглядах. Вам также не нужно добавлять такие вещи, как, (?=(.*5){1})потому что не было бы, 5если бы у вас не было этого взгляда. Одна из проблем заключается в том, что $допускается завершающий перевод строки, поэтому вам нужно использовать \zего вместо того, $как это делал Джимми, но я думаю, что это не будет стоить вам байта, поскольку вы сохраняете его \в первом запросе.
Мартин Эндер

Я знаю, что можно опустить такие вещи, как цифры. Тем не менее, они там, чтобы заставить работать автограмму . Удаление любой части программы приведет к поломке всего остального, потому что она больше не описывает программу правильно. (Счетчики для каждой строки подсчитывают счетчики для каждой строки! Таким образом, в общем случае в принципе невозможно изменить программу.) Что касается $разрешения новой строки в конце строки, это обычно зависит от того, как регулярное выражение вызывается окружающим программа (обычно они выполняются на коде, который уже разбит на строки).

Или, если быть более точным: мне нужно (?=(.*5){1})в этом случае. Если бы я удалил его, в программе было бы 5, потому (?=(.*1){6})что теперь строка должна была бы прочитать (?=(.*1){5}).

Что касается конечного перевода строки, то в вызове нет никаких ограничений по типу ввода в ваше регулярное выражение, так что обычно это означает, что он должен работать для любой строки, и переход $на \zне приносит никакого вреда (и не не ломай автограмму).
Мартин Эндер

А ну понятно; вы изменить \$... $к z... \z. Это работает; Я пойду поменяю это.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.