एक यादृच्छिक गैर-घटते क्रम का नमूना


20

इनपुट: किसी भी रूप में दिए गए दो पूर्णांक n और k आपके कोड के लिए सुविधाजनक है

उत्पादन k पूर्णांकों का एक यादृच्छिक गैर-घटता क्रम, प्रत्येक श्रेणी 1 से n तक। नमूना को 1 से n तक के पूर्णांक वाले k पूर्णांकों के सभी गैर-घटते अनुक्रमों से समान रूप से चुना जाना चाहिए।

आउटपुट किसी भी उचित प्रारूप में हो सकता है जो आपको सुविधाजनक लगता है।

आप जो कुछ भी छद्म यादृच्छिक जनरेटर अपने पसंदीदा पुस्तकालय / भाषा प्रदान करता है का उपयोग कर सकते हैं।

हम मान सकते हैं कि पूर्णांक n, k> 0 है।

उदाहरण

कहो n, k = 2. गैर-घटते क्रम हैं

1,1
1,2
2,2

प्रत्येक अनुक्रम में आउटपुट होने की संभावना 1/3 होनी चाहिए।

बंधन

आपका कोड k = 20 और n = 100 के लिए कुछ सेकंड से अधिक नहीं चलना चाहिए।

क्या काम नहीं करता

यदि आप केवल प्रत्येक पूर्णांक को क्रमांक 1 से n तक का नमूना लेते हैं और फिर सूची को क्रमबद्ध करते हैं तो आपको एक समान वितरण नहीं मिलेगा।


N के लिए गैर-घटते अनुक्रमों की संख्या को
आउटपुट

1
@ETHproductions वास्तव में नहीं, यह सिर्फ एक द्विपद ( इस से संबंधित ) है
Sp3000

@ Sp3000 आह, ठीक है। यह मेरे लिए एक मजेदार चुनौती थी कि मैं यह कैसे कुशलतापूर्वक गणना करूं।
16

आपकी आवश्यकता यह है कि प्रत्येक अनुक्रम में आउटपुट होने की समान संभावना है, अधिकांश उद्यान विविधता PRNGs से संतुष्ट होना संभव नहीं है, जिसमें सिर्फ 32 या 48 बिट राज्य हो सकते हैं। वोल्फ्राम के अनुसार, 1, ..., 100 के 535 क्विंटिलियन 20 तत्व परिणाम हैं (यह जांचना नहीं है कि उनमें से कितने नॉनडीकेंडिक हैं)। 2 ^ 64 सिर्फ 18 क्विंटल है।
सिनान Novnür

जवाबों:


1

दरअसल , १४ 12 बाइट्स

यह जवाब Emigna के 05AB1E उत्तर और इस Math.SE प्रश्न पर उत्तर पर आधारित है । गोल्फ सुझाव का स्वागत करते हैं! इसे ऑनलाइन आज़माएं!

;;ra+DR╚HS♀-

Ungolfing

      Implicit input n, then k.
;;    Duplicate k twice.
r     Push range [0...k] for later.
a     Invert the stack. Stack: n, k, k, [0...k]
+DR   Push the range [1..n+k-1].
╚     Shuffle the range. Stack: shuffled_range, k, [0...k]
H     Push the first k elements of shuffled_range. Call this increasing.
S     Sort increasing so the elements are actually increasing.
♀-    Subtract each element of [0...k] from each element of increasing.
      This gives us our non-decreasing sequence.
      Implicit return.

13

पायथन, 89 बाइट्स

from random import*
lambda n,k:[x-i for i,x in enumerate(sorted(sample(range(1,n+k),k)))]

एक घटते क्रम के बजाय एक बढ़ते क्रम को उत्पन्न करना सीधा होगा: यह संख्याओं के बीच का एक यादृच्छिक सबसेट है औरk1n क्रमबद्ध ।

लेकिन, हम एक बढ़ते हुए क्रम को 1. से लगातार संख्याओं के बीच प्रत्येक अंतर को कम करके गैर-घटते हुए में बदल सकते हैं। इसलिए, 1 का अंतर 0 के अंतर के बराबर हो जाता है, जिससे समान संख्याएं बनती हैं। ऐसा करने के लिए, i'सबसे बड़ा मान' घटाएँi

r[0], r[1], ..., r[n-1]  =>  r[0]-0, r[1]-1, ..., r[n-1]-(n-1)

परिणाम से होने के लिए 1करने के लिए n, इनपुट से किया जाना चाहिए 1करने के लिए n+k-1। इससे 1और के बीच की nबढ़ती संख्याओं के बीच घटते क्रमों के बीच एक द्वंद्व होता है , 1और इसके बीच के अनुक्रमों में वृद्धि होती है n+k-1। इसी तरह के दृश्यों को गिनने के लिए सितारों और बार तर्क में एक ही आक्षेप का उपयोग किया जाता है ।

कोड अजगर फ़ंक्शन का उपयोग करता है random.sample, जो kइनपुट सूची से प्रतिस्थापन के बिना नमूने लेता है । इसे क्रमबद्ध करने से बढ़ता क्रम बढ़ता है।


यह प्रभावशाली है। क्या आप विधि का स्पष्टीकरण जोड़ सकते हैं?

हाँ, अभी व्यस्त हैं, बाद में समझाएंगे।
xnor

मैंने 90 बाइट्स गिना ... (और आप import*1 बाइट भी बचा सकते हैं )
रॉड

@Rod धन्यवाद, मैं इसके बारे में भूल गया।
xnor


7

पायथन, 87 बाइट्स

from random import*
f=lambda n,k:k>random()*(n+k-1)and f(n,k-1)+[n]or k*[7]and f(n-1,k)

अधिकतम संभावित मूल्य nशामिल होने की संभावना बराबर होती है k/(n+k-1)। इसे शामिल करने के लिए, इसे सूची के अंत में रखें, और शेष संख्याओं को घटाएं k। इसे बाहर करने के लिए, ऊपरी सीमा को घटाएं n। फिर, तब तक पुनरावृत्ति करें जब तक कि अधिक मूल्यों की आवश्यकता न हो ( k==0)।

पायथन के randomपास एक बर्नौली चर के लिए अंतर्निहित बिल्ट नहीं है: 1 कुछ संभावना के साथ, और 0 अन्यथा। तो, यह जाँचता है कि क्या 0 और 1 के बीच का यादृच्छिक मूल्य randomनीचे गिरता है k/(n+k-1)। पायथन 2 फ्लोट डिवीजन के रूप में अनुपात होगा, इसलिए हम इसके बजाय हर से गुणा करते हैं k>random()*(n+k-1):।


क्या यहां मदद मिलेगी?

@ लेम्बिक अच्छा सोचा था, लेकिन ऐसा लगता है कि आपको आयात करना होगा numpy.random, जो बहुत लंबा है।
xnor

5

जावास्क्रिप्ट (फ़ायरफ़ॉक्स 30+), 74 बाइट्स

(n,k,i=0,j=k)=>[for(_ of Array(q=k+n-1))if(Math.random(++i)<k/q--)i-j+k--]

व्याख्या

xnor के उत्कृष्ट पायथन उत्तर में इस बात का बहुत अच्छा सारांश है कि यहाँ इस्तेमाल की जाने वाली तकनीक कैसे / क्यों काम करती है। पहला चरण सीमा [1, 2, ..., n + k - 1] बनाने के लिए है :

(n,k,i=0)=>[for(_ of Array(q=k+n-1))++i]

अगला हम लेने की जरूरत कश्मीर इस सीमा से यादृच्छिक आइटम नहीं है। ऐसा करने के लिए, हमें प्रायिकता s / q के साथ प्रत्येक आइटम का चयन करना होगा, जहां s अभी भी आवश्यक वस्तुओं की संख्या है और q रेंज में छोड़ी गई वस्तुओं की संख्या है। चूंकि हम एक सरणी समझ का उपयोग कर रहे हैं, यह काफी आसान है:

(n,k,i=0)=>[for(_ of Array(q=k+n-1))if(Math.random(++i)<k/q--)k--&&i]

यह हमें एक समान रूप से वितरित संख्याओं का बढ़ता क्रम प्रदान करता है। इस आइटम की संख्या को घटा कर ठीक किया जा सकता j है कि हम पहले से पाया है:

(n,k,i=0,j=0)=>[for(_ of Array(q=k+n-1))if(Math.random(++i)<k/q--)k--&&i-j++]

अंत में, जम्मू में कश्मीर स्टोर करके , हम अभिव्यक्ति में शामिल कर सकते हैं और कुछ बाइट्स बचा सकते हैं:k--

(n,k,i=0,j=k)=>[for(_ of Array(q=k+n-1))if(Math.random(++i)<k/q--)i-j+k--]

2

टीआई-बेसिक, 54 बाइट्स

Prompt N,K
K→dim(L1
While K
If rand<K/(N+K-1
Then
N→L1(K
K-1→K
Else
N-1→N
End
End
Disp L1

एक छोटे से चेतावनी के साथ, xnor के तर्क का पालन करें। हम सैद्धांतिक रूप से इस तरह से कुछ करके एक बाइट दाढ़ी कर सकते हैं:

K>rand(N+K-1

लेकिन रैंड (यादृच्छिक संख्याओं की एक सूची बनाने के लिए आरक्षित है, इसलिए हम एक बाइट को बचाने के लिए वांछित निहित गुणा नहीं कर पाएंगे।

यह प्रति प्रतिबंध 84+ पर तेजी से चलना चाहिए, लेकिन मैं यह सुनिश्चित करने के लिए जांच करूंगा कि मैं कब कर सकता हूं।


1

PHP, 77 75 73 बाइट्स

foreach(array_rand(range(2,$argv[1]+$k=$argv[2]),$k)as$v)echo$v+1-$i++,_;

इस तरह से चलाएं:

php -r 'foreach(array_rand(range(2,$argv[1]+$k=$argv[2]),$k)as$v)echo$v+1-$i++,_;' -- 10 5 2>/dev/null;echo
> 1_4_6_9_9_

व्याख्या

foreach(                    # Iterate over...
  array_rand(               #   a (sorted) random number of items from...
    range(                  #     an array with items...
      2,                    #       from 2
      $argv[1]+$k=$argv[2]  #       to n + k (set arg 2 to $k)
    ),
    $k                      #     Take k number of items (their keys)
  )
  as $v
)
  echo $v +1 - $i++,"_";    # Print the value subtracted by the index.
                            # Need to add 1, because keys are 0-indexed.

बदलाव

  • तर्क को छोटा करने के बजाय end()कॉल और सेट $argv[2]को हटाकर 2 बाइट्स सहेजे गए$k
  • तर्जनी को हटाकर 2 बाइट्स बचाए, क्योंकि यह केवल एक वृद्धि की संख्या है। बस को बढ़ा देते $iप्रत्येक यात्रा के बजाय

पहले जावास्क्रिप्ट और अब PHP। सभी बेहतरीन वैज्ञानिक प्रोग्रामिंग भाषाएँ :) धन्यवाद।

@Lembik, आपका स्वागत है। आप पर ध्यान दें, यह एक मूल PRNG का उपयोग करता है। क्रिप्टोग्राफिक सामान के लिए उपयोग न करें । :)
१ross
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.