কীভাবে নির্ধারণ করবেন যে একটি সংখ্যা রেজেস সহ প্রাইম কিনা?


128

আমি রোসটাটা কোডে জাওয়ার জন্য নিম্নলিখিত কোড উদাহরণটি পেয়েছি :

public static boolean prime(int n) {
  return !new String(new char[n]).matches(".?|(..+?)\\1+");
}
  • আমি জাভা বিশেষত জানি না তবে রেজিএক্স বাদে এই স্নিপেটের সমস্ত দিক বুঝতে পারি
  • রেজিএক্সের বিল্ট-ইন পিএইচপি ফাংশনগুলিতে আপনি এটি পেয়ে যাওয়ায় আমার কাছে বুনিয়াদি-প্রাথমিক জ্ঞান রয়েছে

.?|(..+?)\\1+মৌলিক সংখ্যাগুলি কীভাবে মেলে?


9
@ আমির রাছুম: !new String(new char[n]).matches(".?|(..+?)\\1+")সমান !((new String(new char[n])).matches(".?|(..+?)\\1+"))
গম্বো

14
এটি কেবল গণনা ব্যয়বহুল নয়, এটি সম্ভাব্য বিধ্বংসী স্মৃতি-ব্যয়বহুলও। যদি কেউ এই পদ্ধতির ব্যবহার করতে বেছে নেন যা আমি প্রাইমস সন্ধানের জন্য অ্যালগরিদমটি যেহেতু খুব সহজ (যেহেতু বিশ্বে এটি জটিল করে এবং এটিকে অপব্যয়কর করে তোলে) এর বিরুদ্ধে পরামর্শ দিই, "নতুন চর [এন] এর আগে একটি চেক করা উচিত ] "এটি একটি যুক্তিসঙ্গত প্রান্তিকের নীচে নিশ্চিত করা। উদাহরণস্বরূপ "প্রাইম (পূর্ণসংখ্যা।
নিকেরোবট

28
@ কিনারবোট: হালকা?
ক্যাম

6
@ নিউনারোবট: আসলে, আমি এটি ফিরিয়ে নিই। আমি প্রাথমিকভাবে এই প্রশ্নের একাডেমিক স্বভাবটি অনুধাবন করেছি যে এটি কেবল শিক্ষার উদ্দেশ্যেই এর ব্যবহারকে বোঝায়, এবং আপনি একটি দুর্বোধ্য ঘটনা হচ্ছেন। তবে দ্বিতীয় ভাবার ক্ষেত্রে তা নয়; এটি কখনই উল্লেখ করা হয়নি এমনকি এমন প্রশ্নের মধ্যেও বোঝানো হয়নি যে রেজেক্স কেবলমাত্র শিক্ষার উদ্দেশ্যে। প্রকৃতপক্ষে এটি সম্পর্কে আমার প্রথম ধারণাটি হ'ল কোড স্নিপেটগুলি যতটা সরল দেখায় তাই একটি শিক্ষানবিস অবশ্যই অনুমান করতে পারেন যে এটি ব্যবহারে ব্যবহার করা যেতে পারে। +1 টি।
ক্যাম

7
@ চিন্তিতমন কোন উদ্বেগ নেই। আপনি কীভাবে ভাবতে পারেন তা আমি দেখতে পাচ্ছি। এটি ব্যবহারের পরিণতি সম্পর্কে সতর্ক করা আমার উদ্দেশ্য ছিল, এটি কীভাবে কাজ করে তা শিখতে নিরুৎসাহিত না করে। একটি সাধারণ "দয়া করে এটি মোতায়েন করবেন না।" আমার মন্তব্যের বাকী পূর্বে আপনার প্রাথমিক দৃষ্টিকোণ থেকে এটি কম ঘনঘন শব্দ হতে পারে।
নিকিরোবট

উত্তর:


120

আপনি বলেছিলেন যে আপনি এই অংশটি বোঝেন, তবে কেবল জোর দেওয়ার জন্য, উত্পন্ন স্ট্রিংয়ের সরবরাহ করা সংখ্যার সমান দৈর্ঘ্য রয়েছে has সুতরাং স্ট্রিংয়ের তিনটি অক্ষর থাকে এবং যদি কেবল তবে n == 3

.?

রেজেক্সের প্রথম অংশটি বলে, "যে কোনও চরিত্র, শূন্য বা এক বার"। সুতরাং মূলত, শূন্য বা একটি চরিত্র আছে - বা, আমি উপরে উল্লিখিত অনুযায়ী n == 0 || n == 1,। আমাদের যদি ম্যাচ থাকে তবে তার প্রত্যাখ্যানটি ফিরিয়ে দিন। এটি শূন্য এবং একটি প্রধান নয় এমনটির সাথে মিল রয়েছে।

(..+?)\\1+

রেজেক্সের দ্বিতীয় অংশটি সামান্য কৌশলযুক্ত, গ্রুপ এবং ব্যাকরফেরেন্সগুলির উপর নির্ভর করে। একটি গোষ্ঠী হ'ল বন্ধনীগুলির মধ্যে এমন কিছু যা পরে ব্যবহারের জন্য রেজেক্স ইঞ্জিন দ্বারা ক্যাপচার এবং সংরক্ষণ করা হবে। একটি ব্যাক রেফারেন্স হল একটি মিলিত গোষ্ঠী যা পরে একই রেজেক্সে ব্যবহৃত হয়।

গোষ্ঠীটি 1 টি অক্ষর ক্যাপচার করে, তারপরে 1 বা ততোধিক কোনও অক্ষর। (+ অক্ষরটির অর্থ এক বা একাধিক, তবে কেবল পূর্বের চরিত্র বা গোষ্ঠীর একমাত্র। এটি যথাসম্ভব কয়েকটি চরিত্রের সাথে মেলে দেখার চেষ্টা করে + + এটি করতে পারলে সাধারণত পুরো স্ট্রিংটিকে গুঁড়িয়ে দেওয়ার চেষ্টা করে, যা এই ক্ষেত্রে খারাপ because

পরের অংশটি হ'ল ব্যাকরফারেন্স: সেই একই অক্ষরের সেট (দুই বা ততোধিক), আবার উপস্থিত হবে। বলেছে পিছনে উল্লেখ এক বা একাধিকবার প্রদর্শিত হবে times

So. আটককৃত গ্রুপটি প্রাকৃতিক সংখ্যক চরিত্রের সাথে মিলিত হয় (2 থেকে পরবর্তী) সাইড গ্রুপটি তখন বেশ কয়েকটি প্রাকৃতিক সংখ্যক বার উপস্থিত হয় (2 থেকেও পরে)। যদি কোনও মিল থাকে তবে এর থেকে বোঝা যায় যে 2-এর চেয়ে বড় বা সমান 2 সংখ্যার একটি পণ্য পাওয়া সম্ভব যা n দৈর্ঘ্যের স্ট্রিংয়ের সাথে মেলে ... মানে আপনার একটি সংমিশ্রিত এন আছে। সুতরাং আবারও, সফল ম্যাচের প্রত্যাখ্যানটি ফিরিয়ে দিন: n প্রধান নয়।

যদি কোনও মিল খুঁজে পাওয়া যায় না, তবে আপনি 2 এর চেয়ে বড় বা সমান দুটি প্রাকৃতিক সংখ্যার আপনার পণ্যটি নিয়ে আসতে পারবেন না ... এবং আপনার সাথে একটি মিল নেই এবং প্রধান উভয়ই রয়েছে, তাই আবার প্রত্যাবর্তনের প্রত্যাবর্তন ম্যাচ ফলাফল।

আপনি এখন এটি দেখতে? এটি অবিশ্বাস্যভাবে মুশকিল (এবং গণনাগতভাবে ব্যয়বহুল!) তবে একবারে এটি একবারে পাওয়া গেলেও এটি সহজ। :-)

আপনার আরও প্রশ্ন থাকলে রেজেক্স পার্সিং আসলে কীভাবে কাজ করে তা যেমন আমি বিশদভাবে বলতে পারি। তবে আমি এই উত্তরটি আপাতত সহজ রাখার চেষ্টা করছি (বা যত সহজ হতে পারে তত সহজ)।


10
আমি এই যুক্তিটি জেএসের সাথে ক্রোম দেব কনসোলে চেষ্টা করেছি। ওয়েব পৃষ্ঠায়। এবং চেক করতে সবে পাস করেছে 5 পৃষ্ঠাটি ক্রাশ!
আমোগ তালপলিকর

নীচের মন্তব্য আরও ভাল ব্যাখ্যা দেয়। আপনি এগিয়ে যাওয়ার আগে দয়া করে এটি পড়ুন!
ইভান ডেভিডভ 26'15

"বেটার" বিষয়গত - আমি বলব এটি একটি ভিন্ন কোণ থেকে সমস্যাটির কাছে আসে এবং এই উত্তরের একটি দুর্দান্ত পরিপূরক। :-)
প্ল্যাটিনাম Azure

1
আমি আসলে একটি ব্লগ পোস্টে বিস্তারিত সঙ্গে এই ব্যাখ্যা লিখেছিলেন: রেগুলার এক্সপ্রেশন ডিমিস্টিফাইং যে যদি একটি সংখ্যা প্রাইম চেক
ইলিয়া গেরাসিমচুক

73

আমি প্রাথমিকতার পরীক্ষার বাইরে রেজেক্স অংশটি ব্যাখ্যা করব: নীচের রেজেক্স, String sযা পুনরাবৃত্তি নিয়ে গঠিত String t, সন্ধান করেছে t

    System.out.println(
        "MamamiaMamamiaMamamia".replaceAll("^(.*)\\1+$", "$1")
    ); // prints "Mamamia"

এটি যেভাবে কাজ করে তা হ'ল রেজেক্স ক্যাপচার (.*)করে \1এবং তারপরে \1+এটি অনুসরণ করে কিনা তা দেখে । ব্যবহার করে ^এবং $নিশ্চিত করে যে কোনও ম্যাচ অবশ্যই পুরো স্ট্রিংয়ের।

সুতরাং, একটি উপায়ে, আমাদের দেওয়া হয়েছে String s, যা একটি "একাধিক" String tএবং রেজেক্স এমনটি খুঁজে পাবে t(যেহেতু \1লোভী তাই দীর্ঘতম সম্ভব )।

একবার আপনি বুঝতে পারবেন কেন এই রেজেক্সটি কাজ করে, তারপরে (আপাতত ওপি'র রেজেক্সের প্রথম বিকল্পটিকে উপেক্ষা করে) কীভাবে এটি প্রাথমিকতা পরীক্ষার জন্য ব্যবহৃত হয় তা সহজ।

  • এর প্রাথমিকতা পরীক্ষা করতে nপ্রথমে একটি Stringদৈর্ঘ্য তৈরি করুন n(একই সাথে ভরা char)
  • রেজেক্স Stringকিছু দৈর্ঘ্যের (বলুন k) কে ক্যাপচার \1করে এবং বাকীটির সাথে মিলে \1+যাওয়ার চেষ্টা করেString
    • যদি কোনও মিল থাকে তবে nএটির যথাযথ একাধিক হয় kএবং তাই nএটি প্রাইম নয়।
    • যদি কোনও মিল নেই, তবে kবিভাজনকারী এমন কোনও উপস্থিতি নেই nএবং nতাই এটি প্রধান

.?|(..+?)\1+মৌলিক সংখ্যাগুলি কীভাবে মেলে?

আসলে, এটা না! এটি মেলে String যার দৈর্ঘ্য প্রধান নয়!

  • .?: Stringদৈর্ঘ্যের পরিবর্তনের ম্যাচগুলির প্রথম অংশ 0বা 1(সংজ্ঞা অনুসারে প্রধান নয়)
  • (..+?)\1+: আবর্তনে দ্বিতীয় অংশ, Regex একটি প্রকরণ উপরে বর্ণিত, ম্যাচ Stringদৈর্ঘ্যের nএকটি এর "একটি একাধিক" যে Stringদৈর্ঘ্য k >= 2(অর্থাত nএকটি যৌগিক, না একটি মৌলিক যায়)।
    • নোট করুন যে অনিচ্ছুক সংশোধক ?প্রকৃতপক্ষে নির্ভুলতার জন্য প্রয়োজন নেই, তবে এটি kপ্রথমে আরও ছোট চেষ্টা করে প্রক্রিয়াটি গতিতে সহায়তা করতে পারে

বিবৃতিতে ! booleanপরিপূরক অপারেটর নোট করুন return: এটি উপেক্ষা করে matches। এটি যখন রেজেক্স মিলবে না , nপ্রধান! এটি একটি দ্বৈত-নেতিবাচক যুক্তি, তাই এতে বিভ্রান্ত হওয়ার মতো অবাক হওয়ার কিছু নেই !!


সরলীকরণ

কোডটিকে আরও পঠনযোগ্য করে তোলার জন্য এখানে একটি সরল পুনরায় লেখা রয়েছে:

public static boolean isPrime(int n) {
    String lengthN = new String(new char[n]);
    boolean isNotPrimeN = lengthN.matches(".?|(..+?)\\1+");
    return !isNotPrimeN;
}

উপরেরটি মূলত মূল জাভা কোডের সমান, তবে যুক্তিকে বুঝতে সহজ করার জন্য স্থানীয় ভেরিয়েবলগুলিকে অ্যাসাইনমেন্ট সহ একাধিক বিবৃতি বিভক্ত করা হয়েছে।

নিম্নরূপে সীমাবদ্ধ পুনরাবৃত্তি ব্যবহার করে আমরা রেজেক্স আরও সরল করতে পারি:

boolean isNotPrimeN = lengthN.matches(".{0,1}|(.{2,})\\1+");

আবার একই Stringদৈর্ঘ্যে একটি দৈর্ঘ্য দেওয়া হয়েছে ,nchar

  • .{0,1}পরীক্ষা করে দেখুন n = 0,1, প্রধানমন্ত্রী না
  • (.{2,})\1+প্রাইম নয়, এর nসঠিক একাধিক কিনা তা পরীক্ষা করেk >= 2

অনিচ্ছুক পরিবর্তক ব্যতীত ?উপর \1(স্বচ্ছতার জন্য বাদ দেওয়া), উপরে Regex মূল অভিন্ন।


আরও মজা regex

নিম্নলিখিত রেজেক্স একই জাতীয় কৌশল ব্যবহার করে; এটি শিক্ষামূলক হওয়া উচিত:

System.out.println(
    "OhMyGod=MyMyMyOhGodOhGodOhGod"
        .replaceAll("^(.+)(.+)(.+)=(\\1|\\2|\\3)+$", "$1! $2! $3!")
); // prints "Oh! My! God!"

আরো দেখুন


6
+1: আমি মনে করি আপনার পদ্ধতির চেয়ে আমার চেয়ে সম্ভবত ভাল। আমি কেন এতগুলি উত্সাহ বা চেক চিহ্ন পেয়েছি তা জানিনা ... আপনি এটির আরও প্রাপ্য, আমি মনে করি। :-( দুঃখিত
প্ল্যাটিনাম Azure

@ প্ল্যাটিনাম: বাহ, আমি কখনই ভাবিনি যে আপনি প্রকাশ্যে এই কথাটি বলে চলেছেন! সমর্থনের জন্য ধন্যবাদ. আমি এ [Populist]থেকে কিছু দিন পাব ।
বহুবৃত্তীয় পদার্থ

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

25

চমৎকার রেজেক্স ট্রিক (যদিও খুব অদক্ষ) ... :)

রেজেক্স নন-প্রাইমকে নিম্নলিখিতভাবে সংজ্ঞায়িত করেছে:

N প্রাইম নয় এবং কেবল N <= 1 বা N কে কে কে> 1 দ্বারা বিভাজ্য।

রেজেরেক্স ইঞ্জিনে এন এর সাধারণ ডিজিটাল উপস্থাপনাটি পরিবর্তনের পরিবর্তে, এটি পুনরাবৃত্তি করা চরিত্রের সমন্বয়ে দৈর্ঘ্য এন এর ক্রম দিয়ে খাওয়ানো হয় । বিভাজনের প্রথম অংশটি এন = 0 বা এন = 1 এর জন্য অনুসন্ধান করে এবং দ্বিতীয় অংশটি ব্যাকগ্রিফারেন্স ব্যবহার করে বিভাজক কে> 1 এর সন্ধান করে। এটি রেজেক্স ইঞ্জিনকে কিছু খালি উপ-অনুক্রম সন্ধান করতে বাধ্য করে যা সিকোয়েন্সটি গঠনের জন্য কমপক্ষে দুবার পুনরাবৃত্তি করা যেতে পারে। যদি এই জাতীয় উপসর্গ বিদ্যমান থাকে তবে এর অর্থ হ'ল এর দৈর্ঘ্য N কে বিভক্ত করে, সুতরাং এনটি প্রধান নয়।


2
অদ্ভুতভাবে যথেষ্ট, বারবার অন্যান্য দৈর্ঘ্য এবং আরও প্রযুক্তিগত ব্যাখ্যা পড়ার পরেও, আমি এই ব্যাখ্যাটি এটিই আমার মাথায় 'ক্লিক' করে তুলেছিলাম।
আট-বিট গুরু

2
/^1?$|^(11+?)\1+$/

বেস 1 (1 = 1, 2 = 11, 3 = 111, ...) এ রূপান্তর করার পরে সংখ্যায় প্রয়োগ করুন। নন-প্রাইমস এটি মিলবে। যদি এটি মেলে না, তবে এটি প্রধান।

এখানে ব্যাখ্যা ।

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