রেগেক্সেস সংকলন করুন


17

এই টাস্কে আপনাকে এমন একটি প্রোগ্রাম লিখতে হবে যা নিয়মিত এক্সপ্রেশন পড়ে এবং এমন একটি প্রোগ্রাম উত্পন্ন করে যা কোনও ইনপুট স্ট্রিং সেই নিয়মিত এক্সপ্রেশন দ্বারা গৃহীত হয় কিনা তা আউটপুট করে। আউটপুটটি অবশ্যই আপনার জমা দেওয়ার মতো ভাষায় লিখিত একটি প্রোগ্রাম হতে হবে।

ইনপুট

ইনপুট একটি রেগুলার এক্সপ্রেশন হয় নিম্নলিখিত ABNF (প্রাথমিক উৎপাদন নিয়ম মিলে REGEX):

REGEX       = *( STAR / GROUP / LITERAL / ALTERNATIVE )
STAR        = REGEX '*'
GROUP       = '(' REGEX ')'
LITERAL     = ALPHA / DIGIT
ALTERNATIVE = REGEX '|' REGEX

যদি ইনপুটটি এই ব্যাকরণের সাথে মেলে না, তবে আপনার প্রোগ্রামের আচরণটি সংজ্ঞায়িত।

ব্যাখ্যা

নিয়মিত অভিব্যক্তি হিসাবে ইনপুটটির ব্যাখ্যা করুন, যেখানে *ক্লিন-স্টার (যার অর্থ বাম আর্গুমেন্ট শূন্য বা আরও অনেকবার পুনরাবৃত্তি করা ), |এটি বিকল্প (এবং )গ্রুপ এবং কোনও অপারেটর একেবারে কন্টেনটেটেড নয়। গোষ্ঠীকরণ তারার চেয়ে অগ্রাধিকার গ্রহণ করে, তারকা সংক্ষিপ্তকরণের চেয়ে অগ্রাধিকার গ্রহণ করে, বিকল্পের চেয়ে সংক্ষিপ্তকরণকে প্রাধান্য দেয়।

যদি রেজেক্স পুরো স্ট্রিংয়ের সাথে মেলে তবে একটি স্ট্রিং গ্রহণযোগ্য হবে ।

আউটপুট

প্রোগ্রামের আউটপুট একটি স্ট্রিং সার্চ আপনার জমা হিসাবে একই ভাষায় লেখা অন্য প্রোগ্রাম গুলি রানটাইম এ একটি বাস্তবায়ন সংজ্ঞায়িত ভাবে, আউটপুট কিনা গ্রহণ গুলি এবং তারপর বন্ধ। আউটপুটটি ব্যবহারকারী-সংজ্ঞায়িত উপায়ে করা যেতে পারে যদিও স্বীকৃত এবং প্রত্যাখ্যাত প্রোগ্রামগুলির জন্য মাত্র দুটি স্বতন্ত্র আউটপুট থাকতে হবে।

আপনি ধরে নিতে পারেন যে আপনার আউটপুট প্রোগ্রামের ইনপুটটি কখনই 2 16 -1 বাইটের বেশি হয় না ।

বিধিনিষেধ

আপনার জমা বা আপনার জমা দ্বারা উত্পন্ন কোনও প্রোগ্রামই অন্তর্নির্মিত কার্যকারিতা বা লাইব্রেরি ব্যবহার করতে পারে না

  • ম্যাচ রেজেক্সেস
  • নিয়মিত এক্সপ্রেশন রূপান্তর
  • নিয়মিত অভিব্যক্তি সংকলন
  • ব্যাকরণ থেকে পার্সার তৈরি করুন
  • সমস্যাটি এমনভাবে সহজ করুন যাতে আপনার জমাটি তুচ্ছ হয়ে যায়

স্কোরিং

আপনার জমা দেওয়ার স্কোর এটির অক্ষরের সংখ্যা। সর্বনিম্ন স্কোর সহ জমাটি জয়লাভ করে।

Testcases

সমস্ত টেস্টকেসগুলিতে একটি নিয়মিত প্রকাশ, স্বীকৃত স্ট্রিংগুলির একটি সেট, প্রত্যাখ্যাত স্ট্রিংগুলির একটি সেট এবং সি 99 এর একটি উদাহরণ প্রোগ্রাম রয়েছে যা একটি (হাইপোথেটিক্যাল) সি 99 জমা দেওয়ার বৈধ আউটপুট।

(খালি নিয়মিত প্রকাশ)

স্বীকৃত স্ট্রিং

  1. (খালি ইনপুট)

প্রত্যাখাত স্ট্রিং

  1. foo বিন্যাস
  2. বার
  3. বায
  4. quux

উদাহরণ প্রোগ্রাম

#include <stdio.h>

int main() {
    char input[65536];
    gets(input);

    return input[0] != 0;
}

(b|)(ab)*(a|)( aএবং bবিকল্প)

স্বীকৃত স্ট্রিং

  1. a
  2. ba
  3. abababababa
  4. abab

প্রত্যাখাত স্ট্রিং

  1. afba
  2. foo
  3. babba

উদাহরণ প্রোগ্রাম

#include <stdio.h>

int main() {
  char input[65536];
  int state = 0;

  for (;;) switch (state) {
    case 0: switch (getchar()) {
      case 'a': state = 1; break;
      case 'b': state = 2; break;
      case EOF: return 0;
      default:  return 1;
    } break;
    case 1: switch (getchar()) {
      case 'b': state = 2; break;
      case EOF: return 0;
      default:  return 1;
    } break;
    case 2: switch (getchar()) {
      case 'a': state = 1; break;
      case EOF: return 0;
      default:  return 1;
    } break;
}

(0|1(0|1)*)(|A(0|1)*1) (বাইনারি ভাসমান পয়েন্ট সংখ্যা)

স্বীকৃত স্ট্রিং

  1. 10110100
  2. 0
  3. 1A00001

প্রত্যাখাত স্ট্রিং

  1. ২011
  2. 10A
  3. 1A00
  4. 100A010

1
আমি অনুমান করি যে এর মতো প্রোগ্রাম করার return (regex.match(stdin) is not null)অনুমতি নেই।
beary605

1
আপনি বলছেন যে "আউটপুটটি অবশ্যই ইনপুট হিসাবে একই ভাষায় লিখিত একটি প্রোগ্রাম হতে হবে", তবে ইনপুটটি একটি রেজেস। এবং আপনার প্রদত্ত ব্যাকরণটিতে GROUP বিধিটি অন্তর্ভুক্ত নেই, যা সম্ভবত আক্ষরিক বন্ধনী সংজ্ঞায়িত করে।
পিটার টেলর

@ পিটার দুঃখিত, আমি বোঝাতে চাইছিলাম তারা জমা দেওয়ার মতো একই ভাষা লিখবে।
FUZxxl

@ বেরি 605 হ্যাঁ, আপনি ঠিক বলেছেন। বিভাগটি সীমাবদ্ধতাগুলি দেখুন : আপনার জমা দেওয়া বা আপনার জমা দেওয়ার ফলে উত্পন্ন কোনও প্রোগ্রামই বিল্টিন কার্যকরীতা বা লাইব্রেরিগুলি ব্যবহার করতে পারে না যা রেজেক্সগুলির সাথে মেলে (...)।
FUZxxl

আমি মনে করি আপনার দ্বিতীয় উদাহরণের প্রোগ্রামটি ভুল, এটি বাইরের সুইচের চারপাশে একটি লুপ হারিয়েছে
হাস্তুরকুন

উত্তর:


8

রুবি, 641 651 543 টি অক্ষর

H=Hash.new{|h,k|[k]}
d=[[i=0,0,[]]]
o=[?(]
L="t,u,v=d.pop;q,r,s=d.pop;o.pop<?|&&(H[r]<<=t)||(H[q]<<=t;H[r]<<=u);d<<[q,u,s+v]"
gets.chop.chars.map{|c|c==?*&&(q,r,s=d.pop;H[r]|=[q,i+=1];d<<=[r,i,s];next)
eval(L)while/[|)]/=~c ?o[-1]>?(:o[-1]==?.
/[|(]/=~c&&d<<[i+=1,i,o<<c&&[]]||c!=?)&&d<<[i+=1,i+1,["s==#{o<<?.;i}&&c=='#{c}'&&#{i+=1}"]]||o[-1]=?.}
eval(L)while o.size>1
H.map{H.map{|k,v|v.map{|v|H[k]|=H[v]}}}
t,u,v=d[0]
$><<"s=#{H[t]};gets.chop.chars.map{|c|s=s.map{|s|#{v*'||'}}-[!0];#{H.map{|k,v|"s&[#{k}]!=[]&&s|=#{v}"}*?;}};p s&[#{u}]!=[]"

রেগেক্স পার্সারের বেশ কয়েকটি কোণার মামলার কারণে এই রুবি সংস্করণটি বেশ দীর্ঘ হয়ে গেছে (সম্ভবত আমার কোনও ভিন্ন পদ্ধতির চেষ্টা করা উচিত)। এটি STDIN- এ নিয়মিত প্রকাশের প্রত্যাশা করে এবং ম্যাচারের জন্য সম্পর্কিত রুবি কোডটি STDOUT এ আউটপুট করে।

প্রোগ্রামটি সরাসরি একটি এনএফএ- for এর জন্য কোড উত্পন্ন করে যা পরে ম্যাচারে কার্যকর করা হয়।

পরীক্ষার কেস 1: (আউটপুটটিতে অতিরিক্ত নতুন লাইন এবং অন্তর্ভুক্ত থাকে)

>>>

s=[0];
gets.chop.chars.map{|c|
  s=s.map{|s|}-[!0];
};
p s&[0]!=[]

পরীক্ষার কেস 2:

>>> (b|)(ab)*(a|)

s=[0, 1, 2, 4, 9, 5, 10, 6, 11, 12, 14];
gets.chop.chars.map{|c|
  s=s.map{|s|s==2&&c=='b'&&3||s==6&&c=='a'&&7||s==8&&c=='b'&&9||s==12&&c=='a'&&13}-[!0];
  s&[1]!=[]&&s|=[1, 2, 4, 9, 5, 10, 6, 11, 12, 14];
  s&[3]!=[]&&s|=[3, 4, 9, 5, 10, 6, 11, 12, 14];
  s&[0]!=[]&&s|=[0, 1, 2, 4, 9, 5, 10, 6, 11, 12, 14];
  s&[5]!=[]&&s|=[5, 6];
  s&[7]!=[]&&s|=[7, 8];
  s&[9]!=[]&&s|=[9, 5, 10, 6, 11, 12, 14];
  s&[4]!=[]&&s|=[4, 9, 5, 10, 6, 11, 12, 14];
  s&[11]!=[]&&s|=[11, 12, 14];
  s&[13]!=[]&&s|=[13, 14];
  s&[10]!=[]&&s|=[10, 11, 12, 14]
};
p s&[14]!=[]

আরেকটি উদাহরণ:

>>> a|bc

s=[0, 1, 3, 4];
gets.chop.chars.map{|c|
  s=s.map{|s|s==1&&c=='a'&&2||s==4&&c=='b'&&5||s==6&&c=='c'&&7}-[!0];
  s&[0]!=[]&&s|=[0, 1, 3, 4];
  s&[3]!=[]&&s|=[3, 4];
  s&[5]!=[]&&s|=[5, 6];
  s&[2]!=[]&&s|=[2, 7]
};
p s&[7]!=[]

সম্পাদনা করুন: বাগটি সংশোধন করার জন্য একটি ট্রানজিশন যুক্ত হয়েছে প্লিজ স্ট্যান্ড মন্তব্যগুলিতে উল্লিখিত। রাষ্ট্রের আদ্যক্ষর পরিবর্তিত হয়েছে।


011রেজেক্সের (0|1(0|1)*)(|A(0|1)*1)ফলাফলের জন্য ইনপুট true- এটি হওয়া উচিত false
প্লিজ স্ট্যান্ড

@ প্লিজস্ট্যান্ড স্থির আমার সম্পাদনা দেখুন।
হাওয়ার্ড

12

সি, 627 টি অক্ষর

এই প্রোগ্রামটি তার প্রথম কমান্ড-লাইন আর্গুমেন্টটিকে ইনপুট হিসাবে বিবেচনা করে এবং সি কোডটিকে এর আউটপুট হিসাবে উত্পন্ন করে।

#define A(v) F[v]+strlen(F[v])
#define S sprintf
char*B="&&f%d(s)||f%d(s)",*J="&&f%d(s+%d)",*r,F[256][65536];h=2;e(f,n,o,R,C,O,t,g){for(C=O=f;*r;++r)switch(*r){case 40:r++;e(g=h++,C=h++,0,0);r[1]^42?t=g:(t=C,S(A(t),B,g,C=h++),r++);o=!S(A(O),J,t,o);O=C;break;case 41:goto L;case'|':S(A(C),J,n,o);o=!S(A(O=f),"||1");break;default:r[1]^42?S(A(C),"&&s[%d]==%d",o++,*r,O^f||R++):(o=!S(A(O),J,t=h++,o),O=C=h++,g=h++,S(A(g),"&&*s==%d&&f%d(s+1)",*r++,t),S(A(t),B,g,C));}L:S(A(C),J,n,o);}main(int c,char**v){r=v[1];for(e(1,!S(*F,"&&!*s"),0,0);h--;)printf("f%d(char*s){return 1%s;}",h,F[h]);puts("main(int c,char**v){exit(f1(v[1]));}");}

এখানে এর জন্য আউটপুট (0|1(0|1)*)(|A(0|1)*1)(নতুন লাইন যুক্ত করা হয়েছে):

f11(char*s){return 1&&s[0]==49&&f7(s+1);}
f10(char*s){return 1&&s[0]==48&&f9(s+1)||1&&s[0]==49&&f9(s+1);}
f9(char*s){return 1&&f10(s)||f11(s);}
f8(char*s){return 1&&f7(s+0)||1&&s[0]==65&&f9(s+1);}
f7(char*s){return 1&&f0(s+0);}
f6(char*s){return 1&&f2(s+0);}
f5(char*s){return 1&&s[0]==48&&f4(s+1)||1&&s[0]==49&&f4(s+1);}
f4(char*s){return 1&&f5(s)||f6(s);}
f3(char*s){return 1&&s[0]==48&&f2(s+1)||1&&s[0]==49&&f4(s+1);}
f2(char*s){return 1&&f8(s+0);}
f1(char*s){return 1&&f3(s+0);}
f0(char*s){return 1&&!*s;}
main(int c,char**v){exit(f1(v[1]));}

যদি আপনি এর প্রথম কমান্ড-লাইন আর্গুমেন্ট হিসাবে বৈধ ইনপুট সরবরাহ করেন তবে এটি প্রস্থান স্থিতি 1 প্রদান করে Otherwise অন্যথায়, এটি প্রস্থান স্থিতি 0 প্রদান করে।

$ ./Regexcompiler '(0 | 1 (0 | 1) *) (| এ (0 | 1) * 1)'> floatprog.c
$ জিসিসি -o floatprog floatprog.c
floatprog.c: ফাংশন ইন 'প্রধান':
floatprog.c: 1: 519: সতর্কতা: বিল্ট ইন ফাংশন 'প্রস্থান' [ডিফল্টভাবে সক্রিয়] এর বেমানান অন্তর্নিহিত ঘোষণা
$ ./floatprog '1A00001' && প্রতিধ্বনি অবৈধ || echo বৈধ
বৈধ
$ ./floatprog '100A010' && প্রতিধ্বনি অবৈধ || প্রতিধ্বনি বৈধ
অবৈধ

হয় প্রোগ্রাম, আপনি যদি কমান্ড-লাইন আর্গুমেন্ট সরবরাহ করতে ব্যর্থ হন, একটি নাল পয়েন্টারকে dereferences করে, সেগমেন্টেশন ত্রুটি সৃষ্টি করে। পর্যাপ্ত দীর্ঘ রেজেেক্স এই জমা দেওয়ার বাফারগুলিকে উপচে ফেলবে এবং কোনও উত্পন্ন প্রোগ্রামে ইনপুটটির আকার স্ট্যাকের আকার দ্বারা সীমাবদ্ধ। তবে সব পরীক্ষার কেসই কাজ করে।

নোট যা অপরিবর্তিত e(g=h++,C=h++,0,0);আচরণের পরিচয় দেয়। যদি, উদাহরণস্বরূপ, উত্পন্ন প্রোগ্রামগুলি সংকলন না করে, আপনি বিবৃতিটি প্রতিস্থাপনের চেষ্টা করতে পারেন h+=2;e(g=h-1,C=h-2,0,0);, এটি দীর্ঘ পাঁচটি অক্ষর।

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