আমরা কীভাবে জাভা রেগেক্সের সাথে একটি ^ nb match n টি মিলাতে পারি?


99

এটি শিক্ষামূলক রেজেক্স নিবন্ধগুলির একটি সিরিজের দ্বিতীয় অংশ। এটি দেখায় যে কীভাবে লুক-হেডগুলি এবং নেস্টেড রেফারেন্সগুলি অ-নিয়মিত ল্যাঙ্গুয়েজ সাথে মিলিত করতে ব্যবহৃত হতে পারে একটি এন বি এন । নেস্টেড রেফারেন্সগুলি প্রথমে প্রবর্তিত হয়: এই রেজেক্সটি ত্রিভুজাকার সংখ্যাগুলি কীভাবে খুঁজে পায়?

আদি অ এক নিয়মিত ভাষায় হল:

L = { an bএন: n > 0 }

এটি সমস্ত অ-খালি স্ট্রিংয়ের ভাষা যা কিছু সংখ্যক সমন্বিত এবং aএর সমান সংখ্যক সংখ্যার সমন্বয়ে গঠিত b। এই ভাষাতে স্ট্রিং উদাহরণ হল ab, aabb, aaabbb

এই ভাষাটি পাম্পিং লেমা দ্বারা অ-নিয়মিত হতে দেখানো যেতে পারে । এটি আসলে একটি প্রত্নতাত্ত্বিক প্রসঙ্গমুক্ত ভাষা , যা প্রসঙ্গমুক্ত ব্যাকরণ দ্বারা উত্পাদিত হতে পারে S → aSb | ab

তবুও, আধুনিক দিনের রেজেক্স বাস্তবায়নগুলি কেবল নিয়মিত ভাষাগুলির চেয়ে বেশি পরিষ্কারভাবে স্বীকৃতি দেয়। এটি, আনুষ্ঠানিক ভাষা তত্ত্ব সংজ্ঞা দ্বারা তারা "নিয়মিত" নয়। পিসিআরই এবং পার্ল পুনরাবৃত্তিমূলক রেজেক্সকে সমর্থন করে এবং .NET ব্যালেন্সিং গ্রুপ সংজ্ঞা সমর্থন করে। এমনকি "অভিনব" বৈশিষ্ট্যগুলি, যেমন ব্যাকরেফারেন্সের মিল, এর অর্থ হ'ল রেগেক্স নিয়মিত নয়।

তবে এই "বেসিক" বৈশিষ্ট্যগুলি কতটা শক্তিশালী? Lউদাহরণস্বরূপ, আমরা জাভা রেজেক্সের সাথে চিনতে পারি ? আমরা সম্ভবত lookarounds এবং নেস্টেড রেফারেন্স মেশা এবং একটি প্যাটার্ন যে যেমন কাজ করে থাকতে পারে String.matchesমত স্ট্রিং মেলে ab, aabb, aaabbb, ইত্যাদি?

তথ্যসূত্র

সংযুক্ত প্রশ্ন


4
এই সিরিজটি সম্প্রদায়ের কারও অনুমতি নিয়ে শুরু হয়েছিল ( কারও কারও meta.stackexchange.com/questions/62695/… )। যদি অভ্যর্থনাটি ভাল হয়, তবে আমি রেগেক্সের আরও উন্নত এবং সেই সাথে আরও বেসিক বৈশিষ্ট্যগুলিও কভার করে রাখার পরিকল্পনা করছি।
বহুবৃক্ষীয় পদার্থ


বাহ, আমি কখনই জানতাম না জাভা এর রেজেক্সগুলি নিয়মিত অভিব্যক্তিগুলিতে সীমাবদ্ধ থাকবে না। আমি অনুমান করি যে এটি ব্যাখ্যা করে যে কেন আমি সর্বদা ভেবেছিলাম তারা সম্পূর্ণরূপে বাস্তবায়িত হবে না। আমার অর্থ হ'ল জাভা রেজেক্সগুলিতে কোনও পরিপূরক, পার্থক্য বা পণ্য অপারেটর নেই, তবে এটি নিয়মিত ভাষায় সীমাবদ্ধ নয় বলেই তা বোঝা যায়।
ল্যান

এই প্রশ্নটি "অ্যাডভান্সড রেজেক্স-ফু" এর অধীনে স্ট্যাক ওভারফ্লো নিয়মিত এক্সপ্রেশন FAQ এ যুক্ত করা হয়েছে ।
aliteralmind

উত্তর:


141

উত্তরটি বলা বাহুল্য, হ্যাঁ! আপনি সবচেয়ে অবশ্যই একটি জাভা Regex প্যাটার্ন মেলে লিখতে পারেন একটি এন বি এন । এটি দৃ for়তার জন্য ইতিবাচক চেহারা এবং "গণনা" করার জন্য নেস্টেড রেফারেন্স ব্যবহার করে।

তাত্ক্ষণিকভাবে প্যাটার্নটি দেওয়ার পরিবর্তে, এই উত্তরটি পাঠকদের এটিকে উত্পন্ন করার প্রক্রিয়াটির মধ্যে গাইড করবে। সমাধানটি ধীরে ধীরে নির্মিত হওয়ায় বিভিন্ন ইঙ্গিত দেওয়া হয়। এই দিকটিতে, আশা করি এই উত্তরটিতে অন্য একটি ঝরঝরে রেগেক্স প্যাটার্নের চেয়ে অনেক বেশি কিছু থাকবে। আশা করি পাঠকরা কীভাবে "রেগেক্সে ভাববেন" এবং বিভিন্ন কন্সট্রাক্টসকে কীভাবে সুরেলাভাবে স্থাপন করবেন তা শিখবেন, যাতে ভবিষ্যতে তারা নিজেরাই আরও নিদর্শনগুলি অর্জন করতে পারে।

সমাধানটি বিকাশের জন্য ব্যবহৃত ভাষাটি তার সংক্ষিপ্ততার জন্য পিএইচপি হবে। প্যাটার্নটি চূড়ান্ত হওয়ার পরে চূড়ান্ত পরীক্ষা জাভাতে করা হবে।


পদক্ষেপ 1: দৃ for়তা জন্য তাকাতে

আসুন একটি সহজ সমস্যা দিয়ে শুরু করুন: আমরা a+একটি স্ট্রিংয়ের শুরুতে মেলাতে চাই , তবে কেবল যদি তা অবিলম্বে অনুসরণ করা হয় b+। আমরা আমাদের ম্যাচটি নোঙ্গর করতে ব্যবহার ^করতে পারি , এবং যেহেতু আমরা কেবল এটি ছাড়া ম্যাচটি করতে চাইa+b+ , আমরা ব্যবহার করতে পারেন lookahead কথন (?=…)

একটি সাধারণ পরীক্ষার জোতা সহ আমাদের প্যাটার্নটি এখানে:

function testAll($r, $tests) {
   foreach ($tests as $test) {
      $isMatch = preg_match($r, $test, $groups);
      $groupsJoined = join('|', $groups);
      print("$test $isMatch $groupsJoined\n");
   }
}
 
$tests = array('aaa', 'aaab', 'aaaxb', 'xaaab', 'b', 'abbb');
 
$r1 = '/^a+(?=b+)/';
#          └────┘
#         lookahead

testAll($r1, $tests);

আউটপুটটি হয় ( যেমন আদর্শ আইটেম ):

aaa 0
aaab 1 aaa
aaaxb 0
xaaab 0
b 0
abbb 1 a

এটি হ'ল আউটপুট আমরা চাই: আমরা মেলে a+ স্ট্রিংয়ের শুরুতে কেবল তখনই মিলি এবং কেবল যদি তা অবিলম্বে অনুসরণ করা হয় b+

পাঠ : আপনি দৃser়তার সাথে দৃশ্যের জন্য নিদর্শনগুলি ব্যবহার করতে পারেন।


পদক্ষেপ 2: নজরদারি করা ক্যাপচারিং (এবং ফ্রি - স্পেসিং মোড)

এখন বলি যে আমরা b+ম্যাচের অংশ হতে চাই না, তবুও আমরা যেভাবেই হোক এটি গ্রুপ 1 এ ক্যাপচার করতে চাই । এছাড়াও, আমরা আরও জটিল ধাঁচের প্রত্যাশা করে, আসুন ফ্রি-x স্পেসিংয়ের জন্য পরিবর্তনকারীটি ব্যবহার করি আমরা করি যাতে আমরা আমাদের রেজেক্স আরও পঠনযোগ্য করে তুলতে পারে।

আমাদের পূর্ববর্তী পিএইচপি স্নিপেটে বিল্ডিং, আমাদের এখন নিম্নলিখিত প্যাটার্ন রয়েছে:

$r2 = '/ ^ a+ (?= (b+) ) /x';
#             │   └──┘ │
#             │     1  │
#             └────────┘
#              lookahead
 
testAll($r2, $tests);

আউটপুটটি এখন ( আইডিয়োন.কম এ দেখা যায় ):

aaa 0
aaab 1 aaa|b
aaaxb 0
xaaab 0
b 0
abbb 1 a|bbb

নোট করুন যে, প্রতিটি গ্রুপ কী কী ক্যাপচার aaa|bকরেছিল তার ফলাফল । এই ক্ষেত্রে, গ্রুপ 0 (অর্থাত প্যাটার্নটির সাথে কী মিলছে) এবং গ্রুপ ১ টি ক্যাপচার করেছেjoin'|'aaab

পাঠ : আপনি একটি দর্শনীয় স্থানের ভিতরে ক্যাপচার করতে পারেন। আপনি পঠনযোগ্যতা বাড়াতে ফ্রি-স্পেসিং ব্যবহার করতে পারেন।


পদক্ষেপ 3: "লুপ" এর দিকে তাকাতে পুনরুদ্ধার করা

আমরা আমাদের গণনা প্রক্রিয়াটি চালু করার আগে আমাদের প্যাটার্নে একটি পরিবর্তন করতে হবে। বর্তমানে, চেহারাটি +পুনরাবৃত্তি "লুপ" এর বাইরে । এই জরিমানা এতদূর কারণ আমরা শুধু জাহির করা চেয়েছিলেন একটি আছে যে b+নিম্নলিখিত আমাদের a+, কিন্তু কি আমরা সত্যিই অবশেষে কাজ করতে চান দাবী করে যে, প্রতিটি জন্য aযে, আমরা 'লুপ "ভিতরে মেলে, একটি সংশ্লিষ্টb এটা দিয়ে যান।

আসুন আপাতত গণনা প্রক্রিয়া সম্পর্কে উদ্বিগ্ন হবেন না এবং কেবল নীচে রিফ্যাক্টরিংটি করুন:

  • প্রথম refactor a+করার (?: a )+(নোট যে(?:…) কোনো অ-ক্যাপচার গ্রুপ)
  • তারপরে এই নন-ক্যাপচারিং গোষ্ঠীর ভিতরে চেহারাটি সরান
    • নোট করুন যে আমাদের a*"দেখার" আগে আমাদের এখন "এড়িয়ে" যেতে হবে b+, সুতরাং সেই অনুযায়ী প্যাটার্নটি পরিবর্তন করুন

সুতরাং আমাদের এখন নিম্নলিখিত আছে:

$r3 = '/ ^ (?: a (?= a* (b+) ) )+ /x';
#          │     │      └──┘ │ │
#          │     │        1  │ │
#          │     └───────────┘ │
#          │       lookahead   │
#          └───────────────────┘
#           non-capturing group

আউটপুট পূর্বের মতোই ( আইডিয়োন.কম এ দেখা গেছে ), সুতরাং সে ক্ষেত্রে কোনও পরিবর্তন নেই। গুরুত্বপূর্ণ বিষয় যে এখন আমরা কথন উপার্জন হয় প্রতি পুনরাবৃত্তির এর +"লুপ"। আমাদের বর্তমান প্যাটার্ন সহ, এটি প্রয়োজনীয় নয়, তবে পরবর্তী আমরা স্ব-রেফারেন্স ব্যবহার করে আমাদের জন্য গোষ্ঠী 1 "গণনা" করব।

পাঠ : আপনি একটি নন-ক্যাপচারিং গ্রুপের মধ্যে ক্যাপচার করতে পারেন। লুকোয়ারাউন্ডগুলি পুনরাবৃত্তি করা যেতে পারে।


পদক্ষেপ 4: এটি সেই পদক্ষেপ যেখানে আমরা গণনা শুরু করি

এখানে আমরা যা করতে যাচ্ছি: এখানে আমরা ১ টি গ্রুপ আবার লিখব যে:

  • এর প্রথম পুনরাবৃত্তির শেষে +, কখন প্রথমa মেলে, এটি ক্যাপচার করা উচিতb
  • দ্বিতীয় পুনরাবৃত্তির শেষে, যখন অন্যটির aমিল হয়, এটি ক্যাপচার করা উচিতbb
  • তৃতীয় পুনরাবৃত্তির শেষে এটি ক্যাপচার করা উচিত bbb
  • ...
  • N -th পুনরাবৃত্তির শেষে , 1 গোষ্ঠীটি b n কে ক্যাপচার করবে
  • যদি bগ্রুপ 1 এ ক্যাপচার করার জন্য পর্যাপ্ত পরিমাণ না থাকে তবে জোর দেওয়া ব্যর্থ হয়

সুতরাং গ্রুপ 1, যা এখন (b+), এর মতো কিছুতে আবার লিখতে হবে (\1 b)। এটি হ'ল, আমরা bপূর্ববর্তী পুনরাবৃত্তিতে 1 গোষ্ঠীটি কী গ্রুপে বন্দী হয়েছে তা "যুক্ত" করার চেষ্টা করি ।

এখানে একটি সামান্য সমস্যা আছে যে এই প্যাটার্নটি "বেস কেস" অনুপস্থিত, অর্থাত্ আত্ম-রেফারেন্স ছাড়াই এটি মিলবে। একটি বেস কেস প্রয়োজন কারণ গ্রুপ 1 "অবিচ্ছিন্ন" শুরু করে; এটি এখনও কিছু ক্যাপচার করেনি (একটি খালি স্ট্রিংও নয়), সুতরাং একটি স্ব-উল্লেখের চেষ্টা সর্বদা ব্যর্থ হবে।

এর চারপাশে অনেকগুলি উপায় রয়েছে তবে আপাতত স্ব-রেফারেন্সের মিলটি al চ্ছিক করা যাক \1?। এটি পুরোপুরি কার্যকর হতে পারে বা নাও পারে তবে আসুন এটি কী করে তা কেবল দেখুন এবং যদি কোনও সমস্যা হয় তবে আমরা যখন সেতুটি পৌঁছে যাব তখন এটি অতিক্রম করব। এছাড়াও, আমরা যখন থাকি তখন আমরা আরও কয়েকটি পরীক্ষার কেস যুক্ত করব।

$tests = array(
  'aaa', 'aaab', 'aaaxb', 'xaaab', 'b', 'abbb', 'aabb', 'aaabbbbb', 'aaaaabbb'
);
 
$r4 = '/ ^ (?: a (?= a* (\1? b) ) )+ /x';
#          │     │      └─────┘ | │
#          │     │         1    | │
#          │     └──────────────┘ │
#          │         lookahead    │
#          └──────────────────────┘
#             non-capturing group

আউটপুটটি এখন ( আইডিয়োন.কম এ দেখা যায় ):

aaa 0
aaab 1 aaa|b        # (*gasp!*)
aaaxb 0
xaaab 0
b 0
abbb 1 a|b          # yes!
aabb 1 aa|bb        # YES!!
aaabbbbb 1 aaa|bbb  # YESS!!!
aaaaabbb 1 aaaaa|bb # NOOOOOoooooo....

এ-হা! দেখে মনে হচ্ছে আমরা এখন সমাধানের খুব কাছে এসেছি! আমরা স্ব-রেফারেন্স ব্যবহার করে গ্রুপ 1 থেকে "গণনা" করতে সক্ষম হয়েছি! তবে অপেক্ষা করুন ... দ্বিতীয় এবং শেষ পরীক্ষার কেসে কিছু ভুল আছে !! পর্যাপ্ত পরিমাণ নেই b, এবং কোনওভাবে এটি ভুল হিসাবে গণ্য হয়েছে! পরবর্তী পদক্ষেপে কেন এমনটি হয়েছিল তা আমরা পরীক্ষা করব।

পাঠ : স্ব-রেফারেন্সিং গোষ্ঠীর "আরম্ভ" করার এক উপায় হ'ল স্ব-রেফারেন্সের মিলটি alচ্ছিক করে তোলা।


পদক্ষেপ 4½: কী ভুল হয়েছে তা বোঝা

সমস্যাটি হ'ল যেহেতু আমরা স্ব-রেফারেন্সের মিলটি optionচ্ছিকভাবে তৈরি করেছি, তাই পর্যাপ্ত পরিমাণগুলি না থাকলে "কাউন্টার" 0 এ "পুনরায় সেট" করতে পারে b। আসুন নিবিড়ভাবে aaaaabbbইনপুট হিসাবে আমাদের নিদর্শন প্রতিটি পুনরাবৃত্তি যা ঘটে তা পরীক্ষা ।

 a a a a a b b b
↑
# Initial state: Group 1 is "uninitialized".
           _
 a a a a a b b b
  ↑
  # 1st iteration: Group 1 couldn't match \1 since it was "uninitialized",
  #                  so it matched and captured just b
           ___
 a a a a a b b b
    ↑
    # 2nd iteration: Group 1 matched \1b and captured bb
           _____
 a a a a a b b b
      ↑
      # 3rd iteration: Group 1 matched \1b and captured bbb
           _
 a a a a a b b b
        ↑
        # 4th iteration: Group 1 could still match \1, but not \1b,
        #  (!!!)           so it matched and captured just b
           ___
 a a a a a b b b
          ↑
          # 5th iteration: Group 1 matched \1b and captured bb
          #
          # No more a, + "loop" terminates

এ-হা! আমাদের চতুর্থ পুনরাবৃত্তিতে, আমরা এখনও মেলাতে পারি \1, কিন্তু আমরা মেলতে পারি নি \1b! যেহেতু আমরা স্ব-রেফারেন্সের \1?মিলটি withচ্ছিকভাবে করার অনুমতি দিই , ইঞ্জিনটি ব্যাকট্র্যাক করে "না থ্যাঙ্কস" বিকল্পটি গ্রহণ করেছে, যা আমাদের কেবল মিলিয়ে এবং ঠিক ক্যাপচার করতে দেয়b !

তবে মনে রাখবেন যে খুব প্রথম পুনরাবৃত্তি বাদে আপনি সর্বদা কেবল স্ব-রেফারেন্সের সাথে মিল রাখতে পারেন \1। এটি অবশ্যই সুস্পষ্ট, যেহেতু আমরা এটি কেবল আমাদের পূর্ববর্তী পুনরাবৃত্তির উপর ক্যাপচার করেছি এবং আমাদের সেটআপে আমরা সর্বদা এটি আবার মিলাতে পারি (উদাহরণস্বরূপ আমরা যদি গতবারে ক্যাপচার bbbকরি তবে আমাদের নিশ্চয়তা রয়েছে যে সেখানে এখনও থাকবে bbb, তবে সেখানে বা থাকতে পারে এবার নাও থাকতে পারে bbbb)।

পাঠ : ব্যাকট্র্যাকিং থেকে সাবধান থাকুন। রেজেক্স ইঞ্জিন প্রদত্ত প্যাটার্নটি মেলে যতক্ষণ না আপনি অনুমতি দেবেন তত ব্যাকট্র্যাকিং করবে। এটি পারফরম্যান্সকে (যেমন বিপর্যয়মূলক ব্যাকট্র্যাকিং ) এবং / অথবা নির্ভুলতারউপর প্রভাব ফেলতে পারে।


পদক্ষেপ 5: উদ্ধার করার জন্য স্ব-দখল!

"ফিক্স" এখন সুস্পষ্ট হওয়া উচিত: অধিকারী পরিমাণের সাথে al চ্ছিক পুনরাবৃত্তি একত্রিত করুন । এটি হ'ল সহজ পরিবর্তে পরিবর্তে ?ব্যবহার ?+করুন (মনে রাখবেন যে পুনরাবৃত্তি যা অধিকারী হিসাবে পরিমিত হয় তা ব্যাকট্র্যাক করে না, এমনকি যদি এই ধরনের "সহযোগিতা" সামগ্রিক প্যাটার্নের একটি মিল হতে পারে)।

খুব অনানুষ্ঠানিক নিরিখে, এটা কি ?+, ?এবং ??বলে:

?+

  • (alচ্ছিক) "এটি থাকতে হবে না,"
    • (অধিকারে রাখুন) "তবে যদি তা থাকে তবে আপনাকে অবশ্যই এটি নেওয়া উচিত এবং ছেড়ে দেওয়া উচিত নয়!"

?

  • (alচ্ছিক) "এটি থাকতে হবে না,"
    • (লোভী) "তবে এটি যদি আপনি আপাতত নিতে পারেন,"
      • (ব্যাকট্র্যাকিং) "তবে আপনাকে এটি পরে যেতে বলা হতে পারে!"

??

  • (alচ্ছিক) "এটি থাকতে হবে না,"
    • (অনিচ্ছুক) "এবং এটি হলেও আপনাকে এখনও এটি নেওয়া উচিত নয়,"
      • (ব্যাকট্র্যাকিং) "তবে আপনাকে পরে এটি নিতে বলা হতে পারে!"

আমাদের সেটআপে, \1প্রথমবার সেখানে উপস্থিত হবে না, তবে এটি সর্বদা এর পরে যে কোনও সময় থাকবে এবং আমরা সর্বদা এটির সাথে মিল রাখতে চাই। সুতরাং, \1?+আমরা যা চাই ঠিক তা সম্পাদন করবে।

$r5 = '/ ^ (?: a (?= a* (\1?+ b) ) )+ /x';
#          │     │      └──────┘ │ │
#          │     │          1    │ │
#          │     └───────────────┘ │
#          │         lookahead     │
#          └───────────────────────┘
#             non-capturing group

এখন আউটপুটটি ( আইডোন.কম এ প্রদর্শিত হিসাবে ):

aaa 0
aaab 1 a|b          # Yay! Fixed!
aaaxb 0
xaaab 0
b 0
abbb 1 a|b
aabb 1 aa|bb
aaabbbbb 1 aaa|bbb
aaaaabbb 1 aaa|bbb  # Hurrahh!!!

ভয়েল !!! সমস্যা সমাধান!!! আমরা এখন সঠিকভাবে গণনা করছি, ঠিক যেভাবে আমরা এটি করতে চাই!

পাঠ : লোভী, অনিচ্ছুক এবং পুনরাবৃত্তির পুনরাবৃত্তিগুলির মধ্যে পার্থক্য শিখুন। Alচ্ছিক-অধিকারী একটি শক্তিশালী সমন্বয় হতে পারে।


পদক্ষেপ।: স্পর্শ শেষ হচ্ছে

তাই আমরা এই মুহূর্তে আছে একটি প্যাটার্ন ম্যাচ যে aবারবার, এবং প্রত্যেক জন্য aমিল খাওয়া ছিল, আছে অনুরূপ একটি bগ্রুপ 1. ধরা +বন্ধ আছে যখন কেউ আর বেঁচে নেই a, অথবা কথন ব্যর্থ যদি কারণ নয় সেখানে সংশ্লিষ্টb জন্য একটি a

কাজ শেষ করতে, আমাদের কেবল আমাদের প্যাটার্নে যুক্ত হওয়া দরকার \1 $। এটি এখন গ্রুপ 1 এর সাথে কী মিলছে তার পিছনে রেফারেন্স, লাইন অ্যাঙ্কারের শেষে। অ্যাঙ্করটি নিশ্চিত করে যে bস্ট্রিংয়ে কোনও অতিরিক্ত নেই ; অন্য কথায়, আসলে আমাদের একটি এন বি এন রয়েছে

10,000 টি অক্ষরের দৈর্ঘ্যের একটি সহ অতিরিক্ত পরীক্ষার কেস সহ এখানে চূড়ান্ত প্যাটার্নটি দেওয়া আছে:

$tests = array(
  'aaa', 'aaab', 'aaaxb', 'xaaab', 'b', 'abbb', 'aabb', 'aaabbbbb', 'aaaaabbb',
  '', 'ab', 'abb', 'aab', 'aaaabb', 'aaabbb', 'bbbaaa', 'ababab', 'abc',
  str_repeat('a', 5000).str_repeat('b', 5000)
);
 
$r6 = '/ ^ (?: a (?= a* (\1?+ b) ) )+ \1 $ /x';
#          │     │      └──────┘ │ │
#          │     │          1    │ │
#          │     └───────────────┘ │
#          │         lookahead     │
#          └───────────────────────┘
#             non-capturing group

: এটা 4 ম্যাচ খুঁজে বের করে ab, aabb, aaabbb, এবং একটি 50005000আইডোন.কম এ চালাতে এটি কেবল 0.06 সেকেন্ড সময় নেয় ।


পদক্ষেপ 7: জাভা পরীক্ষা

সুতরাং প্যাটার্নটি পিএইচপি-তে কাজ করে, তবে চূড়ান্ত লক্ষ্য জাভাতে কাজ করে এমন একটি প্যাটার্ন লিখতে হয়।

public static void main(String[] args) {
 
        String aNbN = "(?x) (?:  a  (?= a* (\\1?+ b))  )+ \\1";
        String[] tests = {
                "",      // false
                "ab",    // true
                "abb",   // false
                "aab",   // false
                "aabb",  // true
                "abab",  // false
                "abc",   // false
                repeat('a', 5000) + repeat('b', 4999), // false
                repeat('a', 5000) + repeat('b', 5000), // true
                repeat('a', 5000) + repeat('b', 5001), // false
        };
        for (String test : tests) {
                System.out.printf("[%s]%n  %s%n%n", test, test.matches(aNbN));
        }
 
}
 
static String repeat(char ch, int n) {
        return new String(new char[n]).replace('\0', ch);
}

প্যাটার্নটি প্রত্যাশার মতো কাজ করে (আদর্শ আইটেম হিসাবে দেখা যায় )


এবং এখন আমরা সিদ্ধান্তে পৌঁছেছি ...

এটি বলা a*বাহুল্য যে চেহারাতে এবং সত্যই "প্রধান +লুপ" উভয়ই ব্যাকট্র্যাকিংয়ের অনুমতি দেয়। পাঠকদের কেন এটি সঠিকতার দিক থেকে সমস্যা নয় তা নিশ্চিত করতে উত্সাহিত করা হয় এবং একই সাথে উভয়কে দখল করাও কেন কাজ করবে (যদিও একই প্যাটার্নে বাধ্যতামূলক এবং অ-বাধ্যতামূলক অধিক পরিমাণকে মিশ্রণে ভুল ধারণা তৈরি হতে পারে)।

এটিও বলা উচিত যে এটি পরিষ্কারভাবে যখন একটি রেজেক্স প্যাটার্ন রয়েছে যা একটি এন বি এন এর সাথে মিলে যায় তবে এটি অনুশীলনে সর্বদা "সেরা" সমাধান নয়। আরও ভাল সমাধান হ'ল সহজভাবে মেলে ^(a+)(b+)$, এবং তারপরে হোস্টিং প্রোগ্রামিং ভাষার 1 এবং 2 গ্রুপ দ্বারা কক্ষিত স্ট্রিংগুলির দৈর্ঘ্যের তুলনা করুন।

পিএইচপি-তে, এটি দেখতে কিছুটা দেখতে ( যেমন আদর্শের ডটকম-এ দেখা যায় ):

function is_anbn($s) {
   return (preg_match('/^(a+)(b+)$/', $s, $groups)) &&
      (strlen($groups[1]) == strlen($groups[2]));
}

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

উপরে যেমন উল্লেখ করা হয়েছে, এই নিবন্ধটি প্রয়োজনীয়ভাবে [regex]স্ট্যাকওভারফ্লোয়ের জন্য ট্যাগ করা আছে, এটি সম্ভবত এটির চেয়ে বেশি is যদিও দৃser়তা, নেস্টেড রেফারেন্সস, অধিগ্রহণযোগ্য কোয়ান্টিফায়ার ইত্যাদি সম্পর্কে শেখার মূল্য রয়েছে, সম্ভবত এখানে আরও বড় পাঠটি সৃজনশীল প্রক্রিয়া যার মাধ্যমে কেউ সমস্যা সমাধানের চেষ্টা করতে পারেন, দৃ you're় সংকল্প এবং কঠোর পরিশ্রম যা আপনাকে প্রায়শই বশীভূত হওয়ার সময় প্রয়োজন হয় বিভিন্ন সীমাবদ্ধতা, কাজের সমাধান তৈরির জন্য বিভিন্ন অংশ থেকে নিয়মিত রচনা ইত্যাদি


বোনাস উপাদান! পিসিআরই রিকার্সিভ প্যাটার্ন!

যেহেতু আমরা পিএইচপি নিয়ে এসেছি, তাই এটি বলা দরকার যে পিসিআরই পুনরাবৃত্ত প্যাটার্ন এবং সাব্রোটাইনগুলিকে সমর্থন করে। সুতরাং, নিম্নলিখিত প্যাটার্নগুলি preg_match( আইডোন.কম এ প্রদর্শিত হিসাবে ) কাজ করে:

$rRecursive = '/ ^ (a (?1)? b) $ /x';

বর্তমানে জাভার রেজেক্স পুনরাবৃত্ত প্যাটার্ন সমর্থন করে না।


আরও বোনাস উপাদান! সমন্বয় একটি এন বি এন সি এন !!

সুতরাং আমরা দেখেছি কীভাবে একটি এন বি এন মেলানো যায় যা নিয়মিত নয়, তবে এখনও প্রাসঙ্গিক মুক্ত, তবে আমরা কী একটি এন বি এন সি সি মেলতে পারি , যা প্রসঙ্গ-মুক্তও নয়?

উত্তরটি অবশ্যই, হ্যাঁ! পাঠকরা তাদের নিজের থেকে এটি সমাধান করার চেষ্টা করতে উত্সাহিত করা হচ্ছে, তবে সমাধানটি নীচে সরবরাহ করা হয়েছে ( আইডোন.কম এ জাভা প্রয়োগের সাথে )।

^ (?: a (?= a* (\1?+ b) b* (\2?+ c) ) )+ \1 \2 $


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

দারূন কাজ. এটি পড়তে আমার কিছুটা সময় লাগবে, তবে একেবারে শেষ পংক্তিটি পড়া সহজভাবে অসম্ভব; এটি যেমন একটি ছোট ফন্ট। ------ অপেক্ষা কর. এটি কি feature? .... নিশ্চিত না এটি ভাল ধারণা কিনা। আমি জানি সর্বশেষ প্রতীকটি কী, তবে এটি পড়তে পারা যায় না (এটি অনুলিপি করা কপির বাইরে)।
পিটার আজতাই

6
@ পিটার: ছোট লেখাটি হাইলাইট করুন এবং অনুলিপি করুন এবং অন্য কোনও কিছুতে আটকান। উদ্দেশ্য অনুযায়ী এটি পড়তে অসুবিধা হয়েছে: এটি একটি স্পয়লার, বোনাস ধাঁধার সমাধান।
বহুবিশ্বেষকরা

8
+1: কল্পনাপ্রসূত ব্যাখ্যা, এই "উন্নত নিবন্ধগুলি" উজ্জ্বল ধারণা।
কলম রজার্স

4
@LarsH পিএইচপি এর preg_match()একটি উদাহরণ PCRE । জাভা রেজিক্সগুলি পার্ল রেজেক্সপসের পুরানো সংস্করণের উপর ভিত্তি করে বলে মনে হচ্ছে । যার অর্থ এই যে পিএইচপি রেজেক্সেস জাভা সংস্করণের চেয়ে বেশি শক্তিশালী। এর মতো 2013-02-21 , pcre.txt যে এটা পার্ল 5,12 প্রায় অনুরূপ । যখন পার্ল বর্তমানে 5.16-এ রয়েছে, কয়েক মাসের ছুটি 5.18 এর সাথে। (তখনকার রেজিজেসে আসলে খুব বেশি কিছু যুক্ত হয়নি)
ব্র্যাড গিলবার্ট

20

পিসিআরই রিকার্সিভ প্যাটার্ন সমর্থন করে বলে কোন উল্লেখ করা হয়নি, আমি কেবলমাত্র পিসিআরই-এর সহজতম এবং কার্যকর উদাহরণটি উল্লেখ করতে চাই যা প্রশ্নে ভাষাটি বর্ণনা করে:

/^(a(?1)?b)$/

+1 বাহ, আমি জানতাম না পিসিআরই পুনরাবৃত্ত প্যাটার্ন সমর্থন করে (আমি এখনও শিখছি! প্রতিদিন!)। এই তথ্যটি সামঞ্জস্য করার জন্য আমি নিবন্ধটি সংশোধন করেছি। আমি মনে করি না a^n b^n c^nযদিও পুনরাবৃত্ত প্যাটার্নটি মেলতে পারে ।
বহুবৃত্তীয় খাবারগুলি

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

@ কোবি এটি আপনার "ভাল" সংজ্ঞাটির উপর নির্ভর করে। উদাহরণস্বরূপ পুনরাবৃত্ত সমাধানটি অন্য একটি ( কোডপ্যাড.ভিপার-7 . com / CWgy7c ) এর চেয়ে বেশি মাত্রার এক ক্রমের কাছাকাছি । এবং এটি বোঝা অনেক সহজ। রিকার্সিভ দ্রবণটি ব্যাকরণের প্রত্যক্ষ রূপান্তরকে একটি রেজেেক্সে রূপান্তরিত করতে পারে (আসলে আপনি এটি ব্যাকরণযুক্ত আকারে লিখতে পারেন, এটি কার্যকর হবে)।
নিকিসি

4
@ পলিজেনিক্লুব্রিকেন্টস, আপনি সেই প্যাটার্নটি দুটি পুনরাবৃত্ত প্যাটার্নের সাথে মেলে ধরতে পারবেন, একটি ক্যাপচার না করেই aএস এবং bএস গ্রাহ্য করে (এবং এটি একই পরিমাণে ডাব্লু / পুনরাবৃত্তি রয়েছে তা যাচাই করে), তারপরে ক্যাপচারিং রেজেক্স থাকে যা লোভের সাথে সমস্ত একটি গ্রাস করে এবং তারপরে পুনরাবৃত্তির প্রয়োগ করে গ্রাহক এবং একই ধরণের bএস এবং cএস রয়েছে তা যাচাই করতে প্যাটার্ন । Regex হল: /^(?=(a(?-1)?b)c)a+(b(?-1)?c)$/x। ক্রেডিট: nikic.github.io/2012/06/15/…
জোশ

11

হিসাবে প্রশ্নে আপনাকে উল্লেখ করেছে - .NET গ্রুপ, ধরনের নিদর্শন মিট সঙ্গে একটি এন বি এন সি এনN ... z- র এন সহজে যেমন মিলেছে করা যাবে

^
  (?<A>a)+
  (?<B-A>b)+  (?(A)(?!))
  (?<C-B>c)+  (?(B)(?!))
  ...
  (?<Z-Y>z)+  (?(Y)(?!))
$

উদাহরণস্বরূপ: http://www.ideone.com/usuOE


সম্পাদনা করুন:

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

^
  (?=(a(?-1)?b))  a+
  (?=(b(?-1)?c))  b+
  ...
  (?=(x(?-1)?y))  x+
     (y(?-1)?z)
$

উদাহরণস্বরূপ: http://www.ideone.com/9gUwF


4
@ পলি: ধন্যবাদ :) আসলে আমি। নেট প্যাটার্নগুলির সাথে পরিচিত নই, তবে এই ধরণের নিদর্শনগুলির জন্য এটি ভারসাম্যপূর্ণ গ্রুপগুলির সাথে খুব সহজ বলে প্রমাণিত হয়, তাই আমি এই উত্তরটি পরিপূরক করছি।
কেনেটিএম

আপনি কি পুনরাবৃত্ত প্যাটার্ন দিয়ে এটি করতে পারেন? কারণ আপনি যদি না পারেন তবে এটি একটি আকর্ষণীয় মোড় যা ভারসাম্যপূর্ণ গ্রুপ এমন কাজ করতে পারে যা পুনরাবৃত্ত প্যাটার্নগুলি পারে না। (এবং হ্যাঁ, আমি পরিপূরকের খুব প্রশংসা করি)।
বহুবিচ্ছিন্নতা

যাইহোক, আমি বাদ দেওয়ার কারণটি। নেট সমাধানের কারণ ছিল আমার "কীভাবে আমরা a^n b^n.NET রেজেক্সের সাথে ম্যাচ করতে পারি ?" ভবিষ্যতে নিবন্ধ, তবে আপনি যদি চান তবে এটি লেখার জন্য আপনাকে স্বাগত জানানোর চেয়েও বেশি কিছু। আমি এই নিবন্ধগুলি কেবল নিজের জন্য করছি না; আমি অন্যকেও এটি করতে উত্সাহিত করতে চাই পাশাপাশি সাইটে ভাল সামগ্রী রাখতে চাই।
বহুবিশ্লেষকারী

পুনরাবৃত্ত নিদর্শনগুলির সাথে এটি করার কোনও উপায় বের করে থাকলে দয়া করে আপডেট করুন। যে শব্দগুলির দৈর্ঘ্য একটি ফিবোনাচি সিরিজ তৈরি করে, এবং এটি কাজ করতে পারা যায় নি সেই শব্দগুলি ক্যাপচার করতে আমি ভারসাম্যপূর্ণ দলগুলির সাথে ঘুরেছি। আমি যা করেছি তার অনুরূপ লুক-চারিদ ব্যবহার করা সম্ভব হতে পারে।
কোবি

4
আমি কেবল এটিই উল্লেখ করতে চাই যে এই প্যাটার্নের পিসিআরই সংস্করণটি সামান্য ত্রুটিযুক্ত কারণ এটি মিললে যদি পরবর্তী অক্ষরের অক্ষর আগের চেয়ে দীর্ঘ হয়। এখানে দেখুন: regex101.com/r/sdlRTm/1 যোগ করার জন্য আপনার যা দরকার (?!b), (?!c)ইত্যাদি তাই মত ক্যাপচার গ্রুপ পরে: regex101.com/r/sdlRTm/2
jaytea
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.