Problem
Mam kilka wyrażeń regularnych, których muszę użyć w jakimś kodzie, ale używam języka programowania, który nie obsługuje wyrażeń regularnych! Na szczęście wiem, że łańcuch testowy będzie miał maksymalną długość i będzie się składał wyłącznie z drukowalnego ASCII.
Wyzwanie
Musisz wprowadzić wyrażenie regularne i liczbę n
oraz wypisać każdy ciąg złożony z drukowalnego ASCII (kody ASCII od 32 do 126 włącznie, do
~
, bez tabulatorów lub znaków nowej linii) o długości mniejszej lub równej n
tej pasującej do tego wyrażenia regularnego. Nie możesz w ogóle używać wbudowanych wyrażeń regularnych ani funkcji dopasowywania wyrażeń regularnych w kodzie. Wyrażenia regularne będą ograniczone do następujących:
- Dosłowne znaki (i znaki ucieczki, które zmuszają znak do bycia dosłownym, więc
\.
jest dosłowny.
,\n
jest dosłownyn
(równoważny tylkon
) i\w
jest równoważnyw
. Nie trzeba obsługiwać sekwencji specjalnych). .
- znak wieloznaczny (dowolny znak)- Klasy znaków
[abc]
oznaczają „a lub b lub c” i[d-f]
oznaczają wszystko od d do f (tak, d lub e lub f). Jedynymi znakami, które mają specjalne znaczenie w klasie znaków są[
i]
(które zawsze będą ucieczką, więc nie przejmuj się nimi),\
(oczywiście znak ucieczki)^
na początku klasy postaci (co jest negacją ) i-
(który jest zakresem). |
- operator OR, przemiennie.foo|bar
oznacza jednofoo
lubbar
i(ab|cd)e
zapałki alboabe
albocde
.*
- dopasuj poprzedni token powtórzony zero lub więcej razy, chciwy (próbuje powtórzyć tyle razy, ile to możliwe)+
- powtórzył jeden lub więcej razy, zachłanny?
- zero lub jeden raz- Grupowanie w nawiasach na żetony grupowych
|
,*
.+
lub?
Regex wejście zawsze będzie poprawny (tzn nie trzeba obsługiwać wejście jak ?abc
lub (foo
czy każdy nieważny wejścia). Możesz wyprowadzać ciągi w dowolnej kolejności, ale każdy ciąg musi pojawić się tylko raz (nie wysyłaj żadnych duplikatów).
Przypadki testowe
Wejście: .*
, 1
Wyjście: (pusty ciąg znaków), ,
!
, "
, ..., }
,~
Wejście: w\w+
, 3
Wyjście: ww
,www
Wejście: [abx-z][^ -}][\\]
, 3
Wyjście: a~\
, b~\
, x~\
, y~\
,z~\
Wejście: ab*a|c[de]*
, 3
Wyjście: c
, cd
, ce
, aa
, cde
, ced
, cdd
, cee
,aba
Wejście: (foo)+(bar)?!?
, 6
Wyjście: foo
, foo!
, foofoo
,foobar
Wejście: (a+|b*c)d
, 4
Wyjście: ad
, cd
, aad
, bcd
, aaad
,bbcd
Wejście: p+cg
, 4
Wyjście: pcg
,ppcg
Wejście: a{3}
, 4
Wyjście:a{3}
Zwycięzca
To jest golf golfowy , więc wygra najkrótszy kod w bajtach!
|
ma większego sensu. Nie obsługuje grup zagnieżdżonych ania|b|c
. Co jest złego w korzystaniu ze standardowych wyjaśnień dotyczących silnego wiązania konkatenacji i naprzemienności? (I nie masz wytłumaczenia, że nie używasz piaskownicy)Odpowiedzi:
Haskell
757 705 700 692 679667wynik:
Objaśnienie: jest to implementacja regex podręcznika. R jest typem wyrażenia regularnego z konstruktorami A (alternatywny), L (literał), T (wtedy) i E (pusty / epsilon). Zwykła „Gwiazdka” nie pojawia się, ponieważ wstawiam ją na przemian podczas analizy (patrz „%”). „m” uruchamia symulację. Analizator składni (start o 'rs = ....') jest po prostu rekurencyjnym zejściem; „k” analizuje zakresy. Funkcja „#” rozszerza zakresy na przemian.
źródło
Python v2.7
10691036950925897884871833822Ta odpowiedź wydaje się dość długa jak na golfa kodowego, ale jest wielu operatorów, z którymi trzeba sobie poradzić i wiem, jaki jest cel każdego bajtu w tej odpowiedzi. Ponieważ nie ma żadnej odpowiedzi, przesyłam ją jako cel do pokonania przez innych użytkowników. Sprawdź, czy możesz zrobić krótszą odpowiedź :).
Dwie główne funkcje to:
f
analizowanie wyrażenia regularnego rozpoczynającego się odi
litery th id
generowanie pasujących ciągów znaków, używającr
podrzędnych wyrażeń regularnych, w których możemy się powtarzać, „tablica” reprezentująca część bieżącego wyrażenia regularnego, która nie została jeszcze przetworzona, oraz sufiks łańcucha,s
który reprezentuje część łańcucha wygenerowanego do tej pory.Sprawdź także wyjście próbki i uprząż testową .
Zauważ, że karty w oryginalnym rozwiązaniu zostały
expand
edytowane. Aby policzyć liczbę znaków w pierwotnym użyciuunexpand < regex.py | wc
.źródło
def E(a,b):c=a[:];c.extend(b);return c
na toE=lambda a,b:a[:].extend(b)
samoA
elif isinstance(e,str):
wierzę, można zmienić wnętrze identyfikacyjny:exec{'.':'for c in C:d(r,p,s+chr(c))','?':'d(r,p,s);d(r,p[:z],s)','*':'''c=p[:z]#newline for i in R(0,n+1):d(r,c,s);c+=[p[z]]''','+':"d(r,p+['*',p[z]],s)",'\\':'d(r,p,e[1]+s)'}.get(e,'d(r,p,e+s)')
(Zauważ, że#newline
jest to znak nowej linii) (źródło: stackoverflow.com/a/103081/1896169 )Prolog (SWI) , 586 bajtów
Wbudowana zdolność cofania się Prologa sprawia, że jest to świetny wybór do tego wyzwania. Korzystając z cofania, generowanie ciągów dla wyrażenia regularnego staje się dokładnie tym samym zadaniem, co sprawdzanie, czy ciąg jest dopasowywany przez wyrażenie regularne. Niestety, większość moich wysiłków w golfa polegało na napisaniu krótszych parserów wyrażeń regularnych. Właściwe zadanie polegające na rozłożeniu wyrażenia regularnego z łatwością graliśmy w golfa.
Wypróbuj online!
Kod niepoznany
źródło
regex_union(RE, RC, [])
pasuje doregex_union(R) -->...
?phrase\2
. Pierwszy to ciąg, do którego stosuje się DCG, a drugi to jakiś przyrostek, który pozostaje po spełnieniu predykatu DCG. Byłby to odpowiednikphrase(regex_union(RE), RC)
.