একটি ইভেন্ট টোকেনিসার লিখুন


24

পটভূমি

ঘটনাটি মোটামুটি অস্বাভাবিক প্রোগ্রামিংয়ের একটি ভাষা, যাতে এর টোকেনগুলির তালিকাটি পূর্বনির্ধারিত নয়, বরং ইনপুট থেকে অনুমান করা হয়। যেমনটি, কোনও ইভেন্ট প্রোগ্রামটি টোকেনাইজ করা মোটামুটি কঠিন হতে পারে, বিশেষত যদি আপনি দক্ষতার সাথে এটি করতে চান। এই টাস্কটি নিজেই করা সম্পর্কে।

কাজটি

আপনার প্রোগ্রামটিকে ইনপুট হিসাবে একটি স্ট্রিং দেওয়া হবে। ঘটনাটি টোকেনাইজ করার জন্য অ্যালগরিদমটি এখানে ব্যবহার করা হয়েছে:

  1. ঠিক তিনটি উপায়ে ইনপুটটির একটি স্ট্রিং হিসাবে উপস্থিত সমস্ত স্ট্রিংগুলি সনাক্ত করুন (অর্থাত ইনপুটটির মধ্যে সেই স্ট্রিংয়ের ঠিক তিনটি উপস্থিতি রয়েছে)।
  2. এই স্ট্রিং যে একটি অন্য ধরনের স্ট্রিং এর সাবস্ট্রিং করছে কোনো পরিত্যাগ করবেন (যেমন ইনপুট জন্য ababab, একমাত্র অবশিষ্ট স্ট্রিং হতে হবে ab, না aবা b, কারণ aএবং bউভয় সাবস্ট্রিং হয়ab )।
  3. ইনপুটটির মধ্যে ওভারল্যাপ হওয়া কোনও স্ট্রিং ফেলে দিন। (উদাহরণস্বরূপ, aaaaঠিক তিনটি অনুলিপি রয়েছে aa, তবে এই অনুলিপিগুলি দ্বিতীয় এবং তৃতীয় অক্ষরগুলিতে ওভারল্যাপ হয়, তাই এটি বাতিল করে দেওয়া হবে Like একইভাবে, abababaএখানে তিনটি অনুলিপি abএবং তিনটি অনুলিপি রয়েছে ba, তবে দ্বিতীয় থেকে ষষ্ঠ অক্ষরের প্রতিটি রয়েছে) একটি abএবং একটি এর ওভারল্যাপ ba, তাই উভয়ab এবং baপরিত্যাগ করা হবে)।
  4. এই পর্যায়ে থাকা যে কোনও স্ট্রিং হ'ল প্রোগ্রামটি ব্যবহৃত টোকেন। মূল ইনপুটটি এই টোকেনগুলির একটি ক্রমে টোকেন করুন (পূর্ববর্তী পদক্ষেপে বিযুক্ত হওয়ার কারণে, এটি করার একমাত্র উপায় থাকবে)। ইনপুটটিতে থাকা কোনও অক্ষর যা কোনও টোকেনের অংশ নয় সেগুলি মন্তব্য হিসাবে বিবেচিত হবে এবং বাতিল হবে।

আপনার প্রোগ্রামটিকে ইনপুট হিসাবে একটি স্ট্রিং নিতে হবে এবং আউটপুট হিসাবে স্ট্রিংয়ের টোকেনিসিয়েশন (টোকেনগুলির একটি তালিকা, যার প্রতিটি স্ট্রিং হিসাবে প্রকাশ করা হয়) ফিরিয়ে আনতে হবে। অতিরিক্তভাবে, এটি কমপক্ষে পরিমিতভাবে দক্ষতার সাথে করতে হবে; বিশেষত, প্রোগ্রামটি চতুষ্কোণ সময়ে ("O (n²)") বা আরও ভাল চালাতে হবে । (ঘটনাক্রমে, চতুর্ভুজ থেকে দ্রুত যাওয়া প্রায় নিশ্চিতভাবেই সম্ভব তবে এটি , তাই নির্বিঘ্নে সবচেয়ে নিখরচায় অ্যালগরিদম ব্যবহার করতে পারেন যা জটিলতার সীমানার মধ্যে ফিট করে find

ব্যাখ্যা

  • যদিও ঘটনামূলক প্রোগ্রামগুলিতে তাত্ত্বিকভাবে 256 টি অক্টেটের একটি থাকতে পারে তবে আপনার প্রোগ্রামটির জন্য প্রিন্টযোগ্য এএসসিআইআই (স্থান সহ), প্লাস নিউলাইন এবং ট্যাব কেবলমাত্র ইনপুটগুলি পরিচালনা করা আপনার প্রোগ্রামটির জন্য এই চ্যালেঞ্জের উদ্দেশ্যে গ্রহণযোগ্য। (সমস্ত পরিচিত ঘটনা প্রোগ্রামগুলি নিজেকে এই উপসেটটিতে সীমাবদ্ধ করে)। মনে রাখবেন যে স্থান / নিউলাইন / ট্যাবটি বিশেষ নয় এবং টোকেনের মাঝখানে উপস্থিত হতে পারে; ঘটনাটি 256 টি অক্টোটকে অস্বচ্ছ হিসাবে বিবেচনা করে।
  • "চতুর্ভুজ সময়" এর সংজ্ঞাটি হ'ল "যদি ইনপুটটির আকার দ্বিগুণ করা হয় তবে প্রোগ্রামটি ধ্রুবক প্লাস 4 এর গুণক ছাড়া আর ধীরে চলবে না, অর্থাত্ যদি টি ( এক্স ) আপনার প্রোগ্রামে সর্বাধিক সময় নেয় আকার x এর একটি ইনপুট প্রক্রিয়া করুন , তারপরে অবশ্যই কিছু ধ্রুবক কে থাকতে হবে যা সমস্ত x এর জন্য টি (2  x ) <4  টি ( এক্স ) + কে হবে । মনে রাখবেন যে স্ট্রিংগুলির তুলনা করতে স্ট্রিংগুলির দৈর্ঘ্যের সাথে সমানুপাতিক সময় লাগে।
  • আপনার প্রোগ্রামটি তাত্ত্বিকভাবে কোনও ভাষার দৈর্ঘ্যের ইনপুট প্রোগ্রামগুলি পরিচালনা করতে সক্ষম হতে পারে (সম্ভবত অনুমানের) আপনার ভাষার যে কোনও সীমাহীন মেমরি রয়েছে এবং আনবাউন্ডেড পূর্ণসংখ্যা ব্যবহার করে (ঠিক আছে যদি প্রোগ্রামটি অনুশীলনে চালিত হওয়ার সময় এই লক্ষ্য অর্জনে ব্যর্থ হয় তবে) ভাষার পূর্ণসংখ্যা বা মেমরি আসলে চূড়ান্তভাবে বড়) আপনি ধরে নিতে পারেন (জটিলতা নিরূপণের উদ্দেশ্যে) যে ইনপুটগুলির দৈর্ঘ্যের চেয়ে বড় নয় এমন পূর্ণসংখ্যাকে ধ্রুবক সময়ের সাথে তুলনা করা যায় (যদিও মনে রাখবেন যে আপনি যদি বৃহত্তর মান ব্যবহার করেন, উদাহরণস্বরূপ ইনপুটকে রূপান্তর করার কারণে একক পূর্ণসংখ্যা, তারা যে সংখ্যার সাথে আছে তার সংখ্যার সাথে আনুপাতিক তুলনা করতে দীর্ঘ সময় নিবে)।
  • উপরে বর্ণিত অ্যালগরিদমের মতো একই পদক্ষেপগুলি অনুসরণ না করা সত্ত্বেও জটিলতার সীমার মধ্যে উপযুক্ত যে কোনও অ্যালগরিদম ব্যবহার করতে পারেন, যতক্ষণ না এটি একই ফলাফল তৈরি করে।
  • এই ধাঁধাটি ইনপুট টোকনাইজিং সম্পর্কে, আউটপুটকে ফর্ম্যাট করার বিষয়ে নয়। যদি আপনার ভাষায় কোনও তালিকা আউটপুট করার সবচেয়ে প্রাকৃতিক উপায়ে একটি দ্ব্যর্থহীন বিন্যাস জড়িত (যেমন স্ট্রিংগুলিতে আক্ষরিক নিউলাইনগুলি থাকে বা স্ট্রিংগুলির মধ্যে সীমানা ছাড়াই থাকে) তবে আউটপুটটি দ্ব্যর্থহীন হয়ে যায় এই বিষয়টি নিয়ে চিন্তা করবেন না ( যতক্ষণ না তালিকার প্রকৃতপক্ষে নির্মিত হয়)। আপনি পরীক্ষার ক্ষেত্রে সহায়তা দেওয়ার জন্য আপনার জমা দেওয়ার দ্বিতীয় সংস্করণ তৈরি করতে চাইতে পারেন যা দ্ব্যর্থহীন আউটপুট উত্পাদন করে, তবে আসল সংস্করণটি এমন সংস্করণ যা স্কোরিংয়ের জন্য গণনা করা।

পরীক্ষা ক্ষেত্রে

নিম্নলিখিত ইনপুট স্ট্রিংয়ের জন্য:

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নাল-টার্মিনেটেড স্ট্রিং নেয় এবং টোকেনগুলি স্টডআউটে মুদ্রণ করে। নীচের কোড থেকে সমস্ত নতুনলাইন সরানো যেতে পারে।

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)নথ – মরিস – প্র্যাট অ্যালগরিদমের tজন্য প্যাটার্নের pজন্য সারণী তৈরি করে । অনুসন্ধান স্ট্রিং এবং আপডেটগুলির K(c)পরবর্তী চরিত্রটি প্রসেস করুন , এর বৃহত্তম উপসর্গের দৈর্ঘ্যcmp প্রসেস করুন, সর্বাধিক প্রসেস করা অক্ষরের শেষে থাকা পাওয়া যাবে।

প্রথম forলুপটিতে aস্ট্রিংয়ের প্রতিটি সূচকের জন্য আমরা mস্ট্রিংয়ের শুরুতে পুরো স্ট্রিংয়ে অনুসন্ধান করার সময় প্রতিটি সম্ভাব্য মানের বারের সংখ্যা গণনা করি a। তারপরে আমরা lবৃহত্তমটির জন্য সন্ধান করি যে দৈর্ঘ্য- lস্ট্রিংটি শুরু হয়ে aঠিক 3 বার ঘটেছিল। যদি এটি পূর্বের কোনও স্ট্রিংয়ের দ্বারা সম্পূর্ণরূপে অন্তর্ভুক্ত হওয়ার পক্ষে যথেষ্ট হয় তবে aআমরা এটিকে এড়িয়ে চলেছি ignore যদি এটি ওভারল্যাপ হয় তবে আমরা এর থেকে পূর্ববর্তী স্ট্রিংটি মুছব, zঅ্যারে রেকর্ডিং যা টোকেনগুলি রাখা হবে। অন্যথায়, এর দৈর্ঘ্যটি সংরক্ষণ করা হয়z

তারপরে, আমরা রেকর্ড থাকা টোকেনগুলির স্ট্রিংটি অনুসন্ধান করতে আবার কেএমপি ব্যবহার করি z। যদি তাদের মধ্যে 0 টি প্রবেশের জায়গায় কোনও স্থানে পাওয়া যায় তবে zআমরা জানি যে ওভারল্যাপের কারণে এই টোকেনটি মোছা হয়েছিল। টোকেনটি মোছা না হলে এটি মুদ্রিত হয়।


1
এর সময়ের জটিলতা কী? O(n^2)দ্রুত বা দ্রুত হতে হবে। আর কেনই বা আছে !!!!z[x-m]?
Yytsi

2
@ টুকুএক্সএক্স এটি ঠিক ও (n ^ 2)। *Zপরবর্তী টোকেনটির দৈর্ঘ্য যা 0 হওয়া দরকার যদি টোকেনের অন্যান্য উপস্থিতিগুলির মধ্যে যদি !!z[x-m]
কোনওটির সূচকে

ঠিক আছে। তবে কেন আমি সেখানে রয়েছি তা এখনও বুঝতে পারি না !!!!xএখনও থাকা উচিত x, বা এটি এমন কৌশল অবলম্বন করে যা আমি জানি না?
ইয়াতসি

@TuukkaX ওয়েল, !!xতোলে xএকটি বুলিয়ান তার "truthiness" উপস্থাপন করে। সুতরাং, !!1 == trueএবং !!0 == false। আমি সি বিশেষভাবে জানি না, কিন্তু যে কিভাবে এটি সাধারণত যায়
কোনোর ব্রায়েন

7

জাভাস্ক্রিপ্ট, 878 867 842 825 775 752 717 712 704 673 664 650 641 বাইট

কোডটি গল্ফকে সহায়তার জন্য @ ক্রিটিক্সী লিথোসকে ধন্যবাদ
জন্য @ ক্রিটিক্সী লিথোসকে ধন্যবাদ 14 ইউটিউব গল্ফ করার জন্য @ ইউজার 2428118

(আই 7 এ কাজ করবে না) (নিউলাইনগুলি ইনপুট স্ট্রিংয়ে " \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);
}

এরপরে, প্রোগ্রামটি প্রতিটি স্ট্রিংয়ের সাথে শব্দের প্রতিটি একক সূচকে সর্বাধিক মিলের দৈর্ঘ্য সন্ধান করে। (এটি ও (এন ^ 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 বাইট শেষ । আমি যদি কিছু করে না বুঝতে পারি তবে আমাকে নির্দ্বিধায় জিজ্ঞাসা করুন :)
ক্রিটিক্সী লিথোস

এই মুহুর্তে গল্ফ করাতে আমার মূল সমস্যাটি আমি সেখানে কী লিখেছি তা বোঝার চেষ্টা করছে। জাভাস্ক্রিপ্টে গল্ফ করার জন্য আমি কী অপটিমাইজেশন করতে পারি তা আমি জানি না।
fəˈnɛtɪk

আপনি কি আলাদা চ্যাটরুমে এটি নিয়ে আলোচনা করতে চান?
ক্রিটসি লিথোস

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.