रिवर्स में रेगेक्स - नियमित अभिव्यक्ति विघटित


18

समस्या

मेरे पास नियमित अभिव्यक्ति का एक गुच्छा है जिसे मुझे कुछ कोड में उपयोग करने की आवश्यकता है, लेकिन मैं एक प्रोग्रामिंग भाषा का उपयोग कर रहा हूं जो रेगेक्स का समर्थन नहीं करता है! सौभाग्य से, मुझे पता है कि परीक्षण स्ट्रिंग की अधिकतम लंबाई होगी और केवल मुद्रण योग्य ASCII से बना होगा।

चुनौती

आपको एक regex और एक नंबर इनपुट करना चाहिए n, और मुद्रण योग्य ASCII (ASCII कोड 32 से 126 समावेशी, से ~, कोई टैब या newlines) से बना हर स्ट्रिंग जो nउस रेगेक्स से मेल खाता है या उससे कम नहीं है । आप अपने कोड में बिल्ट-इन रेगुलर एक्सप्रेशन या रेगेक्स मैचिंग फंक्शन का इस्तेमाल बिलकुल नहीं कर सकते । नियमित अभिव्यक्तियाँ निम्नलिखित तक सीमित रहेंगी:

  • शाब्दिक वर्ण (और बच जाते हैं, जो एक चरित्र को शाब्दिक होने के लिए मजबूर करते हैं, इसलिए \.एक शाब्दिक है ., \nएक शाब्दिक है n(केवल के बराबर n), और \wइसके बराबर है w। आपको भागने के दृश्यों का समर्थन करने की आवश्यकता नहीं है।)
  • . - वाइल्डकार्ड (कोई भी वर्ण)
  • चरित्र वर्ग, का [abc]अर्थ है "ए या बी या सी" और [d-f]इसका मतलब डी से लेकर एफ (इसलिए, डी या ई या एफ) है। केवल चरित्र वर्ग में विशेष अर्थ रखने वाले हैं [और ](जो हमेशा बच जाएंगे, इसलिए उन लोगों के बारे में चिंता न करें), \(चरित्र का पलायन), निश्चित रूप ^से, चरित्र वर्ग की शुरुआत में (जो एक नकारात्मकता है) ), और -(जो एक सीमा है)।
  • |- OR ऑपरेटर, अल्टरनेशन। या foo|barतो fooया का मतलब है bar, या (ab|cd)eमेल खाता है abeया cde
  • * - पिछले टोकन को दोहराए गए शून्य या अधिक बार मैच करें, लालची (यह यथासंभव कई बार दोहराने की कोशिश करता है)
  • + - एक या एक से अधिक बार, लालची दोहराया
  • ? - शून्य या एक बार
  • कोष्ठकों के साथ समूहन, के लिए समूह टोकन के लिए |, *+, या?

इनपुट regex हमेशा मान्य होगा (यानी, आप की तरह इनपुट संभाल करने की जरूरत नहीं है ?abcया (fooया किसी अमान्य इनपुट)। आप किसी भी क्रम में स्ट्रिंग्स को आउटपुट कर सकते हैं, लेकिन प्रत्येक स्ट्रिंग को केवल एक बार दिखाई देना चाहिए (किसी भी डुप्लिकेट को आउटपुट न करें)।

टेस्ट मामलों

इनपुट: .*, 1
आउटपुट: (रिक्त स्ट्रिंग), , !, ", ..., },~

इनपुट: w\w+, 3
आउटपुट: ww,www

इनपुट: [abx-z][^ -}][\\], 3
आउटपुट: a~\, b~\, x~\, y~\,z~\

इनपुट: ab*a|c[de]*, 3
आउटपुट: c, cd, ce, aa, cde, ced, cdd, cee,aba

इनपुट: (foo)+(bar)?!?, 6
आउटपुट: foo, foo!, foofoo,foobar

इनपुट: (a+|b*c)d, 4
आउटपुट: ad, cd, aad, bcd, aaad,bbcd

इनपुट: p+cg, 4
आउटपुट: pcg,ppcg

इनपुट: a{3}, 4
आउटपुट:a{3}

विजेता

यह , इसलिए बाइट्स में सबसे छोटा कोड जीत जाएगा!


क्या हमें भागने के दृश्यों का समर्थन करने की अनुमति है? फिर यह तुच्छ है।
जॉन ड्वोरक

3
आपकी व्याख्या |बहुत कम समझ में आती है। यह नेस्टेड समूहों को संभालने के लिए प्रतीत नहीं होता है या a|b|c। मानक स्पष्टीकरण का उपयोग करने के मामले में क्या गलत है कितना दृढ़ता से और वैकल्पिक रूप से बांधना? (और आपके पास सैंडबॉक्स का उपयोग न करने के लिए कोई बहाना नहीं है)
पीटर टेलर

1
@PeterTaylor वास्तव में, उनके पास एक बहाना है: meta.codegolf.stackexchange.com/q/1305/9498
जस्टिन

2
अपने परीक्षा पैटर्न से देखते हुए पूरे स्ट्रिंग से मेल खाना है? (एक विकल्प के विपरीत)
मार्टिन एंडर

3
@KyleKanos यह एक शर्म की बात है कि वास्तविक दुनिया की समस्याएं आपको यह नहीं बताती हैं कि आपको नियमित अभिव्यक्ति सीखने की ज़रूरत है। : P लेकिन वे उतने दुर्गम नहीं हैं जितने कि वे लग सकते हैं: regular-expressions.info/tutorial.html
मार्टिन

जवाबों:


8

हास्केल 757 705 700 692 679 667

import Data.List
data R=L Char|A R R|T R R|E
h=[' '..'~']
k(']':s)a=(a,s)
k('^':s)_=l$k[]s
k('-':c:s)(a:b)=k([a..c]++b)s
k('\\':c:s)a=k s$c:a
k(c:s)a=k s$c:a
l(a,b)=(h\\a,b)
c#E=L c
c#r=A(L c)r
o(a,b)=(foldr(#)E a,b)
t%0=E
t%n=A(t%(n-1))$T t$t%(n-1)
d s n=m(fst$r s)[[]] where{m E a=a;m(L c)a=[b++[c]|b<-a,length b<n];m(A r s)x=nub$(m r x)++m s x;m(T r s)a=m s$m r a;r s=w$e s E;w(u,'|':v)=(\(a,b)->(A u a,b))$r v;w x=x;e(')':xs)t=(t,xs);e s@('|':_)t=(t,s);e s@(c:_)t=g t$f$b s;e[]t=(t,[]);g t(u,v)=e v$T t u;f(t,'*':s)=(t%n,s);f(t,'+':s)=(T t$t%n,s);f(t,'?':s)=(A t E,s);f(t,s)=(t,s);b('(':s)=r s;b('\\':s:t)=(L s,t);b('.':s)=o(h,s);b('[':s)=o$k s[];b(s:t)=(L s,t)}

उत्पादन:

ghci> d ".*" 1
[""," ","!","\"","#","$","%","&","'","(",")","*","+",",","-",".","/","0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?","@","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","[","\\","]","^","_","`","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","{","|","}","~"]
ghci> d "w\\w+" 3
["ww","www"]
ghci> d "[abx-z][^ -}][\\\\]" 3
["x~\\","y~\\","z~\\","b~\\","a~\\"]
ghci> d "ab*a|c[de]*" 3
["aa","aba","c","ce","cd","cee","cde","ced","cdd"]
ghci> d "(foo)+(bar)?!?" 6
["foo!","foobar","foo","foofoo"]
ghci> d "(a+|b*c)d" 4
["ad","aad","aaad","cd","bcd","bbcd"]
ghci> d "p+cg" 4
["pcg","ppcg"]
ghci> d "a{3}" 4
["a{3}"]

स्पष्टीकरण: यह एक पाठ्यपुस्तक रेगेक्स कार्यान्वयन है। आर रेगेक्स प्रकार है, जिसमें कंस्ट्रक्टर ए (वैकल्पिक), एल (शाब्दिक), टी (तब) और ई (खाली / एप्सिलॉन) है। सामान्य 'स्टार' दिखाई नहीं देता क्योंकि मैं इसे पार्स के दौरान विकल्प के रूप में इनलाइन करता हूं (देखें '%')। । म ’अनुकरण करता है। पार्सर ('आरएस = ....' पर शुरू) सिर्फ पुनरावर्ती वंश है; ranges के ’पारस पर्वतमाला। फ़ंक्शन '#' का विस्तार विकल्पों में होता है।


9

पायथन v2.7 1069 1036 950 925 897 884 871 833 822

यह जवाब एक कोड गोल्फ के लिए लंबा लगता है, लेकिन बहुत सारे ऑपरेटर हैं जिन्हें संभालने की आवश्यकता है और मुझे पता है कि इस उत्तर में प्रत्येक बाइट का क्या उद्देश्य है। चूंकि कोई मौजूदा जवाब नहीं है इसलिए मैं इसे अन्य उपयोगकर्ताओं को हरा देने के लिए एक लक्ष्य के रूप में प्रस्तुत करता हूं। देखें कि क्या आप कोई छोटा जवाब दे सकते हैं :)।

दो मुख्य कार्य हैं fजो iवें चरित्र पर शुरू होने वाले रेक्स को पार्स करते हैं , और dजो मिलान स्ट्रिंग्स को उत्पन्न करता है, rउप-रेगेक्स का उपयोग करके हम पुन: प्राप्त कर सकते हैं, 'a' वर्तमान उप-रेगेक्स के भाग का प्रतिनिधित्व करने वाला सरणी अभी तक संसाधित नहीं हुआ है, और एक स्ट्रिंग प्रत्यय sजो स्ट्रिंग के उस भाग का प्रतिनिधित्व करता है जो अब तक उत्पन्न होता है।

इसके अलावा नमूना उत्पादन और एक परीक्षण दोहन की जाँच करें

import sys;V=sys.argv;n=int(V[2]);r=V[1];S=len;R=range;C=R(32,127)
Z=[];z=-1;D='d(r,p,';F='for j in '
def f(i,a):
 if i>=S(r):return a,i
 c=r[i];x=0;I="|)]".find(c)
 if c in"([|":x,i=f(i+1,Z)
 if I+1:return([c,a,x],[a],[c,a])[I],i
 if'\\'==c:i+=1;x=c+r[i]
 return f(i+1,a+[x or c])
def d(r,a,s):
 if S(s)>n:return
 while a==Z:
        if r==Z:print s;return
        a=r[z];r=r[:z]
 e=a[z];p=a[0:z]
 if'|'==a[0]:d(r,a[1],s);d(r,a[2],s)
 elif']'==a[0]:
        g=a[1];N=g[0]=='^';g=(g,g[1:])[N];B=[0]*127;O=[ord(c[z])for c in g]
        for i in R(0,S(g)):
         if'-'==g[i]:exec F+'R(O[i-1],O[i+1]):B[j]=1'
         else:B[O[i]]=1
        for c in C:N^B[c]<1or d(r,Z,chr(c)+s)
 elif' '>e:d(r+[p],e,s)
 else:c=p[:z];exec{'.':F+'C:'+D+'chr(j)+s)','?':D+'s);d(r,p[:z],s)','*':F+'R(0,n+1):d(r,c,s);c+=[p[z]]','+':"d(r,p+['*',p[z]],s)"}.get(e,D+'e[z]+s)')
d(Z,f(0,Z)[0],"")

ध्यान दें कि मूल समाधान में टैब expandएड किया गया है । मूल उपयोग में वर्णों की संख्या की गणना करना unexpand < regex.py | wc


9
मैंने कभी नहीं अजगर नज़र देखा है कि भयानक।
user80551

आप नहीं बदल सकते हैं def E(a,b):c=a[:];c.extend(b);return cकरने के लिए E=lambda a,b:a[:].extend(b), डिट्टो के लिएA
user80551

स्पष्ट रूप से, जैसा कि .extend (b) कुछ भी वापस नहीं करता है।
gmatht

1
elif isinstance(e,str):मेरे अनुसार , मेरा मानना ​​है कि आप अंदर कोड बदल सकते हैं: 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)')(ध्यान दें कि #newlineयह एक नई पंक्ति है) (स्रोत: stackoverflow.com/a/103081/1896169 )
जस्टिन

1
यदि आप निष्पादन चाल का उपयोग करने के लिए अधिक स्थान पा सकते हैं, तो हम आसानी से आपके कोड को अपठनीय कोड में बदल सकते हैं :-)
जस्टिन

1

प्रोलोग (एसडब्ल्यूआई) , 586 बाइट्स

प्रोलॉग की बैकट्रैकिंग क्षमता में निर्मित यह इस चुनौती के लिए एक बढ़िया विकल्प है। बैकट्रैकिंग का लाभ उठाकर, रेगेक्स के लिए स्ट्रिंग्स जेनरेट करना बिल्कुल वैसा ही काम हो जाता है, जैसे अगर एक स्ट्रिंग रेगेक्स द्वारा मैच किया जाता है। दुर्भाग्य से, मेरे गोल्फ का अधिकतर प्रयास छोटे रेगेक्स पार्सर लिखने में चला गया। एक नियमित अभिव्यक्ति को डिकम्पोज करने का वास्तविक कार्य जिसे हम आसानी से करते हैं।

R-L-S:-R*A,-(B,A,[]),setof(Z,(0/L/M,length(C,M),C+B+[],Z*C),S).
-R-->e+S,S-R.
R-T-->{R=T};"|",e+S,u+R+S-T.
Z+Y-->(".",{setof(C,32/126/C,R)};"[^",!,\E,"]",{setof(C,(32/126/C,\+C^E),R)};"[",\R,"]";"(",-R,")";{R=[C]},([C],{\+C^`\\.[|+?*(`};[92,C])),("*",{S=k*R};"+",{S=c+R+k*R};"?",{S=u+e+R};{S=R}),({Y=c+Z+S};c+Z+S+Y).
\C-->{C=[H|T]},+H,\T;{C=[]};+A,"-",+B,\T,{setof(C,A/B/C,H),append(H,T,C)}.
+C-->[92,C];[C],{\+C^`\\]-`}.
S+e+S.
[C|S]+D+S:-C^D.
S+(B+L+R)+T:-B=c,!,S+L+U,U+R+T;S+L+T;S+R+T.
S+k*K+U:-S=U;S+K+T,S\=T,T+k*K+U.
A/B/C:-between(A,B,C).
A^B:-member(A,B).
A*B:-string_codes(A,B).

इसे ऑनलाइन आज़माएं!

अघोषित कोड

generate_string(R, L, S) :-
    % parse regex
    string_codes(R, RC),
    regex_union(RE, RC, []),

    % bound string length
    between(0, L, M),
    length(SC, M),

    % find string
    match(SC, RE, []),

    string_codes(S, SC).

% Parsers
%%%%%%%%%  

regex_union(R) -->regex_concat(S), regex_union1(S, R).

regex_union1(R,T) --> [124], regex_concat(S), regex_union1(regex_union(R,S), T).
regex_union1(R, R) --> [].

regex_concat(R) --> regex_op(S), regex_concat1(S, R).

regex_concat1(R, T) --> regex_op(S), regex_concat1(regex_concat(R,S), T).
regex_concat1(R, R) --> [].

regex_op(regex_kleene(R)) --> regex_lit(R), [42].
regex_op(regex_concat(R,regex_kleene(R))) --> regex_lit(R), [43].
regex_op(regex_union(regex_empty,R)) --> regex_lit(R), [63].
regex_op(R) --> regex_lit(R).

regex_lit(regex_char([C])) --> [C], {\+ regex_ctrl(C)}.
regex_lit(regex_char([C])) --> [92], [C].

regex_lit(regex_char(CS)) --> [46], {findall(C, between(32,126, C), CS)}.

regex_lit(regex_char(DS)) --> 
    [91], [94], !, class_body(CS), [93],
    {findall(C, (between(32, 126, C), \+ member(C, CS)), DS)}.
regex_lit(regex_char(CS)) --> [91], class_body(CS), [93].

regex_lit(R) --> [40], regex_union(R), [41].

class_body([C|T]) --> class_lit(C),class_body(T).
class_body(CS) -->
    class_lit(C0), [45], class_lit(C1), class_body(T),
    {findall(C, between(C0, C1, C), H), append(H,T,CS)}.
class_body([]) --> [].

class_lit(C) --> [C], {\+ class_ctrl(C)}.
class_lit(C) --> [92], [C].

class_ctrl(C) :- string_codes("\\[]-", CS), member(C, CS).
regex_ctrl(C) :- string_codes("\\.[]|+?*()", CS), member(C, CS).

% Regex Engine
%%%%%%%%%%%%%% 

% The regex empty matches any string without consuming any characters.
match(S, regex_empty, S).

% A regex consisting of a single character matches any string starting with
% that character. The chanter is consumed.
match([C|S], regex_char(CS), S) :- member(C, CS).

% A union of two regex only needs to satisify one of the branches.
match(S, regex_union(L,R), T) :- match(S, L, T); match(S, R, T).     

% A concat of two regex must satisfy the left and then the right.
match(S, regex_concat(L, R), U) :- match(S, L, T), match(T, R, U).

% The kleene closure of a regex can match the regex 0 times or it can the regex
% once before matching the kleene closure again.
match(S, regex_kleene(_), S).
match(S, regex_kleene(K), U) :- match(S, K, T), S \= T, match(T, regex_kleene(K), U).

मैं प्रोलॉग डीसीजी से परिचित नहीं हूं, कैसे regex_union(RE, RC, [])मैच करता है regex_union(R) -->...?
कृति लिथोस

@KritiiLithos DCG के दो निहितार्थ मानदंड हैं जो DCG या के भाग के भीतर से स्वचालित रूप से दिए जाने पर आपूर्ति की जाती हैं phrase\2। पहला वह स्ट्रिंग है जिसे DCG पर लागू किया जाता है और दूसरा स्ट्रिंग का कुछ प्रत्यय होता है जो DCG विधेय को संतुष्ट करने के बाद रहता है। एक समतुल्य निर्माण होगा phrase(regex_union(RE), RC)
अंख-मोर्फर्क

वैसे, आपको codegolf.stackexchange.com/q/161108 को हल करने में रुचि हो सकती है , चुनौती एक सरल रीगेक्स के लिए पूछती है, इसलिए पार्स करना आसान होगा, और ऐसा लगता है कि कुछ प्रोलोग अच्छी तरह से कर सकते हैं
कृति लिथोस

@KritiiLithos हाँ, regex पूरक निश्चित रूप से एक दिलचस्प काम है। मैंने regex-> nfa-> dfa-> supplement-> regex पाइपलाइन को लागू किया है और यह बिल्कुल छोटा नहीं है। मैं पोस्ट करने से पहले कुछ और टियर कार्यान्वयन पर गौर करना चाहता हूं।
अंख-मोर्फर्क

मैं जानवर-बल का उपयोग करके इसके बारे में जाने की कोशिश कर रहा हूं; मेरे मन में एक एल्गोरिथ्म है, लेकिन प्रोलॉग में ब्रूट-फोर्स भाग को लागू करना अब तक सफल नहीं रहा है। हम्म, यह अच्छा होगा अगर regex <=> dfa में बदलने के लिए एक प्रतिवर्ती विधेय हो। देखना दिलचस्प है कि हमारे दोनों समाधानों में से क्या आता है
क्रिस्सी लिथोस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.