निश्चित संख्या के साथ यादृच्छिक संख्या


32

आपका काम एक प्रोग्राम या फ़ंक्शन लिखना है जो निश्चित संख्या के साथ अंतराल [0,1] से यादृच्छिक संख्याओं को आउटपुट करता है ।ns

इनपुट

n, n≥1उत्पन्न करने के लिए यादृच्छिक संख्या की संख्या

s, s>=0, s<=n, उत्पन्न होने वाली संख्याओं का योग

उत्पादन

अंतराल केn सभी तत्वों के साथ अस्थायी बिंदु संख्याओं का एक यादृच्छिक- अप [0,1] और सभी तत्वों के बराबर s, किसी भी सुविधाजनक अस्पष्ट तरीके से आउटपुट। सभी मान्य n-tuples को समान रूप से फ्लोटिंग पॉइंट नंबरों की सीमाओं के भीतर होने की संभावना है।

यह n-dimensional इकाई क्यूब के अंदर बिंदुओं के प्रतिच्छेदन से समान रूप से नमूने के बराबर है और n-1-dimensional हाइपरप्लेन जो गुजरता है (s/n, s/n, …, s/n)और वेक्टर के लिए लंबवत है (1, 1, …, 1)(तीन उदाहरणों के लिए चित्रा 1 में लाल क्षेत्र देखें)।

N = 3 और रकम 0.75, 1.75 और 2.75 के साथ

चित्रा 1: n = 3 के साथ वैध आउटपुट का विमान और 0.75, 1.75 और 2.75 रकम

उदाहरण

n=1, s=0.8 → [0.8]
n=3, s=3.0 → [1.0, 1.0, 1.0]
n=2, s=0.0 → [0.0, 0.0]
n=4, s=2.0 → [0.2509075946818119, 0.14887693388076845, 0.9449661625992032, 0.6552493088382167]
n=10, s=9.999999999999 → [0.9999999999999,0.9999999999999,0.9999999999999,0.9999999999999,0.9999999999999,0.9999999999999,0.9999999999999,0.9999999999999,0.9999999999999,0.9999999999999]

नियम

  • आपका प्रोग्राम कम से कम n≤10किसी भी मान्य s के साथ आपकी मशीन पर एक सेकंड के तहत समाप्त होना चाहिए ।
  • यदि आप चाहें, तो आपका कार्यक्रम ऊपरी छोर पर अनन्य हो सकता है, अर्थात s<nआधे खुले अंतराल से उत्पादन संख्या [0,1) (दूसरा उदाहरण तोड़कर)
  • यदि आपकी भाषा फ्लोटिंग पॉइंट नंबरों का समर्थन नहीं करती है, तो आप दशमलव बिंदु के बाद कम से कम दस दशमलव अंकों के साथ आउटपुट को नकली कर सकते हैं।
  • मानक कमियां अस्वीकृत हैं और मानक इनपुट / आउटपुट विधियों की अनुमति है।
  • यह , इसलिए सबसे छोटी प्रविष्टि, बाइट्स में मापा जाता है, जीतता है।


जब आप कहते हैं This is equal to uniformly sampling from the intersection- मैं उस चौराहे के कोने से बेतरतीब ढंग से चुनते हुए एक कार्यक्रम देख सकता हूं। क्या यह मान्य होगा?
JayCe

2
@ केविनक्रूजसेन नहीं, यह केवल सच है s==0 or s==3। के अन्य सभी मूल्यों के लिए s, विमान में नॉनजरो क्षेत्र होता है और आपको समान रूप से उस विमान पर एक बिंदु चुनना होता है।
user202729

3
अंतराल को बंद या आधे-बंद (खोलने के विपरीत) की आवश्यकता के लिए सैद्धांतिक रूप से अप्रमाणित आवश्यकता है। कई यादृच्छिक संख्या जनरेटर आउटपुट (0,1) में देते हैं। कैसे परीक्षण करें कि आउटपुट अंतराल [0,1) है और नहीं (0,1)? मान 0 "कभी नहीं" वैसे भी होता है
लुइस मेंडो

2
क्या यह ठीक है यदि हमारा कोड अस्वीकृति नमूने का उपयोग करता है, और इसलिए परीक्षण मामलों की तरह बहुत लंबा समय लगता है s=2.99999999999, n=3? क्या हम गुणकों में यादृच्छिक वास्तविक उत्पन्न करते हैं, कहते हैं 1e-9,?
xnor

जवाबों:


1

वोल्फ्राम लैंग्वेज (गणितज्ञ) , 92 90 बाइट्स

If[2#2>#,1-#0[#,#-#2],While[Max[v=Differences@Sort@Join[{0,#2},RandomReal[#2,#-1]]]>1];v]&

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

गैर-गोल्फ कोड:

R[n_, s_] := Module[{v},
  If[s <= n/2,             (* rejection sampling for s <= n/2:                        *)
    While[
      v = Differences[Sort[
            Join[{0},RandomReal[s,n-1],{s}]]];         (* trial randoms that sum to s *)
      Max[v] > 1           (* loop until good solution found                          *)
    ];
    v,                     (* return the good solution                                *)
    1 - R[n, n - s]]]      (* for s > n/2, invert the cube and rejection-sample       *)

यहां एक समाधान है जो 55 बाइट्स में काम करता है लेकिन अब (मैथमेटिका संस्करण 12) के लिए प्रतिबंधित है n=1,2,3क्योंकि RandomPointउच्च-आयामी हाइपरप्लेन (टीआईओ के संस्करण 11.3 में भी यह विफल रहता है n=1) से अंक आकर्षित करने से इनकार करते हैं । nहालांकि यह भविष्य में उच्चतर के लिए काम कर सकता है :

RandomPoint[1&~Array~#~Hyperplane~#2,1,{0,1}&~Array~#]&

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

गैर-गोल्फ कोड:

R[n_, s_] :=
  RandomPoint[                           (* draw a random point from *)
    Hyperplane[ConstantArray[1, n], s],  (* the hyperplane where the sum of coordinates is s *)
    1,                                   (* draw only one point *)
    ConstantArray[{0, 1}, n]]            (* restrict each coordinate to [0,1] *)


6

पायथन 2 , 144 128 119 बाइट्स

from random import*
def f(n,s):
 r=min(s,1);x=uniform(max(0,r-(r-s/n)*2),r);return n<2and[s]or sample([x]+f(n-1,s-x),n)

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


  • -20 बाइट्स, केविन क्रूज़सेन की बदौलत

@LuisMendo को अब तय किया जाना चाहिए
TFeld

वे अभी भी वर्दी नहीं लगते हैं
l4m2

@ l4m2 मैंने g(4, 2.0)4,000 अंक प्राप्त करने के लिए 1,000 बार दौड़ लगाई और परिणाम इस तरह दिखे जो काफी समान प्रतीत होता है।
इंजीनियर टोस्ट



4

जावा 8, 194 188 196 237 236 बाइट्स

n->s->{double r[]=new double[n+1],d[]=new double[n],t;int f=0,i=n,x=2*s>n?1:0;for(r[n]=s=x>0?n-s:s;f<1;){for(f=1;i-->1;)r[i]=Math.random()*s;for(java.util.Arrays.sort(r);i<n;d[i++]=x>0?1-t:t)f=(t=Math.abs(r[i]-r[i+1]))>1?0:f;}return d;}

+49 बाइट्स (188 → 196 और 196 → 237) 1 के करीब परीक्षण के मामलों की गति को ठीक करने के लिए, साथ ही साथ सामान्य रूप से एल्गोरिथ्म को ठीक करें।

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

स्पष्टीकरण:

में दृष्टिकोण का उपयोग करता इस Stackoverflow जवाब एक पाश के अंदर है, जब तक वस्तुओं में से एक अभी भी की तुलना में 1. बड़ा है
इसके अलावा, अगर 2*s>n, sमें बदल जाएगा n-s, और एक ध्वज इंगित करने के लिए हम का उपयोग करना चाहिए सेट किया गया है 1-diffके बजाय diffपरिणाम सरणी में (टिप @soktinpk और @ l4m2 के लिए धन्यवाद )।

n->s->{              // Method with integer & double parameters and Object return-type
  double r[]=new double[n+1]
                     //  Double-array of random values of size `n+1`
         d[]=new double[n],
                     //  Resulting double-array of size `n`
         t;          //  Temp double
  int f=0,           //  Integer-flag (every item below 1), starting at 0
      i=n,           //  Index-integer, starting at `n`
      x=             //  Integer-flag (average below 0.5), starting at:
        2*s>n?       //   If two times `s` is larger than `n`:
         1           //    Set this flag to 1
        :            //   Else:
         0;          //    Set this flag to 0
  for(r[n]=s=        //  Set both the last item of `r` and `s` to:
       x>0?          //   If the flag `x` is 1:
        n-s          //    Set both to `n-s`
       :             //   Else:
        s;           //    Set both to `s`
      f<1;){         //  Loop as long as flag `f` is still 0
    for(f=1;         //   Reset the flag `f` to 1
        i-->1;)      //   Inner loop `i` in range (n,1] (skipping the first item)
      r[i]=Math.random()*s;
                     //    Set the i'th item in `r` to a random value in the range [0,s)
    for(java.util.Arrays.sort(r);
                     //   Sort the array `r` from lowest to highest
        i<n;         //   Inner loop `i` in the range [1,n)
        ;d[i++]=     //     After every iteration: Set the i'th item in `d` to:
          x>0?       //      If the flag `x` is 1:
           1-t       //       Set it to `1-t`
          :          //      Else:
           t)        //       Set it to `t`
      f=(t=Math.abs( //    Set `t` to the absolute difference of:
            r[i]-r[i+1])) 
                     //     The i'th & (i+1)'th items in `r`
        >1?          //    And if `t` is larger than 1 (out of the [0,1] boundary)
         0           //     Set the flag `f` to 0
        :            //    Else:
         f;}         //     Leave the flag `f` unchanged
  return d;}         //  Return the array `d` as result

समय समाप्त होने परtest(10, 9.99);
l4m2

@ l4m2 हाँ, 10, 9.0मैंने n=10, s=9.999999999999परीक्षण मामले को ठीक करने के लिए संपादित करने के बाद ठीक उसी के साथ देखा । यकीन नहीं होता कि जावा में एक समानता है जबकि अभी भी इसकी समान यादृच्छिकता को पकड़े हुए है .. कुछ समय के लिए इसके बारे में सोचना होगा। अभी के लिए मैं इसे संपादित करने के लिए इसे बाहर का समय बताऊंगा।
केविन क्रूज़सेन

यदि n-s<1आप कॉल कर सकते हैं f(n,n-s)और l4m2 की तरह हर नंबर पर 1/2(यानी के xसाथ बदलें 1-x) फ्लिप कर सकते हैं । यह उन नंबरों के लिए समस्या को हल कर सकता है जहां sपास है n
soktinpk

@soktinpk टिप के लिए धन्यवाद। यह वास्तव में s+s>nइसके बजाय है n-s<1, लेकिन जब मैंने दूसरे जावास्क्रिप्ट उत्तरों को देखा तो यह वास्तव में समझ में आया। अब सब कुछ तय हो गया है, जिसमें एक और बग भी शामिल है जो अभी भी मौजूद था। बाइट्स काफी बढ़ गए, लेकिन अब हर काम करता है। यहां से बाइट-काउंट नीचे काम करेंगे। :)
केविन क्रूज़सेन

मैं एक सामान्य प्रमाण के बारे में नहीं जानता लेकिन मेरा मानना ​​है कि यह एल्गोरिथम काम करता है क्योंकि एक एन-डायमेंशनल हाइपरक्यूब को एन एन-डायमेंशनल हाइपरपिरामिड्स में काटा जा सकता है।
नील


3

सी ++ 11, 284 267 बाइट्स

-17 बाइट्स Zacharý के लिए धन्यवाद
C ++ यादृच्छिक पुस्तकालय, मानक आउटपुट पर आउटपुट

#include<iostream>
#include<random>
typedef float z;template<int N>void g(z s){z a[N],d=s/N;int i=N;for(;i;)a[--i]=d;std::uniform_real_distribution<z>u(.0,d<.5?d:1-d);std::default_random_engine e;for(;i<N;){z c=u(e);a[i]+=c;a[++i]-=c;}for(;i;)std::cout<<a[--i]<<' ';}

कॉल करने के लिए, आपको बस इतना करना होगा:

g<2>(0.0);

जहां टेम्पलेट पैरामीटर (यहां, 2) एन है, और वास्तविक पैरामीटर (यहां, 0.0) एस है


मुझे लगता है कि आप के बीच की जगह को हटा सकते हैं <z>औरu
Zacharý

मैं इसे और नीचे गया typedef float z;template<int N>void g(z s){z a[N],d=s/N;int i=N;for(;i;)a[--i]=d;std::uniform_real_distribution<z>u(.0,d<.5?d:1-d);std::default_random_engine e;for(;i<N;){z c=u(e);a[i]+=c;a[++i]-=c;}for(;i;)std::cout<<a[--i]<<' ';}:। आइटम के बीच विभाजक के लिए एक नई रेखा नहीं है
Zacharý

1
सुझाव है कि से छुटकारा पाने dबदलकर पूरी तरह से d=s/Nकरने के लिए s/=Nदूसरा पाश दोबारा काम सुझाएँ for(z c;i<N;a[++i%N]-=c)a[i]+=c=u(e);बजाय for(;i<N;){z c=u(e);a[i]+=c;a[++i]-=c;}(ध्यान दें जोड़ा %Nक्रम कार्यक्रम calculate बनाने के लिए पहले नंबर सही ढंग से)
मैक्स Yekhlakov

2

स्वच्छ , 221 201 बाइट्स

स्वच्छ, कोड-गोल्फ, या यादृच्छिक संख्या। दो चुनें।

import StdEnv,Math.Random,System._Unsafe,System.Time
g l n s#k=toReal n
|s/k>0.5=[s/k-e\\e<-g l n(k-s)]
#r=take n l
#r=[e*s/sum r\\e<-r]
|all((>)1.0)r=r=g(tl l)n s

g(genRandReal(toInt(accUnsafe time)))

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

आंशिक समारोह शाब्दिक :: (Int Real -> [Real])। केवल एक बार प्रति सेकंड नए परिणाम देगा।
कम से कम 10 दशमलव स्थानों तक सटीक।


2

आर , 99 बाइट्स ( gtoolsपैकेज के साथ )

f=function(n,s){if(s>n/2)return(1-f(n,n-s))
while(any(T>=1)){T=gtools::rdirichlet(1,rep(1,n))*s}
T}

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

हम सेट से समान रूप से नमूना लेना चाहते हैं ~={w1,...,wn:मैं,0<wमैं<1;Σwमैं=रों}। मैं सबको बांट दूंगाwमैं द्वारा रों और इसके बजाय से नमूना ={w1,...,wn:मैं,0<wमैं<1रों;Σwमैं=1}

अगर रों=1, यह आसान है: यह नमूने से मेल खाती है डीमैंआरमैंसीएलटी(1,1,...,1) वितरण (जो सिम्प्लेक्स के ऊपर एक समान है)। सामान्य मामले के लिएरों1, हम अस्वीकृति नमूने का उपयोग करते हैं: सभी प्रविष्टियों हैं जब तक Dirichlet वितरण से नमूना <1/रों, फिर से गुणा करें रों

दर्पण की चाल जब रों>n/2(जो मुझे लगता है कि l4m2 यह पता लगाने वाला पहला था ) आवश्यक है। इससे पहले कि मैंने देखा, अंतिम परीक्षण मामले के लिए अस्वीकृति नमूना में पुनरावृत्तियों की संख्या में विस्फोट हो गया, इसलिए मैंने अच्छी तरह से चुने हुए बीटा वितरण से कुशलतापूर्वक नमूना लेने में बहुत समय बिताया , लेकिन अंत में यह आवश्यक नहीं है।


2

सी, 132 127 125 118 110 110 बाइट्स

-2 बाइट्स @ceilingcat की बदौलत

i;f(s,n,o,d)float*o,s,d;{for(i=n;i;o[--i]=d=s/n);for(;i<n;o[++i%n]-=s)o[i]+=s=(d<.5?d:1-d)*rand()/(1<<31);}

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


दुर्भाग्य से, यह जवाब चुनौती विनिर्देश को पूरा नहीं करता है। आउटपुट रैंडम संख्या तक सीमित नहीं हैं [0,1], और उनका संयुक्त वितरण एक समान नहीं है।
नाइट्रॉडन

@ निट्रॉन हे, क्या आप कृपया एक इनपुट प्रदान कर सकते हैं जिसके लिए आउटपुट [0,1] तक सीमित नहीं है? मैंने कुछ अलग उदाहरणों की कोशिश की और वे सभी सही लग रहे थे, जब तक कि मैंने इस उद्देश्य को गलत नहीं समझा।
ओवरक्लॉकडेनिक

TIO पर RNG राज्य के साथ, और अपने को रखते हुए n=4, मान s=3.23और s=0.89सीमा के बाहर आउटपुट देता है। इस बिंदु पर, वितरण X-s/nपर निर्भर होना चाहिए s, लेकिन ऐसा नहीं है।
१२:१२ पर नाइट्रोडॉन

@Nitrodon ओह, मेरा बुरा। मैं ऊपर दिए गए C ++ उत्तर से कुछ हिस्सों को परिवर्तित कर रहा था और एक चीज जोड़ना भूल गया था। इसे अब ठीक किया जाना चाहिए? इसके अलावा इस प्रक्रिया में कुछ बाइट्स को गोल किया गया।
ओवरक्लॉकडेनिक

1

हास्केल , 122 217 208 बाइट्स

import System.Random
r p=randomR p
(n#s)g|n<1=[]|(x,q)<-r(max 0$s-n+1,min 1 s)g=x:((n-1)#(s-x)$q)
g![]=[]
g!a|(i,q)<-r(0,length a-1)g=a!!i:q![x|(j,x)<-zip[0..]a,i/=j]
n%s=uncurry(!).(n#s<$>).split<$>newStdGen

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

कभी-कभी जवाब थोड़े से बंद हो जाते हैं, मैं मान लेता हूं, फ्लोटिंग पॉइंट एरर के लिए। अगर यह एक समस्या है तो मैं इसे 1 बाइट की कीमत पर ठीक कर सकता हूं। मुझे यह भी निश्चित नहीं है कि यह कितना समान है (बहुत यकीन है कि यह ठीक है, लेकिन मैं इस तरह की चीज से बिल्कुल अच्छा नहीं हूं), इसलिए मैं अपने एल्गोरिथ्म का वर्णन करूंगा।

मूल विचार एक संख्या उत्पन्न xकरना है sऔर फिर उसमें से घटाना और तब तक पुनरावृत्ति करना है जब तक कि हमारे पास nतत्व न हों तब उन्हें फेरबदल करें। मैं x1 या s(जो भी छोटा हो) के ऊपरी बाउंड s-n+1या 0 (या जो भी अधिक हो) के निचले बाउंड के साथ उत्पन्न होता है । यह निचली सीमा है ताकि अगली पुनरावृत्ति परs यह अभी भी n(व्युत्पत्ति) से कम या बराबर हो।s-x<=n-1 -> s<=n-1+x-> s-(n-1)<=x-> - s-n+1<=x) ।

संपादित करें: मेरी एकरूपता के दोष को इंगित करने के लिए @ michi7x7 का धन्यवाद। मुझे लगता है कि मैंने इसे फेरबदल के साथ तय किया है, लेकिन मुझे बताएं कि क्या कोई और समस्या है

EDIT2: बेहतर बाइट काउंट प्लस निश्चित प्रकार प्रतिबंध


3
एकसमान नमूनों का
पीछा

@ michi7x7 मैं आपकी बात देख रहा हूं। क्या होगा अगर मैंने इसे बनाने के बाद सूची का क्रम बदल दिया? मुझे अधिक आँकड़े कक्षाएं लेनी चाहिए
user1472751

संख्या बहुत समान नहीं लगती है। यहां , 8 परिणाम हैं> 0.99, 1 0.96 है, और अंतिम 0.8 है। यह कैसा दिखता है।
स्टीवी ग्रिफिन

@ user1472751 यहाँ कई अच्छे उत्तर हैं: stackoverflow.com/q/8064629/6774250
michi7x7

1
एकरूपता में अभी भी कुछ समस्या है, यहां देखें - बहुत सारे शून्य उत्पन्न होते हैं (1000% 500 से सॉर्ट किए गए मानों का प्लॉट)
18'18

1

हास्केल , 188 बाइट्स

import System.Random
import Data.List
n!s|s>n/2=map(1-)<$>n!(n-s)|1>0=(zipWith(-)=<<tail).sort.map(*s).(++[0,1::Double])<$>mapM(\a->randomIO)[2..n]>>= \a->if all(<=1)a then pure a else n!s

Ungolfed:

n!s
 |s>n/2       = map (1-) <$> n!(n-s)       --If total more than half the # of numbers, mirror calculation 
 |otherwise   = (zipWith(-)=<<tail)        --Calculate interval lengths between consecutive numbers
              . sort                       --Sort
              . map(*s)                    --Scale
              . (++[0,1::Double])          --Add endpoints
              <$> mapM(\a->randomIO)[2..n] --Calculate n-1 random numbers
              >>= \a->if all(<=1)a then pure a else n!s   --Retry if a number was too large

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.