Gere qualquer número inteiro aleatório

17

Seu programa / função deve

  • produzir exatamente um número inteiro
  • gera qualquer número inteiro com probabilidade positiva
  • gerar um número inteiro maior que 1.000.000 ou menor que -1.000.000 com pelo menos 50% de probabilidade.

Exemplo de saídas (tudo deve ser possível):

59875669123
12
-42
-4640055890
0
2014
12
24
-7190464664658648640055894646646586486400558904644646646586486400558904646649001

Esclarecimentos:

  • É permitida uma quebra de linha à direita.
  • Zeros à esquerda não são permitidos.
  • -0 é permitido.

O menor código vence.

randomra
fonte
2
@ Optimizer Por que você está assumindo probabilidade uniforme? A questão não afirma. De fato, parece claro a partir desse ponto que a distribuição não precisa ser uniforme, desde que pelo menos 50% dela fique fora de [-1 milhão, 1 milhão].
hobbs
10
Uma solução que produz uma " distribuição uniforme entre todos os números inteiros" é impossível. Existem infinitos números inteiros; portanto, cada número inteiro individual aparece com uma probabilidade de 0. (Ou: A saída de um número finito significa que você está negligenciando muitos outros!) Qualquer solução terá que desfavorecer valores mais altos para atingir P (total ) = 1.
Joeytwiddle
2
@Ypnypn A RAM do computador também não é um limite. Você não precisa armazenar sua saída parcial em nenhum lugar.
jimmy23013
4
@GiantTree - way too long to fit in an integer- Isso só é verdade se você assumir que integersignifica o inttipo de dados em um arco de 32/64 bits, o que não é necessariamente uma suposição válida. "Inteiro" começou como um termo matemático , que não possui restrições de tamanho.
Fake Name
5
Qualquer pessoa que use um gerador de números pseudo-aleatórios para tomar suas decisões sobre a saída excluirá quase todos os números inteiros e colocará um limite superior no tamanho dos números inteiros que podem ser produzidos (assumindo que o PRNG tenha um período finito). Isso pode ser desconsiderado nas respostas ou uma resposta válida requer um verdadeiro gerador de números aleatórios?
Trichoplax

Respostas:

12

CJam, 16 14 13 bytes

0{Kmr(+esmr}g

Isso será executado por um período muito longo, porque usa o registro de data e hora atual (da ordem de 10 a 12 ) para determinar se o loop deve terminar. Estou usando isso como envio, pois é o mais curto, mas existem duas alternativas de 14 bytes, que têm seus próprios méritos:

0{esmr(+esmr}g

Este não é limitado pelo período do PRNG, pois o intervalo de todos os números aleatórios depende do carimbo de data / hora atual. Portanto, isso deve ser capaz de produzir qualquer número, embora a probabilidade de números positivos negativos ou mesmo pequenos seja muito pequena.

Abaixo está uma versão equivalente que usa em 3e5vez do carimbo de data e hora. E 20para o primeiro intervalo (como o envio de 13 bytes). É muito mais rápido e também cumpre todas as regras. É uma espécie de caso limitativo obter 50% de probabilidade de números além de 1.000.000, mantendo um tempo de execução razoável e um tamanho de código pequeno. A explicação e justificativa matemática se referem a esta versão:

0{Kmr(+3e5mr}g

Isso geralmente leva alguns segundos para ser executado. Você pode substituir o 5por um 2para torná-lo ainda mais rápido. Porém, o requisito com probabilidade de 50% será atendido somente para 1.000, em vez de 1.000.000.

Estou começando em 0. Então eu tenho um loop, do qual rompo com probabilidade 1 / (3 * 10 5 ). Dentro desse loop, adiciono um número inteiro aleatório entre -1 e 18 (inclusive) ao meu total em execução. Há uma probabilidade finita (embora pequena) de que cada número inteiro seja produzido, com números inteiros positivos muito mais prováveis ​​que negativos (não acho que você verá um negativo em sua vida). Romper com uma probabilidade tão pequena e aumentar a maior parte do tempo (e adicionar muito mais do que subtrair) garantem que geralmente ultrapassemos 1.000.000.

0              "Push a 0.";
 {          }g "Do while...";
  Kmr          "Get a random integer in 0..19.";
     (         "Decrement to give -1..18.";
      +        "Add.";
       3e5mr   "Get a random integer in 0..299,999. Aborts if this is 0.";

Alguma justificativa matemática:

  • Em cada etapa, adicionamos 8,5 em média.
  • Para chegar a 1.000.000, precisamos de 117.647 dessas etapas.
  • A probabilidade de fazermos menos que esse número de etapas é

    sum(n=0..117,646) (299,999/300,000)^n * 1/300,000
    

    que avalia como 0.324402. Portanto, em cerca de dois terços dos casos, daremos mais 117.647 etapas e facilmente cada 1.000.000.

  • (Observe que essa não é a probabilidade exata, porque haverá alguma flutuação sobre a média de 8,5, mas para chegar a 50%, precisamos ir além de 117.646 a cerca de 210.000 etapas.)
  • Em caso de dúvida, podemos facilmente explodir o denominador da probabilidade de terminação, 9e9sem adicionar bytes (exceto anos de tempo de execução).

... ou 11 bytes?

Finalmente, há uma versão de 11 bytes, que também não é limitada pelo período do PRNG, mas que fica sem memória quase sempre. Ele gera apenas um número aleatório (com base no registro de data e hora) a cada iteração e o utiliza para incrementar e terminar. Os resultados de cada iteração permanecem na pilha e são resumidos apenas no final. Agradecemos a Dennis por essa ideia:

{esmr(}h]:+
Martin Ender
fonte
Adicionei um comentário à pergunta para ver se as regras exigem um verdadeiro gerador de números aleatórios, mas imaginei que você apreciaria o pedantismo. A sua fonte aleatória aqui é pseudo-aleatória? Isso restringiria o tamanho do conjunto de saídas possíveis a no máximo o período do seu PRNG, certo?
Trichoplax
(+1 independentemente da elegância simples)
trichoplax
Sim, eu estou supondo tudo até agora. Estou curioso para ver se alguém postar uma resposta sem que problema embora ...
Trichoplax
Eu vejo o OP tem afirmado que você pode assumir o seu gerador de números aleatórios é um verdadeiro gerador de números aleatórios se é ou não - de modo que este é redundante agora ... :)
Trichoplax
A soma de Kmrem um período ainda é provavelmente sempre um grande número positivo maior que o período. E não pode produzir todos os números possíveis nesse caso.
jimmy23013
11

Java, 133 149

void f(){String s=x(2)<1?"-":"";for(s+=x(9)+1;x(50)>0;s+=x(10));System.out.print(x(9)<1?0:s);}int x(int i){return new java.util.Random().nextInt(i);}

Saídas de exemplo

-8288612864831065123773
0
660850844164689214
-92190983694570102879284616600593698307556468079819964903404819
3264

Ungolfed

void f() {
    String s = x(2)<1 ? "-" : "";       // start with optional negative sign
    s+=x(9)+1;                          // add a random non-zero digit
    for(; x(50)>0; )                    // with a 98% probability...
        s+=x(10)                        // append a random digit
    System.out.print(x(9)<1 ? 0 : s);   // 10% chance of printing 0 instead
}

int x(int i) {
    return new java.util.Random().nextInt(i);
}

Resposta antiga (antes da alteração da regra)

void f(){if(Math.random()<.5)System.out.print('-');do System.out.print(new java.util.Random().nextInt(10));while(Math.random()>.02);}
Ypnypn
fonte
Ambos estão corretos, mas a pergunta afirma que a probabilidade deve ser de pelo menos 50%, não no intervalo de +/- 1.000.000
GiantTree
@Optimizer Refeito.
Ypnypn
Se você usa literais binários, não precisa imprimir o -.
TheNumberOne
4

Mathematica - 47

Round@RandomVariate@NormalDistribution[0,15*^5]

Basicamente, apenas gere um número aleatório usando distribuição normal com variação igual a 1500000. Isso produzirá um número inteiro entre -10 ^ 6 e 10 ^ 6 com probabilidade 49.5015%.

swish
fonte
"Isso produzirá um número inteiro entre -10 ^ 6 e 10 ^ 6 com probabilidade 50,4985%." - isso não é suficiente. Você interpretou mal as especificações? Talvez você pretendesse usar 10 ^ 7 como variação?
John Dvorak
@JanDvorak Probabilidade errada, desculpe. Agora é o caminho certo.
swish
A implementação disso no Mathematica realmente cobre todos os números inteiros? Eu não tenho acesso à fonte, mas acho que não ...
trichoplax
@ githubphagocyte Dependeria da precisão atual.
swish
4
O que quero dizer é que especificar qualquer precisão específica excluirá números maiores que isso. A única maneira de funcionar é se você puder especificar precisão ilimitada.
tricoplax
4

Python 2, 75 69 bytes

from random import*;s=0;j=randrange
while j(12):s=s*9+j(-8,9)
print s

É trivial verificar se o loop while no meio pode gerar todos os números inteiros (embora com tendência a zero). "12" é escolhido de modo que haja aproximadamente metade dos números excedendo ± 10 6 .


Solução mais antiga:

Python 2, 44 bytes

Com base no solução Mathematica .

from random import*;print int(gauss(0,8**7))

Realmente não funciona porque o Python floattem apenas precisão finita.

kennytm
fonte
Isso não será capaz de gerar todos os números inteiros, porque o gerador de números pseudo-aleatórios possui uma quantidade finita de estado interno. De acordo com a documentação, o Python usa o Mersenne Twister, portanto o estado é bastante grande. Mas como não é infinito, pode produzir apenas um subconjunto finito de todos os números inteiros.
starblue
@ starblue: No OP: "Você pode assumir que o gerador de números aleatórios do seu idioma é um verdadeiro gerador de números aleatórios, mesmo que não seja o caso."
Kennytm
3

Ruby, 70

f=->{m=10**6
r=rand -m..m
r<1?(r>-5e5??-:'')+r.to_s+f[][/\d+/]:r.to_s}

Para possibilitar a geração de números muito grandes, retornarei o número como um String de um lambda. Se isso não for permitido, conte 8 caracteres extras (para puts f[]) para torná-lo um programa em vez de uma função.

Explicação

Gere um número entre -1,000,000e 1,000,000. Se o número é1 maior ou igual, ele será retornado como a String.

Se o número for menor que 1, a função é chamada recursivamente para retornar um número fora do intervalo de números. Para garantir que números negativos também possam ser gerados, a -é prefixado ao resultadoString se o número inicial for maior que -500,000.

Espero ter entendido o desafio corretamente!

britishtea
fonte
3

R, 38

library(Rmpfr)
round(rnorm(1,2e6,1e6))

Empates da distribuição gaussiana com média de 2.000.000, escolhidos aleatoriamente e desvio padrão de 1.000.000, de modo que cerca de 2/3 dos empates se situem entre 1.000.000 e 3.000.000. A distribuição é ilimitada, portanto, em teoria, isso pode gerar qualquer número inteiro. O pacote Rmpfr substitui os R's incorporados em flutuadores duplos por precisão arbitrária.

shadowtalker
fonte
Sim, eu percebi que interpretei errado as especificações. E eu imagino que tem as mesmas limitações na precisão da máquina com Mathematica
shadowtalker
Hmm, nesse caso, não tenho certeza. Vou ter que investigar; considere esta resposta "em espera" por enquanto
shadowtalker
@ MartinBüttner fixo eu acho
shadowtalker
Interessante. Eu não acho que você precise sample(c(1,-1),1)pensar no todo . Apenas centralizar em 1e6 deve ser suficiente .. #
Martin Ender
@ MartinBüttner oh, não precisa ser de 50% nas duas extremidades? Que não estava claro
shadowtalker
2

Perl, 53 caracteres

print"-"if rand>.5;do{print int rand 10}while rand>.1

Certamente não vejo motivo para trabalhar com números inteiros ao imprimir um :)

Tem probabilidade igual de imprimir um número com ou sem um "-" inicial.

Imprime um número de 1 dígito 10% das vezes, um número de 2 dígitos 9% das vezes, um número de 3 dígitos 8,1% das vezes, um número de 4 dígitos 7,29% das vezes, um número de 5 dígitos 6,56% do tempo, um número de 6 dígitos 5,9% do tempo, etc. Qualquer comprimento é possível, com probabilidade decrescente. Os números de um a cinco dígitos representam cerca de 41,5% dos casos de saída, e o número 1.000.000 (ou -1.000.000) apenas 6 milionésimos de um por cento, portanto, o número de saída estará fora do intervalo -1.000.000 a 1.000.000, cerca de 54,6 % do tempo.

"0" e "-0" são saídas possíveis, o que espero não seja um problema.

hobbs
fonte
Isso não imprime "números" como -00000000167? Isso não é realmente um número inteiro.
Isaacg
11
@isaacg Não vejo por que isso não é um número inteiro.
Optimizer
2
@Optimizer É, mas o OP proibiu explicitamente o 0. de zero.
Martin Ender
Você pode gerar um dígito inicial aleatório diferente de zero antes do loop, de -9 a +9. print int(rand(20)-10)||1. Eu preciso de uma maneira de gerar 0 como saída, no entanto. Talvez || morra 0, se o lixo após o zero for permitido. Caso contrário, é necessário um caminho curto para imprimir o zero e sair sem saída adicional se int(rand(20)-10)==0.
Peter Cordes
@ PeterCordes concordou, é uma abordagem decente, mas não tenho vontade de escrever e não acho que seria competitivo em termos de comprimento. Sinta-se livre para enviá-lo em seus próprios :)
Hobbs
2

Perl, 114 caracteres

use Math::BigInt;sub r{$x=Math::BigInt->new(0);while(rand(99)!=0){$x->badd(rand(2**99)-2**98);}print($x->bstr());}

Demolir:

use Math::BigInt;               -- include BigIntegers
  sub r{                        -- Define subroutine "r"
    $x=Math::BigInt->new(0);    -- Create BigInteger $x with initial value "0"
      while(rand(99)!=0){       -- Loop around until rand(99) equals "0" (may be a long time)
        $x->badd(               -- Add a value to that BigInt
          rand(2**99)-2**98);   -- Generate a random number between -2^98 and +2^98-1
        }print($x->bstr());}    -- print the value of the BigInt

A probabilidade de obter um valor entre -1.000.000 e 1.000.000 tende a zero, mas é possível.

Nota: Esta sub-rotina pode ser executada por um longo período e ocorrer um erro com a mensagem "Memória Cheia!" erro, mas tecnicamente está gerando qualquer número inteiro, conforme indicado na pergunta.

Perl, 25

sub r{rand(2**99)-2**98;}

Gera um número inteiro aleatório no intervalo de +/- 2 ^ 99.

Demolir

sub r{                    -- Define subroutine "r"
     rand(2**99)          -- Generate a random integer between 0 and 2^99
                -2**98;}  -- Subtract 2^98 to get negative values as well

Testado com 1 milhão de amostras:

~5 are inside the range of +/-1.000.000
~999.995 are outside that range
= a probability of ~99,99% of generating an integer outside that range.
Compare that number to the probability of 2.000.000 in 2^99: It is approx. the same.

Isso atende a todas as regras:

  • 1 inteiro
  • qualquer número inteiro é possível
  • pelo menos 50% (no meu caso, 99,99%) de todos os números inteiros gerados estão fora do intervalo de +/- 1.000.000.

Isso funciona porque o gerador de número aleatório subjacente define probabilidade igual a cada bit gerado, fazendo-o também com números inteiros gerados.
Todo número inteiro tem uma probabilidade de 1/2 ^ 99 para ser gerado.

Editar:

Eu tive que aumentar o expoente para que números inteiros maiores fossem gerados. Eu escolhi 99 porque mantém o código o mais curto possível.

GiantTree
fonte
Não concordamos que não deveria haver limites superiores / inferiores? Por exemplo, o número inteiro 2 ^ 31 + 1 tem 0 de probabilidade, quebrando a regra 2
Optimizer
@Optimizer para mim um número inteiro é definido como em muitas linguagens de programação: um número dentro dos limites de -2^31e +2^31-1(32 bits). Você pode aumentar facilmente os expoentes se desejar gerar números inteiros maiores, mas isso pode falhar dependendo da implementação do Perl.
GiantTree
Acabei de ver que esse número ridiculamente grande também deve ser gerado. Vou editar meu código rapidamente.
GiantTree
@ MartinBüttner Eu tentei o meu melhor para atender às especificações da pergunta. Simplesmente não é possível para mim (pelo menos não sem ajuda) gerar números inteiros infinitamente grandes. O maior número inteiro do Perl é de 1,7e308, que é um limite que não posso controlar.
GiantTree
@ MartinBüttner Ambos são possíveis, mas por exemplo. a cadeia transbordaria após 2 gb de dados, tornando-a finita novamente. É difícil dizer que um número deve ser infinitamente grande se houver problemas com a memória. Em breve, apresentarei uma abordagem diferente usando o BigInts. Além disso, o número inteiro não transborda em 1.7e308, apenas é convertido em infinito ( 1.#INFpara ser exato) #
GiantTree
2

C #, 126 107 bytes

string F(){var a=new System.Random();var b=a.Next(-1E6,1E6+1)+"";while(a.Next(1)>0)b+=a.Next(10);return b;}

Ungolfed:

string F()
{
    System.Random rand = new System.Random();
    string rtn = rand.Next(-1E6, 1E6 + 1) + "";
    while (rand.Next(1) > 0)
         rtn += a.Next(10);
    return rtn;
}

Chance de gerar um número de n dígitos é 1/2 ^ (n-10), que é maior que 0 para todos os n positivos e 1/2 para n = 11.Também cria zeros à esquerda, que não parecem ser proibidos na pergunta original ou em qualquer um de seus comentários.

LegionMammal978
fonte
Ao usar using System;, você não precisa System.Randomduas vezes, mas apenas Random, certo?
26414 Charlie
@ Charlie Esta é uma função, então não posso usar usinginstruções. Pouparia apenas 1 caractere de qualquer maneira.
usar o seguinte
11
Você pode salvar 1 caractere removendo o espaço em -1E6, 1E6+1.
precisa
2

Perl, 62 bytes

print $n=int rand(20)-10;while($n&&rand>.1){print int rand 10}

Tive a mesma idéia que o @Hobbs, de gerar um dígito de cada vez, mas o código dele não atendia ao requisito adicional de zeros à esquerda. Gerar o primeiro dígito em vez de apenas o sinal resolveu isso. E, a menos que exista uma maneira mais curta de sair, se imprimirmos um zero, ou uma maneira mais curta de gerar os -9 a 9 iniciais, isso deve ser feito pelo tamanho.

Em um loop de shell: while perl -e '...'; do echo;done |less

Eu acho que este é um dos mais curtos que não requer RAM infinita para satisfazer o problema. Como um bônus, a saída não é fortemente influenciada por nada, e o tempo de execução é muito rápido.

Tentei usar o bit a bit e salvar um caractere na condição while, mas acho que isso acaba sendo verdade com mais frequência, para que o loop termine mais cedo. Seria necessário mais caracteres para ajustar outras coisas para combater isso, para manter a probabilidade de gerar abs (saída)> 1M.

Peter Cordes
fonte
Bom, você espremido para fora algumas coisas que eu não teria pensado :)
Hobbs
1

Javascript (73)

Esta solução usa que você pode construir um número com base n multiplicando o número anterior por n e adicionando um dígito na base n . Temos um adicional ..?..:..para podermos criar todos os números inteiros negativos. O código a seguir deve ser testado em um console do navegador.

b=Math.round;c=Math.random;x=0;while(b(c()*99)){x*=b(c())?2:-2;x+=b(c())}

A probabilidade de obter um número inteiro> = 2^1(ou <= -(2^1)) é igual à chance de o loop ser executado 2 vezes. A chance disso acontecer é (98/99)^2. A chance de obter um número maior que 2^20(ou <= -(2^20)) é, portanto, (98/99)^21 = 0.808ou 81%. Isso tudo é teoricamente, e assumindo que Math.random seja verdadeiramente aleatório. Obviamente não é.


Snippet testando esse código. Também de uma maneira mais legível.

Sumurai8
fonte
11
O OP confirmou agora que você pode assumir que seu PRNG é verdadeiramente aleatório, mesmo que não seja.
Trichoplax
1

GolfScript, 20 bytes

0{)8.?rand}do.2&(*4/

Sim, este também é meio lento.

Comparado a idiomas como CJam e Pyth, o GolfScript sofre com uma palavra-chave detalhada de geração de números aleatórios (rand ). Para superar esse problema, eu precisava encontrar uma maneira de usá-lo apenas uma vez.

Esse código funciona escolhendo repetidamente um número aleatório entre 0 e 8 8 −1 = 16.777.215 inclusive, e incrementando um contador até que o número aleatório seja 0. O valor resultante do contador tem uma distribuição geométrica com uma mediana de aproximadamente -1 / log 2 ( 1-8 8) ) , 11.629.080, portanto atende ao teste "mais de 1.000.000 pelo menos 50% do tempo".

Infelizmente, o número aleatório assim gerado é sempre estritamente positivo. Assim, a .2&(*4/parte extra é necessária para deixá-la negativa ou zero. Ele funciona extraindo o segundo bit mais baixo do número (que é, portanto, 0 ou 2), diminuindo-o para torná-lo -1 ou 1, multiplicando-o pelo número original e dividindo o resultado por 4 (para se livrar de os dois bits mais baixos, que agora estão correlacionados com o sinal, e também para permitir que o resultado se torne zero). Mesmo após a divisão por 4, o valor absoluto do número aleatório ainda possui uma mediana de -1 / log 2 (1 - 1/8 8 ) / 4 ≈ 2,907,270, portanto, ainda passa no teste de 50%.

Ilmari Karonen
fonte
1

JavaScript, 81 bytes

Este código cumpre todas as regras:

  • Saída de qualquer número inteiro com probabilidade positiva
  • Inteiros de saída fora do intervalo de +/- 1000000 com pelo menos 50% de probabilidade
  • Sem liderança 0na saída

Como bônus, o algoritmo é executado com uma complexidade de tempo de O (log 10 n) e, portanto, retorna o número inteiro quase instantaneamente.

for(s="",r=Math.random;r()>.1;s+=10*r()|0);r(s=s.replace(/^0*/,"")||0)<.5?"-"+s:s

Isso pressupõe um ambiente REPL. Tente executar o código acima no console do navegador ou use o snippet da pilha abaixo:

D.onclick = function() {
  for(s="", r=Math.random;r()>.1; s+=10*r()|0);
  P.innerHTML += (r(s=s.replace(/^0*/,"") || 0) <.5 ?"-" + s : s) + "<br>"
}
<button id=D>Generate a random number</button><pre id=P></pre>

Algoritmo :

  • Continue anexando dígitos aleatórios à string saté que a Math.random() > 0.1.
  • Com base em Math.random() > 0.5, torne o número negativo (acrescentando a sequência scom -).

Este algoritmo não possui uma distribuição uniforme entre todos os números inteiros. Inteiros com maior número de dígitos são menos prováveis ​​que os mais baixos. Em cada uma das iterações de loop, há uma chance de 10% de parar no dígito atual. Eu só tenho que ter certeza de que paro após 6 dígitos mais de 50% do tempo.

Esta equação de @nutki explica o valor máximo da porcentagem de chance de interrupção com base na condição acima:

1 - 50%^(1/6) ≈ 0.11

Assim, 0,1 está dentro do alcance para satisfazer todas as três regras da questão.

Optimizer
fonte
Há algumas coisas que me confundem sobre esta resposta. Você assumiu que Math.random () gera uma distribuição uniforme de números aleatórios, porque a especificação afirma que depende da implementação. Supondo que seja uma distribuição uniforme, P (Math.random ()> 0.1) = 0.9, existe uma enorme probabilidade de que ele termine entre cada iteração. Uma implementação do seu algoritmo run on Firefox 34,0 Ubuntu me dá uma probabilidade de ~ 0,47 (<0,5) cada vez que eu testá-lo: jsfiddle.net/WK_of_Angmar/dh8gq4pb
Wk_of_Angmar
Além disso, como você conseguiu calcular uma complexidade de tempo para um algoritmo sem entrada?
Wk_of_Angmar
1

TI-BASIC, 14 bytes

1-2int(2rand:randNorm(AnsE6,9

Semelhante à resposta R de @ ssdecontrol, isso se baseia na distribuição gaussiana com média de -1.000.000 ou 1.000.000, escolhida aleatoriamente e desvio padrão 9. A distribuição é ilimitada, portanto, em teoria, isso pode gerar qualquer número inteiro.

Explicação :

1-2int(2rand     - get a random integer 0 or 1, then multiply by 2 and subtract 1
:                - this gives the number 1 or -1 (with equal probability) to Ans
randNorm(AnsE6,9 - displays Gaussian distribution with mean (Ans * 1,000,000) and std. dev. 9
Timtech
fonte
Mas pode gerar "2" ou "-2"?
Kennytm
Sim, obviamente. tibasicdev.wikidot.com/randnorm
Timtech
11
OK, leia o código incorretamente (pensamento :significa "imprimir" devido à forma como a explicação é apresentada). Mas pode gerar números com mais de 20 dígitos?
Kennytm
Qualquer número inteiro longo arbitrário é possível como saída? Isso não é limitado pelo alcance de randNorm?
Otimizador
"A distribuição é ilimitada, portanto, em teoria, isso pode gerar qualquer número inteiro". Não há alcance.
Timtech
1

Bash, 66

LANG=C sed -r '/^-?(0|[1-9][0-9]*)$/q;s/.*/5000000/;q'</dev/random

Quase sempre imprime 5000000. Mas, se encontrar um número válido /dev/random, ele imprimirá esse número.

E este é mais rápido:

LANG=C sed -r '/^-?(0|[1-9][0-9]*)$/q;s/.*/5000000/;q'</dev/urandom
jimmy23013
fonte
11
@ Otimizador É suposto ser lento. Isso porque é uma fonte aleatória real. Mas você pode testá-lo com o /dev/urandomque é menos aleatório.
jimmy23013
@Optimizer Como isso levaria a entrada manual? Está lendo um arquivo, mas tudo é um arquivo.
Nit
@ Otimizador Eu simplesmente não entendo o ponto que você está procurando.
Nit
ler /dev/urandomem um script shell é basicamente o mesmo que chamar rand()em outros idiomas. Embora se você realmente esteja usando o bash, não o POSIX sh, poderá obter números aleatórios echo $RANDOM. O wiki.ubuntu.com/DashAsBinSh fornece hexdump /dev/urandomcomo equivalente o bare-POSIX-minimum /bin/dash.
Peter Cordes
1

C ++, 95 bytes

void f(){int d=-18,s=-1;while(s<9){d=(rand()%19+d+9)%10;cout<<d;s=9-rand()%10*min(d*d+s+1,1);}}

Expandido:

void f() {
    int d=-18,s=-1;
    while(s<9) {
        d=(rand()%19+d+9)%10;
        cout<<d;
        s=9-rand()%10*min(d*d+s+1,1);
    }
}

Explicação:

A função continua imprimindo dígitos aleatórios consecutivos até que uma chave com valor aleatório use o valor necessário para interromper a função. d é a variável que mantém o valor do próximo dígito a ser impresso. s é a variável de comutação que aceita valores inteiros aleatórios no intervalo [0, 9], se s == 9, não serão impressos mais dígitos e a função será encerrada.

As variáveis ​​d e s são inicializadas para dar tratamento especial ao primeiro dígito (tirando-o do intervalo [-9, 9] e se o primeiro dígito for zero, a função deve terminar para evitar zeros à esquerda). O valor de d pode ser atribuído como d = rand ()% 10, mas o primeiro dígito não pode ser negativo. d é atribuído como d = (rand ()% 19 + d + 9)% 10 e inicializado em -18, de modo que o primeiro valor de d varia de [-9, 9] e os próximos valores sempre variam de [0 9].

A variável s varia aleatoriamente entre [0, 9] e, se s é igual a 9, a função termina. Assim, após a impressão do primeiro dígito, o próximo será impresso com uma probabilidade de 90% (assumindo que rand () seja verdadeiramente aleatório e para satisfazer a terceira condição). s pode ser facilmente atribuído como s = rand ()% 10; no entanto, há uma exceção: se o primeiro dígito for zero, a função deverá terminar. Para lidar com essa exceção, s foi atribuído como s = 9-rand ()% 10 * min (d * d + s + 1,1) e inicializado como -1. Se o primeiro dígito for zero, o mínimo retornará 0 es será igual a 9-0 = 9. A atribuição da variável s sempre varia de [0, 9]; portanto, a exceção pode ocorrer apenas no primeiro dígito.

Características (supondo que rand () seja verdadeiramente aleatório)

  • O número inteiro é impresso dígito por dígito, com uma probabilidade fixa de 90% de imprimir outro dígito após a impressão do último.

  • 0 é o número inteiro com maior chance de ser impresso, com uma probabilidade de aproximadamente 5,2%.

  • A probabilidade de imprimir um número inteiro no intervalo [-10 ^ 6, 10 ^ 6] é de aproximadamente 44% (o cálculo não está escrito aqui).

  • Números positivos e negativos são impressos com a mesma probabilidade (~ 47,4%).

  • Nem todos os dígitos são impressos com a mesma probabilidade. Por exemplo: no meio da impressão do número inteiro, se o último dígito for 5, o dígito 3 terá uma chance ligeiramente menor de ser impresso a seguir. Em geral, se o último dígito foi d, o dígito (d + 18)% 10 terá uma chance ligeiramente menor de ser impresso a seguir.

Exemplo de saídas (10 execuções)

-548856139437
7358950092214
507
912709491283845942316784
-68
-6
-87614261
0
-5139524
7

Process returned 0 (0x0)   execution time : 0.928 s
Press any key to continue.
Daniel Turizo
fonte
1

Bash, 42 bytes

printf "%d\n" 0x$(xxd -p -l5 /dev/random)
/ dev / random no OSX tem apenas bytes aleatórios, xxd -p -l5converte 5 dos caracteres ascii em hexadecimal e o printftransforma em formato decimal.

Camden
fonte
0

Pitão , 11 bytes

WOyG~ZtOT)Z

Nota: este programa provavelmente trava com um erro de memória em qualquer computador real. Para testá-lo, tente substituir Gpor uma sequência mais curta, como neste código, que gera números com uma média de 28000:

pyth -c 'WOy"abcdefghijklm"~ZtOUT)Z'

Esse código faz um loop, adicionando um número aleatório de -1 a 8 a Z, com uma probabilidade de 2 ^ -26 de sair do loop em cada repetição. A probabilidade 2 ^ -26 é obtida selecionando-se um elemento aleatório ( O) do conjunto de todos os subconjuntos ( y) do alfabeto ( G).

Detalhes técnicos e justificativa:

A probabilidade 2 ^ -26 é derivada de dois fatos: yquando chamada em seqüências, é a função de conjunto de potência, constrói a lista de todos os subconjuntos da entrada. Como a entrada,, Gpossui 26 caracteres, este conjunto de energia yGpossui 2 ^ 26 entradas. OyGseleciona um elemento aleatório dessas 2 ^ 26 entradas. Exatamente uma dessas entradas, a sequência vazia, será avaliada como falsa quando transmitida paraW o loop while. Portanto, há uma probabilidade de 2 ^ -26 de sair do loop a cada vez.

Em qualquer número fixo de ciclos de loop K, a probabilidade de obter o número K * 3,5 + me obter K * 3,5 - m é igual, porque cada sequência de adendos que atinge um total pode ser invertida, -1 -> 8, 0 -> 7, etc., para alcançar o outro. Além disso, números mais próximos de K * 3.5 são claramente mais prováveis ​​que números mais distantes. Portanto, se K> 2000000 / 3.5 = 571428.5, a probabilidade de obter um número acima de 1000000 é maior que 75%, porque alguns dos resultados acima desse número podem ser colocados em uma correspondência individual com todos os resultados abaixo desse número. O número e a metade inferior podem ser colocados em uma correspondência individual com aqueles abaixo de 1000000. A probabilidade de obter pelo menos 571429 loops é (1-2 ^ -26) ^ 571429, o que não é menor que (1-2 ^ -26 * 571429), o número esperado de vezes que sai do loop nas primeiras 571429 tentativas, que é de 99,1%. Assim, em 99,1% ou mais dos ensaios, há uma chance de 75% ou mais de obter pelo menos 1000000, portanto, há mais de 50% de chance de obter mais de 1000000.

Esse código baseia-se no comportamento de Oonde um bug foi introduzido acidentalmente há 3 dias e foi corrigido hoje. Ele deve funcionar em qualquer versão do Pyth 3 antes de 22 de dezembro ou depois de hoje. O código a seguir é equivalente e sempre funcionou:

WOyG~ZtOUT)Z
isaacg
fonte
O que aconteceu com o compilador online?
Optimizer
@Optimizer Problemas com o site, vou trabalhar nele.
Isaacg
Ah legal. Queria trabalhar na tradução Pyth da minha resposta CJam ontem e constatou que dá 404.
Optimizer
0

Java, 113 bytes

void g(){String a=Math.random()>0?"10":"01";for(;Math.random()>0;)a+=(int)(Math.random()*2);System.out.print(a);}

Este programa imprime um número binário no fluxo de saída padrão. Você pode ter que esperar um pouco porque a probabilidade de terminar o número (ou ser positivo) é de aproximadamente 0. A idéia de que o valor absoluto de um número gerado seja menor que 1 milhão é divertida, mas possível.

Ungolfed:

void g(){
    String a=Math.random()>0?"10":"01";             //Make sure there are no trailing zeroes.
    for(;Math.random()>0;)a+=(int)(Math.random()*2);//Add digits
    System.out.print(a);                            //Print
}

Saída de amostra: será lançada quando um número terminar de ser gerado.

O número um
fonte
0

Java (JDK) , 140 127 bytes

()->{int i;var o=System.out;for(o.print(i=(int)(19*Math.random())-10);i!=0&Math.random()<.9;)o.print((int)(11*Math.random()));}

-13 bytes introduzindo mais lógica no cabeçalho do loop - graças a @ceilingcat

Experimente online!

Sara J
fonte