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.