Duct Tape Decex Decider

11

Twoim zadaniem jest stworzenie programu, który określa, czy dany ciąg jest prawidłowym wyrażeniem regularnym, czy też nie używa fragmentów kodu pochodzących z witryn w sieci StackExchange.

Dla celów tego wyzwania, dialekt wyrażenie regularne będzie okrojona i przeważnie minimalny zestaw meta-znaki: ()*?|\. W związku z tym nie będzie można używać wbudowanych analizatorów wyrażeń regularnych.

  • \służy do ucieczki od meta-znaków. Po nim musi być meta-znak.
  • Nierozpoznane nawiasy muszą być zrównoważone
  • *i ?musi być poprzedzony albo niemeta-znakiem, grupą w nawiasach okrągłych lub meta-znakiem ucieczki.
  • Wszystkie inne drukowalne znaki ASCII oraz znak nowej linii, tabulator i spacja muszą być obsługiwane jako znaki niemeta. To, co dzieje się z ciągiem zawierającym inne znaki, jest niezdefiniowane.
  • Rzeczywiste znaczenie wyrażenia regularnego nie jest ważne dla tego wyzwania.

Przykłady

Truthy:
  abc
  a?
  (a|)*
  ()
  a|b*
  \*
  \\
  \\*
  a*b?(cd|e)
  +
  [
  }
  (123\))*
  \|
  (a(b(c|d)*e)*f)*
  (|\)*)
  (abc)+*
  (abc)+
  +abc

^ last test case is an actual newline

Falsy:
  ?abc
  *
  **
  \
  (
  a*?
  a?*
  ?
  a)
  (\)
  (|\)*
  \()
  |*
  (?:abc)
  \\**
  \n

Punktacja

Twój ogólny wynik to liczba urywków z pytań i odpowiedzi dotyczących StackExchange.

  • Powtarzane fragmenty liczą się tyle razy, ile są używane.
  • Białe spacje można dowolnie dodawać i usuwać (z powodu języka Python, Haskell i innych języków wrażliwych na spacje) i nie są wliczane do liczby urywków.
    • Wyjątkiem byłby fakt, że kod jest rzeczywiście napisany w białej spacji .
  • Fragmenty są dozwolone z dowolnej witryny StackExchange, o ile pochodzą one z pytań, odpowiedzi i komentarzy starszych (w tym według czasu edycji - w razie potrzeby użyj starszych wersji) niż to wyzwanie. (24 września 2019 o 15:30 UTC)
  • Fragmenty mogą pochodzić z dowolnego miejsca w treści pytania, odpowiedzi lub komentarza, niezależnie od tego, czy znajdują się we wstępnie sformatowanym bloku kodu, czy nie.
  • Łączenie fragmentu w środku innego powoduje, że fragment zewnętrzny liczy się jako dwa fragmenty

Najniższy wynik wygrywa!

Wołowina
źródło
1
@RobinRyder tak, zmieniono
Beefster
Czy post może być starszy lub równy temu wyzwaniu, tzn. Czy możemy użyć fragmentów z tego wyzwania?
Jo King
1
„W związku z tym nie będziesz mógł używać wbudowanych parserów wyrażeń regularnych” Czy to znaczy, że jest zaprojektowany tak, aby udaremnić używanie go przez zwykłe tak / nie, czy też w ogóle nie wolno nam używać wyrażeń regularnych w naszych odpowiedziach?
user0721090601
@ guifa jest zaprojektowany tak, że nie możesz po prostu wziąć silnika wyrażeń regularnych języka i sprawdzić, czy skompiluje dany wyrażenie regularne. Każdy język, który znam, obsługuje większy zestaw metaznaków i wyspecjalizowane grupy przechwytywania, więc nie pasują one poprawnie do tego zestawu znaków we wszystkich przypadkach.
Beefster,
1
@ JL2210 To sprawi, że będą to dwa fragmenty: jeden na początek, a drugi na koniec. Można użyć pojedynczego fragmentu tak długo, jak to przechodzi wszelkie przypadki testowe i pochodzi z odpowiedzią / pytanie / post, który jest starszy niż to wyzwanie
Beefster

Odpowiedzi:

6

Perl 6 , 20 urywków

{$_ eq m/[[<-[()*?|\\]>|\\<[()*?|\\]>|'(' <~~>* ')']<[*?]>?|\|]+/}

Wypróbuj online!

Fragmenty pochodzą z:

{$_ eq, m/[, <-[, ()*?, |\\, ]>, |\\, <[, ()*?, |\\, ]>, |, '(' <~~>* ')', <[, *?, ]>, ?|, \|, ]+/, }.

Jest to głównie podejście zachłanne (widoczne przez wszystkie fragmenty jednego lub dwóch znaków). Użyłem SymbolHound do wyszukiwania pojedynczych znaków, a jedyną prawdziwą optymalizacją był '(' <~~>* ')'fragment kodu , który pochodzi z mojej własnej odpowiedzi na rekurencyjne wyrażenia regularne Perla 6.

Wyjaśnienie:

To w zasadzie sprawdza, czy dane wejściowe są równe zachłannemu dopasowaniu prawidłowego wyrażenia regularnego. Nie możemy po prostu użyć samego wyrażenia regularnego i dodać ^$do oznaczenia końców, ponieważ używamy wyrażenia regularnego, które nie działałoby, gdyby istniały ^$znaczniki. Sam regex to:

m/[                             ]+/   # Match one or more times
   [              ]  # Any of 
    <-[()*?|\\]> |     # Not a metacharacter
    \\<[()*?|\\]>      # A metacharacter preceded by a \
    '(' <~~>* ')'      # Brackets surrounding a valid regex
                   <[*?]>?  # Optionally followed by a ? or *
                           | \|    # Or just the | metacharacter
Jo King
źródło
TIL ~~, dzięki!
user0721090601
@ guifa Tak, nauczyłem się tego dzięki specyfikacji P6 , która zawiera wiele rzeczy, które nie zostały jeszcze odpowiednio udokumentowane. Podejrzewam, ~~że nie pojawia się, ponieważ nie jest jeszcze w pełni zaimplementowany (na przykład <~~0>), chociaż są tam inne ukryte klejnoty.
Jo King,