Aleatorizar hasta 0


29

Reto

Publicación de sandbox

Dado un entero positivo (K)Produce un entero uniformemente aleatorio (Y)entre [0, K).

Si Y > 0asume K = Yy repite el proceso hasta Y = 0.

Reglas

  • La entrada debe imprimirse al principio
  • Formato de salida como desee
  • Tu programa debe terminar.
  • 0 debe ser la salida final, opcionalmente una línea vacía en su lugar 0

Si el envío es una función, ¿puede devolver 0 además de imprimirlo?
Adám

1
@ Adám sí, puedes volver además
Luis felipe De jesus Munoz

¿Necesito sembrar mi RNG?
SIGSTACKFAULT

¿Podemos imprimir sin delimitadores?
Tito

Tengo curiosidad Es bastante fácil demostrar que el número promedio de pasos que toma este programa antes de que termine es H (K-1) + 1 donde H (K) es el número armónico K'th . Para n = 1000, eso es 8.484 pasos en promedio.
J.Doe

Respuestas:


19

Pyth , 6 5 4 bytes

.uOW

Pruébalo aquí!

Cómo funciona

.uOW Programa completo. Toma un número entero de STDIN y genera una lista en STDOUT.
.u Punto fijo acumulativo. Aplicar la función dada con un valor inicial dado,
        que se asigna implícitamente a la entrada, hasta que se produce un resultado 
        antes se encuentra. Devuelve la lista de resultados intermedios.
   W Aplicación condicional. Si el argumento (el valor actual) es verdadero, entonces
        aplique la función a continuación, de lo contrario no la cambie.
  O Entero aleatorio en el rango [0, N).
        IOW: en cada iteración de .u, asigne una variable N al valor actual, comenzando
        con la entrada Si N no es 0, elija un entero aleatorio en [0, N), de lo contrario
        devuelve N sin cambios. Siempre que encontremos un 0, la siguiente iteración también debe
        da como resultado un 0 y, por lo tanto, el ciclo se detiene allí.

1
Vi una manera de hacer esto en Pyth pero soy un principiante. El respeto. ¿Idioma del mes de agosto quizás?
ElPedro

15

C (gcc) , 42 bytes

f(_){printf("%d\n",_);(_=rand()%_)&&f(_);}

Pruébalo en línea!

Utiliza lógica y cortocircuito.

f(_){                 // f(int _) {
    printf("%d\n",_); // print argument and a newline
    (_=rand()%_)      // set _ to rand()%_
    &&f(_);}          // short-circuit AND to recursively call f if _ not zero

C (gcc) , 40 bytes (sin imprimir el valor inicial)

f(_){printf("%d\n",_=rand()%_);_&&f(_);}

Pruébalo en línea!

Utiliza lógica y cortocircuito.

f(_){              // f(int _) {
    printf("%d\n", // print an integer and a newline 
    _=             // The integer is _ which we set to...
    rand()%_);     // a random value modulo the input _
    _&&f(_);}      // short-circuit AND to recursively call f if _ not zero

44
rand()%_no es uniforme
njzk2

(si no está convencido, intente usar un dado de 6 lados para generar un valor [1,5] con este método).
njzk2

3
Soy plenamente consciente de que rand () casi siempre está sesgado (debido al truncamiento), pero el estándar no lo garantiza (RAND_MAX podría en teoría ser un múltiplo de todos nuestros números, solo por suerte: P aunque generalmente es ~ 65k ) En la práctica, para los rangos con los que estamos lidiando, parecerá lo suficientemente aleatorio como para no destacarse en presentaciones similares en este desafío.
LambdaBeta

1
eso es del desafío "Mostrar un entero uniformemente aleatorio", por lo que, estrictamente hablando, esto no es válido
njzk2

3
Estrictamente hablando, todos los idiomas aquí usan prng's. Ninguno de ellos dará un verdadero número aleatorio uniforme (que requeriría una fuente perfecta de entropía). Si bien muchos son más uniformes que esto, eso no se nota en las iteraciones log (k).
LambdaBeta

10

R , 66 60 56 43 41 bytes

function(n)while(print(n))n=sample(n,1)-1

Pruébalo en línea!


No creo que necesites >0y cat(n,"")(cadena vacía) también funcionará.
Giuseppe

Pero creo que printes más eficiente aquí, ya que devuelve su argumento: 56 bytes
Giuseppe

También 56 bytes:k=scan();while(x<-sample(1:k-1,1))k=c(x,k);cat(rev(k),0)
JAD

1
Olvidé quitar los corchetes, para que pueda guardar 2 bytes más;) ¡ Pruébelo en línea!
digEmAll

2
39 bytes:n=scan();while(print(n))n=sample(n,1)-1
djhurio

6

MATL , 6 bytes

`tYrqt

Pruébalo en línea!

Explicación

`        % Do...while
  t      %   Duplicate. Takes input (implicit) the first time
  Yr     %   Uniform random integer from 1 to n, included
  q      %   Subtract 1
  t      %   Duplicate. This will be used as loop condition
         % End (implicit). Proceeds with next iteration if non-zero
         % Display stack (implicit)

6

Pepe , 25 bytes

Pepe es un lenguaje de programación creado por el usuario Soaku .

REeErEErReEEreeEREEeEEree 

Pruébalo en línea!

Explicación:

REeErEErReEEreeEREEeEEree # full program

REeE                      # input as num, in stack 1
    rEE                   # create loop in stack 2 with name 0
       rReEE              # - output and preserve the number in stack 1
            reeE          # - output a newline "\n"
                REEeEE    # - random number by 0 to input
                      ree # goto loop with name 0 if stack 1 is not equal
                            to stack 2

5

Perl 6 , 18 bytes

{$_,(^*).pick...0}

Pruébalo en línea!

Bloque de código anónimo que devuelve una lista de valores. Si no le importa que los números sean rangos, puede hacer:

{^$_,^*.pick...0}

por 17 bytes. Curiosamente, otra función aleatoria incorporada roll, tiene el mismo comportamiento en esta instancia para la misma cantidad de bytes.



5

Gelatina ,  4  3 bytes

XƬ0

Este es un enlace monádico (función) que imprime una matriz y devuelve 0 .

Pruébalo en línea!

Cómo funciona

XƬ0  Monadic link. Argument: n

XƬ   Pseudo-randomly pick (X) an integer k in [1, ..., n], set n = k, and repeat.
     Do this 'til (Ƭ) the results are no longer unique and return the array of
     unique results, including the initial value of n.
     This stops once X returns k with argument k. The second k will be omitted
     from the return value.
  0  Print the resulting array and set the return value to 0.

¡Muy buen tachado de los 4!
ngm

1
No nos gustaría tachar 4 para que parezca 4 normal, ¿verdad?
Dennis

4

Brachylog , 8 bytes

ẉ?ℕ₁-₁ṙ↰

Pruébalo en línea!

Explicación

ẉ          Write the input followed by a linebreak
 ?ℕ₁       The input must be in [1, …, +∞)
    -₁ṙ    Generate an integer in [0, …, input - 1] uniformly at random
       ↰   Recursive call with that random integer as the new input

La recursión se detendrá una vez que ?ℕ₁falle, es decir, cuando la entrada sea 0.


4

05AB1E , 8 7 bytes

Δ=L<Ω0M

Pruébalo en línea!

Explicación

Δ         # loop until value doesn't change
 =        # print current value
  L<Ω     # push a random number in ([1 ... X] - 1)
          # will return -1 when X=0
     0M   # push max of that and 0

1
Δ=ݨΩ0Mes equivalente.
Magic Octopus Urn

4

J, 13 bytes

[:}:? ::]^:a:

En el metro, disculpas por falta de TIO (espero que no haya falta de corrección).

Emite una lista de valores.

Presumiblemente, el enfoque APL será más corto, pero esto es lo que pensé.

Cómo funciona

^:a: aplicar repetidamente hasta la convergencia, almacenando resultados intermedios en una matriz.

?entero aleatorio en el rango [0, K)de Kmayor que 0. Para 0, da un entero aleatorio en el rango (0,1). Para un número de coma flotante, errores.

::]detectar un error para una entrada ?y, en lugar de generar un error , generar la entrada que causó el error.

}: deshacerse del último valor en la matriz (esto es para que no se genere un número de coma flotante).

Pruébalo en línea!


¿Soy solo yo o el código devuelve la misma salida?
Luis felipe De jesus Munoz

@LuisfelipeDejesusMunoz alguien que conoce a J mejor de lo que podría explicar, pero creo que RNG siempre comienza con la misma semilla. También está la semilla fija ?., pero no creo que esté usando eso.
cole

@cole tienes razón.
Jonás

4

JavaScript (ES6), 38 37 bytes

-1 byte gracias a @Arnauld

f=n=>[n,...n?f(Math.random()*n|0):[]]


¿Puedes reducir las matemáticas al azar? por ejemplo, con codegolf.stackexchange.com/a/35648/67066
Marie

1
El uso de @Marie new Date%nrealmente no funciona aquí, ya que no cambia lo suficientemente rápido como para ser útil para generar múltiples números aleatorios
Herman L

4

C, 38 bytes

f(k){printf("%d ",k);k?f(rand()%k):0;}

Pruébalo en línea

Sin golf

void f(int k){
    printf("%d ",k);
    if(k)
        f(rand()%k);
}

1
Puede guardar un byte reemplazando el operador ternario con a &&; Además, puede considerar sembrar el RNG en su mainfunción: ¡ Pruébelo en línea!
ErikF

1
También puede deshacerse del ternario por completo y terminar en un error. 34 bytes
Jo King

4

Pyth , 4 bytes

W
~O

Pruébalo en línea!

Básicamente, esto implementa el algoritmo:

QentradaRmipagsmiunat1)tmimetropagsQ2)Qunif{0 0,Q-1}3)PAGSryonortet(tmimetropags)Unortetyoltmimetropags=0 0

Para traducir Pyth al algoritmo, podemos examinar principalmente lo que significa cada personaje. Dado que Pyth está escrito en notación de prefijo ( * + 1 2 3es decir, es (1 + 2) * 3), podemos comenzar desde la izquierda y completar los argumentos a medida que avanzamos.

Wcomienza un ciclo while tradicional. La primera declaración después es la condición del bucle y la segunda declaración después es el cuerpo del bucle. Si la segunda declaración está vacía, se convierte en un no-op . Esto funciona exactamente igual que Python while, por lo que evaluará enteros distintos de cero como Verdadero y cero como falso.

La primera declaración después del tiempo comienza con el carácter de nueva línea. Esto corresponde a la función "imprimir y volver con una nueva línea" de Pyth. Esto requiere un argumento, que luego se imprime y también se devuelve sin modificar. Esto nos permite imprimir los pasos intermedios mientras realizamos las operaciones necesarias.

El argumento pasado a esta función de impresión comienza con lo ~que es un poco especial. Si el carácter inmediatamente posterior ~es una variable, toma dos argumentos; de lo contrario, toma uno. Como Ono es una variable ~, solo se consumirá un argumento. ~funciones un poco como +=lo hace en muchos lenguajes convencionales, aunque el operador más cercano sería el operador de incremento ++de C. Puede saber que x++será como usarlo xcomo valor actual, pero a partir de entonces xlo será x+1. ~es la misma idea, pero generalizada a cualquiera que sea el resultado del primer argumento. La forma en que elige a qué variable asignar se abordará más adelante.

El argumento de ~es Oque es muy simple. Cuando su único argumento es un entero, Odevuelve un valor de 0 a uno menos que ese entero de manera uniforme al azar.

Ahora puede haber notado Oque no tiene un argumento. Aquí el intérprete de Pyth rellena amablemente una suposición, que aquí es la variable Q. Qtiene un significado especial en Pyth: cada vez que está presente en un programa, el programa Pyth comienza con la asignación Qa la entrada del programa. Como esta es la primera variable que ocurre en ~el argumento de '', Qahora también es la variable a la que se ~le asignará un valor.

En resumen, nuestro programa "legible" podría verse así:

while print_and_return( assign_variable( Q, unif(0, Q-1) ) ):
    pass

Y una muestra de "ejecución" podría verse así:

  1. Q = 5
  2. Odevuelve 3, ~devuelve 5,\n devuelve e imprime 5, lo cual es cierto
  3. Q = 3
  4. Odevuelve 0, ~devuelve 3, \ndevuelve e imprime 3, lo cual es cierto
  5. Q = 0
  6. Odevuelve algo irrelevante, ~devuelve 0, \ndevuelve e imprime 0 que es falso
  7. Q = algo irrelevante
  8. Terminar

3

APL (Dyalog Unicode) , 12 9 bytes

Función de prefijo tácito anónimo. Asume ⎕IO( I ndex O rigin) para ser0 , que es predeterminado en muchos sistemas. Devuelve el valor final (0) además de imprimir mientras se ejecuta.

{⌊?⎕←⍵}⍣=

Pruébalo en línea!

{...}⍣=  aplique la siguiente función hasta que sea estable:

⎕←⍵ dar salida al argumento

? devuelve un número aleatorio distribuido uniformemente en el rango de 0 a ese – 1

 redondear hacia abajo (porque ?0da un flotador (0,1))


3

C (gcc) , 40 42 bytes

Some idiot ™ olvidó imprimir primero el valor inicial.

f(K){while(K)printf("%d\n",K,K=rand()%K);}

No entres en pánico.


Usted me ataron, la cuestión también requiere que se imprime el primer K. Sin ella yo también tengo 40. También puede obtener la versión totalmente compatible con 42 de una manera similar: f(K){while(K)printf("%d\n",K),K=rand()%K;}. ¡Aún tienes mi +1 para una solución igual!
LambdaBeta

Aún mejor:f(K){while(K)printf("%d\n",K,K=rand()%K);}
SIGSTACKFAULT

3

x86 + rdrand, 19 bytes

Implementación directa. Toma la entrada K ecxy las salidas a una memoria intermedia ebx.

0000000a <start>:
   a:   0f c7 f0                rdrand %eax
   d:   31 d2                   xor    %edx,%edx
   f:   f7 f1                   div    %ecx
  11:   89 13                   mov    %edx,(%ebx)
  13:   83 c3 04                add    $0x4,%ebx
  16:   89 d1                   mov    %edx,%ecx
  18:   85 c9                   test   %ecx,%ecx
  1a:   75 ee                   jne    a <start>
  1c:   c3                      ret  

3

Python 3 , 39 bytes

f=lambda k:print(k)or f(hash('.'*k)%k)

Probablemente no sea el generador de números aleatorios más seguro criptográficamente, pero para el ojo humano parece lo suficientemente aleatorio ...

Pruébalo en línea!


Notas: 1) la entrada da (generalmente) resultados diferentes cada vez que se ejecuta en un nuevo intérprete, pero puede dar el mismo resultado si se ejecuta dentro de la misma sesión de Python. 2) Supongo que terminar con un error sin verificar explícitamente k=0es aceptable.
Luca Citi

Lo sentimos, pero las funciones deben ser reutilizables arbitrariamente a menudo en el mismo entorno. Sin embargo
Jo King

La tarea requiere un número aleatorio uniforme del rango dado. hash() intenta mantener pero no garantiza esta propiedad. Para esa tarea, debe usar el randommódulo.
David Foerster

Con solo 57 bytes, puede modificar su solución para usar números aleatorios uniformes de random.randrange():from random import*;f=lambda k:print(k)or f(randrange(k))
David Foerster

3

TI-Basic (TI-84 Plus CE), 17 13 bytes

While Ans
Disp Ans
int(randAns
End
Ans

-4 bytes de Misha Lavrov

Toma entrada Anscomo50:prgmNAME .

TI-Basic es un lenguaje tokenizado . Todas las fichas utilizadas aquí son de un byte.

Explicación:

While Ans    # 3 bytes, While the number we hold is not zero:
Disp Ans     # 3 bytes,   Display it on its own line
int(randAns  # 4 bytes,   and replace it with a number randomly
                        # chosen from 0 to one less than it (inclusive)
End          # 2 bytes, end While loop
Ans          # 1 byte,  Display (and return) zero

Una solución de 11 bytes sugerida por Misha Lavrov que requiere presionar enterdespués de cada línea que sigue a la primera.

Ans
While Ans
Pause int(randAns
End

1
int(AnsrandEs más corto. Además, usando en Pauselugar de Disp, puede hacer que la única instrucción en el bucle sea Pause int(Ansrand, que también se actualiza Ans.
Misha Lavrov

3

Python 2 , 64 62 60 bytes

from random import*
k=input()
while k:print k;k=randrange(k)

Pruébalo en línea!


Salvado

  • -2 bytes, gracias a Jonathan Allan

"La entrada debe imprimirse al principio" ... while 1:print k;k=randint(0,~-k)debería funcionar (con un error al final)
Jonathan Allan

... y luego while 1:print k;k=randrange(k)salva dos.
Jonathan Allan

1
@ JonathanAllan Gracias :), las preguntas dicen que puedo usar una línea vacía en lugar de 0, así que no hay error.
TFeld

3

C ++ (gcc), 98 bytes

#import<cstdio>
#import<cstdlib>
#define d printf("%i ",x 
int p(int x){d);while(x>0)d=rand()%x);}

Pruébalo aquí!

Uso

int main() {
    p(100);
}

Este es mi primer intento de código de golf. Cualquier comentario o comentario son bienvenidos.

Editar: se eliminó la función principal como se sugiere para que sea válida.


1
Hola, y bienvenido a PPCG :) No es necesario que incluya la llamada de muestra en su conteo de bytes (es decir, no necesita escribir la función principal) ya que aceptamos funciones como envíos válidos. De lo contrario, su envío no es técnicamente válido ya que si la entrada fuera un número de dos o más dígitos, la salida podría ser ambigua. Si solo agrega un espacio al final de la cadena de formato en su macro, debería estar bien. ¡Feliz golf!
FryAmTheEggman

Agregar el indicador del compilador en -Dd='printf("%i,",x'lugar de #defineahorraría algunos bytes (-4), y se permite siempre que cuente los bytes hacia su resultado (porque es una directiva de preprocesador no estándar. También puede omitir las importaciones (en menos con -std=c++98y -w, que no cuentan para bytes), y los tipos de variables. Entonces, tendría p(x){d);while(x>0)d=rand()%x;}y -Dd='printf("%i,",x'.

Además, probablemente debería consultar los agujeros y consejos estándar para jugar golf en C , si aún no lo ha hecho :)

3

> <>, 92 + 2 bytes

:nao:0=?;0_1>:{:}(?\\
}(?!\$2*1>x~\$+1$*2/\~00:{{:@}
8+1.\~:{:}\+>$1+f
~~@~~47*0.\(a2*1@@?!.

+ 2B para la bandera -v

Pruébalo en línea!

La única fuente de aleatoriedad de> <> proviene de la instrucción 'x', que establece la dirección del puntero de la instrucción en un valor aleatorio. Como tal, generar un número aleatorio de 0 a n no es trivial.

Primero calculo cuántos bits se requieren para representar un número en el rango [0, n), luego genero bits aleatorios para generar un número aleatorio. Esto deja la posibilidad de que genere un número ligeramente mayor que n, en cuyo caso simplemente lo descartamos e intentamos nuevamente.

Explicación:

:nao                              Print the current number followed by a newline
    :0=?;                         If the current n is 0, terminate

Calculate how many random bits we need to be generating:
         0 1                      Initialise the variables for this loop: 
                                      numberOfBits = 0, maxValue = 1
             :{:}(?\              If maxValue >= n, break out of the loop
                 *2               maxValue *= 2
             $+1$                 numberOfBits += 1

Generate the random number:
                     ~            Delete maxValue
                      00          Initialise randomNumber = 0, i = 0
}(?!\                   :{{:@}    If i >= numberOfBits, break out of the (inner) loop
     $2*                          randomNumber *= 2
          _
        1>x~\                     The random bit: If the IP goes up or 
          \+>                     left, it'll be redirected back onto the 'x', 
                                  if it goes down, it adds one to randomNumber
                                  If it goes right, it does nothing to randomNumber

             $1+                  increment i
8+1.            f                 Jump back to the start of the inner loop

After we've generated our number, check that it's actually below n
     ~                            Delete i
      :{:} (      ?               Test that the number is less than n
            a2*1    .             If it's not, jump back to the start 
                                  of the number generation section
  @~~                             Otherwise delete the old value of n, and numberOfBits
     47*0.                        Then jump back to the start of the program

¡Muy agradable! Se me ocurrió la misma idea de forma independiente; sin espacios en blanco, mi solución utiliza varios caracteres menos que los suyos, pero ha logrado crear un bloque de código mucho más compacto.
Théophile

2
El meta consenso actual es que no tiene que contar los bytes utilizados en las banderas
Jo King

3

MATLAB ( 49 46 bytes)

@(k)eval('while k;disp(k);k=randi(k)-1;end;0')

Salida de muestra:

>> @(k)eval('while k;disp(k);k=randi(k)-1;end;0')
ans(5)

ans = 

    @(k)eval('while k;disp(k);k=randi(k)-1;end;0')

     5    
     3    
     2    
     1   

ans =    
     0

1
Supongo que puedes hacerlo k=randi(k)-1por unos pocos bytes menos.
Sanchises

2

Retina , 21 bytes

.+
*
L$`.
$.`
+¶<)G?`

Pruébalo en línea! Explicación:

+

Repita hasta que el valor deje de cambiar (es decir, 0).

¶<)

Imprima el valor antes de cada pasada a través del bucle.

.+
*

Convierte a unario.

L$`.
$.`

Crea el rango y convierte a decimal.

G?`

Elige un elemento aleatorio.


2

Pyth , 6 7 bytes

QWQ=OQQ

Pruébalo en línea!

+1 para imprimir el valor de entrada inicial.

Si bien Q es verdadero, configure Q para que sea un entero aleatorio entre 0 y Q e imprima Q.

No es la respuesta más corta de Pyth, pero solo estoy aprendiendo y solo publicando debido a la reciente discusión sobre que ya nadie usa Pyth :)


2
Logré vincular usando la reducción acumulativa pero manteniéndolo como un programa de procedimiento. Gracias por la motivación para trabajar en un golf :)
FryAmTheEggman

Eso es genial. Todavía estoy tratando de averiguar cómo (por qué) funciona.
ElPedro

Por defecto, =y ~utilizar la primera variable de una expresión como la variable que se asignará si no se especifica. Por ejemplo, ~hTse establecerá Ten 11 mientras devuelve 10. El único otro truco elegante es que el carácter de nueva línea imprime su entrada y luego devuelve ese valor sin modificar, para que podamos tener un cuerpo de bucle vacío. Avísame si hay algo más confuso :)
FryAmTheEggman

1
@FryAmTheEggman Eso es hermoso.
isaacg

1
@isaacg ¡Gracias! Originalmente quise editarlo aquí, pero decidí escribir algo porque quería probar MathJax. Este tipo de respuestas de Pyth siempre fueron mis favoritas, ya que se sienten intencionales pero también abusivas :)
FryAmTheEggman


2

Fórmula IBM / Lotus Notes, 48 ​​bytes

o:=i;@While(i>0;i:=@Integer(i*@Random);o:=o:i);o

Fórmula de campo que toma datos de otro campo i.

No hay TIO para la fórmula, así que aquí hay una captura de pantalla de una salida de muestra:

ingrese la descripción de la imagen aquí



2

PowerShell , 35 bytes

for($a="$args";$a;$a=Random $a){$a}

Pruébalo en línea!

Programa completo Toma datos $args, los almacena $ay entra en un forbucle. Cada iteración que estamos verificando si $asigue siendo positiva (como lo 0es falsey en PowerShell). Luego lo dejamos $aen la tubería y pasamos a la siguiente iteración, donde establecemos $ael resultado Get-Random $a, que devuelve un número entero en el rango0..($a-1) .

(Ab) utiliza el hecho de que PowerShell genera una nueva línea final adicional en lugar de generar el cero final (permitido por las reglas tal como están escritas actualmente).


"$args"- bonito. Estaba atrapado $args[0]en este caso
mazzy

2

Lua , 58 bytes

p,r=print,...+0 p(r)while r>0 do r=math.random(0,r)p(r)end

Pruébalo en línea!

Para más amor Lua aquí :)


Oye, puedes eliminar el +0 en la rdeclaración y moverlo a la rinstrucción while, al hacerlo, usarás 1 byte menos para el espacio ( p,r=print,...p(r)while).
Visckmart
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.