एक दुर्घटना टोकन लिखें


24

पृष्ठभूमि

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

काम

आपके प्रोग्राम को इनपुट के रूप में एक स्ट्रिंग दी जाएगी। यहाँ एल्गोरिथ्म है कि हादसा टोकन का उपयोग करता है:

  1. सभी स्ट्रिंग्स को पहचानें जो इनपुट के विकल्प के रूप में ठीक तीन तरीकों से होते हैं (यानी इनपुट के भीतर उस स्ट्रिंग के बिल्कुल तीन घटनाएँ हैं)।
  2. इन तार कि एक और इस तरह के तार का एक स्ट्रिंग के किसी भी त्यागें (जैसे इनपुट के लिए ababab, केवल शेष स्ट्रिंग होगा ab, नहीं aया b, क्योंकि aऔर bदोनों सबस्ट्रिंग हैं ab)।
  3. इनपुट के भीतर ओवरलैप करने वाले किसी भी तार को छोड़ दें। (उदाहरण के लिए, aaaaइसमें ठीक तीन प्रतियां शामिल हैं aa, लेकिन ये प्रतियां दूसरे और तीसरे वर्ण पर ओवरलैप होती हैं, इसलिए इसे छोड़ दिया जाएगा। इसी तरह, abababaतीन प्रतियों की abऔर तीन प्रतियां हैं ba, लेकिन दूसरे से छठे वर्ण हैं। एक का ओवरलैप abऔर एक ba, दोनों बहुत abऔर baखारिज कर दिया जाएगा)।
  4. इस बिंदु पर बने रहने वाले कोई भी तार कार्यक्रम द्वारा उपयोग किए जाने वाले टोकन हैं। इन टोकन के अनुक्रम में मूल इनपुट को टोकन करें (पिछले चरण में त्यागने के कारण, इसे करने का केवल एक ही तरीका होगा)। इनपुट में कोई भी वर्ण जो किसी भी टोकन का हिस्सा नहीं है उसे टिप्पणियों के रूप में माना जाता है और खारिज कर दिया जाता है।

आपके प्रोग्राम को इनपुट के रूप में एक स्ट्रिंग लेनी है, और आउटपुट के रूप में स्ट्रिंग (टोकन की एक सूची, जिनमें से प्रत्येक को स्ट्रिंग के रूप में व्यक्त किया गया है) के संगत टोकन वापस करना है। इसके अतिरिक्त, यह कम से कम कुशलता से किया जाना है; विशेष रूप से, कार्यक्रम को द्विघात समय ("O (n") ") या बेहतर में चलाना है । (संयोग से, यह लगभग निश्चित रूप से द्विघात से तेज जाना संभव है, लेकिन यह नहीं , इसलिए बेझिझक का उपयोग करने के लिए स्वतंत्र महसूस करें जो आप पा सकते हैं कि जटिलता सीमा के भीतर फिट बैठता है।)

स्पष्टीकरण

  • हालांकि हादसे के कार्यक्रम में कोई भी 256 ऑक्टेट शामिल हो सकते हैं, यह आपके प्रोग्राम के लिए इस चुनौती के उद्देश्य से स्वीकार्य है कि केवल मुद्रण योग्य ASCII (अंतरिक्ष सहित), प्लस न्यूलाइन और टैब से बाहर किए गए इनपुट को संभाल सकें। (सभी ज्ञात हादसे कार्यक्रम खुद को इस सबसेट तक सीमित रखते हैं)। ध्यान दें कि स्पेस / न्यूलाइन / टैब विशेष नहीं हैं और टोकन के बीच में दिखाई दे सकते हैं; हादसा सभी 256 ओकटेट्स को अपारदर्शी मानता है।
  • "द्विघात समय" की परिभाषा है "यदि इनपुट का आकार दोगुना हो जाता है, तो प्रोग्राम धीमी गति से चलेगा और स्थिर 4 से अधिक कारक नहीं होगा", अर्थात यदि t ( x ) आपके कार्यक्रम को अधिकतम समय लेता है तो आकार x के इनपुट की प्रक्रिया करें , फिर कुछ स्थिर k होना चाहिए जैसे कि t (2  x ) <4  t ( x ) + k सभी x के लिए । यह ध्यान रखें कि स्ट्रिंग्स की तुलना स्ट्रिंग्स की लंबाई के लिए आनुपातिक होती है।
  • आपके प्रोग्राम को सैद्धांतिक रूप से किसी भी लम्बाई के इनपुट प्रोग्राम्स को संभालने में सक्षम होना चाहिए यदि आपकी भाषा में (संभवतः काल्पनिक) संस्करण है जिसमें असीमित मेमोरी है और अनबाउंड पूर्णांक का उपयोग करता है (यह ठीक है यदि प्रोग्राम अभ्यास के कारण चलने पर इस लक्ष्य को प्राप्त करने में विफल रहता है भाषा का पूर्णांक या मेमोरी वास्तव में बहुत बड़ी है)। आप मान सकते हैं (जटिलता की गणना के उद्देश्य से) कि पूर्णांक जो इनपुट की लंबाई से अधिक नहीं हैं, उनकी तुलना निरंतर समय में की जा सकती है (हालांकि ध्यान रखें कि यदि आप बड़े मूल्यों का उपयोग करते हैं, जैसे इनपुट को एक में परिवर्तित करने के कारण। एकल पूर्णांक, वे अंकों की संख्या की तुलना करने के लिए समय की एक लंबाई लेंगे जो उनके पास है)।
  • आप किसी भी एल्गोरिथ्म का उपयोग कर सकते हैं जो जटिलता सीमा के भीतर फिट बैठता है, भले ही यह ऊपर वर्णित एल्गोरिथ्म के समान चरणों का पालन नहीं करता है, इसलिए जब तक यह एक ही परिणाम नहीं देता है।
  • यह पहेली इनपुट को टोकन देने के बारे में है, वास्तव में आउटपुट को प्रारूपित करने के बारे में नहीं है। यदि आपकी भाषा में किसी सूची को आउटपुट करने का सबसे प्राकृतिक तरीका एक अस्पष्ट प्रारूप शामिल है (उदाहरण के लिए जब न्यूलाइन-अलग हो जाते हैं जब तार शाब्दिक newlines, या तार के बीच सीमांकक के बिना) होते हैं, तो इस तथ्य के बारे में चिंता न करें कि आउटपुट अस्पष्ट है। जब तक सूची वास्तव में निर्मित है)। आप अपने सबमिशन का दूसरा संस्करण बनाना चाहते हैं, जो परीक्षण में सहायता के लिए असंदिग्ध आउटपुट का उत्पादन करता है, लेकिन मूल संस्करण वह संस्करण है जो स्कोरिंग के लिए मायने रखता है।

परीक्षण का मामला

निम्नलिखित इनपुट स्ट्रिंग के लिए:

aaabcbcbcdefdfefedghijghighjkllkklmmmmonono-nonppqpq-pqprsrsrstststuvuvu

आपके प्रोग्राम को निम्न आउटपुट सूची तैयार करनी चाहिए:

a a a bc bc bc d e f d f e f e d gh gh gh k l l k k l pq pq pq u u u

विजय की स्थिति

यह , इसलिए सबसे छोटा मान्य (यानी सही इनपुट / आउटपुट व्यवहार और निष्पादित करने के लिए पर्याप्त रूप से तेज़), बाइट्स में मापा जाता है, जीतता है।


उन लोगों के लिए जो हटाए गए पोस्ट देख सकते हैं: सैंडबॉक्स पोस्ट यहां था ।

16
आपने कितनी भाषाएँ बनाई हैं? ... प्रतीक्षा, 35 !
लुइस मेंडो

जवाबों:


14

सी (जीसीसी), 324 बाइट्स

फ़ंक्शन fएक शून्य-समाप्त स्ट्रिंग लेता है और टोकन को stdout में प्रिंट करता है। सभी नए समाचारों को नीचे दिए गए कोड से हटाया जा सकता है।

f(char*s){
int n=strlen(s),b=0,z[n-~n],F[n+1],u,a,x=0,l,m,*t=z+n;
int K(i){~m&&s[i]^s[a+m]?m=t[m],K(i):++m;}
for(;b<2*n;){
for(a=b++%n,m=l=-1;a+l<n;K(a+l))t[++l]=m;
for(l=0;l<n;++F[m])K(l++),F[l]=z[a]*=b>n?m^z[a]||~(m=t[z[l-m]]):0;
for(printf("%.*s",z[a],s+a);n/b*l&&a+l>x;l--)F[l]^3?F[t[l]]+=F[l]:(a<x?z[u]=0:(z[u=a]=l),x=a+l);
}
}

यह पुराना 376-बाइट संस्करण पढ़ने में थोड़ा आसान है; नीचे दिया गया स्पष्टीकरण इस पर लागू होता है।

*t,m;
char*p;
K(c){for(;~m&&c^p[m];)m=t[m];++m;}
k(i){for(*t=m=-1;p[i];t[++i]=m)K(p[i]);m=0;}
f(char*s){
int n=strlen(s),z[n-~n],F[n+1],u,*Z=z,a=0,x=0,l;
for(t=z+n;a<n;a++){
p=s+a;
for(k(l=z[a]=0);l<n;++F[m])K(s[l++]),F[l]=0;
for(;l&&a+l>x;l--)F[l]^3?F[t[l]]+=F[l]:(a<x?z[u]=0:(z[u=a]=l),x=a+l);
}
for(p=s;*p;printf("%.*s",*Z++,p++))
for(k(x=0);x<n;m==*Z?*Z*=!!z[x-m],m=t[m]:0)
K(s[x++]);
}

k(0)Knuth-Morris-Pratt एल्गोरिथ्म के tलिए पैटर्न के pलिए तालिका बनाता है। खोज स्ट्रिंग और अद्यतनों K(c)के अगले वर्ण cको संसाधित करें m, जिनमें से सबसे बड़े उपसर्ग की लंबाई pसबसे हाल ही में संसाधित चरित्र पर समाप्त हो सकती है।

पहले forलूप aमें, स्ट्रिंग में प्रत्येक सूचकांक के लिए, हम प्रत्येक स्ट्रिंग के mघटित होने के संभावित समय को गिनते हैं, जब सब स्ट्रिंग में खोज शुरू होती है a। तब हम सबसे बड़े की तलाश करते हैं, lजो लंबाई- lसबस्ट्रिंग की शुरुआत a3 बार हुई। यदि यह पहले से पाए गए स्ट्रिंग द्वारा पूरी तरह से निहित होने के लिए पर्याप्त छोटा है a, तो हम इसे अनदेखा करते हैं। यदि यह ओवरलैप हो जाता है, तो हम पिछली स्ट्रिंग को हटा देते हैं z, सरणी रिकॉर्डिंग जो टोकन रखी जाएगी। अन्यथा, इसकी लंबाई में संग्रहीत किया जाता है z

फिर, हम केएमपी का उपयोग फिर से दर्ज टोकन के लिए स्ट्रिंग को खोजने के लिए करते हैं z। यदि उनमें से एक को 0 प्रविष्टि के साथ एक स्थान पर पाया जाता है z, तो हम जानते हैं कि यह टोकन ओवरलैप के कारण हटा दिया गया था। यदि टोकन हटाया नहीं गया था, तो इसे मुद्रित किया जाता है।


1
इस की समय जटिलता क्या है? O(n^2)या तेज होना है । और वहां !!पर क्यों है !!z[x-m]?
यति

2
@TuukkaX यह बिल्कुल हे (n ^ 2) है। *Zअगले टोकन की लंबाई है जो 0 बनने की आवश्यकता है यदि टोकन के अन्य घटनाओं में से किसी का मान 0 उनके सरणी में अनुक्रमणिका पर है, या समान मान को अन्यथा रखें (उस स्थिति में !!z[x-m]1. होना चाहिए
feersum

ठीक है। लेकिन मुझे अभी भी समझ नहीं आया कि ऐसा क्यों !!है। !!xअभी भी होना चाहिए x, या यह एक चाल है जो मुझे नहीं पता है?
यति

@TuukkaX ठीक है, !!xबनाता है xएक बूलियन अपने 'truthiness "का प्रतिनिधित्व। तो, !!1 == trueऔर !!0 == false। मैं सी को विशेष रूप से नहीं जानता, लेकिन यह है कि यह आमतौर पर कैसे जाता है
कॉनर ओ'ब्रायन

7

जावास्क्रिप्ट, 878 867 842 825 775 752 717 712 704 673 664 650 641 बाइट्स

गोल्फ को कोड में मदद करने के लिए @Kritii लिथोस को धन्यवाद।
14 बाइट से गोल्फिंग के लिए @ User2428118 पर धन्यवाद

(IE7 में काम नहीं करेगा) ( इनपुट स्ट्रिंग में ("के \nरूप में टैब" को " " के रूप में दर्ज किया जाना चाहिए) \t, किसी भी यूनिकोड वर्ण को दर्ज किया जाना चाहिए \u####)

w=>{for(a=[],b=[],c=[],d=[],f=[],e=[],k=0;k<(g=w.length);a[k++]=h)for(b[R='push']([]),h=[d[k]=f[k]=j=i=0];i++<g-k;){while(j&&w[k+i]!=w[k+j])j=h[j-1];w[k+i]==w[k+j]&&j++,h[R](j)}for(k=0;k<g;k++)for(j=i=0;i<g;i++)if(w[i]!=w[k+j]){while(j&&w[i]!=w[k+j])j=a[k][j-1];w[i]==w[k+j]?i--:b[k][R](j)}else b[k][R](++j);for(k=0;k<g;c[k++]=l){for(h=f.map(Q=>i=l=0);i<g;)h[b[k][i++]]++;for(;i;)h[i]==3?(l=i,i=0):a[k][--i]?h[a[k][i]]+=h[i+1]:0}for(k=0;g>k++;)for(i=0;(S=c[k])&&i<g;)b[k][i++]==S?d[i-S]=S:0;for(k=0;k<g;k++)for(e[R](w.slice(k,(S=d[k])+k)),i=1;i<S;)f[k+i]=1,f[k]|=S<d[k+i]+i++;f.map((X,i)=>(P=e[i],X?e=e.map(Y=>P==Y?"":Y):0));return e.join``}

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

यह कैसे काम करता है और असम्बद्ध कोड की व्याख्या

सबसे पहले, कार्यक्रम हर संभव विकल्प के लिए नथ मॉरिस प्रैट सरणियों को उत्पन्न करता है;

for(index=0;index<word.length;index++){
  kmpArray=[0];
  j=0;
  for(i=1;i<word.length-index;i++){
    while(j&&word.charAt(index+i)!=word.charAt(index+j)){
      j=kmpArray[j-1];
    }
    if(word.charAt(index+i)==word.charAt(index+j)){
      j++;
    }
    kmpArray.push(j);
  }
  kmpArrays.push(kmpArray);
}

इसके बाद, प्रोग्राम प्रत्येक सब्जेक्ट के साथ शब्द के प्रत्येक इंडेक्स पर अधिकतम मिलान लंबाई पाता है। (यह O (n ^ 2) समय है)

for(index=0;index<word.length;index++){
  j=0;
  matchLength=[];
  for(i=0;i<word.length;i++){
    if(word.charAt(i)!=word.charAt(index+j)){
      while(j&&word.charAt(i)!=word.charAt(index+j)){
        j=kmpArrays[index][j-1];
      }
      if(word.charAt(i)==word.charAt(index+j)){
        i--;
      }else{
        matchLength.push(j);
      }
    }else{
      j++;
      matchLength.push(j);
      if(j==kmpArrays[index].length){
        j=kmpArrays[index][j-1];
      }
    }
  }
  matchLengths.push(matchLength);
}

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

for(index=0;index<word.length;index++){
  counts=[]
  max=0;
  for(i=0;i<=word.length;i++){
    counts.push(0);
  }
  for(i=0;i<word.length;i++){
    counts[matchLengths[index][i]]++;
  }
  for(i=word.length-1;i>0;i--){
    if(counts[i]==3){
      max=i;
      break;
    }
    if(kmpArrays[index][i-1]){ //if this value has a smaller value it could be as well
      counts[kmpArrays[index][i]]+=counts[i-1];
    }
  }
  maxLengths.push(max);
}

प्रोग्राम इस डेटा का उपयोग उन सभी सब्सट्रिंग को खत्म करने के लिए करता है जो तीन बार बिल्कुल नहीं दिखाई देते हैं और सबसे लंबे समय तक के सब सब्सट्रेटिंग होते हैं।

for(index=0;index<word.length;index++){
  if(!maxLengths[index])
    continue;
  for(i=0;i<word.length;i++){
    if(matchLengths[index][i]==maxLengths[index]){
      tokens[i-maxLengths[index]+1]=maxLengths[index];
    }
  }
}

इसके बाद, प्रोग्राम को हटाए जाने के रूप में सभी अतिव्यापी या आंशिक सबस्ट्रिंग सेट करता है।

for(index=0;index<word.length;index++){
  sStrs.push(word.substring(index,tokens[index]+index));
  for(i=1;i<tokens[index];i++){
    toRemove[index+i]=1;
    if(tokens[index]<tokens[index+i]+i){
      toRemove[index]=1;
    }
  }
}

प्रत्येक निकाले जाने वाले मानों के लिए, सभी समतुल्य सबस्ट्रिंग को भी हटा दिया जाता है।

for(index=0;index<word.length;index++){
  if(toRemove[index]){
    removal=sStrs[index];
    for(i=0;i<3;i++){
      indxOf=sStrs.indexOf(removal);
      sStrs[indxOf]="";
      toRemove[indxOf]=0;
    }
  }
}

अंत में, कार्यक्रम एक साथ सबस्ट्रिंग की सरणी में शामिल होता है और इसे आउटपुट करता है।


1
आपके पास कुछ whileऔर ifब्लॉक हैं जिनके अंदर केवल 1 स्टेटमेंट है। आप {}उन विवरणों के आसपास ब्रेसिज़ निकाल सकते हैं । उदाहरण के लिए, if(word.charAt(index+i)==word.charAt(index+j)){j++;}बन सकते हैंif(word.charAt(index+i)==word.charAt(index+j))j++;
कृति लिथोस

मैंने बयानों &&को प्रतिस्थापित करने के लिए उपयोग किया if, मैंने लूप्स में चारों ओर बयानों को स्थानांतरित किया ताकि वे उनके तहत एक बयान के साथ समाप्त हो जाएं ताकि मैं ब्रेसिज़ निकाल सकूं। मैंने कुछ बयानों को बदलने के लिए टर्नरीज़ का इस्तेमाल किया। मैंने सामान इधर-उधर किया और 946 बाइट पर समाप्त हुआ । अगर आपको कुछ समझ नहीं आ रहा है, तो बेझिझक मुझसे पूछें :)
Kritii Lithos

इस बिंदु पर गोल्फिंग के साथ मेरी मुख्य समस्या यह समझने की कोशिश है कि मैंने वहां क्या लिखा है। मुझे यह भी पता नहीं है कि मैं जावास्क्रिप्ट में गोल्फिंग के लिए क्या अनुकूलन कर सकता हूं।
f --n 18:tɪk

क्या आप एक अलग चैट रूम में इस पर चर्चा करना चाहते हैं?
क्रिकेई लिथोस

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