ग्लोब मैचर को लागू करें


15

मिलान होने के लिए पैटर्न और स्ट्रिंग के एक फंक्शन को लागू करें, यदि पैटर्न WHOLE स्ट्रिंग से मेल खाता है, तो सही है, अन्यथा गलत है।

हमारा ग्लोब पैटर्न सिंटैक्स है:

  • ? किसी एक पात्र से मेल खाता है
  • + एक या अधिक वर्णों से मेल खाता है
  • * शून्य या अधिक वर्णों से मेल खाता है
  • \ पलायन

नियम:

  • कोई निष्कासन, कोई नियमित अभिव्यक्ति में परिवर्तित नहीं, कोई सिस्टम ग्लोब फ़ंक्शन नहीं।
  • I / O की आवश्यकता नहीं है: आप केवल एक फ़ंक्शन लिख सकते हैं
  • सबसे छोटी जीत

उदाहरण:

glob('abc', 'abc') => true
glob('abc', 'abcdef') => false IMPORTANT!
glob('a??', 'aww') => true
glob('a*b', 'ab') => true
glob('a*b', 'agwijgwbgioeb') => true
glob('a*?', 'a') => false
glob('?*', 'def') => true
glob('5+', '5ggggg') => true
glob('+', '') => false
glob('a\*b', 'a*b') => true

यहाँ आरंभ करने के लिए एक टिप है: http://en.wikipedia.org/wiki/Backtracking


1
क्या मुझे अतिरिक्त टैग "पैटर्न-मिलान" का सुझाव देना चाहिए?
dmckee --- पूर्व-मध्यस्थ ने बिल्ली का बच्चा

1
क्या आप स्पष्ट कर सकते हैं कि "नो स्टैंडर्ड फंक्शन" से आपका क्या मतलब है? आप मानक पुस्तकालय से कार्यों को नहीं बुला सकते हैं? यह कैसे काम करने वाला है?
sepp2k

कृपया बच निकलने पर कुछ उदाहरण? ("\")
12

जवाबों:


4

गोल्फस्क्रिप्ट - 82 वर्ण

{1,\@n+:|;{:<;{:I)I|="\\+*?"[<]+?[{|=<={I))}*}I~{I\C}{}.{;}]=~}:C%}/{|>'*'-n=},}:g

मान लेता है कि तार में कोई नयापन नहीं हैं। झूठे के लिए एक खाली सरणी देता है, और सच के लिए एक गैर-खाली सरणी (सच / झूठ की गोल्फस्क्रिप्ट परिभाषा के अनुरूप)।

यह एक गैर-पुनरावर्ती समाधान है (लगातार *एस को छोड़कर ), जो पैटर्न स्ट्रिंग में iऐसे pattern[0..i]मैच की स्थिति की एक सूची रखता है string[0..cur]

यह बहुत लंबे समय तक चलने की क्षमता रखता है। आप इसे रोकने के .&बाद जोड़ सकते हैं :C%


5

हास्केल, 141 अक्षर

c('\\':a:z)s=a&s>>=c z
c(a:z)s=a%s>>=c z
c[]s=[null s]
p&(a:z)|a==p=[z]
_&_=[]
'?'%(a:z)=[z]
'*'%a=a:'+'%a
'+'%(a:z)='*'%z
l%a=l&a
g=(or.).c

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

इसे निम्नलिखित परीक्षण चालक के साथ चलाया जा सकता है:

main = do
    globtest "abc" "abc"    True
    globtest "abc" "abcdef" False
    globtest "a??" "aww"    True
    globtest "a*b" "ab"     True
    globtest "a*b" "agwijgwbgioeb" True
    globtest "a*?" "a"      False
    globtest "?*" "def"     True
    globtest "5+" "5ggggg"  True
    globtest "+" ""         False
    globtest "a\\*b" "a*b"  True
  where
    globtest p s e =
      if g p s == e
        then putStrLn "pass"
        else putStrLn$"fail: g " ++ show p ++ " " ++ show s ++ " /= " ++ show e

अद्यतन: मैंने इस विशेष उत्तर के बारे में एक ब्लॉग पोस्ट लिखा है , जैसा कि मुझे लगता है कि यह अच्छी तरह से दिखाता है कि हास्केल इतनी आसानी से समस्या को कैसे बताता है।


  • संपादित करें: (181 -> 174) प्रतिस्थापित dऔर mऑपरेटरों के साथ
  • संपादित करें: (174 -> 151) inlined rमेंc
  • संपादित करें: (151 -> 149) ने +मामले में एक अनावश्यक रूप से उत्पन्न विकल्प को हटा दिया
  • संपादित करें: (149 -> 141) के लिए एक अनावश्यक क्लॉज को हटा दिया %, जो इसके द्वारा नियंत्रित किया गया था&

2

PHP - 275 243 अक्षर

<?function g($P,$I){$o='array_shift';if(@$I[0]==="")return 0;for(;$P;$o($P)){$p=$P[0];if($p=='?'|$p=='+'&&@$N===$o($I))return 0;if($p=='+'|$p=='*'&&$I&&g($P,array_slice($I,1)))return 1;if(!strpos(" ?+*\\",$p)&&$p!==$o($I))return 0;}return!$I;}

Ungolfed:

<?php

function g($P,$I) {
        if ($I && $I[0] === "") return false;
        for(;$P;array_shift($P)) {
                $p = $P[0];
                if( $p == '?' || $p == '+') {
                        if (NULL === array_shift($I)) {
                                return false;
                        }
                }
                if( $p=='+' || $p=='*' ) {
                        if ($I && g($P, array_slice($I,1))) {
                                return true;
                        }
                }
                if (!strpos(" ?+*\\",$p) && $p !== array_shift($I)) {
                        return false;
                }
        }
        return !$I;
}

function my_glob($pattern,$subject) {
    return !!g(str_split($pattern),str_split($subject));
}

2

वर्बोज़ पायथन ( 384 367 वर्ण)

t=lambda a:a[1:] 
h=lambda a:a[0] 
n=lambda p,s:s and(h(p)==h(s)and m(t(p),t(s))) 
def m(p,s): 
 if not p: 
  return not s 
 else: 
  return { 
   '?':lambda p,s:s and m(t(p),t(s)), 
   '+':lambda p,s:s and(m(p,t(s))or m(t(p),t(s))), 
   '*':lambda p,s:m(t(p),s)or(s and m(p,t(s))), 
   '\\':lambda p,s:n(t(p),s), 
  }.get(h(p),n)(p,s) 
glob=lambda p,s:not not m(p,s)

यह सबसे छोटा नहीं है, लेकिन यह अच्छा और कार्यात्मक है। प्रेषण के बीच में प्रचलित तानाशाही चीज़ को संभवतः (h(p) == '?') and (? lambda body)प्रकार की चीजों पर एक अस्वीकृति के रूप में फिर से लिखा जा सकता है । उस एच ऑपरेटर को परिभाषित करने से मुझे बिना किसी लाभ के कुछ पात्रों की लागत मिलती है, लेकिन सिर के लिए एक कीवर्ड होना अच्छा है।

मैं चाहूंगा कि अगर समय की अनुमति हो तो बाद में इसे गोल्फ की कटिंग में दरार कर दूं।

संपादित करें: उपयोगकर्ता के माणिक उत्तर को पढ़ने के बाद '*' मामले में अनावश्यक तीसरी शाखा को हटा दिया गया


2

छोटा स्नैपर पायथन 2.6 (272 वर्ण)

golfed:

n=lambda p,s:p[0]==s[0]and m(p[1:],s[1:]) 
def m(p,s): 
 q,r,t,u=p[0],p[1:],s[0],s[1:] 
 return any((q=='?'and(t and m(r,u)),q=='+'and(t and(m(p,u)or m(r,u))),q=='*'and(m(r,s)or(t and m(p,u))),q=='\\'and n(r,s),q==t==0))or n(p,s) 
glob=lambda*a:m(*[list(x)+[0]for x in a])

ungolfed:

TERMINATOR = 0 

def unpack(a): 
    return a[0], a[1:] 

def terminated_string(s): 
    return list(s) + [TERMINATOR] 

def match_literal(p, s): 
    p_head, p_tail = unpack(p) 
    s_head, s_tail = unpack(s) 
    return p_head == s_head and match(p_tail, s_tail) 

def match(p, s): 
    p_head, p_tail = unpack(p) 
    s_head, s_tail = unpack(s) 
    return any(( 
        p_head == '?' and (s_head and match(p_tail, s_tail)), 
        p_head == '+' and (s_head and(match(p, s_tail) or match(p_tail, s_tail))), 
        p_head == '*' and (match(p_tail, s) or (s_head and match(p, s_tail))), 
        p_head == '\\' and match_literal(p_tail, s), 
        p_head == s_head == TERMINATOR, 
    )) or match_literal(p, s) 

def glob(p, s): 
    return match(terminated_string(p), terminated_string(s))

विशेषता:

  • आलसी का मूल्यांकन तार्किक गड़बड़!
  • सी स्टाइल के तार!
  • प्यारा कई तुलना मुहावरे!
  • बहुत बदसूरत!

यह देखने के लिए user300 के जवाब का श्रेय कि कैसे चीजें सरलीकृत होती हैं यदि आप किसी खाली स्ट्रिंग से सिर को पॉप करते समय किसी प्रकार के टर्मिनेटर मान प्राप्त कर सकते हैं।

काश सिर / पूंछ अनपैकिंग एम के तर्कों की घोषणा के दौरान इनलाइन किया जा सकता है। तब मी एक मेमना हो सकता है, जैसे उसके दोस्त n और ग्लोब। python2 यह नहीं कर सकता है, और थोड़ा पढ़ने के बाद, ऐसा लगता है कि python3 या तो नहीं कर सकता है। शोक।

परिक्षण:

test_cases = { 
    ('abc', 'abc') : True, 
    ('abc', 'abcdef') : False, 
    ('a??', 'aww') : True, 
    ('a*b', 'ab') : True, 
    ('a*b', 'aqwghfkjdfgshkfsfddsobbob') : True, 
    ('a*?', 'a') : False, 
    ('?*', 'def') : True, 
    ('5+', '5ggggg') : True, 
    ('+', '') : False, 
}   
for (p, s) in test_cases: 
    computed_result = glob(p, s) 
    desired_result = test_cases[(p, s)] 
    print '%s %s' % (p, s) 
    print '\tPASS' if (computed_result == desired_result) else '\tFAIL' 

2

रूबी - 199 171

g=->p,s{x=(b=->a{a[1..-1]})[p];y=s[0];w=b[s];v=p[0];_=->p,s{p[0]==y&&g[x,w]}
v==??? g[x,y&&w||s]:v==?+? y&&g[?*+x,w]:v==?*?
y&&g[p,w]||g[x,s]:v==?\\? _[x,s]:v ? _[p,s]:!y}

Ungolfed:

def glob(pattern, subject)
        b=->a{a[1..-1]}
        _=->p,s{ p[0]==s[0] && glob(b[p],b[s]) }
        ({
                ??=>->p,s { glob(b[p], s[0] ? b[s] : s) },
                ?+=>->p,s { s[0] && glob(?*+b[p], b[s]) },
                ?*=>->p,s { s[0] && glob(p,b[s]) || glob(b[p],s) },
                ?\\=>->p,s{ _[b[p],s] },
                nil=>->p,s{ !subject[0] }
        }[pattern[0]] || _)[pattern, subject]
end

टेस्ट:

p glob('abc', 'abc')
p glob('abc', 'abcdef')
p glob('a??', 'aww')
p glob('a*b', 'ab')
p glob('a*b', 'agwijgwbgioeb')
p glob('a*?', 'a')
p glob('?*', 'def')
p glob('5+', '5ggggg')
p glob('+', '')

बदमाशों के जवाब से प्रेरित


मुझे माणिक के बारे में कुछ नहीं पता है, लेकिन आपके कोड से मैंने सीखा है कि सीमा सूचकांकों से पहुंचना शून्य हो जाता है। इसलिए एक रिक्त स्ट्रिंग को पॉप करने से शून्य मान प्राप्त होता है जिसे स्ट्रिंग टर्मिनेटर प्रतीक के रूप में उपयोग किया जा सकता है। सी-शैली! निफ्टी! मुझे लगता है कि यह प्रत्येक इनपुट स्ट्रिंग के माध्यम से अजगर में नकल किया जा सकता हैlambda s : list(s)+[None]
रॉब्स

इसके लुक से लेकर रूबी ने पैटर्न मैचिंग में बनाया है। इस तरह की समस्या के लिए यह निश्चित रूप से उपयोगी है।
जोनाथन एम डेविस

वास्तव में ??शाब्दिक वर्ण हैं, =>रूबी हैश में कुंजी / मान विभाजक हैं, और ->एक लैम्ब्डा :-) ( मूल्य के रूप { ?? => ->{...} }में एक हैश "?"और एक लैम्ब्डा के साथ एक हैश शुरू होता है ।) लेकिन हां जिस तरह से एक साथ उपयोग किया जाता है वह एकल वर्णों के पैटर्न-मिलान जैसा दिखता है। :-)
अरनौद ले ब्लांक

2

सी फ़ंक्शन - 178 आवश्यक वर्ण

जीसीसी के साथ संकलित, यह कोई चेतावनी नहीं पैदा करता है।

#define g glob
int g(p,s)const char*p,*s;{return*p==42?g(p+1,s)||(*s&&g(p,
s+1)):*p==43?*s&&(g(p+1,++s)||g(p,s)):*p==63?*s&&g(p+1,s+1)
:*p==92?*++p&&*s++==*p++&&g(p,s):*s==*p++&&(!*s++||g(p,s));}
#undef g

पहली और आखिरी पंक्तियों को वर्ण गणना में शामिल नहीं किया गया है। उन्हें केवल सुविधा के लिए प्रदान किया जाता है।

उड़ना:

int glob(p,s)
const char *p, *s; /* K&R-style function declaration */
{
    return
        *p=='*'  ? glob(p+1,s) || (*s && glob(p,s+1)) :
        *p=='+'  ? *s && (glob(p+1,++s) || glob(p,s)) :
        *p=='?'  ? *s && glob(p+1,s+1)                :
        *p=='\\' ? *++p && *s++==*p++ && glob(p,s)    :
        *s==*p++ && (!*s++ || glob(p,s));
}

2

जावास्क्रिप्ट - 259 अक्षर

मेरा कार्यान्वयन बहुत पुनरावर्ती है, इसलिए यदि बहुत लंबे पैटर्न का उपयोग किया जाता है तो स्टैक ओवरफ्लो हो जाएगा। प्लस साइन को अनदेखा करना (जिसे मैं अनुकूलित कर सकता था लेकिन सादगी के लिए नहीं चुना गया था), प्रत्येक टोकन के लिए एक स्तर की पुनरावृत्ति का उपयोग किया जाता है।

glob=function f(e,c){var b=e[0],d=e.slice(1),g=c.length;if(b=="+")return f("?*"+d,c);if(b=="?")b=g;else if(b=="*"){for(b=0;b<=g;++b)if(f(d,c.slice(b)))return 1;return 0}else{if(b=="\\"){b=e[1];d=e.slice(2)}b=b==c[0]}return b&&(!d.length&&!g||f(d,c.slice(1)))}

फ़ंक्शन कभी-कभी बूलियन के बजाय एक संख्या देता है। यदि वह समस्या है, तो आप इसका उपयोग कर सकते हैं !!glob(pattern, str)


एक उपयोगी संसाधन के रूप में सेवा करने के लिए अपुष्ट (अघोषित, बल्कि):

function glob(pattern, str) {
    var head = pattern[0], tail = pattern.slice(1), strLen = str.length, matched;
    if(head == '+') {
        // The plus is really just syntactic sugar.
        return glob('?*' + tail, str);
    }
    if(head == '?') { // Match any single character
        matched = strLen;
    } else if(head == '*') { // Match zero or more characters.
        // N.B. I reuse the variable matched to save space.
        for(matched = 0; matched <= strLen; ++matched) {
            if(glob(tail, str.slice(matched))) {
                return 1;
            }
        }
        return 0;
    } else { // Match a literal character
        if(head == '\\') { // Handle escaping
            head = pattern[1];
            tail = pattern.slice(2);
        }
        matched = head == str[0];
    }
    return matched && ((!tail.length && !strLen) || glob(tail, str.slice(1)));
}

ध्यान दें कि सरणी तत्वों के लिए स्ट्रिंग के वर्णों में अनुक्रमण पुराने (ECMAScript 3) भाषा मानक का हिस्सा नहीं है, इसलिए यह पुराने ब्राउज़रों में काम नहीं कर सकता है।


1

पायथन (454 वर्ण)

def glob(p,s):
  ps,pns=[0],[]
  for ch in s:
    for i in ps:
      if i<0:
        pns+=[i]
        if i>-len(p) and p[-i]==ch:pns+=[-i]
      elif i<len(p):
        pc=p[i]
        d={'?':[i+1],'+':[i,-i-1],'*':[i+1,-i-1]}
        if pc in d:pns+=d[pc]
        else:
          if pc=='\\':pc=p[i+1]
          if pc==ch:pns+=[i+1]
    ps,pns=pns,[]
  if (s or p in '*') and (len(p) in ps or -len(p)+1 in ps or -len(p) in ps): return True
  return False

1

डी: 363 वर्ण

bool glob(S)(S s,S t){alias front f;alias popFront p;alias empty e;while(!e(s)&&!e(t)){switch(f(s)){case'+':if(e(t))return false;p(t);case'*':p(s);if(e(s))return true;if(f(s)!='+'&&f(s)!='*'){for(;!e(t);p(t)){if(f(s)==f(t)&&glob(s,t))return true;}}break;case'\\':p(s);if(e(s))return false;default:if(f(s)!=f(s))return false;case'?':p(s);p(t);}}return e(s)&&e(t);}

अधिक कानूनी रूप से:

bool glob(S)(S s, S t)
{
    alias front f;
    alias popFront p;
    alias empty e;

    while(!e(s) && !e(t))
    {
        switch(f(s))
        {
            case '+':
                if(e(t))
                    return false;

                p(t);
            case '*':
                p(s);

                if(e(s))
                    return true;

                if(f(s) != '+' && f(s) != '*')
                {
                    for(; !e(t); p(t))
                    {
                        if(f(s) == f(t) && glob(s, t))
                            return true;
                    }
                }

                break;
            case '\\':
                p(s);

                if(e(s))
                    return false;
            default:
                if(f(s) != f(s))
                    return false;
            case '?':
                p(s);
                p(t);
        }
    }

    return e(s) && e(t);
}

1

golfscript

{{;;}2$+}:x;{x if}:a;{x\if}:o;{1$1$}:b;{(@(@={\m}a}:r;{b(63={\({\m}a}a{b(43={\({\b m{'+'\+m}o}a}a{b(42={b m{\({\'*'\+m}a}o}a{b(92={r}a{b 0=0=\0=0=*{r}o}o}o}o}o}:m;{[0]+\[0]+m}:glob;

यह उन कार्यों से बना है जो स्टैक, एस और पी से दो तर्कों का उपभोग करते हैं, और एक एकल बूलियन रिटर्न वैल्यू का उत्पादन करते हैं। आलसी और आलसी या संचालकों के साथ संगत बनाने के लिए थोड़ा संभल कर चलना है। मुझे वास्तव में संदेह है कि यह दृष्टिकोण कहीं भी इष्टतम के पास है, या यहां तक ​​कि सही दिशा में भी है।

कुछ मनोरंजक मूर्खतापूर्ण क्षण भी हैं, जैसे '*'कि पैटर्न को बंद करना, '*'तुलना में उपभोग करना , केवल यह महसूस करने के लिए कि बाद की शाखा मैच से मेल खाती है। दूसरी शाखा से नीचे जाने के लिए, हमें '*'सामने की ओर पैटर्न की आवश्यकता होती है , लेकिन जब हम पॉपअप करते हैं '*', तो हमने उस मूल पैटर्न का उपभोग किया है , और हमने इसका उपभोग किया है '*', इसलिए स्वयं को फिर से प्राप्त करने के लिए हम एक चमकदार नए तार को लोड करते हैं निरंतर '*', और इसे जगह में रखना। यह और भी बदसूरत हो जाता है क्योंकि किसी कारण से चरित्र मिलान को अस्की मूल्यों के साथ करने की आवश्यकता होती है, लेकिन स्ट्रिंग पर दबाव कम करने के लिए पीछे हटना पड़ता है।

कम गोल्फ वाली गोल्फ

{[0]+}:terminate_string;
{{;;}2$+if}:_and;
{{;;}2$+\if}:_or;
{1$1$}:branch;
{(@(@={\match}_and}:match_literal;
{0=0=\0=0=*}:match_terminator;
{(92={match_literal}_and}:match_escape;
{(63={\({\match}_and}_and}:match_wildcard;
{(43={\({\branch match{'+'\+match}_or}_and}_and}:match_wildcard_plus;
{(42={branch match{\({\'*'\+match}_and}_or}_and}:match_wildcard_star;
{branch match_wildcard{branch match_wildcard_plus{branch match_wildcard_star{branch match_escape{branch match_terminator{match_literal}_or}_or}_or}_or}_or}:match;
{terminate_string\terminate_string match}:glob;

परीक्षण

{2$2$glob = "test passed: " "test FAILED: " if print \ print ' ; ' print print "\n" print}:test_case;

'abc' 'abc' 1 test_case
'abc' 'abcdef' 0 test_case
'a??' 'aww' 1 test_case
'a*b' 'ab' 1 test_case
'a*b' 'agwijgwbgioeb' 1 test_case
'a*?' 'a' 0 test_case
'?*' 'def' 1 test_case
'5+' '5ggggg' 1 test_case
'+' '' 0 test_case

1

सी # (251 वर्ण)

static bool g(string p,string i){try{char c;System.Func<string,string>s=t=>t.Remove(0,1);return p==i||((c=p[0])==92?p[1]==i[0]&g(s(s(p)),s(i)):c==42?g(s(p),i)||g(p,s(i)):c==43?g(s(p),s(i))|g(p,s(i)):g(s(p),s(i))&(c==i[0]|c==63));}catch{return false;}}

थोड़ा अधिक पठनीय:

static bool g(string p /* pattern */, string i /* input string */)
{
    // Instead of checking whether we’ve reached the end of the string, just
    // catch the out-of-range exception thrown by the string indexing operator
    try
    {
        char c;

        // .Remove(0,1) is shorter than .Substring(1)...
        System.Func<string, string> s = t => t.Remove(0, 1);

        // Note that every glob matches itself!† This saves us having to write
        // “(p=="" & i=="")” which would be much longer — very convenient!
        return p == i || (

            // backslash escapes
            (c = p[0]) == 92 ? p[1] == i[0] & g(s(s(p)), s(i)) :

            // '*' — need “||” so that s(i) doesn’t throw if the first part is true
            c == 42 ? g(s(p), i) || g(p, s(i)) :

            // '+'
            c == 43 ? g(s(p), s(i)) | g(p, s(i)) :

            // '?' or any other character
            g(s(p), s(i)) & (c == i[0] | c == 63)
        );
    }

    // If we ever access beyond the end of the string, we know the glob doesn’t match
    catch { return false; }
}

Containing मुझे पता है, मुझे पता है ... बैकस्लैश वाले ग्लब्स को छोड़कर। जो वास्तव में दुर्भाग्यपूर्ण है। यह वास्तव में अन्यथा चालाक होता। :(

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.