मिलर-राबिन मजबूत स्यूडोप्राइम


16

एक गैर-नकारात्मक पूर्णांक को देखते हुए N, सबसे छोटे विषम धनात्मक पूर्णांक को आउटपुट करते हैं जो कि पहले Nप्रमुख आधारों में से सभी के लिए एक मजबूत छद्मरूप है ।

यह OEIS अनुक्रम A014233 है

परीक्षण मामले (एक-अनुक्रमित)

1       2047
2       1373653
3       25326001
4       3215031751
5       2152302898747
6       3474749660383
7       341550071728321
8       341550071728321
9       3825123056546413051
10      3825123056546413051
11      3825123056546413051
12      318665857834031151167461
13      3317044064679887385961981

के लिए परीक्षण के मामले N > 13उपलब्ध नहीं हैं क्योंकि उन मूल्यों को अभी तक नहीं मिला है। यदि आप अनुक्रम में अगला शब्द ढूंढते हैं, तो इसे OEIS को सबमिट करना सुनिश्चित करें!

नियम

  • आप Nशून्य-अनुक्रमित या एक-अनुक्रमित मान के रूप में लेना चुन सकते हैं ।
  • यह आपके समाधान के लिए स्वीकार्य है कि केवल आपकी भाषा की पूर्णांक सीमा ( N = 12अनसाइनड 64-बिट पूर्णांकों के लिए) के भीतर मौजूद मानों के लिए काम करें , लेकिन आपके समाधान को सैद्धांतिक रूप से इस धारणा के साथ किसी भी इनपुट के लिए काम करना होगा कि आपकी भाषा मनमाने ढंग से लंबाई वाले भागीदारों का समर्थन करती है।

पृष्ठभूमि

किसी भी सकारात्मक पूर्णांक xको उस रूप में लिखा जा सकता है x = d*2^sजहां dविषम हो। dऔर 2 sसे बार-बार विभाजित करके गणना की जा सकती है nजब तक कि भागफल 2 से विभाज्य नहीं है। dवह अंतिम भागफल है, और s2 बार विभाजित होने की संख्या है n

यदि एक धनात्मक पूर्णांक nप्रमुख है, तो फ़र्मेट की छोटी प्रमेय बताती है:

फर्मेट

किसी भी परिमित क्षेत्र में Z/pZ (जहाँ pकुछ अभाज्य) हैं, केवल वर्गमूल 1हैं 1और -1(या, समतुल्य, 1और p-1)।

हम यह साबित करने के लिए इन तीन तथ्यों का उपयोग कर सकते हैं कि निम्नलिखित दो कथनों में से एक को प्रधान के लिए सही होना चाहिए n(जहां d*2^s = n-1और rकुछ पूर्णांक है [0, s)):

मिलर-राबिन की स्थिति

मिलर-राबिन primality परीक्षण ऊपर दावा यिद परीक्षण द्वारा संचालित: अगर वहाँ एक आधार है aऐसी है कि उपरोक्त शर्तों के दोनों झूठे हैं, तो nप्रधानमंत्री नहीं है। उस आधार aको साक्षी कहा जाता है ।

अब, हर आधार का परीक्षण [1, n)बड़े पैमाने पर गणना समय में निषेधात्मक रूप से महंगा होगा n। मिलर-राबिन परीक्षण का एक संभावित संस्करण है जो केवल परिमित क्षेत्र में कुछ बेतरतीब ढंग से चुने गए ठिकानों का परीक्षण करता है। हालांकि, यह पता चला कि केवल प्रधान aठिकानों का परीक्षण पर्याप्त है, और इस प्रकार यह परीक्षण कुशल और निर्धारक तरीके से किया जा सकता है। वास्तव में, सभी प्रमुख ठिकानों का परीक्षण करने की आवश्यकता नहीं है - केवल एक निश्चित संख्या की आवश्यकता होती है, और यह संख्या मूल्य के आकार पर निर्भर होती है, जो कि मौलिकता के लिए परीक्षण किया जाता है।

यदि मुख्य आधारों की अपर्याप्त संख्या का परीक्षण किया जाता है, तो परीक्षण झूठी सकारात्मकता पैदा कर सकता है - विषम समग्र पूर्णांक जहां परीक्षण उनकी समग्रता को साबित करने में विफल रहता है। विशेष रूप से, यदि कोई आधार aकिसी विषम संयुक्त संख्या की संरचना को प्रमाणित करने में विफल रहता है , तो उस संख्या को आधार के लिए एक मजबूत छद्मरूप कहा जाता है a। यह चुनौती विषम संयुक्त संख्याओं को खोजने के बारे में है, जो सभी प्रमुख ठिकानों की तुलना में या उससे कम संख्या वाले सभी आधारों के लिए मजबूत psuedoprimes हैं N(जो यह कहने के बराबर है कि वे सभी अभाज्य संख्याओं से कम या बराबर संख्या वाले सभी प्रमुख ठिकानों के लिए मजबूत छद्म संस्कार हैं N) ।


1
सैंडबॉक्स पोस्ट (अब हटा दिया गया)
मेगो

एक एल्गोरिथ्म है जो नियमों द्वारा अनुमति दी गई मजबूत छद्म-समृद्धि के लिए 1 से सभी विषम मूल्य का परीक्षण करता है?
user202729

@ user202729 मैं यह नहीं देखता कि यह क्यों नहीं होगा। आपको क्या लगता है कि यह क्या है?
Mego

मैं इसे सबसे तेज़ कोड प्रश्न बनाने का सुझाव दूंगा क्योंकि अधिकांश उत्तर केवल पाशविक बल होंगे।
नील ए।

@NeilA। मैं असहमत हूं कि यह सबसे तेज कोड के रूप में बेहतर होगा। हालांकि यह सच है कि उत्तर लगभग निश्चित रूप से जानवर बल होगा (क्योंकि एक और एल्गोरिथ्म अभी तक विकसित नहीं हुआ है और मुझे पीपीसीजी से ऐसा करने की उम्मीद नहीं है), कोड गोल्फ बहुत सरल है, प्रवेश के लिए बहुत कम बाधा है (सबमिटर के बाद से) अपने स्वयं के समाधान स्कोर कर सकते हैं), मुझे हर समाधान चलाने और स्कोर करने की आवश्यकता नहीं है (और भूतपूर्व रनटाइम्स से निपटने के लिए), और यह समस्या एक गोल्फ चुनौती के रूप में काफी दिलचस्प है।
मीगो

जवाबों:


4

सी, 349 295 277 267 255 बाइट्स

N,i;__int128 n=2,b,o,l[999];P(m){i<N&&P(m<2?l[i++]=n:n%m?m-1:n++);}main(r){for(P(scanf("%d",&N));r|!b;)for(++n,b=i=N;i--&&b;){for(b=n-1,r=0;~b&1;b/=2)++r;for(o=1;b--;o=o*l[i]%n);for(b=o==1;r--;o=o*o%n)b|=o>n-2;for(o=r=1;++o<n;r&=n%o>0);}printf("%llu",n);}

स्टड पर 1-आधारित इनपुट लेता है, जैसे:

echo "1" | ./millerRabin

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

  • नील ए के जवाब से प्रेरणा लेकर थोड़ा तेज और छोटा, ( a^(d*2^r) == (a^d)^(2^r))
  • महत्वपूर्ण रूप से यह महसूस करने के बाद फिर से धीमा हो जाता है कि इस चुनौती के सभी समाधान विषम होंगे, इसलिए स्पष्ट रूप से लागू करने की आवश्यकता नहीं है कि हम केवल विषम संख्याओं की जांच करते हैं।
  • अब GCC का उपयोग करना __int128, जो कि unsigned long longबड़ी संख्या के साथ काम करते हुए भी कम है ! छोटे-एंडियन मशीनों पर भी, प्रिंटफ के साथ %lluअभी भी ठीक काम करता है।

कम-न्यूनतम किया गया

N,i;
__int128 n=2,b,o,l[999];
P(m){i<N&&P(m<2?l[i++]=n:n%m?m-1:n++);}
main(r){
    for(P(scanf("%d",&N));r|!b;)
        for(++n,b=i=N;i--&&b;){
            for(b=n-1,r=0;~b&1;b/=2)++r;
            for(o=1;b--;o=o*l[i]%n);
            for(b=o==1;r--;o=o*o%n)b|=o>n-2;
            for(o=r=1;++o<n;r&=n%o>0);
        }
    printf("%llu",n);
}

(आउटडेटेड) ब्रेकडाउन

unsigned long long                  // Use the longest type available
n=2,N,b,i,d,p,o,                    // Globals (mostly share names with question)
l[999];                             // Primes to check (limited to 999, but if you
                                    // want it to be "unlimited", change to -1u)
m(){for(o=1;p--;o=o*l[i]%n);}       // Inefficiently calculates (l[i]^p) mod n

// I cannot possibly take credit for this amazing prime finder;
// See /codegolf//a/5818/8927
P(m){i<N&&P(m<2?l[i++]=n:n%m?m-1:n++);}

main(r){
    for(
        P(scanf("%llu",&N));        // Read & calculate desired number of primes
        r|!b;){                     // While we haven't got an answer:
        n=n+1|1;                    // Advance to next odd number
        for(b=1,i=N;i--&&b;){       // For each prime...
            for(d=n-1,r=0;~d&1;d/=2)++r; // Calculate d and r: d*2^r = n-1
            // Check if there exists any r such that a^(d*2^r) == -1 mod n
            // OR a^d == 1 mod n
            m(p=d);
            for(b=o==1;r--;b|=o==n-1)m(p=d<<r);
            // If neither of these exist, we have proven n is not prime,
            // and the outer loop will keep going (!b)
        }
        // Check if n is actually prime;
        // if it is, the outer loop will keep going (r)
        for(i=r=1;++i<n;r&=n%i!=0);
    }
    printf("%llu",n);               // We found a non-prime; print it & stop.
}

जैसा कि उल्लेख किया गया है, यह 1-आधारित इनपुट का उपयोग करता है। लेकिन n = 0 के लिए यह 9 का उत्पादन करता है, जो संबंधित अनुक्रम https://oeis.org/A006945 का अनुसरण करता है । अब नहीं है; अब यह 0 पर लटका हुआ है।

सभी n के लिए काम करना चाहिए (कम से कम जब तक आउटपुट 2 ^ 64 तक नहीं पहुंच जाता) लेकिन अविश्वसनीय रूप से धीमा है। मैंने इसे n = 0, n = 1 और ( बहुत प्रतीक्षा के बाद ), n = 2 पर सत्यापित किया है ।


मैं अपने समाधान पर एक सफलता बनाता हूं, और फिर आप सिर्फ मुझे एक-अप ... नाइस!
नील ए।

@NeilA। माफ़ करना! इससे पहले कि आप अपना अपडेट पोस्ट करते मैं छोटे इंट प्रकार के साथ खेल रहा था। मुझे यकीन है कि आपको कहीं-कहीं 2 बाइट्स मिलेंगे; यह आश्चर्यजनक रूप से प्रतिस्पर्धी हो रहा है क्योंकि यह 2 अलग-अलग गैर-गोल्फ भाषाओं पर विचार कर रहा है: D
डेव

3

पायथन 2, 633 465 435 292 282 275 256 247 बाइट्स

0 अनुक्रमित

अपने कार्यान्वयन पर सवाल उठाएं और कुछ नया करने का प्रयास करें

एक फंक्शन से एक प्रोग्राम में बदलने से कुछ बाइट्स किसी तरह बचती हैं ...

यदि पायथन 2 मुझे एक ही काम करने के लिए एक छोटा रास्ता देता है, तो मैं पायथन 2 का उपयोग करने जा रहा हूं। डिफॉल्ट रूप से पूर्णांक है, इसलिए 2 से विभाजित करने का एक आसान तरीका है, और printइसे कोष्ठक की आवश्यकता नहीं है।

n=input()
f=i=3
z={2}
a=lambda:min([i%k for k in range(2,i)])
while n:
 if a():z|={i};n-=1
 i+=2
while f:
 i+=2;d,s,f=~-i,0,a()
 while~d&1:d/=2;s+=1
 for y in z:
  x=y**d%i
  if x-1:
   for _ in[]*s:
    x*=x
    if~x%i<1:break
   else:f=1
print i

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

अन्य भाषाओं की तुलना में पायथन बेहद धीमा है।

पूर्ण शुद्धता के लिए एक परीक्षण प्रभाग परीक्षण को परिभाषित करता है, फिर मिलर-राबिन परीक्षण को बार-बार लागू करता है जब तक कि एक छद्मरूप नहीं पाया जाता है।

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

संपादित करें : अंत में जवाब दिया

EDIT : minट्रायल डिवीजन प्राइमलिटी टेस्ट के लिए उपयोग किया जाता है और इसे बदलकर ए lambda। कम कुशल, लेकिन कम। इसके अलावा अपने आप को मदद नहीं कर सका और बिटकॉइन ऑपरेटरों के एक जोड़े का उपयोग किया (कोई लंबाई अंतर नहीं)। सिद्धांत रूप में इसे (थोड़ा) तेजी से काम करना चाहिए।

संपादित करें : धन्यवाद @Dave मेरे संपादक ने मुझे ट्रोल किया। मुझे लगा कि मैं टैब का उपयोग कर रहा हूं, लेकिन इसे 4 स्थानों में बदला जा रहा है। इसके अलावा बहुत से हर एक पायथन टिप के माध्यम से चला गया और इसे लागू किया।

EDIT : 0-इंडेक्सिंग पर स्विच किया गया, मुझे प्राइम उत्पन्न करने के साथ कुछ बाइट्स बचाने की अनुमति देता है। साथ ही तुलना के एक जोड़े को पुनर्विचार किया

संपादित करें : for/elseबयानों के बजाय परीक्षणों के परिणाम को संग्रहीत करने के लिए एक चर का उपयोग किया।

संपादित करें : lambdaएक पैरामीटर की आवश्यकता को समाप्त करने के लिए फ़ंक्शन के अंदर ले जाया गया ।

EDIT : बाइट्स को बचाने के लिए एक प्रोग्राम में परिवर्तित किया गया

संपादित करें : अजगर 2 मुझे बाइट्स बचाता है! इसके अलावा मुझे इनपुट को रूपांतरित नहीं करना हैint


जिस तरह से आप को संभाला +1 a^(d*2^r) mod n!
डेव

क्या आप जानते हैं कि आप अजगर को बचाने के लिए सिंगल-स्पेस (या सिंगल-टैब) इंडेंटेशन का उपयोग कर सकते हैं ... वास्तव में बहुत सारे बाइट्स
डेव

@ डव: यह 1 टैब प्रति इंडेंटेशन स्तर का उपयोग कर रहा है
नील ए।

मुझे लगता है कि आपका आईडीई आपके साथ खिलवाड़ कर रहा है और यह बताकर कि आप टैब का उपयोग कर रहे हैं, रिक्त स्थान बचा रहे हैं; जब मैं उन्हें सिंगल स्पेस के लिए रिप्लेस करता हूं, तो मुझे सिर्फ 311 बाइट्स की बाइट मिलती है! इसे ऑनलाइन आज़माएं!
डेव

@Dave: ठीक है, यह अजीब है, धन्यवाद, मैं जवाब अपडेट करूंगा।
नील ए।

2

पर्ल + मठ :: प्राइम :: यूटिल, 81 + 27 = 108 बाइट्स

1 until!is_provable_prime(++$\)&&is_strong_pseudoprime($\,2..nth_prime($_));$_=""

-lpMMath::Prime::Util=:all(27-बाइट पेनल्टी, ouch) के साथ चलाएँ ।

व्याख्या

यह केवल गणितज्ञ नहीं है जो मूल रूप से किसी भी चीज के लिए एक बिलिन है। पर्ल के पास पहली बड़ी लाइब्रेरी रिपॉजिटरी में से एक CPAN है, और इस तरह के कार्यों के लिए तैयार समाधानों का एक विशाल संग्रह है। दुर्भाग्य से, वे डिफ़ॉल्ट रूप से आयात (या भी स्थापित) नहीं हैं, जिसका अर्थ है कि यह मूल रूप से में उनका उपयोग करने का एक अच्छा विकल्प नहीं है , लेकिन जब उनमें से एक समस्या को पूरी तरह से फिट करने के लिए होता है ...

हम लगातार पूर्णांक के माध्यम से चलाते हैं जब तक कि हम एक ऐसा नहीं पाते हैं जो कि प्रधान नहीं है, और फिर भी 2 से n वें अभाज्य से सभी पूर्णांक आधारों के लिए एक मजबूत छद्मरूप है । कमांड-लाइन विकल्प उस लाइब्रेरी को आयात करता है जिसमें प्रश्न में बिलियन होता है, और निहित इनपुट भी सेट करता है (लाइन-ए-ए-समय पर, Math::Prime::Utilइसकी अपनी बिलिन बिग्नम लाइब्रेरी है जो अपने पूर्णांकों में नईलाइन्स पसंद नहीं करती है)। यह $\अजीब पार्स को कम करने और आउटपुट को अंतर्निहित रूप से उत्पन्न करने की अनुमति देने के लिए चर के रूप में (आउटपुट लाइन सेपरेटर) के मानक पर्ल ट्रिक का उपयोग करता है।

ध्यान दें कि हमें is_provable_primeयहाँ प्रोबिनिस्टिक, प्राइम टेस्ट के बजाय एक निर्धारक का अनुरोध करने के लिए उपयोग करने की आवश्यकता है । (विशेष रूप से यह देखते हुए कि पहली बार मिलर-राबिन का उपयोग करने की संभावना है, जो हम इस मामले में विश्वसनीय परिणाम देने की उम्मीद नहीं कर सकते हैं!)

पर्ल + मैथ :: प्राइम :: यूटिल, 71 + 17 = 88 बाइट्स, @ दादा के सहयोग से

1until!is_provable_prime(++$\)&is_strong_pseudoprime$\,2..n‌​th_prime$_}{

-lpMntheory=:all(17 बाइट पेनल्टी) के साथ चलाएं ।

यह कुछ पर्ल गोल्फिंग ट्रिक्स का उपयोग करता है जिसे मैं या तो नहीं जानता था (जाहिरा तौर पर Math :: Prime :: Util का एक संक्षिप्त नाम है!), के बारे में जानता था लेकिन उपयोग }{करने के बारे में नहीं सोचा था ( $\एक बार "$_$\"अनुमानित रूप से हर पंक्ति के बजाय एक बार आउटपुट करने के लिए ) या के बारे में जानता था, लेकिन किसी तरह गलत तरीके से काम कर रहा था (फ़ंक्शन कॉल से कोष्ठक को हटा रहा था)। इनको इंगित करने के लिए @ दादा को धन्यवाद। इसके अलावा, यह समान है।


बेशक एक गोल्फ-इश भाषा आती है और बाकी को हरा देती है। बहुत बढ़िया!
नील ए।

आप उपयोग कर सकते हैं ntheoryके बजाय Math::Prime::Util। इसके अलावा, }{के बजाय ;$_=""ठीक होना चाहिए। और आप 1कुछ फ़ंक्शन कॉल के बाद और कोष्ठक के स्थान को छोड़ सकते हैं । इसके अलावा, के &बजाय काम करता है &&। 88 बाइट्स देनी चाहिए:perl -Mntheory=:all -lpe '1until!is_provable_prime(++$\)&is_strong_pseudoprime$\,2..nth_prime$_}{'
दादा

मैं पूरी तरह से भूल गया हूँ }{। (काफी अजीब है, मुझे कोष्ठक की बात याद आ गई, लेकिन जब से मैंने पर्ल में गोल्फ किया है और इसे छोड़ने के नियमों को याद नहीं कर पाया, मुझे थोड़ी देर हो गई है।) मुझे इस बारे में बिल्कुल भी जानकारी नहीं थी ntheory
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.