Sabit bir rasgele kaynak kullanarak 0 ile n arasında rastgele bir sayı seçin.


26

Görev

Seçtiğiniz herhangi bir şekilde giriş olarak belirtilenden ndaha düşük bir pozitif tamsayı verildiğinde 2^30, kodunuzun 0ve n, dahil olmak üzere rasgele bir tamsayı vermesi gerekir . Ürettiğiniz sayı rastgele eşit şekilde seçilmelidir . Bu, her bir değer 0için neşit olasılıkla cereyan etmesi gerekmektedir (Kurallar ve belgesine bakınız).

Kurallar ve Uyarılar

Kodunuz, kendi dilinizde ya da aynı şekilde rastgele olduğunu iddia eden standart kitaplığın içindeki herhangi bir rasgele sayı üreticisinin aslında tek tip olduğunu varsayabilir. Bu, kullandığınız rasgele kaynağın kalitesi hakkında endişelenmenize gerek yok. Ancak,

  • Kullanmakta olduğunuz rastgele kaynağın tek tip olması durumunda, kodunuzun doğrudan tek biçimli bir rasgele tamsayı ürettiğini 0belirlemeniz gerekir n.
  • Bir yerleşik veya kitaplık rastgele işlevini çağırırken herhangi bir argüman sabit olmalıdır. Bu, girdi değerinden tamamen bağımsız olmaları gerektiğidir.
  • Kodunuz, sonlandırılması garanti edilmek yerine olasılık 1 ile sona erebilir.

notlar

  • randInt(0,n) girişi yerleşik veya kütüphane işlevine bir argüman olarak aldığı için geçerli değil.
  • rand()%nolacak değil genel olarak tekdüze rasgele sayı verir. Betseg tarafından verilen Örnek olarak, eğer intmax == 15ve n = 10o zaman almak için çok daha muhtemel olacaktır 0-5daha 6-10.
  • floor(randomfloat()*(n+1)) ayrıca, genel olarak 0 ve 1 arasındaki muhtemel farklı kayan nokta değerlerinin sonlu sayısından dolayı tek tip rastgele bir sayı vermeyecektir.

Çıktının eşit olarak rastgele olduğunu nasıl onaylayacaksınız? Belirli bir dilin / kütüphanenin düzgün rastgele sayılar üretmesi olabilir, ancak manipülasyon düzgün olmayan çıktılara neden olabilir. (örneğin rng()sağlar 0- 100, eğer n = 75, ve fonksiyon ise rng()%75, 0-25 daha yaygın olacaktır ...)
Baldrickk

1
@Baldrickk Kalabalıkların bilgeliği ile :) Sadece kodu okuyabilir ve düşünebiliriz.

Mümkün olan en basit olasılık-teori sorusunu sormanın üzücü bir sonucu: rastgelelik ve olasılık çok az anlaşılmıştır. :( (Ve kuralları okumak zor, görünüşe göre zor.)
Martin Ender

Bu akla geliyor: Rastgele Sayı
BgrWorker

Üç tane daha kısa olduğunda neden x86 cevabını kabul ettiniz?
Dennis,

Yanıtlar:


25

x86 komutlu makineler rdrand, 10 bayt

BITS 64

_try_again:

 rdrand eax
jnc _try_again

 cmp eax, edi
ja _try_again

 ret

makine kodu

0FC7F0 73FB 39F8 77F7 C3

Giriş kayıt defterinde rdive çıkış ise giriş rax.
Bu, SYS V AMD64 ABI'ye saygılıdır, böylece kod etkin bir C işlevi uygular.

unsigned int foo(unsigned int max); 

32-bit ints ile.

Talimat rdrandIntel tarafından açıklanmıştır.

RDRANDşifreli olarak güvenli, deterministik rastgele bit üretici DRBG tarafından sağlanan rasgele sayıları döndürür. DRBG, NIST SP 800-90A standardını karşılayacak şekilde tasarlanmıştır .

CSRNG ile ilgili olarak, NIST SP 800-90A’dan alıntı yaparak, yine de dağılımın tek biçimli olduğu açıktır:

Rastgele bir sayı, tarafsız bir rastgele değişkenin bir örneğidir, yani, düzgün dağılmış bir rastgele işlem tarafından üretilen çıktı .


Prosedür rastgele bir sayı oluşturur ve eğer girdiden kesinlikle katı değilse, döndürülür.
Aksi takdirde, işlem tekrarlanır.

Bu yana eax, 32-bit, rdrand0 ve 2 arasında bir sayı döndürür 32 bu yüzden her için, -1 n içinde [0, 2 32 -1] beklenen yineleme sayısı 2 32 / (n + 1) Tüm için tanımlandığı gibidir , n [0, 2 30 ] 'da.


Zekice düşük seviye. Teşekkür ederim.

Ne jnciçin?
14m2

@ l4m2 rdrand, CFdöndürülen verilerin geçerli olup olmadığını belirler . Entropi havuzunu çok fazla istek boşalttığı için veriler geçersiz olabilir. Rdrand ve bunun için manuel girişe bakın .
Margaret Bloom

20

Jöle , 7 6 bayt

⁴!!X%‘

1 byte'lık golf için @JonathanAllan'a teşekkürler!

TIO'da çalıştırılamaz çünkü (16!)! çok büyük bir sayı.

Nasıl çalışır

⁴!!X%‘  Main link. Argument: n

⁴       Set the return value to 16.
 !!     Compute (16!)!.
   X    Pseudo-randomly choose an integer between 1 and (16!)!.
        Since (16!)! is evenly divisible by any k ≤ 2**30, it is evenly divisible
        by n+1.
    %‘  Take the result modulo n+1.

Bu silinen cevabımın sabit bir versiyonudur, aynı fikir. Buna rağmen gereksiz bir üsüm vardı.
orlp

Üzgünüm, göndermeden önce bakmadım.
Dennis,

Oh önemli değil, yine de tamir etmeyi planlamıyordum. Jelly'le oynamayı çok fazla rahatsız ettim.
orlp

1
“Efendim neden kızdığınızı bilmiyorum. Algoritma sürekli bir zaman. Bu iyi bir şey, doğru mu? Neden güvenlik ve İK kapının dışında?”
corsiKa

1
Kabul. 8 basamaklı bir sayı ile 417 beşinci bir rakamlı sayı arasındaki farkın biti: p
Jonathan Allan

11

Mathematica, 29 bayt

Dennis'in Jelly cevabına dayanarak .

RandomInteger[2*^9!-1]~Mod~#&

Aslında bu çalıştırmayı tavsiye etmem. 2e9!oldukça büyük bir sayıdır ...

Mümkün olan tüm girdiler tarafından bölünebilen büyük bir sayı üretmek için en kısa olduğu ve sonuçta basit bir modülo ile istenen aralığın sonucunu belirlediği görülmektedir.

Reddetme Örneklemesi, 34 bayt

Biraz daha ilginç bir koda neden olan eski yaklaşımım:

13!//.x_/;x>#:>RandomInteger[13!]&

Temel ret örneklemesi. Çıkışı 13'e çıkardık! (bu maksimum giriş 2 30'dan daha büyüktür ) ve sonra tekrar tekrar 0 ila 13 arasında rasgele bir tamsayı ile değiştirin ! değer girişten büyük olduğu sürece.


1
"Girişten küçük veya eşit" mi demek istiyorsunuz?

1
@Lembik Hayır. İstenilen aralığa girmediği sürece değeri yeniden oluşturmak istiyoruz.
Martin Ender

Ah anlıyorum. Bazı nedenlerden dolayı tekrar tekrar istenen aralıktan örnekleme yaptığımızı sanıyordum. Teşekkürler.

1
Bir dahaki sefere bir zaman sınırı eklememi hatırlat :)

9

Brachylog , 9 bayt

≥.∧13ḟṙ|↰

Çevrimiçi deneyin!

Bu 13!Martin Ender'in cevabındaki gibi kullanır ( 13ḟbir bayttan küçük 2^₃₀).

kullanılarak gerçekleştirilir random_between/3kaynağını kazma zaman, kullanım ki, random_float/0bağlantılı random/1olan bizim için üniform Mersenne twister algoritması kullanır.

açıklama

≥.           Input ≥ Output
  ∧          And
   13ḟṙ      Output = rand(0, 13!)
       |     Else
        ↰    Call recursively with the same input

7

Prolog (SWI) , 38 bayt

X*Y:-Z is 2^31,random(0,Z,Y),Y=<X;X*Y.

Reddetme örneklemesiyle çalışır.

Girdiden küçük veya eşit bir sayı bulunana kadar 0 ile 2 ^ 31-1 = 2147483647 arasında rasgele bir sayı oluşturun .

Öteki yerine bir kesim kullanabilmem gerektiğini hissediyorum, ancak nasıl olduğunu göremiyorum.


1
Kullanmadan kaçınabilirsiniz repeat, ancak sonuç 3 bayt daha uzun olur… Tekrar etmekten çok sınırsız seçim noktasına sahip olmanın daha kısa bir yolu olup olmadığından emin değilim.
17:17

@Fatalize: Evet, ben de tekrar etmeyi denedim. ,!.Bir geri dönüşü zorlamak gibi bir şey kullanma hafızam vardı, ama ya yanlış hatırlıyorum ya da bu çözüm için geçerli değil.
Emigna

7

Labirent , 63 bayt

 ?
 #00}__""*_
 ;    #"  _
{-{=  } "><)
!{ : ;"({ +
@  }}:  >`#

(Burada ağır golf oynamaya yardımcı olduğu için @MartinEnder'e teşekkürler.)

Labirent, 2B dilidir ve tek rastgele kaynağı şu şekildedir:

   x
  "<)
 " "
 " "

Talimat göstergesinin üstünde xve aşağı doğru hareket ettiğini varsayalım . Bir sonraki aşamada, <eğer yığının tepesi 0 ise (bu her zaman yukarıdaki gerçek programda olduğu gibi) mevcut satırı 1 değerinde değiştirir:

   "
 "<)
 " "
 " "

Talimat işaretçisi şimdi < aşağı doğru hareket ediyor. Bir kavşakta, Labyrinth yığının tepesine göre döner - negatif sola, pozitif sağa ve sıfır ileri gider. Yığının tepesi bu noktada hala sıfırsa, yol olmadığından ileri veya geri hareket edemeyiz, bu nedenle Labyrinth, eşit olasılıkla sola veya sağa çevirme arasında rasgele hareket eder.

Temel olarak yukarıdaki programın yaptığı şey, 100 bit sayılar üretmek için rastgelelık özelliğini kullanmaktır (100 ile #00 burada ) üretene kadar döngülemeye devam<= n .

Test için, büyük olasılıkla #0"10 bitlik sayılar yerine bunun kullanılması muhtemelen" no-op yolu . Çevrimiçi deneyin!

Kaba açıklama:

 ?            <--- ? is input and starting point
 #0"}__""*_   <--- * here: first run is *0, after that is *2 to double
 ;    #"  _
{-{=  } "><)  <--- Randomness section, +0 or +1 depending on path.
!{ : ;"({ +        After <, the >s reset the row for the next inner loop.
@  }}:  >`#

 ^    ^
 |    |
 |    The " junction in this column checks whether the
 |    100-bit number has been generated, and if not then
 |    continue by turning right into }.
 |
 Minus sign junction here checks whether the generated number <= n.
 If so, head into the output area (! is output as num, @ is terminate).
 Otherwise, head up and do the outer loop all over again.

7

Python, 61 bayt

from random import*
lambda n,x=2.**30:int(randrange(x)*-~n/x)

Düzenleme: Yasaklı formu önlemek için güncellendi

Edit2: 2 bayt kaydedildi, teşekkürler @ JonathanAllan

Edit3: Tamamen işlevsel bir çözüm için 2 byte ödedi - tekrar teşekkürler @JonathanAllan

Düzen4: Kaldırıldı f= , 2 bayt kaydediliyor

Edit5: @ sayesinde 1 bayt daha kaydedildi JonathanAllan

Düzenleme6: @ JonathanAllan sayesinde 2 bayt daha kaydedildi

Şimdilik, git suçlama bana kötü şeyler, JonathanAllan yardımcı olacaklar için işaret ederdi.

Düzenleme7: Yağmur yağdığında, dökülür - başka bir 2 bayt

Edit8: Ve başka 2 bayt


1
Bu asla çıkmaz n, ancak kullanarak from random import*ve bırakarak düzelttiğinizde iki byte tasarruf edebilirsiniz r..
Jonathan Allan,

1
Evet, aksi gerekli parantez önlemek, böylece için "iribaş operatörünü" kullanabilirsiniz ...*(-~n*1.0/2**30))ziyade...*((n+1)*1.0/2**30))
Jonathan Allan

1
Gerçekten mi? Tatlı! 70 numaraya karşı uzun süredir devam eden kin var mı? Yardımınız için çok teşekkürler
iwaseatenbyagrue

1
Aslında randrangebir şamandırayı kabul ediyor gibi görünüyor, bu yüzden lambda n,x=2.**30:int(randrange(x)*-~n/x)başka iki [değiştir ...] dört kaydeder!
Jonathan Allan,

1
^ orada parantez kaldırılması ile iki tane daha. Sadece çarpma işleminin yol olduğunu göstermeye gider!
Jonathan Allan

6

Python 2,61 bayt

from random import*
lambda n:map(randrange,range(1,2**31))[n]

Sözde rastgele arasındaki tam sayıları tercih 0 ve k tüm değerleri için k arasında 0 ve 2 31 - 2 , daha sonra tekabül eden bir tam sayı alır k = n .


5

Toplu iş, 64 bayt

@set/ar=%random%*32768+%random%
@if %r% gtr %1 %0 %1
@echo %r%

%random%sadece 15 bit rasgelelik veriyor, bu yüzden iki rasgele sayıyı birleştirmem gerekiyor. Rastgele değer istenen aralıkta olana kadar döngüler, çok düşük için yavaş n; Daha hızlı sürüm için 98 bayt:

@set/a"n=%1+1,m=~(3<<30)/n*n,r=%random%*32768+%random%
@if %r% geq %m% %0 %1
@cmd/cset/a%r%%%%n%

Kod yavaş olabilir ama cevabınız hızlıydı!

3
@Lembik Cevabını silinmiş soruna gitmeye hazırdım ...
Neil

Bu, önce istenen sayıyı, ardından daha büyük hale gelen diğer tüm sayıları yankılamaz nmı?
Outgolfer Erik,

@EriktheOutgolfer Hayır; Kullanmak sürece call, bir toplu komut dosyası çağırma akım komut sonlandırır.
Neil,

5

MATL , 12 bayt

@AdmBorkBork ve @Suever'a , TIO önbelleğini nasıl devre dışı bırakacağımı söyledikleri için teşekkürler .

`30WYrqG>}2M

Çevrimiçi deneyin! .

Bu kullanan reddi yöntem bir rasgele bir tamsayı oluşturur: 0için 2^30-1bu giriş üzerinde iken, ve tekrar n. Bu olasılıkla sona ermesi garantilidir 1, ancak ortalama yineleme sayısı şudur 2^30/nve bundan nönemli ölçüde daha küçükler için çok uzun sürer 2^30.

`         % Do...while
  30W     %   Push 2^30
  Yr      %   Random integer from 1 to 2^30
  q       %   Subtract 1
  G>      %   Does it exceed the input? If so: next iteration. Else: exit
}         % Finally (execute right before exiting the loop)
  2M      %   Push the last generated integer
          % End (implicit). Display (implicit)

4

JavaScript (ES6), 55 54 bayt

f=(n,m=1)=>m>n?(x=Math.random()*m|0)>n?f(n):x:f(n,m*2)

Aralığındaki tamsayıları oluşturur [0 ... 2 k - 1] , k şekildedir tamsayıdır küçük olan 2 K daha büyüktür , n . Sonuç [0 ... n] içine düşene kadar tekrar eder .

Niye ya?

Bu, aşağıdaki varsayımlara dayanmaktadır:

  • Dahili olarak, JS motorunun beslemesi Math.random()için üretilen sözde rasgele tamsayı değerleri , herhangi bir aralıkta [0 ... 2 k -1] ( k <32 ile ) aynıdır .

  • Kesin güç 2 ile çarpıldığında, geri getirilen IEEE 754 Math.random()değişken değerleri bu aralıklar boyunca hala aynıdır.

Herhangi biri bu hipotezleri onaylayabilir veya çürütebilirse, lütfen yorumlarda bana bildirin.

gösteri

[0 ... 2] 'de 1 milyon değer üretir ve sonuç istatistiklerini görüntüler.


Math.floor (Math.random () * (n + 1)) benim için daha az düzgün dağıtılmış bir sonuç üretmiyor, bu yüzden herhangi bir dağıtım anomalisi yaratacak herhangi bir gerçekçi N <2 ^ 30 olup olmadığını görmek güzel olurdu hiç.
zeplin

1
@zeppelin herhangi bir anomaliyi belirlemek için çok fazla deneme çalışması yapmanız gerekecek, çünkü o aralıktaki rastgele bir kayan nokta, 2 ^ 30 sonuçlara mümkün olduğunca eşit bir şekilde dağıtılacak olan 2 ^ 53 değerden birine sahip olacaktır. Bu nedenle, aralıktaki büyük sayılar için bile, hata 2 ^ 23'te 1 gibi bir şey olacaktır, bu da çok sayıda denemeye ihtiyaç duyacağınız anlamına gelir. Muhtemelen ilk örneklerin sayısından (2 ^ 53) birkaç büyüklük daha isteyeceksin. Bununla birlikte, eğer çarpan, numune sayısını eşit bir şekilde bölmezse, bu yüzden Arnauld'un iki kişilik bir güç kullanması tam olarak üniform olamaz.
Martin Ender

4

Bash (+ coreutils), 44 bayt

/ dev / urandom tabanlı çözüm

od -w4 -vtu4</d*/ur*|awk '($0=$2)<='$1|sed q

İmzasız 32 bit tam sayıları okuyacak /dev/urandomve awkbelirli bir aralıkta bir tane bulana kadar bunları filtreleyecek , sonra sed qboruyu iptal edecek.


Bash için Yaşasın :)

4

Haskell, 70 bayt

import System.Random
g n=head.filter(<=n).randomRs(0,2^30)<$>getStdGen

Çok verimli bir algoritma değil, işe yarıyor. [0,2 ^ 30] ile sınırlandırılmış sonsuz bir tamsayı listesi (veya gerekirse Haskell'in tipi sistemi nedeniyle yüzer) oluşturur ve birincisini n'den küçük veya ona eşittir. Küçük n için bu uzun zaman alabilir. Rastgele sayılar için, rastgele R belgelerinde belirtildiği gibi rastgele sayılar dağıtılmalıdır, bu nedenle [0,2 ^ 30] arasındaki tüm sayılar aynı olasılıkta olmalıdır (1 / (2 ^ 30 + 1)); 0, n] aynı olasılığa sahiptir.

Alternatif Sürüm:

import System.Random
g n=head.filter(<=n).map abs.randoms<$>getStdGen

Bu sürüm korkunç ama bütün bayttan tasarruf sağlıyor. randomsSonsuz sayıların listesini oluşturmak için türün tanımladığı keyfi bir aralığı kullanır Bu, negatifleri içerebilir, bu yüzden absonları pozitif (veya sıfır) zorlamak için haritalandırmamız gerekir . Bu, çok büyük olmayan n değerleri için son derece yavaştır. EDIT : Daha sonra bu versiyonun düzgün dağılmadığını fark ettim çünkü 0 alma olasılığı kullanımdan dolayı diğer numaralardan daha kötü abs. Bir sayı üretmek miçin jeneratör üretebilir mveya -mancak 0 olması durumunda sadece 0 kendisi çalışacaktır, bu nedenle olasılığı diğer sayıların yarısıdır.


Haskell için Yaşasın (çok)!

4

Jöle , 9 bayt

⁴!Ẋ’>Ðḟ⁸Ṫ

Çevrimiçi deneyin! - yukarıdaki kod, 16 boyutundan beri TIO'da çalışmayacak! önce inşa edilmeleri gerekir (karıştırılmaları ve sonra filtrelenmeleri gerektiği gerçeğinden bahsetmemeliler!), bu yüzden aynı şey daha küçük bir ölçekte, 10'luk bir giriş ile 3'lük bir giriş için 30 kez tekrarlandı.

Nasıl?

⁴!Ẋ’>Ðḟ⁸Ṫ - Main link: n
⁴         - 16
 !        - factorial: 20922789888000
  Ẋ       - shuffle random: builds a list of the integers 1 through to 16! inclusive and
          - returns a random permutation via Python's random.shuffle (pretty resource hungry)
   ’      - decrement (vectorises - a whole pass of this huge list!)
     Ðḟ   - filter out if: (yep, yet another pass of this huge list!)
    >     -     greater than
       ⁸  -     left argument, n
        Ṫ - tail: return the rightmost remaining entry.

Not:ȷ⁵ Birinin ondan onuna dönmesini bekler ve ona geri döndürürse , aynı bayt sayısı için binin üzerinde bir zaman daha verimli olacaktır, ancak bu, kullanılması gereken değişmez on olarak değerlendirilmediği için durum böyle değildir. değişmez sayısına göre, ȷ...ancak iki ayrı değişmez ayrıştırılır, ȷvarsayılan üçe bin bin, üstelik on verir.


Huh, şu 9 karakter ama 22 bayt
Kristoffer Sall-Storgaard

@ KristofferSall-Storgaard Her karakter Jelly'in kod sayfasındaki 256 bayttan biridir, bayt kelimesini genellikle yaptığım gibi bir bağlantı yapmayı unuttum.
Jonathan Allan

1
yıl, ben baktım ve aynı şeyi öğrendim
Kristoffer Sall-Storgaard

4

Jshell üzerinde JDK 9, 75 59 bayt

n->(new Random()).ints(0,1<<30).dropWhile(x->x>n).findAny()

kullanım

((IntFunction)(n->(new Random()).ints(0,1<<30).dropWhile(x->x>n).findAny())).apply(<n>)
  • -16 bytes: Teşekkürler Jakob!
  • Jshell'i geçerli bir çalışma zamanı ortamı olarak kabul ettiğimizi varsayar.
  • Çalışma zamanı ortamı olarak jshell, çekirdek kütüphaneler için açık bir ithalat gerektirmez ve noktalı virgül gerektirmez.
  • Bir döndürür OptionalInt. Kurallar, dönüş türünün ilkel olması gerektiğini belirtmez OptionalIntve sonucun geçerli bir temsili olduğunu düşünüyorum.

1
İlham için @ kevin-cruijssen teşekkürler. İlk golf kodum!
Pete Terlep

Kutulu çıktının kabul edilip edilmediği, kabul edilenden farklıdır Optional. Senin yerinde olsam posterle onaylardım. Ayrıca, tüm ödevi saymaya gerek yoktur; sadece lambda ifadesi yeterlidir.
Jakob,

1
Lambda parametresi nve etrafındaki parantezleri kaldırarak 4 byte tasarruf edebilirsiniz new Random().
Jakob

3

PHP, 30 bayt

    while($argn<$n=rand());echo$n;

İle koş echo <N> | php -Rn '<code>' .

0 ile getrandmax()(64 bit makinemde 2 ** 31-1) rastgele bir sayı seçiyor ;
girişden daha büyükken tekrar eder.

Bu olabilir almak bir süre ... benim AMD C-50 için 0.3 ve 130 saniye arasında gerekli (1 GHz)N=15 .

Ortalama için daha hızlı bir yol N( 46 bayt ):

for(;++$i<$x=1+$argn;)$n+=rand()%$x;echo$n%$x;

veya

for(;++$i<$x=1+$argn;$n%=$x)$n+=rand();echo$n;

alır N+1 onları özetliyor, rasgele tamsayılar ve birlikte modulo alır N+1.
C-50'nin yakl. 1 milyon koşu için 8 saniye.

19 bayt için geçersiz bir çözüm :

echo rand(0,$argn);

3

PowerShell , 35 bayt

for(;($a=Random 1gb)-gt"$args"){}$a

Çevrimiçi deneyin!

Başka bir ret örnekleme yöntemi. Bu, sonsuz fordeğerini ayarlama, döngü $abir olmak Randomtamsayı arasında 0ve 1gb( = 1073741824 = 2^30), ve bu kadar uzun tamsayı olduğu döngü devam -greater than girişi $args. Döngü tamamlandıktan sonra, sadece$a boru hattını ve çıktı kapalıdır.

Not: Girdi küçük bir sayı ise, bu uzun zaman alacaktır .


3

Python 2 , 72 69 bayt

Xnor sayesinde -3 bayt ( idyerleşik olarak değişken olarak geçersiz kıl )

from random import*
n=input()
while id>n:id=randrange(2**30)
print id

Çevrimiçi deneyin!

randrange(2**30)[0,2 30 ] aralığından sahte olarak dağılmış bir sayı (Mersenne Twister 2 19937-1 ) üretir . Yana aşağıda olması sağlanır 2 30 o girdi büyüktür olmayana kadar basitçe tekrar tekrar çağrılabilir bu. Çok düşük değerler için uzun süre beklenen bir zaman alacaktır , ancak 50 dakikaya kadar olan girişler için bile bir dakika içinde çalışır.nn


2
r=''"Sonsuzluk" olarak başlatabilirsiniz . Ya da, daha iyisi, başlatmayın rve bunun yerine idher yerde kullanın r.
xnor


2

05AB1E , 11 bayt

žIÝ.rDI›_Ϥ

Çevrimiçi deneyin!

açıklama

žIÝ          # push the inclusive range [0 ... 2^31]
   .r        # get a random permutation (pythons random.shuffle)
     D       # duplicate this list
      I      # push input
       ›_Ï   # keep only elements from the list not greater than input
          ¤  # take the last one

Liste [0 ... 2147483648]TIO için çok büyük olduğundan, bağlantı 1.000.000yerine kullanılır.

Alternatif (ortalama) çok daha hızlı 11 bayt çözüm

[žIÝ.RD¹›_#

Çevrimiçi deneyin

açıklama

[             # start loop
 žIÝ          # push the inclusive range [0 ... 2^31]
    .R        # pick a random integer (pythons random.chiose)
      D       # duplicate
       ¹      # push input
        ›_#   # break if random number is not greater than input
              # implicitly output top of stack (the random number)

žJL.R% for 6 unless I'm missing something huge. Push 2^32, list from 0 to 2^32, random pick. Modulo input. Will absolutely screw the efficiency that you have.
Magic Octopus Urn

@carusocomputing.You'd need an I in there for 7 bytes to get the arguments for modulus in the right order (and maybe Ý instead of L), but otherwise that's certainly a shorter solution. I saw Dennis doing that in his Jelly answer, but as this was my first idea I kept this. As that approach is different from this you could post it as a separate answer.
Emigna

DI‹Ï would avoid the loop.
Magic Octopus Urn

Also, as-is, this is not guaranteed to terminate; if I'm not mistaken, an input of 0 would almost always result in a near-infinite loop, making it hard to terminate. Though the solution does allow for the possibility to terminate in all scenarios it isn't guaranteed due to randomness.
Magic Octopus Urn

@carusocomputing: For very small input the second version would on average take a very long time to finish yes, but given enough time it would.
Emigna

2

Python 2, 89 bytes

l=range(2**31)
import random
random.shuffle(l)
n=input()
print filter(lambda x:x<=n,l)[0]

Explanation

L=range(2**31)      # Create a list from 0 to 2^31 exclusive. Call it <L>.
import random       # Import the module <random>.
random.shuffle(L)   # Use 'shuffle' function from <random> module,
                    # to shuffle the list <L>.
n=input()           # Take the input -> <n>.

print
    filter(         # Create a new sequence,
    lambda x:x<=n   # where each element is less than or equal to <n>.
    ,L)             # from the list <L>.
    [0]             # Take the first element.

This is very inefficient, as it creates 2^31 integers, shuffles and filters them.

I see no point in sharing a TIO link, where it's creating such large lists, so here is a TIO link for n = 100.

Try it online!


2

Java 8, 84 83 80 71 62 bytes

n->{int r;for(;(r=(int)(Math.random()*(1<<30)))>n;);return r;}

-1 byte thanks to @OliverGrégoire.
-3 bytes thanks to @Jakob.
-9 bytes converting Java 7 to Java 8.
-9 bytes by changing java.util.Random().nextInt(1<<30) to (int)(Math.random()*(1<<30)).

Explanation:

Try it here.

n->{        // Method with integer parameter and integer return-type
  int r;    //  Result-integer
  for(;(r=(int)(Math.random()*(1<<30)))>n;);
            //  Loop as long as the random integer is larger than the input
            //  (the random integer is in the range of 0 - 1,073,741,824 (2^30))
  return r; //  Return the random integer that is within specified range
}           // End method

NOTE: May obviously take very long for small inputs.

Example output:

407594936

2
@Aaron I questioned this as well but see the second bullet point: "Any arguments when calling a built in or library random function must be constant. That is they must be completely independent of the input value." This is the reason max int is used.
Poke

1
2^30 = 1073741824. You preferred to use -1>>>1 (= 2147483647). But this exists: 1<<30 which is exactly equals to 2^30; and is 1 byte shorter.
Olivier Grégoire

1
How about int c(int n){int r;for(;(r=new java.util.Random().nextInt(1<<30))>n;);return r;}?
Jakob

@Jakob Thanks. I even shortened it by 18 more bytes by using Java 8 instead of 7, and using Math.random() instead of java.util.Random().nextInt.
Kevin Cruijssen

2

Python 3, 51 bytes

Here is a python solution with an unorthodox random source.

print(list(set(map(str,range(int(input())+1))))[0])

Try it online!

So to break this down.

int(input())+1

Gets the input number, and adds 1 to it.

set(range(...))

Creates the set {0, 1, 2, 3, 4, ... n} for all possible results.

print(list(...)[0])

Takes the set, converts it to list, and grabs the first item.

This works because in Python 3, the order of set() is established by PYTHONHASHSEED (can't be obtained but is established on script execution).

Admittedly, I am guessing that this is a uniform distribution, as the hash() value is randomly assigned and I am looking at randomly picking the value with a specific hash(), rather then just returning the hash(input()) itself.

If anyone knows whether this is a uniform distribution, or how I could test that, please comment.


1

C#, 57 bytes

n=>{int x=n+1;while(x>n)x=new Random().Next();return x;};

Anonymous function which returns an integer between 0 and n inclusive.

The smaller the input number, the longer the time to return a random value.

Full program:

using System;

class RandomNumber
{
    static void Main()
    {
        Func<int, int> f =
        n=>{int x=n+1;while(x>n)x=new Random().Next();return x;};

        // example
        Console.WriteLine(f(100000));
    }
}

2
"Any arguments when calling a built in or library random function must be constant. That is they must be completely independent of the input value." The argument to Next is not static.
Yytsi

1

Bash + coreutils, 20 bytes

Golfed

seq 0 $1|shuf|sed 1q

shuf - generate random permutations

Shuf will use the following code: to generate permutations:

permutation = randperm_new (randint_source, head_lines, n_lines);

which ends up in randint_genmax

/* Consume random data from *S to generate a random number in the range
0 .. GENMAX.  */

randint
randint_genmax (struct randint_source *s, randint genmax) 
{
      ...

      randread (source, buf, i);

      /* Increase RANDMAX by appending random bytes to RANDNUM and
         UCHAR_MAX to RANDMAX until RANDMAX is no less than
         GENMAX.  This may lose up to CHAR_BIT bits of information
         if shift_right (RANDINT_MAX) < GENMAX, but it is not
         worth the programming hassle of saving these bits since
         GENMAX is rarely that large in practice.  */
      ...
}

which, in turn, will read a few bytes of the random data from the low-level source of randomness:

/* Consume random data from *S to generate a random buffer BUF of size
   SIZE.  */

void
randread (struct randread_source *s, void *buf, size_t size)
{
  if (s->source)
    readsource (s, buf, size);
  else
    readisaac (&s->buf.isaac, buf, size);
}

i.e. at the low-level, there is no direct dependency between the shuf input value and the data read from the source of randomness (aside from computing the required byte buffer capacity).


6
Isn't this giving the input as an argument to your random number generator?
Martin Ender

Even if this is not valid, please submit another bash answer!

@MartinEnder well, not directly, it just uses the input to define the upper limit for the generated integer range and jot will arrange for all the values in the range to appear in the output with an equal probability (that's probably borderline, but still).
zeppelin

2
If I dig deep enough into any random number generator I'm sure I'll find a call into a lower-level RNG that doesn't directly use the original argument. The point of the challenge is to obtain an arbitrary-size uniform distribution from a fixed -size distribution, which you're still not doing.
Martin Ender

1

SmileBASIC, 38 bytes

INPUT N@L
R=RND(1<<30)ON N<=R GOTO@L?R

Generates random numbers until it gets one that is smaller than the input.


1

Ruby, 23 15 23 32 29 bytes

->n{1while n<q=rand(2**30);q}

How it works:

  • 1while [...]; executes the statement at least once: 1 before while acts as a nop
  • Get a random number in the range 0..2^30-1 (lower than 2^30, as specified)
  • Repeat if the number is higher than the input parameter (Could take some time when n is small)

1

Ohm, 26 bytes

IΩ
D31º#╬D0[>?D-+∞;,

Explanation:

IΩ                 ■Main wire
IΩ                 ■Call wire below

D31º#╬D0[>?D-+∞;,  ■"Real main" wire
D                  ■Duplicate input
 31º#╬D            ■Push random_int in [0..2^31] twice
       0[          ■Push input again
         >?    ;   ■If(random_int > input){
           D-+     ■  remove the random_int
              ∞    ■  recursion
               ;   ■}
                ,  ■Print random_int

Is there an interpreter for this language? And what about Code-page?
ATaco

@ATaco: Interpreter, Code-page: CP-437
Emigna


1

Golang, 84 78 71 bytes

import."math/rand"
func R(n int)int{q:=n+1;for;q>=n;q=Int(){};return q}

Simple rejection sampling.

Note: since the math/rand seed is a constant 1, the caller must seed unless a constant result is desired.

Test: https://play.golang.org/p/FBB4LKXo1r No longer practically testable on a 64-bit system, since it's returning 64-bit randomness and using rejection testing.

package main

import "fmt"
import "time"

/* solution here *//* end solution */

func main() {
    Seed(time.Now().Unix())
    fmt.Println(R(1073741823))
}

1
if you use import."math/rand" then Int31 is available in the global namespace and you can save 4 bytes, also intis guaranteed to be at least 32 bits, saving you another 6 bytes
Kristoffer Sall-Storgaard

Use := syntax for another 3 bytes
Kristoffer Sall-Storgaard

Using int instead of int32 doesn't save any bytes since we need to cast the result of Int31() - 3*int + () = 11 bytes versus 2*int32 = 10 bytes.
Riking

1
No need to cast, there is an Int() function in the rand package, also, you can remove the space after import
Kristoffer Sall-Storgaard
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.