Dopasuj permutacje!

15

Wyzwanie polega na utworzeniu wyrażenia regularnego pasującego do każdej permutacji ciągu znaków i nic więcej. W dopasowaniu należy również rozróżniać małe i wielkie litery.

Na przykład jeśli wyrażenie regularne to:

ABC

Powinien pasować (i tylko pasować) następujące ciągi:

ABC
ACB
BAC
BCA
CAB
CBA

Nie powinno pasować do takich rzeczy jak:

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)

Zasady:

  • Możesz używać dowolnego smaku wyrażenia regularnego, który ci się podoba.
  • Obowiązują standardowe luki.
  • Musisz mieć co najmniej dwa różne znaki w kodzie. Oznacza to, że takie rozwiązania 1są nieprawidłowe.
  • Wyrażenie regularne powinno zawierać tylko ASCII do wydruku i nic więcej.
clismique
źródło
Powiązane również: Liczba znaków w kodzie źródłowym
jimmy23013
Myślałem, (ABC|ACB|BAC|BCA|CAB|CBA)ale chciałeś uogólnionej odpowiedzi.
Stephen Quan

Odpowiedzi:

11

JavaScript, 64 57 bajtów

4 bajty usunięte dzięki Martinowi Enderowi.

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

Wypróbuj tutaj.

Objaśnienia (nieaktualne)

^                                  # 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.
jimmy23013
źródło
2
Myślę, że to działa na 60: ^(?!.*(\S)(.*\1){3}[^1]?)[]zzSS[-^?!!.'''-*1{33}0066-]{60}\z regex101
Martin Ender
To prawie działa w .NET:^(?'4'(?!(.*\4){3})[]$$[\\^^?!!..'-*{}33-5-]){54}$[5]*
jimmy23013
Co nie działa? Końcowe podawanie linii?
Martin Ender,
@MartinEnder Tak.
jimmy23013
2

Wyrażenia regularne Perl i PCRE, 280 bajtów

^(?=(.*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

(Nieco) bardziej czytelny:

^
(?=(.*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

Działa to w czasie O (2 ^ n), jak napisano, więc jest niezwykle nieefektywne. Najprostszym sposobem, aby go przetestować ma zastąpić wszystkie wystąpienia .*z .*?, co powoduje sytuację, w której to pasuje do sprawdzenia pierwszy (co oznacza, że mecze w czasie liniowym, ale nadal trwa wykładniczą czasu, jeżeli nie pasuje).

Podstawową ideą jest to, że wymuszamy długość wyrażenia regularnego równego 280 i używamy twierdzeń typu lookahead, aby zmusić każdy znak w wyrażeniu regularnym do pojawienia się co najmniej pewną liczbę razy, np. (?=(.*z){2})Zmusza zpostać do pojawienia się co najmniej dwa razy. 2+43+43+22+23+2+6+16+7+4+1+3+2+2+1+22+22+11+2+23+23wynosi 280, więc nie możemy mieć żadnych „dodatkowych” wystąpień żadnych znaków.

To jest przykład programowania autogramu , zdanie, które opisuje się, wymieniając liczbę każdego znaku, który zawiera (a w tym przypadku także całkowitą długość). Miałem dość szczęścia w jego tworzeniu (zwykle musisz użyć brutalnej siły, ale natknąłem się na to rozwiązanie podczas testowania mojego programu brutalnej siły, zanim w pełni go napisałem).

Wyrażenia regularne Perl i PCRE, 253 bajty, we współpracy z Martinem Enderem

Postawiłem hipotezę, że mogą istnieć krótsze rozwiązania pomijające niektóre cyfry (najprawdopodobniej 9, 8 lub 7). Martin Ender znalazł taki, pokazany poniżej:

^(?=(.*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

Wersja do odczytu:

^
(? = (. * 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

źródło
Nie sądzę, że musisz uciec przed tymi {}z ostatnich dwóch lat. Nie musisz też dodawać takich rzeczy, (?=(.*5){1})ponieważ nie byłoby 5, gdybyś nie miał tego spojrzenia w przyszłość. Jednym z problemów jest to, że $zezwala na końcowe podawanie linii, więc musisz użyć go \zzamiast $jak Jimmy, ale myślę, że to nie będzie kosztować bajtu, ponieważ zapisujesz go \w pierwszym spojrzeniu.
Martin Ender,
Wiem, że można pominąć cyfry. Są jednak po to, aby uruchomić autogram . Usunięcie dowolnej części programu spowoduje uszkodzenie całej reszty, ponieważ nie opisuje już poprawnie programu. (Liczby dla każdej linii liczą liczby dla każdej linii! W związku z tym zmiana programu jest zasadniczo niemożliwa.) Jeśli chodzi o $zezwolenie na nową linię na końcu łańcucha, to na ogół zależy od tego, jak regex jest wywoływany przez otaczające program (zwykle są uruchamiane na kodzie, który został już parsowany na linie).
A ściślej: potrzebuję tego (?=(.*5){1})w tym przypadku. Gdybym go usunął, w programie byłoby 5, ponieważ (?=(.*1){6})linia musiałaby teraz czytać (?=(.*1){5}).
Jeśli chodzi o końcowy feed line, wydaje się, że nie ma żadnych ograniczeń w wyzwaniu dotyczącym rodzaju danych wejściowych do wyrażenia regularnego, więc zwykle oznacza to, że powinien on działać dla dowolnego łańcucha, a zmiana $na \znie powoduje żadnej szkody (i nie złamać autogram).
Martin Ender
Rozumiem; zmieniasz \$$na z\z. To działa; Pójdę to zmienić.