Scegli un numero casuale tra 0 e n usando una fonte costante di casualità


26

Compito

Dato un numero intero positivo ninferiore a quello 2^30specificato come input in qualsiasi modo tu scelga, il tuo codice dovrebbe generare un numero intero casuale compreso tra 0e n, incluso. Il numero che generi dovrebbe essere scelto in modo uniforme a caso . Questo significa che ogni valore da 0a ndeve apparire con uguale probabilità (vedi Regole e Avvertenze).

Regole e avvertenze

Il tuo codice può presumere che qualsiasi generatore di numeri casuali incorporato nella tua lingua o libreria standard che afferma di essere uniformemente casuale sia in effetti uniforme. Cioè non devi preoccuparti della qualità della fonte casuale che stai usando. Tuttavia,

  • Devi stabilire che se la sorgente casuale che stai usando è uniforme, il tuo codice emette correttamente un intero casuale uniforme da 0a n.
  • Qualsiasi argomento quando si chiama una funzione casuale incorporata o in libreria deve essere costante. Cioè devono essere completamente indipendenti dal valore di input.
  • Il tuo codice può terminare con probabilità 1 anziché essere garantito per terminare.

Gli appunti

  • randInt(0,n) non è valido poiché accetta l'input come argomento per una funzione di libreria o incorporata.
  • rand()%nsarà non dare un numero casuale uniforme in generale. A titolo di esempio dato da betseg, se intmax == 15e n = 10, allora si sarà molto più probabile per ottenere 0-5rispetto 6-10.
  • floor(randomfloat()*(n+1)) inoltre non fornirà un numero casuale uniforme in generale a causa del numero finito di diversi possibili valori in virgola mobile compresi tra 0 e 1.

Come confermerai che l'output è uniformemente casuale? Può darsi che una determinata lingua / libreria produrrà numeri uniformemente casuali, ma la manipolazione potrebbe produrre un output non uniforme. (es. rng()fornisce 0- 100, se n = 75e la funzione è rng()%75, allora 0-25 sarà più comune ...)
Baldrickk

1
@Baldrickk Per la saggezza delle folle :) Possiamo solo leggere il codice e pensarci.

La triste conclusione di porre la più semplice domanda possibile sulla teoria della probabilità: casualità e probabilità sono capite molto male. :( (E leggere le regole è difficile, a quanto pare.)
Martin Ender

Questo mi viene in mente: Numero casuale
BgrWorker

Perché hai accettato la risposta x86 quando ce ne sono tre più brevi?
Dennis,

Risposte:


25

macchine x86 con rdrandistruzione, 10 byte

BITS 64

_try_again:

 rdrand eax
jnc _try_again

 cmp eax, edi
ja _try_again

 ret

codice macchina

0FC7F0 73FB 39F8 77F7 C3

L'ingresso è nel registro rdie l'uscita è dentro rax.
Questo rispetta l' ABI SYS V AMD64, quindi il codice implementa efficacemente una funzione C.

unsigned int foo(unsigned int max); 

con ints a 32 bit.

Le istruzioni rdrandsono descritte da Intel

RDRANDrestituisce numeri casuali forniti da un generatore di bit casuali deterministico crittograficamente sicuro DRBG. Il DRBG è progettato per soddisfare lo standard NIST SP 800-90A .

Trattando con CSRNG è implicito che la distribuzione sia uniforme, comunque, citando il NIST SP 800-90A:

Un numero casuale è un'istanza di una variabile casuale imparziale, ovvero l'output prodotto da un processo casuale distribuito uniformemente .


La procedura genera un numero casuale e se è non strettamente maggiore dell'input viene restituito.
Altrimenti, il processo viene ripetuto.

Poiché eaxè a 32 bit, rdrandrestituisce un numero compreso tra 0 e 2 32 -1, quindi per ogni n in [0, 2 32 -1] il numero di iterazioni previste è 2 32 / (n + 1) che è definito per tutti n in [0, 2 30 ).


Livello brillantemente basso. Grazie.

A cosa serve jnc?
l4m2

@ l4m2 rdrandimposta CFse i dati restituiti sono validi. I dati potrebbero non essere validi perché troppe richieste hanno svuotato il pool di entropia. Vedi l'inserimento manuale di rdrand e questo .
Margaret Bloom,

20

Gelatina , 7 6 byte

⁴!!X%‘

Grazie a @JonathanAllan per il golf off 1 byte!

Non può essere eseguito su TIO perché (16!)! è un numero enorme .

Come funziona

⁴!!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.

Questa è una versione fissa della mia risposta eliminata, stessa idea. Anche se avevo un esponenziale non necessario.
orlp,

Mi dispiace, non l'ho visto prima di pubblicare.
Dennis,

Oh, non importa, non avevo intenzione di sistemarlo comunque. Sono troppo a disagio con Jelly per giocarci davvero.
orlp,

1
"Signore, non so perché sei arrabbiato. L'algoritmo è un tempo costante. È una buona cosa, vero? Perché la sicurezza e le risorse umane sono fuori dalla porta?"
corsiKa

1
Concordato. Un po 'di differenza tra un numero di 8 cifre e un numero di 417 quintilioni di cifre: p
Jonathan Allan

11

Mathematica, 29 byte

Basato sulla risposta di Jelly di Dennis .

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

Non consiglierei davvero di eseguirlo. 2e9!è un numero piuttosto grande ...

Risulta essere il più breve per generare un numero enorme che è divisibile per tutti gli input possibili e mappare il risultato nell'intervallo richiesto con un semplice modulo.

Campionamento di rifiuto, 34 byte

Il mio vecchio approccio ha portato a un codice un po 'più interessante:

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

Campionamento di rifiuto di base. Inizializziamo l'output a 13! (che è maggiore dell'ingresso massimo 2 30 ) e quindi sostituirlo ripetutamente con un numero intero casuale compreso tra 0 e 13! purché il valore sia maggiore dell'input.


1
Intendi "minore o uguale all'input"?

1
@Lembik No. Vogliamo rigenerare il valore purché non rientri nell'intervallo desiderato.
Martin Ender,

Oh, capisco. Per qualche ragione ho pensato che stessimo ripetutamente campionando dalla gamma desiderata. Grazie.

1
Ricordami di aggiungere un limite di tempo la prossima volta :)

9

Brachylog , 9 byte

≥.∧13ḟṙ|↰

Provalo online!

Questo usa 13!come nella risposta di Martin Ender ( 13ḟè un byte in meno di 2^₃₀).

è implementato usando random_between/3, che, quando si scava la sua fonte, usa ciò random_float/0che è collegato al random/1quale usa l'algoritmo di Mersenne Twister che è uniforme per i nostri scopi.

Spiegazione

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

7

Prolog (SWI) , 38 byte

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

Funziona mediante campionamento di rifiuto.

Generare un numero casuale compreso tra 0 e 2 ^ 31-1 = 2147483647 fino a quando non viene trovato uno inferiore o uguale all'ingresso.

Sento che dovrei essere in grado di usare un taglio invece dell'altro, ma non riesco a vedere come.


1
Potresti evitare che l'altro utilizzi repeat, ma finisce per essere 3 byte più a lungo ... Non sono sicuro che ci sia un modo più breve di avere infiniti punti di scelta che ripetere.
Fatalizza il

@Fatalize: Sì, ho provato anche a ripetere. Avevo un ricordo dell'uso di qualcosa come ,!.forzare un backtrack, ma o lo ricordo male o non è applicabile a questa soluzione.
Emigna,

7

Labirinto , 63 byte

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

(Grazie a @MartinEnder per l'aiuto con un po 'di golf pesante qui.)

Labyrinth è un linguaggio 2D e la sua unica fonte di casualità è in una situazione come la seguente:

   x
  "<)
 " "
 " "

Supponiamo che il puntatore dell'istruzione sia sul xe che si sposti verso il basso. Successivamente atterra su <, che se la parte superiore dello stack è 0 (che è sempre il caso nel programma reale sopra) sposta la riga corrente a sinistra di 1:

   "
 "<)
 " "
 " "

Il puntatore dell'istruzione è ora in <movimento verso il basso. A un incrocio, Labyrinth gira in base alla parte superiore dello stack: il negativo è la svolta a sinistra, il positivo la svolta a destra e lo zero è lo spostamento in avanti. Se la parte superiore dello stack è ancora zero a questo punto, non possiamo spostarci in avanti o indietro poiché non esiste alcun percorso, quindi Labyrinth si sposterà casualmente tra girare a sinistra o girare a destra con uguale probabilità.

In sostanza, ciò che fa il programma sopra è usare la funzionalità di casualità per generare numeri a 100 bit (100 specificati #00qui) e continuare il ciclo fino a quando non genera un numero <= n.

Per i test, sarà probabilmente utile utilizzare #0"invece per i numeri a 10 bit, "essendo un percorso no-op. Provalo online!

Spiegazione approssimativa:

 ?            <--- ? 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 byte

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

Modifica: aggiornato per evitare la forma proibita

Edit2: salvato 2 byte, grazie @ JonathanAllan

Edit3: pagato 2 byte per una soluzione completamente funzionale - grazie ancora @JonathanAllan

Edit4: rimosso f=, salvando 2 byte

Edit5: salvato un altro byte grazie a @ JonathanAllan

Edit6: salvato altri 2 byte grazie a @ JonathanAllan

Ormai, la colpa di git mi avrebbe indicato le cose cattive e Jonathan Allan per le cose che aiutano.

Edit7: quando piove, si riversa - altri 2 byte

Edit8: E altri 2 byte


1
Questo non nverrà mai emesso , ma è possibile salvare due byte quando lo si risolve utilizzando from random import*e rilasciando il r..
Jonathan Allan,

1
Sì, è possibile utilizzare l '"operatore girino" per evitare le parentesi altrimenti necessarie, quindi ...*(-~n*1.0/2**30))piuttosto che...*((n+1)*1.0/2**30))
Jonathan Allan,

1
Veramente? Dolce! Hai qualche rancore di vecchia data contro il numero 70? Grazie mille per il vostro aiuto
iwaseatenbyagrue,

1
In effetti randrangesembra accettare un float, quindi ne lambda n,x=2.**30:int(randrange(x)*-~n/x)salva altri due [modifica ...] quattro!
Jonathan Allan,

1
^ altri due dentro con rimozione delle parentesi. Va solo a mostrare che la tua moltiplicazione è stata la strada da percorrere!
Jonathan Allan,

6

Python 2 , 61 byte

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

Pseudo-casualmente sceglie numeri interi tra 0 e k per tutti i valori di k tra 0 e 2 31 - 2 , quindi accetta il numero intero corrispondente a k = n .


5

Lotto, 64 byte

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

%random%dà solo 15 bit di casualità, quindi devo combinare due numeri casuali. Fa un ciclo fino a quando il valore casuale rientra nell'intervallo desiderato, quindi lento per basso n; 98 byte per una versione più veloce:

@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%

Il codice potrebbe essere lento ma la tua risposta è stata veloce!

3
@Lembik Avevo la risposta pronta per andare nella tua domanda cancellata ...
Neil,

Non riecheggerà prima il numero desiderato e poi tutti gli altri numeri che sono diventati più grandi di n?
Erik the Outgolfer,

@EriktheOutgolfer No; a meno che tu non lo usi call, invocare uno script batch termina lo script corrente.
Neil,

5

MATL , 12 byte

Grazie a @AdmBorkBork e @Suever per avermi detto come disabilitare la cache TIO.

`30WYrqG>}2M

Provalo online! .

Questo utilizza un metodo di rifiuto : genera un numero intero casuale da 0a 2^30-1, e ripeti mentre supera l'input n. Questo è garantito per terminare con probabilità 1, ma il numero medio di iterazioni è 2^30/n, e quindi ci vuole molto tempo per nsignificativamente più piccolo di 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 byte

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

Genera numeri interi nell'intervallo [0 ... 2 k - 1] , dove k è il numero intero più piccolo in modo che 2 k sia maggiore di n . Si ripete fino a quando il risultato non cade in [0 ... n] .

Perché?

Questo si basa sui seguenti presupposti:

  • Internamente, i valori interi pseudo-casuali generati dal motore JS per l'alimentazione Math.random()sono uniformi su qualsiasi intervallo [0 ... 2 k -1] (con k <32 ).

  • Una volta moltiplicato per una potenza esatta di 2, i valori float IEEE 754 restituiti Math.random()sono ancora uniformi su tali intervalli.

Se qualcuno può confermare o confutare queste ipotesi, per favore fatemi sapere nei commenti.

dimostrazione

Genera 1 milione di valori in [0 ... 2] e visualizza le statistiche dei risultati.


Math.floor (Math.random () * (n + 1)) produce risultati non meno uniformemente distribuiti per me, quindi sarebbe bello vedere se ci sono N <2 ^ 30 realistici, che produrranno anomalie di distribuzione affatto.
Zeppelin,

1
@zeppelin avresti bisogno di troppe esecuzioni di prova per individuare eventuali anomalie poiché un float casuale in quell'intervallo avrà uno di 2 ^ 53 valori che saranno distribuiti il ​​più uniformemente possibile sugli esiti 2 ^ 30. Quindi, anche per grandi numeri nell'intervallo, l'errore sarà qualcosa come 1 su 2 ^ 23, il che significa che avresti bisogno di un numero ridicolo di prove. Probabilmente avrai bisogno di alcuni ordini di grandezza in più rispetto al numero di campioni iniziali (2 ^ 53). Tuttavia, non può essere perfettamente uniforme se il moltiplicatore non divide uniformemente il numero di campioni, motivo per cui Arnauld utilizza una potenza di due.
Martin Ender,

4

Bash (+ coreutils), 44 byte

/ Dev / urandom soluzione basata su

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

Leggerà numeri interi a 32 bit senza segno /dev/urandome li filtrerà awkfino a quando non ne trova uno all'interno di un determinato intervallo, quindi sed qinterromperà la pipe.


Evviva bash :)

4

Haskell, 70 byte

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

Non è un algoritmo molto efficiente ma funziona. Genera un elenco infinito di numeri interi (o float se necessario, a causa del sistema di tipi di Haskell) delimitato da [0,2 ^ 30] e accetta il primo minore o uguale a n. Per piccoli n questo può richiedere molto tempo. I numeri casuali dovrebbero essere distribuiti uniformemente, come specificato nella documentazione per randomR quindi tutti i numeri nell'intervallo [0,2 ^ 30] dovrebbero avere la stessa probabilità (1 / (2 ^ 30 + 1)), quindi tutti i numeri in [ 0, n] hanno la stessa probabilità.

Versione alternativa:

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

Questa versione è terribile ma salva un intero byte. randomsutilizza un intervallo arbitrario definito dal tipo per generare un elenco infinito di numeri. Ciò può includere aspetti negativi, quindi è necessario mapparlo absper forzarli positivi (o zero). Questo è estremamente lento per tutti i valori di n che non sono assurdamente grandi. EDIT : Mi sono reso conto in seguito che questa versione non è distribuita uniformemente perché la probabilità di ottenere 0 è peggiore rispetto agli altri numeri a causa dell'uso di abs. Per produrre un numero, mil generatore potrebbe produrre mo, -mnel caso di 0, funzionerà solo 0, quindi la sua probabilità è la metà degli altri numeri.


Evviva anche Haskell!

4

Gelatina , 9 byte

⁴!Ẋ’>Ðḟ⁸Ṫ

Provalo online! - il codice sopra non funzionerà su TIO da un intervallo di dimensioni 16! deve essere costruito prima (per non parlare del fatto che devono quindi essere mescolati e quindi filtrati!), quindi questa è la stessa cosa su una scala molto più piccola, ripetuta 30 volte per un input di 3 con un limite di 10.

Come?

⁴!Ẋ’>Ðḟ⁸Ṫ - 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.

Nota: sarebbe più di mille volte più efficiente per lo stesso conteggio byte se ȷ⁵farebbe ciò che uno si aspetterebbe ingenuamente e restituirebbe dieci su dieci, ma non è così poiché non viene valutato come un dieci letterale da usare dal numero letterale, ȷ...ma vengono analizzati due letterali separati, ȷcon il suo esponente predefinito di tre che produce mille e che produce dieci.


Eh, sono 9 caratteri, ma 22 byte
Kristoffer Sall-Storgaard

@ KristofferSall-Storgaard Ogni personaggio è uno dei 256 byte nella tabella codici di Jelly , ho dimenticato di rendere la parola byte un collegamento come faccio di solito.
Jonathan Allan,

1
anno, ho cercato e scoperto lo stesso
Kristoffer Sall-Storgaard

4

JDK 9 su jshell, 75 59 byte

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

uso

((IntFunction)(n->(new Random()).ints(0,1<<30).dropWhile(x->x>n).findAny())).apply(<n>)
  • -16 byte: grazie Jakob!
  • Presuppone che consideriamo jshell un ambiente di runtime valido.
  • jshell stesso, come ambiente di runtime, non richiede importazioni esplicite per le librerie core e non richiede punti e virgola.
  • Restituisce un OptionalInt. Le regole non specificano che il tipo restituito deve essere una primitiva e sto considerando una OptionalIntrappresentazione valida del risultato.

1
Grazie a @ kevin-cruijssen per l'ispirazione. Il mio primo codice golf!
Pete Terlep

L'accettazione o meno dell'output in box è diversa dall'accettazione o meno di un output Optional. Confermerei con il poster se fossi in te. Inoltre, non è necessario contare l'intero incarico; solo l'espressione lambda è sufficiente.
Jakob,

1
È possibile salvare 4 byte rimuovendo le parentesi attorno al parametro lambda ne new Random().
Jakob,

3

PHP, 30 byte

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

Corri con echo <N> | php -Rn '<code>'.

seleziona un numero casuale compreso tra 0 e getrandmax() (2 ** 31-1 sulla mia macchina a 64 bit);
si ripete mentre quello è più grande dell'input.

Questo potrebbe richiedere del tempo ... il mio AMD C-50 (1 GHz) è necessario tra 0,3 e 130 secondi per N=15.

Un modo più veloce per la media N( 46 byte ):

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

o

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

prende N+1numeri interi casuali, li somma e prende il modulo con N+1.
Il C-50 necessita di ca. 8 secondi per 1 milione di corse.

Una soluzione non valida per 19 byte :

echo rand(0,$argn);

3

PowerShell , 35 byte

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

Provalo online!

Un altro metodo di campionamento del rifiuto. Questo è un forciclo infinito , che imposta il valore di $aessere un Randomnumero intero compreso tra 0e 1gb( = 1073741824 = 2^30), e continua il ciclo fino a quando quel numero intero è più -grecente dopo tl'input $args. Una volta completato il ciclo, abbiamo appena inserito $ala pipeline e l'output è implicito.

Nota: questo richiederà molto tempo se l'ingresso è un numero piccolo.


3

Python 2 , 72 69 byte

-3 byte grazie a xnor (sovrascrive l' idintegrato come variabile)

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

Provalo online!

randrange(2**30)produce un numero distribuito pseudo-uniformemente (Mersenne Twister 2 19937-1 ) nell'intervallo [0,2 30 ) . Poiché nè garantito che è inferiore a 2 30, questo può essere semplicemente chiamato ripetutamente fino a quando non è maggiore dell'input. Ci vorrà molto tempo per valori molto bassi di n, ma di solito funziona entro un minuto anche per input a partire da 50.


2
You can initialize r='' as "infinity". Or, better yet, don't initialize r and instead use id everywhere for r.
xnor


2

05AB1E, 11 bytes

žIÝ.rDI›_Ϥ

Try it online!

Explanation

ž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

As the list [0 ... 2147483648] is too large for TIO, the link uses 1.000.000 instead.

Alternate (on average) much faster 11 byte solution

[žIÝ.RD¹›_#

Try it online

Explanation

[             # 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.