Escolha um número aleatório entre 0 e n usando uma fonte constante de aleatoriedade


26

Tarefa

Dado um número inteiro positivo nmenor que o 2^30especificado como entrada da maneira que você escolher, seu código deve gerar um número inteiro aleatório entre 0e n, inclusive. O número que você gerar deve ser escolhido de maneira uniforme e aleatória . Cada valor de 0a ndeve ocorrer com a mesma probabilidade (consulte Regras e Advertências).

Regras e Advertências

Seu código pode assumir que qualquer gerador de números aleatórios incorporado à sua linguagem ou biblioteca padrão que afirma ser aleatoriamente uniforme é de fato uniforme. Ou seja, você não precisa se preocupar com a qualidade da fonte aleatória que está usando. Contudo,

  • Você precisa estabelecer que, se a fonte aleatória que você está usando é uniforme, seu código gera corretamente um número inteiro aleatório uniforme de 0para n.
  • Qualquer argumento ao chamar uma função aleatória interna ou de biblioteca deve ser constante. Ou seja, eles devem ser completamente independentes do valor de entrada.
  • Seu código pode terminar com probabilidade 1, em vez de ser garantido.

Notas

  • randInt(0,n) não é válido, pois leva a entrada como argumento para uma função interna ou de biblioteca.
  • rand()%nvai não dar um número aleatório uniforme em geral. Como exemplo dado pela betseg, if intmax == 15e n = 10, então você terá muito mais chances de obter 0-5que 6-10.
  • floor(randomfloat()*(n+1)) também não fornecerá um número aleatório uniforme em geral devido ao número finito de diferentes valores possíveis de ponto flutuante entre 0 e 1.

Como você confirma que a saída é uniformemente aleatória? Pode ser que um determinado idioma / biblioteca produza números uniformemente aleatórios, mas a manipulação possa resultar em resultados não uniformes. (por exemplo, rng()fornece 0- 100se n = 75, e função é rng()%75, em seguida, 0-25 será mais comum ...)
Baldrickk

1
@ Baldrickk Pela sabedoria das multidões :) Só podemos ler o código e pensar sobre isso.

A triste conclusão de fazer a pergunta mais simples possível sobre a teoria da probabilidade: aleatoriedade e probabilidade são muito pouco compreendidas. :( (E lendo regras é difícil, aparentemente.)
Martin Ender


Por que você aceitou a resposta x86 quando existem três mais curtas?
Dennis

Respostas:


25

máquinas x86 com rdrandinstrução, 10 bytes

BITS 64

_try_again:

 rdrand eax
jnc _try_again

 cmp eax, edi
ja _try_again

 ret

Código da máquina

0FC7F0 73FB 39F8 77F7 C3

A entrada está no registrador rdie a saída está em rax.
Isso respeita o SYS V AMD64 ABI, para que o código efetivamente implemente uma função C

unsigned int foo(unsigned int max); 

com entradas de 32 bits.

A instrução rdrandé descrita pela Intel

RDRANDretorna números aleatórios que são fornecidos por um DRBG gerador de bits aleatórios, determinístico e criptograficamente seguro. O DRBG foi projetado para atender ao padrão NIST SP 800-90A .

Ao lidar com o CSRNG, está implícito que a distribuição é uniforme, de qualquer maneira, citando o NIST SP 800-90A:

Um número aleatório é uma instância de uma variável aleatória imparcial, ou seja, a saída produzida por um processo aleatório distribuído uniformemente .


O procedimento gera um número aleatório e, se não for estritamente maior que a entrada, será retornado.
Caso contrário, o processo é reiterado.

Como eaxé de 32 bits, rdrandretorna um número entre 0 e 2 32 -1; portanto, para cada n em [0, 2 32 -1], o número de iterações esperadas é 2 32 / (n + 1), definido para todos os n em [0, 2 30 ).


Nível brilhantemente baixo. Obrigado.

Para que serve jnc?
L4m2

@ l4m2 rdranddefine o CFiif se os dados retornados forem válidos. Os dados podem ser inválidos porque muitas solicitações esgotaram o conjunto de entropia. Veja a entrada manual para rdrand e isso .
Margaret Bloom

20

Geléia , 7 6 bytes

⁴!!X%‘

Graças a @ JonathanAllan por jogar fora um byte!

Não pode ser executado no TIO porque (16!)! é um número enorme .

Como funciona

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

Esta é uma versão fixa da minha resposta excluída, mesma ideia. Embora eu tivesse uma exponenciação desnecessária.
orlp

Desculpe, eu não olhei antes de postar.
Dennis

Ah, não importa, eu não estava planejando consertá-lo de qualquer maneira. Estou muito desconfortável com Jelly para realmente brincar com ele.
orlp

1
"Senhor, eu não sei por que você está bravo. O algoritmo é de tempo constante. Isso é uma coisa boa, certo? Por que a segurança e o RH estão do lado de fora?"
corsiKa

1
Acordado. Bits de uma diferença entre um número de 8 dígitos e um número dígito 417 quintillion: p
Jonathan Allan

11

Mathematica, 29 bytes

Baseado na resposta da geléia de Dennis .

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

Eu não recomendaria realmente executar isso. 2e9!é um número bastante grande ...

É mais curto gerar um número enorme que é divisível por todas as entradas possíveis e mapear o resultado para o intervalo necessário com um módulo simples.

Amostragem de rejeição, 34 bytes

Minha antiga abordagem que levou a um código um pouco mais interessante:

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

Amostragem básica de rejeição. Inicializamos a saída para 13! (que é maior que a entrada máxima 2 30 ) e substitua-a repetidamente por um número inteiro aleatório entre 0 e 13! desde que o valor seja maior que a entrada.


1
Você quer dizer "menor ou igual à entrada"?

1
@Lembik No. Queremos regenerar o valor contanto que ele não caia na faixa desejada.
Martin Ender

Ah eu vejo. Por alguma razão, pensei que estávamos amostrando repetidamente a partir do intervalo desejado. Obrigado.

1
Lembre-me de adicionar um limite de tempo na próxima vez :)

9

Braquilog , 9 bytes

≥.∧13ḟṙ|↰

Experimente online!

Isso usa 13!como na resposta de Martin Ender ( 13ḟé um byte a menos que 2^₃₀).

é implementado usando random_between/3, que, ao cavar sua fonte, usa o random_float/0qual está vinculado ao random/1qual usa o algoritmo Mersenne Twister, que é uniforme para nossos propósitos.

Explicação

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

7

Prolog (SWI) , 38 bytes

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

Trabalhos por amostragem por rejeição.

Gere um número aleatório entre 0 e 2 ^ 31-1 = 2147483647 até que um menor ou igual à entrada seja encontrado.

Sinto como se eu pudesse usar um corte em vez do outro, mas não consigo ver como.


1
Você pode evitar o uso repeat, mas acaba sendo 3 bytes mais longo ... Não sei se há uma maneira mais curta de ter pontos de escolha infinitos do que repetir.
Fatalize 28/02

@Fatalize: Sim, eu tentei repetir também. Eu tinha uma memória de usar algo como ,!.para forçar um retorno, mas ou estou lembrando errado ou não é aplicável a esta solução.
Emigna

7

Labirinto , 63 bytes

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

(Agradecemos a @MartinEnder por ajuda com alguns esportes pesados ​​aqui.)

O labirinto é uma linguagem 2D e sua única fonte de aleatoriedade está em uma situação como a seguinte:

   x
  "<)
 " "
 " "

Suponha que o ponteiro de instruções esteja no xe movendo-se para baixo. Em seguida, ele pousa no <, que, se o topo da pilha for 0 (o que é sempre o caso no programa real acima), desloca a linha atual deixada por 1:

   "
 "<)
 " "
 " "

O ponteiro de instruções está agora se <movendo para baixo. Em uma junção, o labirinto gira com base no topo da pilha - negativo é virar à esquerda, positivo é virar à direita e zero é avançar. Se o topo da pilha ainda for zero neste momento, não podemos avançar ou retroceder, pois não há caminho, portanto, o Labyrinth irá aleatoriamente entre virar à esquerda ou virar à direita com igual probabilidade.

Essencialmente, o que o programa acima faz é usar o recurso de aleatoriedade para gerar números de 100 bits (100 especificados por #00aqui) e continuar fazendo um loop até gerar um número <= n.

Para o teste, provavelmente será útil usar #0"números de 10 bits, sendo o "caminho não operacional. Experimente online!

Explicação aproximada:

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

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

Edit: Atualizado para evitar o formulário proibido

Edit2: salvou 2 bytes, obrigado @ JonathanAllan

Edit3: Pago 2 bytes por uma solução totalmente funcional - obrigado novamente @ JonathanAllan

Edit4: Removido f=, economizando 2 bytes

Edit5: economizou mais 1 byte graças a @ JonathanAllan

Edit6: salvou mais 2 bytes graças a @ JonathanAllan

A essa altura, a culpa seria apontada para mim pelas coisas ruins e JonathanAllan pelas coisas que ajudam.

Edit7: Quando chove, derrama - outros 2 bytes

Edit8: E mais 2 bytes


1
Isso nunca será exibido n, mas você pode salvar dois bytes ao corrigi-lo usando from random import*e soltando o r..
Jonathan Allan

1
Sim, você pode usar o "operador de girino" para evitar os parênteses de outro modo necessárias, por isso ...*(-~n*1.0/2**30)), em vez de...*((n+1)*1.0/2**30))
Jonathan Allan

1
Sério? Doce! Você tem algum ressentimento de longa data contra o número 70? Muito obrigado pela sua ajuda
iwaseatenbyagrue

1
De fato, randrangeparece aceitar um carro alegórico, então lambda n,x=2.**30:int(randrange(x)*-~n/x)salva outros dois [edit]]!
Jonathan Allan

1
^ outros dois lá com remoção de parênteses. Apenas mostra a sua multiplicação!
Jonathan Allan

6

Python 2 , 61 bytes

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

Pseudo-aleatoriamente escolhe números inteiros entre 0 e k para todos os valores de k entre 0 e 2 31 de - 2 , em seguida, converte o número inteiro que corresponde a k = n .


5

Lote, 64 bytes

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

%random%só dá 15 bits de aleatoriedade, então eu tenho que combinar dois números aleatórios. Loops até que o valor aleatório esteja dentro do intervalo desejado, então é lento para baixo n; 98 bytes para uma versão mais rápida:

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

O código pode estar lento, mas sua resposta foi rápida!

3
@Lembik eu tinha a resposta pronta para ir em sua pergunta apagado ...
Neil

Isso não ecoará o número desejado primeiro e depois todos os outros números que se tornaram maiores que n?
Erik the Outgolfer

@EriktheOutgolfer No; a menos que você use call, invocar um script em lotes encerra o script atual.
Neil

5

MATL , 12 bytes

Agradecemos a @AdmBorkBork e a @Suever por me dizerem como desativar o cache TIO.

`30WYrqG>}2M

Experimente online! .

Isso usa um método de rejeição : gere um número inteiro aleatório de 0para 2^30-1e repita enquanto excede a entrada n. É garantido que ele termine com probabilidade 1, mas o número médio de iterações é 2^30/ne, portanto, leva muito tempo para nsignificativamente menor que 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 bytes

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

Gera números inteiros no intervalo [0 ... 2 k - 1] , onde k é o menor número inteiro, de modo que 2 k é maior que n . Repete-se até o resultado cair em [0 ... n] .

Por quê?

Isso se baseia nas seguintes suposições:

  • Internamente, os valores inteiros pseudo-aleatórios gerados pelo mecanismo JS para alimentar Math.random()são uniformes em qualquer intervalo [0 ... 2 k -1] (com k <32 ).

  • Uma vez multiplicados por uma potência exata de 2, os valores flutuantes IEEE 754 retornados por Math.random()ainda são uniformes nesses intervalos.

Se alguém puder confirmar ou refutar essas hipóteses, informe-me nos comentários.

Demo

Gera 1 milhão de valores em [0 ... 2] e exibe as estatísticas do resultado.


Math.floor (Math.random () * (n + 1)) produz resultados não menos uniformemente distribuídos para mim, então seria bom ver se existe algum N <2 ^ 30 realista, que produzirá anomalias de distribuição em absoluto.
Zeppelin #

1
@zeppelin, você precisaria de muitas tentativas para identificar qualquer anomalia, uma vez que uma flutuação aleatória nesse intervalo terá um dos 2 ^ 53 valores que serão distribuídos o mais uniformemente possível pelos resultados de 2 ^ 30. Portanto, mesmo para grandes números no intervalo, o erro será algo como 1 em 2 ^ 23, o que significa que você precisaria de um número ridículo de tentativas. Você provavelmente desejará mais ordens de magnitude que o número de amostras iniciais (2 ^ 53). No entanto, não pode ser perfeitamente uniforme se o multiplicador não dividir uniformemente o número de amostras, razão pela qual Arnauld usa uma potência de duas.
Martin Ender

4

Bash (+ coreutils), 44 bytes

Solução baseada em / dev / urandom

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

Lerá números inteiros de 32 bits não assinados /dev/urandome os filtrará awkaté encontrar um dentro de um determinado intervalo e sed qabortará o pipe.


Hooray para a festança :)

4

Haskell, 70 bytes

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

Não é um algoritmo muito eficiente, mas funciona. Ele gera uma lista infinita de números inteiros (ou flutua, se necessário, devido ao sistema de tipos de Haskell) delimitado por [0,2 ^ 30] e leva o primeiro menor ou igual a n. Para n pequeno, isso pode levar muito tempo. Os números aleatórios devem ser distribuídos uniformemente, conforme especificado na documentação para randomR, para que todos os números no intervalo [0,2 ^ 30] tenham a mesma probabilidade (1 / (2 ^ 30 + 1)), portanto, todos os números em [ 0, n] têm a mesma probabilidade.

Versão alternativa:

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

Esta versão é terrível, mas salva um byte inteiro. randomsusa um intervalo arbitrário definido pelo tipo para gerar uma lista infinita de números. Isso pode incluir negativos, por isso precisamos mapeá-lo abspara forçá-los positivos (ou zero). Isso é extremamente lento para quaisquer valores de n que não sejam absurdamente grandes. EDIT : Percebi mais tarde que esta versão não é distribuída uniformemente porque a probabilidade de obter 0 é pior que os outros números devido ao uso de abs. Para produzir algum número, mo gerador poderia produzir mou, -mmas no caso de 0, apenas 0 funcionará, portanto sua probabilidade é metade dos outros números.


Viva o Haskell (também)!

4

Geléia , 9 bytes

⁴!Ẋ’>Ðḟ⁸Ṫ

Experimente online! - o código acima não será executado no TIO desde uma faixa de tamanho 16! deve ser construído primeiro (sem mencionar o fato de que eles precisam ser embaralhados e depois filtrados!); portanto, é a mesma coisa em uma escala muito menor, repetida 30 vezes para uma entrada de 3 com um limite de 10.

Quão?

⁴!Ẋ’>Ðḟ⁸Ṫ - 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: seria mais de mil vezes mais eficiente para a mesma contagem de bytes se ȷ⁵fizesse o que seria esperado ingenuamente e retornasse dez para os dez, mas esse não é o caso, pois o não é avaliado como um dez literal a ser usado pelo número literal, ȷ...mas dois literais separados são analisados, ȷcom o expoente padrão de três produzindo mil e dez.


Ah, isso é 9 caracteres, mas 22 bytes
Kristoffer Sall-Storgaard 2/17

@ KristofferSall-Storgaard Cada caractere é um dos 256 bytes na página de códigos de Jelly , esqueci de transformar a palavra bytes em um link, como normalmente faço.
Jonathan Allan

1
ano, eu olhei para cima e encontrou o mesmo
Kristoffer Sall-Storgaard

4

JDK 9 no jshell, 75 59 bytes

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 bytes: Obrigado Jakob!
  • Assume que consideramos jshell um ambiente de tempo de execução válido.
  • O próprio jshell, como um ambiente de tempo de execução, não requer importações explícitas para bibliotecas principais e não requer ponto e vírgula.
  • Retorna um OptionalInt. As regras não especificam que o tipo de retorno deve ser primitivo e estou considerando uma OptionalIntrepresentação válida do resultado.

1
Obrigado a @ kevin-cruijssen pela inspiração. Meu primeiro código de golfe!
Pete Terlep

A aceitação ou não da saída em caixa é diferente da Optionalaceitação de uma. Eu confirmaria com o pôster se fosse você. Além disso, não há necessidade de contar toda a tarefa; apenas a expressão lambda é suficiente.
21417 Jakob

1
Você pode salvar 4 bytes removendo parênteses ao redor do parâmetro lambda ne new Random().
21417 Jakob

3

PHP, 30 bytes

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

Corra com echo <N> | php -Rn '<code>'.

escolhe um número aleatório entre 0 e getrandmax()(2 ** 31-1 na minha máquina de 64 bits);
repete enquanto é maior que a entrada.

Isso pode demorar um pouco ... meu AMD C-50 (1 GHz) precisou entre 0,3 e 130 segundos por N=15.

Uma maneira mais rápida para a média N( 46 bytes ):

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

ou

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

pega N+1inteiros aleatórios, resume-os e pega o módulo com N+1.
O C-50 precisa de aprox. 8 segundos para 1 milhão de execuções.

Uma solução inválida para 19 bytes :

echo rand(0,$argn);

3

PowerShell , 35 bytes

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

Experimente online!

Outro método de amostragem de rejeição. Este é um infinito forciclo, definindo o valor $ada ser um Randominteiro entre 0e 1gb( = 1073741824 = 2^30), e continua looping tanto tempo quanto aquele inteiro é -greater than a entrada $args. Uma vez concluído o loop, apenas colocamos $ano pipeline e a saída está implícita.

Nota: Isso levará muito tempo se a entrada for um número pequeno.


3

Python 2 , 72 69 bytes

-3 bytes graças ao xnor (substitua o idembutido como uma variável)

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

Experimente online!

randrange(2**30)produz um número distribuído pseudo-uniformemente (Mersenne Twister 2 19937-1 ) a partir do intervalo [0,2 30 ) . Como né garantido que esteja abaixo de 2 30, isso pode ser simplesmente chamado repetidamente até que não seja maior que a entrada. Levará muito tempo para valores muito baixos de n, mas geralmente funciona dentro de um minuto, mesmo para entradas tão baixas quanto 50.


2
Você pode inicializar r=''como "infinito". Ou, melhor ainda, não inicialize re use em idqualquer lugar r.
xnor 28/02


2

05AB1E , 11 bytes

žIÝ.rDI›_Ϥ

Experimente online!

Explicação

ž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

Como a lista [0 ... 2147483648]é muito grande para o TIO, o link é usado 1.000.000.

Solução alternativa (em média) de 11 bytes muito mais rápida

[žIÝ.RD¹›_#

Experimente online

Explicação

[             # 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%por 6, a menos que esteja perdendo algo enorme. Pressione 2 ^ 32, lista de 0 a 2 ^ 32, escolha aleatória. Entrada de módulo. Absolutamente estragar a eficiência que você tem.
Magia Octopus Urna

@ carusocomputing.Você precisaria Ide 7 bytes para obter os argumentos do módulo na ordem certa (e talvez em Ývez de L), mas, caso contrário, essa certamente é uma solução mais curta. Vi Dennis fazendo isso em sua resposta Jelly, mas como essa foi minha primeira ideia, guardei isso. Como essa abordagem é diferente, você pode publicá-la como uma resposta separada.
Emigna

DI‹Ïevitaria o loop.
Octopus mágico Urn

Além disso, no estado em que se encontra, não há garantia de término; se não me engano, uma entrada de 0quase sempre resultaria em um loop quase infinito, dificultando a finalização. Embora a solução permita a possibilidade de terminar em todos os cenários, ela não é garantida devido à aleatoriedade.
Octopus mágico Urn

@carusocomputing: Para entradas muito pequenas, a segunda versão levaria, em média, muito tempo para terminar sim, mas com tempo suficiente.
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]

Explicação

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.

Isso é muito ineficiente, pois cria 2 ^ 31 números inteiros, embaralha e os filtra.

Não vejo sentido em compartilhar um link TIO, onde ele está criando listas tão grandes, então aqui está um link TIO para n= 100.

Experimente 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 graças a @ OliverGrégoire .
-3 bytes graças a @Jakob .
-9 bytes convertendo Java 7 em Java 8.
-9 bytes alterando java.util.Random().nextInt(1<<30)para (int)(Math.random()*(1<<30)).

Explicação:

Experimente aqui.

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

NOTA: Obviamente, pode demorar muito para pequenas entradas.

Exemplo de saída:

407594936

2
@ Aaron Também questionei isso, mas veja o segundo ponto: "Qualquer argumento ao chamar uma função aleatória interna ou de biblioteca deve ser constante. Ou seja, eles devem ser completamente independentes do valor de entrada". Esta é a razão pela qual max int é usado.
Puxa

1
2^30= 1073741824. Você preferiu usar -1>>>1(= 2147483647). Mas isso existe: o 1<<30que é exatamente igual a 2^30; e é 1 byte mais curto.
Olivier Grégoire

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

@Jakob Obrigado. Até reduzi-o em mais 18 bytes usando Java 8 em vez de 7 e usando em Math.random()vez de java.util.Random().nextInt.
Kevin Cruijssen

2

Python 3, 51 bytes

Aqui está uma solução python com uma fonte aleatória não ortodoxa.

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

Experimente online!

Então, para quebrar isso.

int(input())+1

Obtém o número de entrada e adiciona 1a ele.

set(range(...))

Cria o conjunto {0, 1, 2, 3, 4, ... n}para todos os resultados possíveis.

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

Pega o conjunto, converte-o para a lista e pega o primeiro item.

Isso funciona porque no Python 3, a ordem de set()é estabelecida pelo PYTHONHASHSEED ( não pode ser obtida, mas é estabelecida na execução do script).

É certo que estou supondo que essa seja uma distribuição uniforme, pois o hash()valor é atribuído aleatoriamente e estou olhando aleatoriamente para escolher o valor com um específico hash(), em vez de apenas retornar o hash(input())próprio.

Se alguém souber se é uma distribuição uniforme ou como eu poderia testar isso, comente.


1

C #, 57 bytes

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

Função anônima que retorna um número inteiro entre 0 e n, inclusive.

Quanto menor o número de entrada, maior o tempo para retornar um valor aleatório.

Programa completo:

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
"Qualquer argumento ao chamar uma função aleatória interna ou de biblioteca deve ser constante. Ou seja, eles devem ser completamente independentes do valor de entrada." O argumento para Nextnão é estático.
Yytsi 28/02

1

Bash + coreutils, 20 bytes

Golfe

seq 0 $ 1 | shuf | sed 1q

shuf - gera permutações aleatórias

Shuf usará o seguinte código : para gerar permutações:

permutation = randperm_new (randint_source, head_lines, n_lines);

que acaba em 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.  */
      ...
}

que, por sua vez, lerá alguns bytes dos dados aleatórios da fonte de aleatoriedade de baixo nível:

/* 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);
}

ou seja, no nível baixo, não há dependência direta entre o shufvalor de entrada e os dados lidos da fonte de aleatoriedade (além de calcular a capacidade de buffer de bytes necessária).


6
Isso não está dando a entrada como argumento para o seu gerador de números aleatórios?
Martin Ender

Mesmo que isso não seja válido, envie outra resposta do bash!

@MartinEnder bem, não diretamente, ele apenas usa a entrada para definir o limite superior para o intervalo inteiro gerado e jot will arrange for all the values in the range to appear in the output with an equal probability(isso provavelmente é limítrofe, mas ainda assim).
Zeppelin

2
Se eu me aprofundar o suficiente em qualquer gerador de números aleatórios, tenho certeza de que encontrarei uma chamada em um RNG de nível inferior que não use diretamente o argumento original. O objetivo do desafio é obter uma distribuição uniforme de tamanho arbitrário de uma distribuição de tamanho fixo, o que você ainda não está fazendo.
Martin Ender

1

SmileBASIC, 38 bytes

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

Gera números aleatórios até obter um menor que a entrada.


1

Ruby, 23 15 23 32 29 bytes

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

Como funciona:

  • 1while [...];executa a instrução pelo menos uma vez: 1before whileage como um nop
  • Obtenha um número aleatório no intervalo 0..2 ^ 30-1 ( menor que 2 ^ 30 , conforme especificado)
  • Repita se o número for maior que o parâmetro de entrada (pode levar algum tempo quando n for pequeno)

1

Ohm, 26 bytes

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

Explicação:

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

Existe um intérprete para esse idioma? E a página de código?
Ataco

@ATaco: Intérprete , página de código: CP-437
Emigna 2/17/17


1

Golang, 84 78 71 bytes

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

Amostragem simples de rejeição.

Nota: como a semente matemática / rand é uma constante 1, o chamador deve propagar a menos que um resultado constante seja desejado.

Teste: https://play.golang.org/p/FBB4LKXo1r Não é mais praticamente testável em um sistema de 64 bits, pois está retornando a aleatoriedade de 64 bits e usando o teste de rejeição.

package main

import "fmt"
import "time"

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

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

1
se você usar import."math/rand", em seguida, Int31está disponível no espaço global e você pode salvar 4 bytes, também inté garantida para ser pelo menos 32 bits, poupando-lhe mais 6 bytes
Kristoffer Sall-Storgaard

Use :=a sintaxe por mais 3 bytes
Kristoffer Sall-Storgaard

Usar int em vez de int32 não salva nenhum bytes, pois precisamos converter o resultado de Int31 () - 3 * int + () = 11 bytes versus 2 * int32 = 10 bytes.
Riking

1
Não há necessidade de elenco, há uma Int()função no pacote rand, também, você pode remover o espaço depoisimport
Kristoffer Sall-Storgaard
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.