दिलचस्प पोस्ट
थ्रेड सेफ़ सिंगलटन क्लास सी-स्टाइल सरणी से std :: vector को कैसे प्रारंभ करें? रिएक्ट वेरिएबल स्टेटमेंट्स (जेएसएक्स) के साथ एचटीएमएल सम्मिलित करें आईबीएम वर्कलाइट – पिछले रिलीज को कहाँ मिलेगा Jquery UI संवाद में "पुष्टिकरण" संवाद को कैसे कार्यान्वित करें? अस्थिर structs "बुराई" क्यों कर रहे हैं? कैसे ngClick प्रोग्राम को ट्रिगर करने के लिए UITableViewCell सफेद पृष्ठभूमि दिखाता है और IOS7 पर संशोधित नहीं किया जा सकता कस्टम ऑब्जेक्ट्स को NSUserDefaults में सहेजें डेटाबेस प्रबंधन प्रणाली में सामान्यकरण कैसे केवल एकल उद्धरणों से बचने के लिए? लिखने के संदर्भ में विधि वापसी मान का उपयोग नहीं कर सकते चेतावनी: DOMDocument :: loadHTML (): htmlParseEntityRef: अपेक्षित ';' इकाई में, क्यों एक संरचना उदाहरण से संपत्ति की निरंतर बाधाएं लेकिन कक्षा उदाहरण नहीं? JList से JLabel में कस्टम ऑब्जेक्ट खींचें और ड्रॉप करें

आप कश्मीर को दोहराए जाने वाले पूर्णांक की सूची 0 और एक ऊपरी बाउंड एन के बीच कैसे प्रभावी ढंग से उत्पन्न करते हैं

प्रश्न सभी आवश्यक डेटा देता है: किसी दिए गए अंतराल [0, N-1] के भीतर के नॉन-दोहराते हुए पूर्णांक के अनुक्रम उत्पन्न करने के लिए एक कुशल एल्गोरिथ्म क्या है? तुच्छ एल्गोरिथ्म (यादृच्छिक संख्या पैदा करना और, क्रम में उन्हें जोड़ने से पहले, उन्हें देखने के लिए कि वे पहले से वहां थे) बहुत महंगा है यदि कश्मीर बड़े और एन के पास पर्याप्त है

कुशलतापूर्वक एक लिंक्ड सूची से यादृच्छिक तत्वों का एक सेट चुनने में दिए गए एल्गोरिथ्म आवश्यकतानुसार अधिक जटिल लगता है, और कुछ कार्यान्वयन की आवश्यकता होती है। मुझे सिर्फ एक और एल्गोरिदम मिल गया है जो काम को ठीक करने के लिए लगता है, जब तक कि आप एक एकल पास में सभी प्रासंगिक मापदंडों को जानते हैं

वेब के समाधान से एकत्रित समाधान "आप कश्मीर को दोहराए जाने वाले पूर्णांक की सूची 0 और एक ऊपरी बाउंड एन के बीच कैसे प्रभावी ढंग से उत्पन्न करते हैं"

अजगर पुस्तकालय से यादृच्छिक मॉड्यूल यह बेहद आसान और प्रभावी बनाता है:

from random import sample print sample(xrange(N), K) 

sample फ़ंक्शन दिए गए अनुक्रम से चुने गए के अनन्य तत्वों की एक सूची देता है।
xrange एक "सूची एमुलेटर" है, अर्थात् यह लगातार संख्याओं की सूची जैसे स्मृति में xrange बिना व्यवहार करता है, जो इस तरह के कार्यों के लिए सुपर फास्ट बनाता है

कंप्यूटर प्रोग्रामिंग की कला में, खंड 2: सेमिनिमिकल एल्गोरिदम, तीसरा संस्करण , नुत निम्नलिखित चयन नमूनाकरण एल्गोरिदम का वर्णन करता है:

एल्गोरिदम एस (चयन नमूना तकनीक) N के सेट से यादृच्छिक पर एन रिकॉर्ड चुनने के लिए, जहां 0 <n ≤ N

एस 1। [प्रारंभ करें।] सेट टी ← 0, मी 0 0 (इस एल्गोरिथ्म के दौरान, मी अभी तक चयनित अभिलेखों की संख्या का प्रतिनिधित्व करता है, और टी हमारे द्वारा निपटाए गए इनपुट रिकॉर्ड की कुल संख्या है।)

एस 2। [जेनरेट यू] एक यादृच्छिक संख्या यू उत्पन्न करता है, समान रूप से शून्य और एक के बीच वितरित किया जाता है।

S3। [टेस्ट।] यदि (एन – टी) यू ≥ एन – एम, स्टेप एस 5 पर जाएं।

एस 4। [चयन करें।] नमूना के लिए अगले रिकॉर्ड का चयन करें, और 1 से मी और टी को बढ़ाएं। यदि मी <n, चरण 2 पर जाएं; अन्यथा नमूना पूरा हो गया है और एल्गोरिद्म समाप्ति है।

S5। [छोड़ें।] अगले रिकॉर्ड छोड़ें (इसे नमूना में शामिल न करें), 1 से बढ़ाएं और चरण 2 पर वापस जाएं।

वर्णन से पालन करने के लिए एक कार्यान्वयन आसान हो सकता है यहां एक सामान्य लिस्प कार्यान्वयन है, जो सूची से यादृच्छिक सदस्यों को चुनता है:

 (defun sample-list (n list &optional (length (length list)) result) (cond ((= length 0) result) ((< (* length (random 1.0)) n) (sample-list (1- n) (cdr list) (1- length) (cons (car list) result))) (t (sample-list n (cdr list) (1- length) result)))) 

और यहां एक कार्यान्वयन है जो पुनरावर्ती का उपयोग नहीं करता, और जो सभी प्रकार के दृश्यों के साथ काम करता है:

 (defun sample (n sequence) (let ((length (length sequence)) (result (subseq sequence 0 n))) (loop with m = 0 for i from 0 and u = (random 1.0) do (when (< (* (- length i) u) (- nm)) (setf (elt result m) (elt sequence i)) (incf m)) until (= mn)) result)) 

आपके द्वारा चुने गए कुल सेट के अनुपात के बावजूद, आप जिस सेट से चयन कर रहे हैं, उसके बजाए चयनित तत्वों की संख्या के लिए आनुपातिक रूप से अंतरिक्ष में ऐसा करना संभव है। आप ऐसा एक यादृच्छिक क्रमचय उत्पन्न करते हैं, फिर इसे इस तरह से चुनना:

एक ब्लॉक सिफर चुनें, जैसे कि चाय या XTEA ब्लॉक आकार को उस सेट के मुकाबले दो बड़े आकार की छोटी शक्ति में कम करने के लिए XOR तह का उपयोग करें, जिसे आप चुन रहे हैं। सिफर की कुंजी के रूप में यादृच्छिक बीज का उपयोग करें क्रमांतरण में एक तत्व n उत्पन्न करने के लिए, सिफर के साथ एन्क्रिप्ट एन यदि आउटपुट संख्या आपके सेट में नहीं है, तो एन्क्रिप्ट करें संख्या सेट के अंदर होने तक दोहराएं। औसतन आपको प्रति जनरेटेड संख्या से कम दो एन्क्रिप्शन करना होगा। इसके अतिरिक्त लाभ यह है कि यदि आपका बीज क्रिप्टोग्राफ़िक रूप से सुरक्षित है, तो आपका संपूर्ण क्रमचय है।

मैंने इस बारे में बहुत अधिक विस्तार से लिखा है

निम्न कोड (सी में, अज्ञात मूल) समस्या को बहुत अच्छी तरह से हल करने के लिए लगता है:

  /* generate N sorted, non-duplicate integers in [0, max[ */ int *generate(int n, int max) { int i, m, a; int *g = (int *)calloc(n, sizeof(int)); if ( ! g) return 0; m = 0; for (i=0; i<max; i++) { a = random_in_between(0, max - i); if (a < n - m) { g[m] = i; m ++; } } return g; } 

क्या किसी को पता है कि मुझे इस तरह की अधिक रत्न कहां मिल सकते हैं?

सरणी 0...N-1 उत्पन्न करें 0...N-1 ने a[i] = i भरी

फिर पहली K वस्तुओं को घसीटना

पुथल:

  • प्रारंभ करें J = N-1
  • एक यादृच्छिक संख्या 0...J (say, R )
  • a[R] साथ a[R] स्वैप करें
    • चूंकि R J बराबर हो सकता है, तत्व को स्वतः ही बदल दिया जा सकता है
  • 1 से J और दोहराएँ।

अंत में, K आखिरी तत्व ले लो।

यह अनिवार्य रूप से सूची से एक यादृच्छिक तत्व उठाता है, इसे बाहर ले जाता है, फिर शेष सूची से एक यादृच्छिक तत्व उठाता है, और इसी तरह।

हे (के) और ओ (एन) समय में काम करता है, ओ (एन) भंडारण की आवश्यकता होती है।

फेफर्स -येट्स फेरफिल या नुथ का फेरबदल , द आर्ट ऑफ़ कंप्यूटर प्रोग्रामिंग के दूसरे संस्करण में वर्णित है, फेरबदल भाग को कहा जाता है

एक हैशिंग स्टोर में कश्मीर संख्या को संग्रहीत करके तुच्छ एल्गोरिथ्म को गति दें। प्रारंभ करने से पहले कश्मीर को जानने से हश का नक्शा डालने की सभी अक्षमता दूर हो जाती है, और आपको अभी भी तेजी से देखने के लाभ मिलते हैं

चरण 1: अपनी सूची को पूर्णांक बनाएं
चरण 2: नुथ शफल प्रदर्शन करें

ध्यान दें कि आपको पूरी सूची को फेरबदल करने की आवश्यकता नहीं है, क्योंकि Knuth Shuffle एल्गोरिथ्म आपको केवल n शफल्स को लागू करने की अनुमति देता है, जहां n वापस लौटने वाले तत्वों की संख्या है। सूची तैयार करने से सूची के आकार में अभी भी आनुपातिक समय लगेगा, लेकिन आप किसी भी भविष्य की फेरबदल की ज़रूरतों के लिए अपनी मौजूदा सूची का पुन: उपयोग कर सकते हैं (आकार संभालने में समान रहता है) आंशिक रूप से फेरबदल की सूची को फेरबदल करने से पहले फेरबदल एल्गोरिदम

Knuth साधा के लिए मूल एल्गोरिथ्म यह है कि आप पूर्णांक की एक सूची के साथ शुरू करते हैं। उसके बाद, आप सूची में किसी भी संख्या के साथ पहली पूर्णांक को स्वैप करते हैं और वर्तमान (नया) पहले पूर्णांक लौटाते हैं फिर, आप सूची में किसी भी संख्या के साथ दूसरा पूर्णांक स्वैप (प्रथम को छोड़कर) और वर्तमान (नया) दूसरा पूर्णांक वापस लौटाएं तो फिर … आदि …

यह एक मूर्खतापूर्ण सरल एल्गोरिथ्म है, लेकिन सावधान रहें कि आप स्वैप करते समय सूची में वर्तमान आइटम को शामिल करते हैं या आप एल्गोरिदम को तोड़ देंगे।

जलाशय नमूनाकरण संस्करण बहुत आसान है:

 my $N = 20; my $k; my @r; while(<>) { if(++$k <= $N) { push @r, $_; } elsif(rand(1) <= ($N/$k)) { $r[rand(@r)] = $_; } } print @r; 

एसटीडीआईएन से $ N यादृच्छिक रूप से चुनी गई पंक्तियाँ यदि आप किसी फ़ाइल से पंक्तियों का उपयोग नहीं कर रहे हैं, तो << / $ _ सामान को कुछ और के साथ बदलें, लेकिन यह एक बहुत सीधा एल्गोरिथ्म है।

मेरा समाधान सी ++ उन्मुख है, लेकिन मुझे यकीन है कि इसे अन्य भाषाओं में अनुवाद किया जा सकता है क्योंकि यह बहुत आसान है।

  • सबसे पहले, कश्मीर तत्वों के साथ एक लिंक्ड सूची तैयार करें, जो 0 से K तक जा रहे हैं
  • तब तक जब तक सूची खाली न हो, 0 और वेक्टर के आकार के बीच एक यादृच्छिक संख्या उत्पन्न करें
  • उस तत्व को लें, उसे किसी अन्य वेक्टर में दबाएं, और उसे मूल सूची से हटा दें

इस समाधान में केवल दो लूप पुनरावृत्तियों शामिल हैं, और कोई हैश तालिका देखने या सॉर्ट के कुछ भी नहीं है तो वास्तविक कोड में:

 // Assume K is the highest number in the list std::vector<int> sorted_list; std::vector<int> random_list; for(int i = 0; i < K; ++i) { sorted_list.push_back(i); } // Loop to K - 1 elements, as this will cause problems when trying to erase // the first element while(!sorted_list.size() > 1) { int rand_index = rand() % sorted_list.size(); random_list.push_back(sorted_list.at(rand_index)); sorted_list.erase(sorted_list.begin() + rand_index); } // Finally push back the last remaining element to the random list // The if() statement here is just a sanity check, in case K == 0 if(!sorted_list.empty()) { random_list.push_back(sorted_list.at(0)); } 

यदि सूची को सॉर्ट किया गया है, उदाहरण के लिए, यदि आप कश्मीर तत्वों को एन से बाहर निकालना चाहते हैं, लेकिन आप उनके रिश्तेदार ऑर्डर के बारे में परवाह नहीं करते हैं, तो कागज में एक कुशल एल्गोरिथ्म प्रस्तावित है, क्रमिक रैंडम नमूनाकरण के लिए एक कुशल एल्गोरिदम (जेफरी स्कॉट विटर, गणितीय सॉफ्टवेयर पर एसीएम लेनदेन , खंड 13, नंबर 1, मार्च 1 9 87, पृष्ठ 56-67।)।

को बढ़ावा देने के द्वारा कोड को जोड़ने के लिए संपादित किया गया मैंने इसे बस टाइप किया है और कई त्रुटियां हो सकती हैं यादृच्छिक संख्या को बढ़ावा पुस्तकालय से आता है, एक बेवकूफ बीज के साथ, इसलिए इस के साथ कुछ गंभीर मत करो।

 /* Sampling according to [Vitter87]. * * Bibliography * [Vitter 87] * Jeffrey Scott Vitter, * An Efficient Algorithm for Sequential Random Sampling * ACM Transactions on MAthematical Software, 13 (1), 58 (1987). */ #include <stdlib.h> #include <string.h> #include <math.h> #include <string> #include <iostream> #include <iomanip> #include <boost/random/linear_congruential.hpp> #include <boost/random/variate_generator.hpp> #include <boost/random/uniform_real.hpp> using namespace std; // This is a typedef for a random number generator. // Try boost::mt19937 or boost::ecuyer1988 instead of boost::minstd_rand typedef boost::minstd_rand base_generator_type; // Define a random number generator and initialize it with a reproducible // seed. // (The seed is unsigned, otherwise the wrong overload may be selected // when using mt19937 as the base_generator_type.) base_generator_type generator(0xBB84u); //TODO : change the seed above ! // Defines the suitable uniform ditribution. boost::uniform_real<> uni_dist(0,1); boost::variate_generator<base_generator_type&, boost::uniform_real<> > uni(generator, uni_dist); void SequentialSamplesMethodA(int K, int N) // Outputs K sorted random integers out of 0..N, taken according to // [Vitter87], method A. { int top=NK, S, curr=0, currsample=-1; double Nreal=N, quot=1., V; while (K>=2) { V=uni(); S=0; quot=top/Nreal; while (quot > V) { S++; top--; Nreal--; quot *= top/Nreal; } currsample+=1+S; cout << curr << " : " << currsample << "\n"; Nreal--; K--;curr++; } // special case K=1 to avoid overflow S=floor(round(Nreal)*uni()); currsample+=1+S; cout << curr << " : " << currsample << "\n"; } void SequentialSamplesMethodD(int K, int N) // Outputs K sorted random integers out of 0..N, taken according to // [Vitter87], method D. { const int negalphainv=-13; //between -20 and -7 according to [Vitter87] //optimized for an implementation in 1987 !!! int curr=0, currsample=0; int threshold=-negalphainv*K; double Kreal=K, Kinv=1./Kreal, Nreal=N; double Vprime=exp(log(uni())*Kinv); int qu1=N+1-K; double qu1real=qu1; double Kmin1inv, X, U, negSreal, y1, y2, top, bottom; int S, limit; while ((K>1)&&(threshold<N)) { Kmin1inv=1./(Kreal-1.); while(1) {//Step D2: generate X and U while(1) { X=Nreal*(1-Vprime); S=floor(X); if (S<qu1) {break;} Vprime=exp(log(uni())*Kinv); } U=uni(); negSreal=-S; //step D3: Accept ? y1=exp(log(U*Nreal/qu1real)*Kmin1inv); Vprime=y1*(1. - X/Nreal)*(qu1real/(negSreal+qu1real)); if (Vprime <=1.) {break;} //Accept ! Test [Vitter87](2.8) is true //step D4 Accept ? y2=0; top=Nreal-1.; if (K-1 > S) {bottom=Nreal-Kreal; limit=NS;} else {bottom=Nreal+negSreal-1.; limit=qu1;} for(int t=N-1;t>=limit;t--) {y2*=top/bottom;top--; bottom--;} if (Nreal/(Nreal-X)>=y1*exp(log(y2)*Kmin1inv)) {//Accept ! Vprime=exp(log(uni())*Kmin1inv); break; } Vprime=exp(log(uni())*Kmin1inv); } // Step D5: Select the (S+1)th record currsample+=1+S; cout << curr << " : " << currsample << "\n"; curr++; N-=S+1; Nreal+=negSreal-1.; K-=1; Kreal-=1; Kinv=Kmin1inv; qu1-=S; qu1real+=negSreal; threshold+=negalphainv; } if (K>1) {SequentialSamplesMethodA(K, N);} else { S=floor(N*Vprime); currsample+=1+S; cout << curr << " : " << currsample << "\n"; } } int main(void) { int Ntest=10000000, Ktest=Ntest/100; SequentialSamplesMethodD(Ktest,Ntest); return 0; } $ time ./sampling|tail 

मेरे लैपटॉप पर निम्नलिखित ऑप्टुत देता है

 99990 : 9998882 99991 : 9998885 99992 : 9999021 99993 : 9999058 99994 : 9999339 99995 : 9999359 99996 : 9999411 99997 : 9999427 99998 : 9999584 99999 : 9999745 real 0m0.075s user 0m0.060s sys 0m0.000s 

यह रूबी कोड जलाशय नमूनाकरण, एल्गोरिथ्म आर विधि दिखाता है। प्रत्येक चक्र में, मैं [0,N=10) श्रेणी से n=5 अद्वितीय यादृच्छिक पूर्णांक का चयन करता हूं:

 t=0 m=0 N=10 n=5 s=0 distrib=Array.new(N,0) for i in 1..500000 do t=0 m=0 s=0 while m<n do u=rand() if (Nt)*u>=nm then t=t+1 else distrib[s]+=1 m=m+1 t=t+1 end #if s=s+1 end #while if (i % 100000)==0 then puts i.to_s + ". cycle..." end end #for puts "--------------" puts distrib 

उत्पादन:

 100000. cycle... 200000. cycle... 300000. cycle... 400000. cycle... 500000. cycle... -------------- 250272 249924 249628 249894 250193 250202 249647 249606 250600 250034 

0-9 के बीच सभी पूर्णांक लगभग एक ही संभावना से चुने गए थे

यह अनिवार्य रूप से नैथ के एल्गोरिथ्म को मनमाना अनुक्रमों पर लागू किया गया है (वास्तव में, इसका उत्तर में इसका एक लिस्प संस्करण है) एल्गोरिथ्म समय में हे (एन) है और ओ (1) मेमोरी में हो सकता है यदि अनुक्रम @ मायकेलकैमेर के उत्तर में दिखाए गए अनुसार उसमें प्रवाहित होता है।

यह अतिरिक्त भंडारण के बिना ओ (एन) में ऐसा करने का एक तरीका है मुझे पूरा यकीन है कि यह विशुद्ध रूप से यादृच्छिक वितरण नहीं है, लेकिन यह संभवतः कई उपयोगों के लिए करीब है।

 /* generate N sorted, non-duplicate integers in [0, max[ in O(N))*/ int *generate(int n, int max) { float step,a,v=0; int i; int *g = (int *)calloc(n, sizeof(int)); if ( ! g) return 0; for (i=0; i<n; i++) { step = (max-v)/(float)(ni); v+ = floating_pt_random_in_between(0.0, step*2.0); if ((int)v == g[i-1]){ v=(int)v+1; //avoid collisions } g[i]=v; } while (g[i]>max) { g[i]=max; //fix up overflow max=g[i--]-1; } return g; } 

यह पर्ल कोड है Grep एक फिल्टर है, और हमेशा की तरह मैंने इस कोड का परीक्षण नहीं किया था।

 @list = grep ($_ % I) == 0, (0..N); 
  • मैं = अंतराल
  • N = ऊपरी बाउंड

केवल मॉड्यूलस ऑपरेटर के माध्यम से आपके अंतराल से मेल खाने वाले नंबर प्राप्त करें।

 @list = grep ($_ % 3) == 0, (0..30); 

0, 3, 6, … 30 वापस आ जाएगी

यह छद्म पर्ल कोड है इसे संकलित करने के लिए आपको इसे ज़ूम करने की आवश्यकता हो सकती है।