Genera cualquier número entero aleatorio


17

Su programa / función debería

  • salida exactamente un entero
  • generar cualquier número entero con probabilidad positiva
  • genera un número entero mayor que 1,000,000 o menor que -1,000,000 con al menos un 50% de probabilidad.

Ejemplos de salidas (todo debe ser posible):

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

Aclaraciones:

  • Se permite un salto de línea final.
  • Los ceros iniciales no están permitidos.
  • -0 esta permitido.

El código más corto gana.


2
@Optimizer, ¿por qué asumes una probabilidad uniforme? La pregunta no lo dice. De hecho, parece claro a partir de ese punto que la distribución no tiene que ser uniforme siempre que al menos el 50% esté fuera de [-1 millón, 1 millón].
hobbs

10
Una solución que produce una " distribución uniforme entre todos los enteros" es imposible. Hay infinitos números enteros, por lo que cada número entero aparecería con una probabilidad de 0. (O: ¡Dar un número finito significaría que está descuidando infinitos otros!) Cualquier solución tendrá que desfavorecer valores más altos para lograr P (total ) = 1.
joeytwiddle

2
@Ypnypn La RAM de la computadora tampoco es un límite. No tiene que almacenar su salida parcial en ningún lado.
jimmy23013

44
@GiantTree - way too long to fit in an integer- Esto solo es cierto si asume que eso integersignifica el inttipo de datos en un arco de 32/64 bits, lo cual no es necesariamente una suposición válida. "Entero" comenzó como un término matemático , que no tiene restricciones de tamaño.
Nombre falso

55
Cualquiera que use un generador de números pseudoaleatorios para tomar sus decisiones sobre la salida excluirá casi todos los enteros y colocará un límite superior en el tamaño de los enteros que se pueden producir (suponiendo que el PRNG tenga un período finito). ¿Se puede descartar esto en las respuestas o una respuesta válida requiere un verdadero generador de números aleatorios?
trichoplax

Respuestas:


12

CJam, 16 14 13 bytes

0{Kmr(+esmr}g

Este tendrá una duración de un muy largo tiempo, ya que utiliza la marca de tiempo actual (del orden de 10 12 ) para determinar si el bucle debe terminar. Estoy usando esto como el envío, ya que es el más corto, pero hay dos alternativas de 14 bytes, que tienen sus propios méritos:

0{esmr(+esmr}g

Este no está limitado por el período del PRNG, ya que el rango de todos los números aleatorios depende de la marca de tiempo actual. Por lo tanto, esto debería ser capaz de producir cualquier número, aunque la probabilidad de números negativos, o incluso pequeños números positivos, es muy pequeña.

A continuación se muestra una versión equivalente que utiliza en 3e5lugar de la marca de tiempo. Y 20para el primer rango (como el envío de 13 bytes). Es mucho más rápido y también cumple con todas las reglas. Es una especie de caso limitante obtener una probabilidad del 50% para números más allá de 1,000,000 mientras se mantiene un tiempo de ejecución razonable y un tamaño de código pequeño. La explicación y la justificación matemática se refieren a esta versión:

0{Kmr(+3e5mr}g

Esto suele tardar unos segundos en ejecutarse. Puede reemplazarlo 5con a 2para que funcione aún más rápido. Pero luego, el requisito de la probabilidad del 50% solo se cumplirá para 1,000 en lugar de 1,000,000.

Estoy empezando en 0. Luego tengo un bucle, que rompo con probabilidad 1 / (3 * 10 5 ). Dentro de ese ciclo agrego un número entero aleatorio entre -1 y 18 (inclusive) a mi total acumulado. Hay una probabilidad finita (aunque pequeña) de que cada número entero se genere, con números enteros positivos que son mucho más probables que los negativos (no creo que vea uno negativo en su vida). Romper con una probabilidad tan pequeña e incrementar la mayor parte del tiempo (y agregar mucho más que restar) asegura que usualmente iremos más allá de 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.";

Alguna justificación matemática:

  • En cada paso agregamos 8.5 en promedio.
  • Para llegar a 1,000,000 necesitamos 117,647 de estos pasos.
  • La probabilidad de que hagamos menos que este número de pasos es

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

    que evalúa a 0.324402. Por lo tanto, en aproximadamente dos tercios de los casos, daremos más 117,647 pasos, y fácilmente cada 1,000,000.

  • (Tenga en cuenta que esta no es la probabilidad exacta, porque habrá alguna fluctuación sobre esos 8.5 promedio, pero para llegar al 50%, tenemos que ir más allá de 117,646 a unos 210,000 pasos).
  • En caso de duda, podemos volar fácilmente el denominador de la probabilidad de terminación, hasta 9e9sin agregar ningún byte (pero años de tiempo de ejecución).

... o 11 bytes?

Finalmente, hay una versión de 11 bytes, que tampoco está limitada por el período del PRNG, pero que se quedará sin memoria casi siempre. Solo genera un número aleatorio (basado en la marca de tiempo) en cada iteración, y lo usa tanto para incrementar como para terminar. Los resultados de cada iteración permanecen en la pila y solo se resumen al final. Gracias a Dennis por esta idea:

{esmr(}h]:+

Agregué un comentario a la pregunta para ver si las reglas requieren un verdadero generador de números aleatorios, pero supuse que apreciaría la pedantería. ¿Su fuente aleatoria aquí es seudoaleatoria? Eso restringiría el tamaño del conjunto de posibles resultados a lo más durante el período de su PRNG, ¿verdad?
trichoplax

(+1 independientemente de la elegancia simple)
trichoplax

Sí, estoy adivinando todo hasta ahora. Sin embargo, tengo curiosidad por ver si alguien publica una respuesta sin ese problema ...
trichoplax

Veo que el OP ha declarado que puede asumir que su generador de números aleatorios es un verdadero generador de números aleatorios, lo sea o no, así que esto es redundante ahora ... :)
trichoplax

La suma de Kmren un período todavía es probable que siempre sea un gran número positivo mayor que el período. Y no puede producir todos los números posibles en ese 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);}

Salidas de ejemplo

-8288612864831065123773
0
660850844164689214
-92190983694570102879284616600593698307556468079819964903404819
3264

Sin golf

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

Respuesta anterior (antes del cambio de regla)

void f(){if(Math.random()<.5)System.out.print('-');do System.out.print(new java.util.Random().nextInt(10));while(Math.random()>.02);}

Ambos tienen razón, pero la pregunta establece que la probabilidad tiene que ser al menos 50%, no en el rango de +/- 1.000.000
GiantTree

@Optimizer Redone.
Ypnypn

Si usa literales binarios no tiene que imprimir el -.
TheNumberOne

4

Mathematica - 47

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

Básicamente solo genera un número aleatorio usando una distribución normal con una varianza igual a 1500000. Esto producirá un número entero entre -10 ^ 6 y 10 ^ 6 con una probabilidad del 49.5015%.


"Esto producirá un número entero entre -10 ^ 6 y 10 ^ 6 con una probabilidad del 50.4985%". - Eso no es suficiente. ¿Has leído mal la especificación? ¿Quizás quiso usar 10 ^ 7 como la varianza?
John Dvorak

@JanDvorak Probabilidad incorrecta, lo siento. Ahora es el correcto.
swish

¿La implementación de esto en Mathematica realmente cubre todos los enteros? No tengo acceso a la fuente, pero supongo que no ...
trichoplax

@ githubphagocyte Dependería de la precisión actual.
swish

44
Lo que quiero decir es que especificar cualquier precisión específica excluirá números mayores que eso. La única forma en que podría funcionar es si pudiera especificar una precisión ilimitada.
trichoplax

4

Python 2, 75 69 bytes

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

Es trivial comprobar que el ciclo while en el medio puede generar todos los enteros (aunque sesgados hacia cero). "12" se elige de modo que haya aproximadamente la mitad de los números que excedan ± 10 6 .


Solución anterior:

Python 2, 44 bytes

Basado en la solución de Mathematica .

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

Realmente no funciona porque Python floattiene solo una precisión finita.


Esto no podrá generar todos los enteros, porque el generador de números pseudoaleatorios tiene una cantidad finita de estado interno. Según la documentación, Python usa el Mersenne Twister, por lo que el estado es bastante grande. Pero no es infinito, por lo que solo puede producir un subconjunto finito de todos los enteros.
starblue

@starblue: Desde el OP: "Puede suponer que el generador de números aleatorios de su idioma es un verdadero generador de números aleatorios, incluso si no es el caso".
kennytm

3

Rubí, 70

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

Para hacer posible la generación de números muy grandes, estoy devolviendo el número como Stringde una lambda. Si eso no está permitido, cuente 8 caracteres adicionales (para puts f[]) para que sea un programa en lugar de una función.

Explicación

Genere un número entre -1,000,000y 1,000,000. Si el número es 1o mayor, el número se devuelve como a String.

Si el número es menor que 1, la función se llama recursivamente para devolver el número fuera del rango de números. Para asegurarse de que también se pueden generar números negativos, a -se antepone al resultado resultante Stringsi el número inicial es mayor que -500,000.

¡Espero haber entendido el desafío correctamente!


3

R, 38

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

Sorteos de la distribución gaussiana con un promedio de 2,000,000, elegidos al azar, y una desviación estándar de 1,000,000, de modo que aproximadamente 2/3 de los sorteos se ubicarán entre 1,000,000 y 3,000,000. La distribución no tiene límites, por lo que en teoría esto puede generar cualquier número entero. El paquete Rmpfr reemplaza los R's flotantes dobles incorporados con precisión arbitraria.


Sí, me di cuenta de que leí mal las especificaciones. Y me imagino que tiene las mismas limitaciones en la precisión de la máquina con Mathematica
shadowtalker

Hmm en ese caso no estoy seguro. Tendré que investigarlo; considere esta respuesta "en espera" por ahora
shadowtalker

@ MartinBüttner solucionado creo
shadowtalker

Interesante. Sin sample(c(1,-1),1)embargo , no creo que necesites todo el pensamiento. Centrarse en 1e6 debería ser suficiente ...
Martin Ender

@ MartinBüttner oh, ¿no necesita ser 50% en ambos extremos? Eso no estaba claro
shadowtalker

2

Perl, 53 caracteres

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

Ciertamente no veo ninguna razón para trabajar con enteros al imprimir uno :)

Tiene la misma probabilidad de imprimir un número con o sin un "-" inicial.

Imprime un número de 1 dígito el 10% del tiempo, un número de 2 dígitos el 9% del tiempo, un número de 3 dígitos el 8,1% del tiempo, un número de 4 dígitos el 7,29% del tiempo, un número de 5 dígitos 6.56% del tiempo, un número de 6 dígitos 5.9% del tiempo, etc. Cualquier longitud es posible, con probabilidad decreciente. Los números de uno a cinco dígitos representan aproximadamente el 41.5% de los casos de salida, y el número 1,000,000 (o -1,000,000) solo 6 millonésimas de porcentaje, por lo que el número de salida estará fuera del rango -1,000,000 a 1,000,000 aproximadamente 54.6 % del tiempo.

Tanto "0" como "-0" son salidas posibles, lo que espero no sea un problema.


¿No imprime "números" como -00000000167? Eso no es realmente un número entero.
isaacg

1
@isaacg No veo por qué eso no es un número entero.
Optimizador

2
@Optimizer lo es, pero el OP ha prohibido explícitamente el 0.
Martin Ender

Puede generar un dígito inicial aleatorio distinto de cero antes del ciclo, de -9 a +9. print int(rand(20)-10)||1. Sin embargo, necesito una forma de generar 0 como salida. Tal vez || muere 0, si se permite la basura final después del cero. De lo contrario, se necesita un camino corto para imprimir el cero y salir sin más salida si int(rand(20)-10)==0.
Peter Cordes

@PeterCordes estuvo de acuerdo, ese es un enfoque decente, pero no tengo ganas de escribirlo y no creo que sea competitivo a largo plazo. Siéntase libre de enviarlo por su cuenta :)
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());}

Descompostura:

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

La probabilidad de obtener un valor entre -1.000.000 y 1.000.000 tiende a cero PERO es posible.

Nota: Esta subrutina puede ejecutarse durante mucho tiempo y generar un error con un mensaje "¡Sin memoria!" error pero técnicamente está generando cualquier número entero como se indica en la pregunta.

Perl, 25

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

Genera un entero aleatorio dentro del rango de +/- 2 ^ 99.

Descompostura

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

Probado con 1 millón de muestras:

~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.

Esto cumple con todas las reglas:

  • 1 entero
  • cualquier entero es posible
  • Al menos el 50% (en mi caso 99,99%) de todos los enteros generados están fuera del rango de +/- 1.000.000.

Esto funciona porque el generador de números aleatorios subyacente define la misma probabilidad para cada bit que se genera, haciendo así también en los enteros generados.
Cada entero tiene una probabilidad de 1/2 ^ 99 para ser generado.

Editar:

Tuve que aumentar el exponente para que se generen enteros más grandes. Elegí 99 porque mantiene el código lo más corto posible.


¿No estuvimos de acuerdo en que no debería haber ningún límite superior / inferior? Por ejemplo, el número entero 2 ^ 31 + 1 tiene probabilidad 0, rompiendo la regla 2
Optimizador

@Optimizer para mí, un número entero se define como en muchos lenguajes de programación: un número dentro de los límites de -2^31y +2^31-1(32bits). Puede aumentar fácilmente los exponentes si desea generar enteros más grandes, pero puede fallar dependiendo de la implementación de Perl.
GiantTree

Acabo de ver que ese número entero ridículamente grande también debe generarse. Editaré mi código rápidamente.
GiantTree

@ MartinBüttner Hice mi mejor esfuerzo para cumplir con las especificaciones de la pregunta. Simplemente no es posible para mí (al menos no sin ayuda) generar enteros infinitamente grandes. El número entero más grande de Perl es aproximadamente 1.7e308, que es un límite que no puedo controlar.
GiantTree

@ MartinBüttner Ambos son posibles pero, por ejemplo. la cadena se desbordaría después de 2 gb de datos, volviéndola finita nuevamente. Es difícil decir que un número debe ser infinitamente grande si hay problemas con la memoria. Pronto propondré un enfoque diferente usando BigInts. Además, el número entero no se desborda en 1.7e308, solo se convierte en infite ( 1.#INFpara ser exactos)
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;}

Sin golf:

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;
}

La posibilidad de generar un número de n dígitos es 1/2 ^ (n-10), que es mayor que 0 para todos los n positivos, y 1/2 para n = 11.También crea ceros a la izquierda, que no parecen estar prohibidos en la pregunta original o en ninguno de sus comentarios.


Cuando se usa using System;, no necesita System.Randomdos veces, pero solo Random, ¿verdad?
Charlie

@ Charlie Esta es una función, así que no puedo usar usingdeclaraciones. De todos modos, solo ahorraría 1 char.
LegionMammal978

1
Puede ahorrar 1 carácter eliminando el espacio en -1E6, 1E6+1.
ProgramFOX

2

Perl, 62 bytes

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

Tuve la misma idea que @Hobbs, de generar un dígito a la vez, pero su código no cumplía con el requisito agregado de cero a la izquierda. Generar el primer dígito en lugar de solo el signo lo resolvió. Y a menos que haya una forma más corta de salir si imprimimos un cero, o una forma más corta de generar los primeros -9 a 9, esto debería hacerlo por tamaño.

En un bucle de shell: while perl -e '...'; do echo;done |less

Creo que este es uno de los más cortos que no requiere RAM infinita para satisfacer el problema. Como beneficio adicional, la salida no está fuertemente sesgada hacia nada, y el tiempo de ejecución es muy rápido.

Intenté usar bitwise y guardar un personaje en la condición while, pero creo que esto termina siendo cierto con más frecuencia, por lo que el ciclo termina antes. Necesitaría más caracteres para ajustar otras cosas para contrarrestar eso, para mantener la probabilidad de generar abdominales (salida)> 1M.


Bien

1

Javascript (73)

Esta solución utiliza que puede construir un número con base n multiplicando el número anterior con ny agregando un dígito en base n . Tenemos un adicional ..?..:..allí para poder crear todos los enteros negativos. El siguiente código debe probarse en una consola del navegador.

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

La probabilidad de obtener un número entero> = 2^1(o <= -(2^1)) es igual a la posibilidad de que el ciclo se ejecute 2 veces. La posibilidad de que eso suceda es (98/99)^2. La posibilidad de obtener un número mayor que 2^20(o <= -(2^20)) es, por lo tanto, del (98/99)^21 = 0.80881%. Sin embargo, todo esto es en teoría, y suponiendo que Math.random es verdaderamente aleatorio. Obviamente no lo es.


Fragmento de prueba de este código. También de una manera más legible.


1
El OP ahora ha confirmado que puede asumir que su PRNG es verdaderamente aleatorio, incluso si no lo es.
trichoplax

1

GolfScript, 20 bytes

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

Sí, este también es un poco lento.

En comparación con lenguajes como CJam y Pyth, GolfScript sufre de una palabra clave detallada de generación de números aleatorios ( rand). Para superar esta desventaja, necesitaba encontrar una manera de usarla solo una vez.

Este código funciona seleccionando repetidamente un número aleatorio entre 0 y 8 8 −1 = 16,777,215 inclusive, e incrementando un contador hasta que el número aleatorio sea 0. El valor del contador resultante tiene una distribución geométrica con una mediana de aproximadamente -1 / log 2 (1 - 1/8 8 ) ≈ 11,629,080, por lo que cumple con la prueba "más de 1,000,000 al menos el 50% del tiempo".

Por desgracia, el número aleatorio así generado siempre es estrictamente positivo. Por lo tanto, la .2&(*4/parte adicional es necesaria para que sea negativa o cero. Funciona extrayendo el segundo bit más bajo del número (que es 0 o 2), decrementándolo para que sea -1 o 1, multiplicándolo con el número original y dividiendo el resultado entre 4 (para deshacerse de los dos bits más bajos, que ahora están correlacionados con el signo, y también para permitir que el resultado sea cero). Incluso después de la división por 4, el valor absoluto del número aleatorio todavía tiene una mediana de -1 / log 2 (1 - 1/8 8 ) / 4 ≈ 2,907,270, por lo que todavía pasa la prueba del 50%.


1

JavaScript, 81 bytes

Este código cumple todas las reglas:

  • Salida de cualquier número entero con probabilidad positiva
  • Enteros de salida fuera del rango de +/- 1000000 con al menos un 50% de probabilidad
  • Sin liderazgo 0en la salida

Como beneficio adicional, el algoritmo se ejecuta con una complejidad temporal de O (log 10 n), por lo que devuelve el entero casi al instante.

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

Esto supone un entorno REPL. Intente ejecutar el código anterior en la consola de su navegador, o use el fragmento de pila a continuación:

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 :

  • Siga agregando dígitos aleatorios a la cadena shasta que a Math.random() > 0.1.
  • De acuerdo con Math.random() > 0.5, haga que el número sea negativo (anteponiendo la cadena scon -).

Este algoritmo no tiene una distribución uniforme entre todos los enteros. Los enteros con un conteo de dígitos más alto son menos probables que los más bajos. En cada iteración de bucle for, hay un 10% de posibilidades de que me detenga en el dígito actual. Solo tengo que asegurarme de parar después de 6 dígitos más del 50% del tiempo.

Esta ecuación de @nutki explica el valor máximo del porcentaje de probabilidad de frenado basado en la condición anterior:

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

Por lo tanto, 0.1 está dentro del rango para satisfacer las tres reglas de la pregunta.


Hay algunas cosas que me confunden acerca de esta respuesta. ¿Ha asumido que Math.random () genera una distribución uniforme de números aleatorios, porque la especificación establece que depende de la implementación. Suponiendo que es una distribución uniforme, P (Math.random ()> 0.1) = 0.9, por lo que hay una gran probabilidad de que termine entre cada iteración. Una implementación de su algoritmo ejecutado en Firefox 34.0 Ubuntu me da una probabilidad de ~ 0.47 (<0.5) cada vez que lo pruebo
Wk_of_Angmar

Además, ¿cómo ha logrado calcular una complejidad de tiempo para un algoritmo sin una entrada?
Wk_of_Angmar

1

TI-BASIC, 14 bytes

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

Similar a la respuesta R de @ssdecontrol, esto se basa en la distribución gaussiana con una media de -1,000,000 o 1,000,000, elegida al azar y desviación estándar 9. La distribución no tiene límites, por lo que en teoría esto puede generar cualquier número entero.

Explicacion :

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

¿Pero puede generar "2" o "-2"?
kennytm


1
OK, lea el código incorrectamente (pensamiento :significa "imprimir" debido a cómo se presenta la explicación). ¿Pero puede generar números de más de 20 dígitos?
kennytm

¿Un entero largo arbitrario es posible como salida? ¿No está esto limitado por el rango de randNorm?
Optimizador

"La distribución no tiene límites, por lo que en teoría esto puede generar cualquier número entero". No hay rango.
Timtech

1

Bash, 66

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

Casi siempre imprime 5000000. Pero si encuentra un número válido /dev/random, imprimirá ese número en su lugar.

Y este es más rápido:

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

1
@Optimizer Se supone que es lento. Eso es porque es una fuente aleatoria real. Pero puedes probarlo con lo /dev/urandomque es menos aleatorio.
jimmy23013

@Optimizer ¿Cómo sería tomar entrada manual? Está leyendo un archivo, pero todo es un archivo.
Nit

@Optimizer Simplemente no entiendo el punto al que te diriges.
Nit

leer /dev/urandomen un script de shell es básicamente lo mismo que llamar rand()en otros idiomas. Aunque si realmente está usando bash, no POSIX sh, puede obtener números aleatorios de echo $RANDOM. wiki.ubuntu.com/DashAsBinSh se ofrece hexdump /dev/urandomcomo equivalente de bare-POSIX-mínimo /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);
    }
}

Explicación:

La función sigue imprimiendo dígitos aleatorios consecutivos hasta que un interruptor de valor aleatorio toma el valor requerido para detener la función. d es la variable que mantiene el valor del siguiente dígito a imprimir. s es la variable de cambio que toma valores enteros aleatorios en el intervalo [0, 9], si s == 9 entonces no se imprimen más dígitos y la función finaliza.

Las variables dys se inicializan para dar un tratamiento especial al primer dígito (tomándolo del intervalo [-9, 9] y si el primer dígito es cero, entonces la función debe finalizar para evitar los ceros iniciales). El valor de d podría asignarse como d = rand ()% 10 pero luego el primer dígito no podría ser negativo. d se asigna en su lugar como d = (rand ()% 19 + d + 9)% 10 y se inicializa en -18, por lo que el primer valor de d variará entre [-9, 9] y los siguientes valores siempre variarán desde [0 , 9].

La variable s varía aleatoriamente desde [0, 9], y si s es igual a 9, la función finaliza, por lo que después de imprimir el primer dígito, el siguiente se imprimirá con una probabilidad del 90% (suponiendo que rand () es verdaderamente aleatorio, y para satisfacer la tercera condición). s podría asignarse fácilmente como s = rand ()% 10, sin embargo, existe una excepción, si el primer dígito es cero, la función debe finalizar. Para manejar dicha excepción, s ha sido asignado como s = 9-rand ()% 10 * min (d * d + s + 1,1) e inicializado como -1. Si el primer dígito es cero, el mínimo devolverá 0 y s será igual a 9-0 = 9. La asignación de la variable s siempre oscilará entre [0, 9], por lo que la excepción solo puede ocurrir en el primer dígito.

Características (suponiendo que rand () es verdaderamente aleatorio)

  • El número entero se imprime dígito a dígito, con una probabilidad fija del 90% de imprimir otro dígito después de imprimir el último.

  • 0 es el número entero con mayor probabilidad de ser impreso, con una probabilidad de aproximadamente 5.2%.

  • La probabilidad de imprimir un número entero en el intervalo [-10 ^ 6, 10 ^ 6] es aproximadamente del 44% (el cálculo no se escribe aquí).

  • Los enteros positivos y negativos se imprimen con la misma probabilidad (~ 47.4%).

  • No todos los dígitos se imprimen con la misma probabilidad. Por ejemplo: en medio de la impresión del número entero, si el último dígito fue 5, el dígito 3 tendrá una probabilidad ligeramente menor de imprimirse a continuación. En general, si el último dígito fue d, el dígito (d + 18)% 10 tendrá una probabilidad ligeramente menor de imprimirse a continuación.

Resultados de ejemplo (10 ejecuciones)

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

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

1

Bash, 42 bytes

printf "%d\n" 0x$(xxd -p -l5 /dev/random)
/ dev / random en OSX es solo bytes aleatorios, y xxd -p -l5convierte 5 de los caracteres ascii a hexadecimal, y lo printfconvierte en formato decimal.


0

Pyth , 11 bytes

WOyG~ZtOT)Z

Nota: este programa probablemente se bloqueará con un error de memoria en cualquier computadora real. Para probarlo, intente reemplazarlo Gpor una cadena más corta, como en este código, que genera números con un promedio de alrededor de 28000:

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

Este código se repite, agregando un número aleatorio de -1 a 8 a Z, con una probabilidad de 2 ^ -26 de salir del ciclo en cada repetición. La probabilidad de 2 ^ -26 se logra seleccionando un elemento aleatorio ( O) del conjunto de todos los subconjuntos ( y) del alfabeto (G ).

Detalles técnicos y justificación:

La probabilidad 2 ^ -26 se deriva de dos hechos: ycuando se llama a secuencias, es la función de conjunto de potencia, construye la lista de todos los subconjuntos de la entrada. Dado que la entrada, Gtiene 26 caracteres de longitud, este conjunto de potencia yGtiene 2 ^ 26 entradas. OyGselecciona un elemento aleatorio de esas 2 ^ 26 entradas. Exactamente una de esas entradas, la cadena vacía, se evaluará como falsa cuando se pase aW ciclo while. Por lo tanto, hay una probabilidad de 2 ^ -26 de salir del ciclo cada vez.

En cualquier número fijo de ciclos de bucle K, la probabilidad de obtener el número K * 3.5 + my obtener K * 3.5 - m es igual, porque cada secuencia de sumandos que logra un total puede invertirse, -1 -> 8, 0 -> 7, etc., para lograr el otro. Además, los números más cercanos a K * 3.5 son claramente más probables que los números más lejanos. Por lo tanto, si K> 2000000 / 3.5 = 571428.5, la probabilidad de obtener un número por encima de 1000000 es mayor que 75%, porque algunos de los resultados por encima de ese número se pueden poner en una correspondencia uno a uno con todos los resultados a continuación. número, y la parte superior inferior a la mitad, se puede poner en una correspondencia uno a uno con los menores de 1000000. La probabilidad de obtener al menos 571429 bucles es (1-2 ^ -26) ^ 571429, que es no menos de (1-2 ^ -26 * 571429), el número esperado de veces que se abandona el ciclo durante los primeros 571429 intentos, que es 99.1%. Por lo tanto, en el 99.1% o más de las pruebas, hay un 75% o más de posibilidades de obtener al menos 1000000, por lo que hay más del 50% de posibilidades de obtener más de 1000000.

Este código se basa en un comportamiento de Odónde se introdujo un error accidentalmente hace 3 días y se corrigió hoy. Debería funcionar en cualquier versión de Pyth 3 antes del 22 de diciembre o después de hoy. El siguiente código es equivalente y siempre ha funcionado:

WOyG~ZtOUT)Z

¿Qué pasó con el compilador en línea?
Optimizador

@Optimizer Problemas con el sitio web, trabajaré en él.
isaacg

Ah, guay. Quería trabajar en la traducción Pyth de mi respuesta de CJam ayer y descubrí que da 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 un número binario en la secuencia de salida estándar. Es posible que tenga que esperar un tiempo porque la probabilidad de que termine el número (o sea positivo) es aproximadamente 0. La idea de que el valor absoluto de un número generado es inferior a 1 millón es divertida, pero posible.

Sin golf:

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
}

Salida de muestra: se publicará cuando se haya generado un número.


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 introduciendo más lógica en el encabezado del bucle, gracias a @ceilingcat

Pruébalo en línea!

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.