Simulando dados explosivos

31

Su tarea es hacer un programa que tome un número entero n > 1y ngenere el resultado de un dado de un solo lado. Sin embargo, este dado sigue las reglas para explotar dados .

Cuando tires el dado, verifica qué valor arrojaste. Si obtuviste el máximo para ese tipo de dado (en un d4 estándar que sería 4, o 6 en un d6, etc.), lanza nuevamente y agrega el nuevo lanzamiento a ese total. Cada lanzamiento continúa sumando al total, hasta que ya no obtengas el número máximo. Sin embargo, ese número final todavía se agrega.

Su programa debe tener un solo número entero ny tirar el ndado que explota. Aquí hay una distribución de ejemplo para mostrar cómo debería ser n=4. Tenga en cuenta que nunca debe generar ningún múltiplo de n, ya que siempre explotarán.

Puede suponer que el tamaño de la pila para cualquier recursividad que haga es infinito, y su función aleatoria debe cumplir con nuestros estándares de aleatoriedad (generador aleatorio incorporado o hora / fecha ). Su función aleatoria también debe ser lo más uniforme posible, en comparación con una distribución geométrica, ya que estamos hablando de dados.

Rɪᴋᴇʀ
fuente
1
¿El programa tiene que ser perfecto? ¿Cómo puede su distribución estar apagada en una cantidad extremadamente baja?
Maltysen
Para: Riker; RE: comentario de @ Maltysen arriba; o cantidad extremadamente alta?
Artemisa apoya a Mónica el
2
@ArtemisFowl Vea nuestros estándares de aleatoriedad. Además, aquí .
Rɪᴋᴇʀ

Respuestas:

36

Código de máquina x86 (para Intel Ivy Bridge y posterior), 17 bytes

31 C9 0F C7 F0 31 D2 F7 F6 42 01 D1 39 F2 74 F2 C3

Los bytes de código anteriores definen una función que simula un dado explosivo. Se necesita una sola entrada, pasada en el ESIregistro, que indica el número máximo de dados. Devuelve un solo valor en el ECXregistro, que es el resultado de los rollos.

Internamente, utiliza la RDRANDinstrucción para generar un número aleatorio. Utiliza un generador de números aleatorios (RNG) integrado en el hardware de los procesadores Intel Ivy Bridge y posteriores (algunas CPU AMD también admiten esta instrucción).

La lógica de la función es bastante sencilla. El número aleatorio generado se escala para ubicarse dentro del rango deseado utilizando la técnica estándar ( (rand % dieSize) + 1), y luego se verifica para ver si debería causar una explosión. El resultado final se mantiene en un registro acumulador.

Aquí hay una versión anotada que muestra la mnemotecnia en lenguaje ensamblador:

           unsigned int RollExplodingDie(unsigned int dieSize)
31 C9        xor     ecx, ecx    ; zero-out ECX, which accumulates the final result
           Roll:
0F C7 F0     rdrand  eax         ; generate a random number in EAX
31 D2        xor     edx, edx    ; zero-out EDX (in preparation for unsigned division)
F7 F6        div     esi         ; divide EDX:EAX by ESI (the die size)
                                 ;   EAX receives the quotient; EDX receives the remainder
42           inc     edx         ; increment the remainder
01 D1        add     ecx, edx    ; add this roll result to the accumulator
39 F2        cmp     edx, esi    ; see if this roll result should cause an explosion
74 F2        jz      Roll        ; if so, re-roll; otherwise, fall through
C3           ret                 ; return, with result in ECX register

Estoy haciendo trampa un poco . Todas las convenciones de llamadas estándar x86 devuelven el resultado de una función en el EAXregistro. Pero, en el verdadero código de máquina, no hay convenciones de llamadas. Puede usar cualquier registro que desee para entrada / salida. El uso ECXpara el registro de salida me ahorró 1 byte. Si desea usar EAX, inserte una XCHG eax, ecxinstrucción de 1 byte inmediatamente antes de la retinstrucción. Esto intercambia los valores de los registros EAXy ECX, copiando efectivamente el resultado de ECXen EAX, y desechando ECXcon el valor anterior de EAX.

Pruébalo en línea!

Aquí está la función equivalente transcrita en C, usando el __builtin_ia32_rdrand32_stepintrínseco soportado por GCC, Clang e ICC para generar la RDRANDinstrucción:

#include <immintrin.h>

unsigned int RollExplodingDie(unsigned int dieSize)
{
    unsigned int result = 0;
Roll:
    unsigned int roll;
    __builtin_ia32_rdrand32_step(&roll);
    roll    = ((roll % dieSize) + 1);
    result += roll;
    if (roll == dieSize)   goto Roll;
    return result;
}

Curiosamente, GCC con la -Osbandera transforma esto en casi exactamente el mismo código de máquina . Toma la entrada en EDIlugar de ESI, lo cual es completamente arbitrario y no cambia nada sustancial sobre el código. Debe devolver el resultado EAX, como mencioné anteriormente, y utiliza la MOVinstrucción más eficiente (pero más grande) para hacer esto inmediatamente antes del RET. De lo contrario, samezies. Siempre es divertido cuando el proceso es completamente reversible: ¡escriba el código en ensamblado, transcríbalo a C, ejecútelo a través de un compilador de C y recupere su ensamblaje original!

Cody Gray
fuente
12

Python 2 , 66 64 61 bytes

-3 bytes gracias a xnor

f=lambda n,c=0:c%n or c+f(n,randint(1,n))
from random import*

Pruébalo en línea!

El rollo anterior se almacena c, lo que nos permite acceder a él varias veces sin tener que almacenarlo en una variable, que no se puede hacer en una Python lambda. En cada recursión, verificamos si lanzamos dados explosivos.

cse inicializa a cero, por c%nlo que falsey está allí. En las próximas iteraciones, solo será falsey si se tiraron los dados explosivos.

Python 2 , 55 bytes

f=lambda n:randint(1,n)%n or n+f(n)
from random import*

Pruébalo en línea!

Mi otra respuesta parece estar un poco sobredimensionada, ya que esto parece funcionar también ... Lo dejaré de todos modos.

ArBo
fuente
2
Las funciones recursivas donde la condición de ruptura se basa en la aleatoriedad siempre tendrán una probabilidad distinta de cero de desbordamiento de pila. Probabilidad estadísticamente insignificante, pero aún así ...
mypetlion
3
Por lo general, se supone que el tamaño de la pila es infinito en los desafíos de golf de código en mi experiencia. A medida que el tamaño de la pila aumenta hasta el infinito, la probabilidad de desbordamiento de la pila converge rápidamente a cero.
ArBo
ArBo do @mypetlion antes de escribir su comentario para poder hacer ping al usuario
MilkyWay90
1
Creo que c*(c<n)puede ser c%n.
xnor
@xnor Por supuesto, soy un idiota ...
ArBo
12

R , 39 bytes

n=scan();n*rgeom(1,1-1/n)+sample(n-1,1)

Pruébalo en línea!

Explicación: esta solución evita los bucles recursivos / while calculando directamente la distribución del número de explosiones que ocurrirán. Sea norte el número de lados en el dado. Si Usted indica que el éxito como rodar una norte y el fracaso como rodar cualquier otra cosa, entonces usted tiene probabilidad 1norte de éxito. El número total de explosiones es el número de éxitos antes del primer fracaso. Esto corresponde a unsolmiometromitryodo(1-1norte)distribución (consulte lapágina de wikipedia, que define el éxito y el fracaso al revés). Cada explosión traenorteal total. La tirada final sigue unadistribuciónUnorteyoFormetro(1,2,...,norte-1)que sumamos al total.

Robin Ryder
fuente
¡muy agradable! ¡Tengo que amar las distribuciones incorporadas para desafíos aleatorios !
Giuseppe
¿Cumple samplecon los estándares de aleatoriedad, dado su sesgo ?
Xi'an
@ Xi'an Estoy bastante seguro de que sí : es el generador aleatorio incorporado para variables aleatorias discretas.
Robin Ryder
Lo sé, lo sé, pero revise el enlace que puse: la discretización inherente a esto sampleconduce a una falta de uniformidad que da una relación de probabilidad máxima a mínima tan alta como 1.03 ... ¡Sorprendente, no es así!
Xi'an
Si, es impactante. Pero, de nuevo, ¿con qué frecuencia utiliza samplecon ? ;-)metro231
Robin Ryder
9

Perl 6 , 26 bytes

{sum {roll 1..$_:}...*-$_}

Pruébalo en línea!

Explicación

{                        } # Anonymous block
                  ...      # Sequence constructor
     {roll 1..$_:}         #   Next elem is random int between 1 and n
                           #   (Called as 0-ary function with the original
                           #   $_ for the 1st elem, then as 1-ary function
                           #   with $_ set to the previous elem which
                           #   equals n.)
                     *-$_  #   Until elem not equal to n (non-zero difference)
 sum                       # Sum all elements
nwellnhof
fuente
2
Agradable, mi propia solución fue{sum roll(*,1..$_)...$_>*}
Jo King
9

J , 16 11 bytes

(+$:)^:=1+?

Pruébalo en línea!

Explicación

TL; DR 1+? realiza el lanzamiento del dado, (+$:)^:=reitera solo cuando es igual a la entrada.


La función es un tren de 4 verbos:

             ┌─ + 
         ┌───┴─ $:
  ┌─ ^: ─┴─ =     
  │               
──┤      ┌─ 1     
  └──────┼─ +     
         └─ ?     

Un tren es cuando 2 o más verbos se concatenan. Aquí, la respuesta es de la forma f g h j:

(+$:)^:=  1  +  ?
    f     g  h  j

Un llamado "tren 4" se analiza como un gancho y un tenedor:

f g h j   ⇔   f (g h j)

Por lo tanto, la respuesta es equivalente a:

(+$:)^:= (1 + ?)

Ganchos: (f g) xyx (f g) y

Un gancho monádico (un argumento) de dos verbos, dado un argumento x, se cumple la siguiente equivalencia:

(f g) x   ⇔   x f (g x)

Por ejemplo, (* -) 5evalúa a 5 * (- 5), que evalúa a _25.

Esto significa que nuestro 4-tren, un gancho de fy (g h j), es equivalente a:

(f (g h j)) x   ⇔   x f ((g h j) x)

¿Pero qué hace faquí? (+$:)^:=es una conjunción de dos verbos que usan la conjunción Power^: : otro hook ( (+$:)) y un verbo ( =). Tenga en cuenta que esto fes diádico: tiene dos argumentos ( xy (g h j) x). Entonces tenemos que ver cómo se ^:comporta. La conjunción de poder f^:otoma un verbo fy un verbo o un sustantivo o(un sustantivo es solo un dato) y aplica f otiempos. Por ejemplo, toma o = 3. Se cumplen las siguientes equivalencias:

(f^:3) x     ⇔   f (f (f x))
x (f^:3) y   ⇔   x f (x f (x f y))

Si oes un verbo, la conjunción de potencia simplemente evaluará olos argumentos y usará el resultado del sustantivo como recuento repetido.

Para nuestro verbo, oes =, el verbo de igualdad. Se evalúa 0para diferentes argumentos y 1para argumentos iguales. Repetimos el gancho (+$:)una vez para argumentos iguales y no para los diferentes. Para facilitar la notación de la explicación, dejemos y ⇔ ((g h j) x). Recuerde que nuestro gancho inicial es equivalente a esto:

x   (+$:)^:=   ((g h j) x)
x   (+$:)^:=   y

Expandiendo la conjunción, esto se convierte en:

x ((+$:)^:(x = y)) y

Si xy yson lo mismo, esto se convierte en:

x (+$:)^:1 y   ⇔   x (+$:) y

De lo contrario, esto se convierte en:

x (+$:)^:0 y   ⇔   y

Ahora, hemos visto tenedores monádicos. Aquí tenemos un tenedor diádico:

x (f g) y   ⇔   x f (g y)

Entonces, cuando xy yson lo mismo, obtenemos:

x (+$:) y   ⇔   x + ($: y)

¿Qué es $:? Se refiere al verbo completo y permite la recursividad. Esto significa que, cuando xy y are the same, we apply the verb toy and addx`.

Tenedores: (g h j) x

Ahora, ¿qué hace la horquilla interna? Esto fue yen nuestro último ejemplo. Para una bifurcación monádica de tres verbos, dado un argumento x, se cumple la siguiente equivalencia:

(g h j) x   ⇔   (g x) h (j x)

Para el siguiente ejemplo, supongamos que hemos llamado verbos SUM, DIVIDEy LENGTHque haga lo que supongo que podría hacerlo. Si concatenamos los tres en una bifurcación, obtenemos:

(SUM DIVIDE LENGTH) x   ⇔   (SUM x) DIVIDE (LENGTH x)

Esta bifurcación evalúa el promedio de x(suponiendo que xsea ​​una lista de números). En J, realmente escribiríamos esto como ejemplo como +/ % #.

Una última cosa sobre tenedores. Cuando el "diente" más a la izquierda (en nuestro caso simbólico anterior g) es un sustantivo, se trata como una función constante que devuelve ese valor.

Con todo esto en su lugar, ahora podemos entender el tenedor anterior:

(1 + ?) x   ⇔   (1 x) + (? x)
            ⇔   1 + (? x)

?[0 0,X)[1,X]

Poniendolo todo junto

Dadas todas estas cosas, nuestro verbo es equivalente a:

((+$:)^:=1+?) x   ⇔   ((+$:)^:= 1 + ?) x
                  ⇔   ((+$:)^:= (1 + ?)) x
                  ⇔   x ((+$:)^:=) (1 + ?) x
                  ⇔   x ((+$:)^:=) (1 + (? x))
                  ⇔   x (+$:)^:(x = (1 + (? x))
(let y = 1 + (? x))
if x = y          ⇒   x + $: y
otherwise         ⇒   y

Esto expresa la funcionalidad deseada.

Conor O'Brien
fuente
1
(+$:)^:=1+?­­
NGN
@ngn Gracias! Incorporado.
Conor O'Brien
7

Jalea , 7 bytes

X+ß}¥=¡

Pruébalo en línea!

Utiliza la recursividad. Ejecuta el programa nuevamente ( ß) y agrega ( +) si ( ¡) el número aleatorio ( X) es igual ( =) a la entrada del programa. }hace ßactuar sobre la entrada del programa y se ¥combina +ß}en un solo enlace para ¡consumir.

Aquí una distribución de 1000 salidas para n = 6 que recolecté usando este programa. Trazado con python / matplotlib. histograma

Aquí hay 5000 puntos de datos de n = 3 en un gráfico de semilog que muestra la distribución exponencial (¿aproximadamente?). ingrese la descripción de la imagen aquí

dylnan
fuente
Bonitas parcelas! La distribución que obtienes es una distribución geométrica (ver mi respuesta R ), que está estrechamente relacionada con la distribución exponencial.
Robin Ryder
6

Pyth - 12 11 bytes

Utiliza funcional mientras. Siento que debería haber una respuesta más inteligente que simplemente simule la distribución.

-.W!%HQ+hOQ

-         (Q)         Subtract Q. This is because we start Z at Q to save a char
 .W                   While, functionally
  !                   Logical not. In this case, it checks for 0
   %HQ                Current val mod input
  +     (Z)           Add to current val
   h                  Plus 1
    OQ                Random val in [0, input)

Pruébalo en línea .

Maltysen
fuente
4

Python 3 , 80 bytes

import random as r,math
lambda n:int(-math.log(r.random(),n))*n+r.randint(1,n-1)

Pruébalo en línea!

Lynn
fuente
1
Sin embargo, hay una pequeña posibilidad de fracaso si r.random()devuelve 0. 1-r.random()debería funcionar.
nwellnhof
Aunque técnicamente esa posibilidad es 0
Quintec
1
¡Un caso raro donde import ... as _es más corto!
xnor
@xnor de hecho! La única otra vez que recuerdo que gané en una respuesta mía es aquí
Lynn
4

05AB1E , 10 bytes

[ILΩDIÊ#}O

Pruébelo en línea o verifique las listas .

Alternativa de 10 bytes:

[LΩDˆÊ#}¯O

Pruébelo en línea o verifique las listas .

Aunque me gusta más el primero porque tiene la "palabra" DIÊ, que se adapta al desafío.

Explicación:

[         # Start an infinite loop:
 IL       #  Create a list in the range [1, input]
   Ω      #  Pop and push a random value from this list
    D     #  Duplicate it
     IÊ   #  If it's NOT equal to the input:
       #  #   Stop the infinite loop
}O        # After the loop: sum all values on the stack
          # (which is output implicitly as result)

[         # Start an infinite loop
 L        #  Create a list in the range [1, (implicit) input]
  Ω       #  Pop and push a random value from this list
   Dˆ     #  Add a copy to the global_array
     Ê    #  If it's NOT equal to the (implicit) input:
      #   #   Stop the infinite loop
        # After the loop: push the global_array
  O       # Pop and push its sum
          # (which is output implicitly as result)  
Kevin Cruijssen
fuente
Estaba tratando de pensar en una forma de usar o algo.
Urna mágica de pulpo
3

R , 47 42 bytes

function(n){while(!F%%n)F=F+sample(n,1)
F}

Pruébalo en línea!

Crédito al enfoque de ArBo .

Aún un byte más largo que el de Robin Ryder , ¡vota el suyo!

Giuseppe
fuente
Interesante, volví a trabajar esto de forma recursiva ifpara 46 bytes, pero terminé obteniendo un 52 en un rollo que no debería ser posible con n = 4, por lo que no sé si está sucediendo algo extraño de límite de recursión baja, pero yo creo que puede tener errores. Pruébalo en línea!
CriminallyVulgar
Intenté un recursivo y obtuve una solución de 54 bytes. Luego probé algo similar al tuyo por 44 ¡ Pruébalo en línea!
Aaron Hayman
3

Haskell , 77 76 bytes

import System.Random
f x=randomRIO(1,x)>>=(x!)
x!y|y<x=pure y|0<1=(y+)<$>f x

Pruébalo en línea!

Gracias a killmous por un byte.

Si <|>estuviéramos en el preludio, podríamos mejorar con MonadComprehensions:

Haskell , no competidor, 66 bytes

import System.Random
f x=do y<-randomRIO(1,x);[y|y<x]<|>(y+)<$>f x

Pruébalo en línea!

dfeuer
fuente
1
Puede guardar un byte si define g como una función infija.
killmous
1
@killmous, gracias. A primera vista, pensé que sería igual o peor, pero es mejor.
dfeuer
3

Python 2 , 53 bytes

f=lambda n:random()*n//1or n+f(n)
from random import*

Pruébalo en línea!

Utiliza la oridea de cortocircuito de la respuesta de ArBo . La expresión random()*n//1genera un número desde 0hasta n-1, 0tomando el lugar de un rollo de n. El ortoma el número que, excepto si se trata de cero (Falsey-) que sigue a n+f(n).

xnor
fuente
Parece que tu respuesta ya estaba arriba cuando edité en mi versión más corta ... No vi esto, pero si quieres que lo elimine porque es bastante parecido, lo haré.
ArBo
3

Japt , 13 bytes

ö)g@¶°X?X+ß:X

Intentalo

La respuesta del puerto de Arnauld . Descubrí cómo hacer una llamada recursiva;)

JS transpuesto:

// U: Implicit input
// ö: generate a random number [0,U)
(U.ö())
  // g: run the result through a function
  .g(function(X, Y, Z) {
    // increment the result and compare to input
    return U === (++X)
      // if they are the same, roll again and add to current roll
      ? (X + rp())
      // if they are different, use current roll
      : X
   })
dana
fuente
1
Muy buen uso de N.g(f):)
Shaggy
Tomé una puñalada en este meself y terminé con 12 bytes, pero no quiero publicarlo porque me gusta mucho tu solución.
Shaggy
Publíquelo como una respuesta diferente :)
dana
Puede ser más corto, pero es mucho más feo que el tuyo: petershaggynoble.github.io/Japt-Interpreter/…
Shaggy
Ya veo, sí, estaba tratando de encontrar una manera de no contaminar U. Saltar una línea parece funcionar también. Ese es un buen truco :)
dana
3

Japt , 12 bytes

Puede ser más corto que la solución de dana, pero es mucho más feo. Solo lo estoy publicando porque parece una eternidad ya que teníamos una solución Japt que comenzó con una línea vacía.


ö
>°V©VªV+ß

Intentalo

Lanudo
fuente
2

PowerShell , 49 bytes

for($a=$l="$args";$a-eq$l){$o+=$l=1..$a|Random}$o

Pruébalo en línea!

Método iterativo Ajusta la entrada $argsa $ay el $lrodillo ast (hecho hasta entrar en el bucle al menos una vez). Luego, mientras el último lanzamiento sea -equal a la entrada, seguimos rodando. Dentro del bucle, acumulamos en $oel último rollo, que se actualiza creando un rango de 1entrada $ay seleccionando un Randomelemento del mismo. (Honestamente, estoy un poco sorprendido de que $o+=$l=funcione). Una vez que estamos fuera del ciclo, nos vamos $oa la tubería y la salida es implícita.

AdmBorkBork
fuente
2

Adelante (gforth) , 72 bytes

include random.fs
: f >r 0 begin i random 1+ >r i + r> i < until rdrop ;

Pruébalo en línea!

Explicación del Código

include random.fs      \ include library file for random
: f                    \ start a new word definition
  >r                   \ stick the input on the return stack (for easy access)
  0                    \ add a counter to hold the sum
  begin                \ start an indefinite loop
    i random 1+        \ generate a random number from 1 to n
    >r i + r>          \ add the result to the counter, use the return stack to save a few bytes
    i <                \ check if result was less than n
  until                \ end the loop if it was, otherwise go back to begin
  rdrop                \ remove n from the return stack
;                      \ end the word definition
reffu
fuente
2

Lote, 70 bytes.

@set t=0
:g
@set/at+=d=%random%%%%1+1
@if %d%==%1 goto g
@echo %t%

Toma la entrada ncomo un parámetro de línea de comando %1. des el rollo actual, tel total acumulado. Simplemente sigue rodando hasta dque no sea igual a n.

Neil
fuente
2

Jalea , 9 bytes

x⁹X€Ä%ƇµḢ

Pruébalo en línea!

2256

Una alternativa que no tiene esta limitación es:

Jalea , 10 bytes

X³X¤+¥³ḍ¥¿

Pruébalo en línea!

Tenga en cuenta que ambos enlaces TIO generan 400 números para mostrar la distribución.

Nick Kennedy
fuente
2

Python 3 , 81 72 bytes

from random import*
def f(x,a=0):
 while a%x<1:a+=randint(1,x)
 return a

Pruébalo en línea!

-9 bytes gracias a ArBo

Explicación

import random             #load the random module              
def explodeDice(num):     #main function
    ans = 0                     #set answer to 0
    while a % num != 0:         #while a isn't a multiple of the input
        ans += random.randint(1, num) #add the next dice roll to answer
    return ans                  #return the answer
Artemisa apoya a Mónica
fuente
Puede guardar 1 byte usando en su from random import*lugar.
orthoplex
1
Puede reducir esto a 74 bytes con esta solución recursiva
reinstale Monica el
1
@squid Puede guardar 1 byte como este .
orthoplex
1
@orthoplex y luego puedes acortar el if / else, y hacerlo de una sola línea . Comienza a parecerse a mi solución entonces;)
ArBo
1
@ArBo Sí, por eso no cambié a recursivo, no quería simplemente copiarte.
Artemisa apoya a Mónica el
2

TI-BASIC, 28 23 bytes

-5 bytes gracias a esta meta publicación!

Ans→N:0:Repeat fPart(Ans/N:Ans+randInt(1,N:End:Ans

La entrada está adentro Ans.
La salida está en Ansy se imprime implícitamente.

Ejemplos:

4
              4
prgmCDGF11
              5
6
              6
prgmCDGF11
              3

Explicación:

Ans→N:0:Repeat fPart(Ans/N:Ans+randInt(1,N:End:Ans   ;full logic

Ans→N                                                ;store the input in "N"
      0                                              ;leave 0 in "Ans"
        Repeat fPart(Ans/N                 End       ;loop until the sum
                                                     ; is not a multiple of
                                                     ; the input
                               randInt(1,N           ;generate a random
                                                     ; integer in [1,N]
                           Ans+                      ;then add it to "Ans"
                                               Ans   ;leave the sum in "Ans"
                                                     ;implicitly print "Ans"

Notas:

  • TI-BASIC es un lenguaje tokenizado. El recuento de caracteres no es igual al recuento de bytes.
Tau
fuente
Como startTmrya no es necesario, este envío ahora funcionará para versiones de TI-BASIC anteriores a la TI-84 +
Tau
2

SmileBASIC 3, 49 bytes

La función D N OUT Rimplementa tiradas de dados explosivas de forma recursiva.

DEF D N OUT R
R=RND(N)+1IF R==N THEN R=R+D(N)
END

Sin golf

DEF D N OUT R  'N is sides and R is output param (shorter than using RETURN in this case)
 R=RND(N)+1  'random number in [1, N]
 IF R==N THEN R=R+D(N)  'if roll is same as N then roll again and add
END

Tenga en cuenta que en SmileBASIC, las funciones pueden tener múltiples valores de retorno. Si una función tiene un valor de retorno, entonces fun in OUT varyvar = fun(in) son exactamente iguales, es por eso que podemos definir la función en OUTforma y también llamarla en una expresión en el cuerpo de la función. Si hubiera definido la función como DEF D(N)tendría que declarar explícitamente RETURN Ren el cuerpo de la función; mezclar ambas sintaxis me ahorró bytes.

caracol_
fuente
2

Jalea , 7 bytes

X=п⁸S_

Un enlace monádico que acepta un número entero n, que produce un número entero.

105

¿Cómo?

X=п⁸S_ - Link: integer, n
  п    - Collect up while...
 =  ⁸   - ...condition: equal to chain's left argument, n
X       - ...next value: random number in [1..n]
     S  - sum
      _ - subtract n (since the collection starts with [n])
Jonathan Allan
fuente
2

SmileBASIC, 41 bytes

INPUT N@L
S=S+RND(N)+1ON S MOD N GOTO@L?S

Despues de leer:

Tenga en cuenta que nunca debe generar múltiplos de n, ya que siempre explotarán.

Me di cuenta de que, en lugar de verificar si era una tirada de dados n, puedes repetir mientras la suma es un múltiplo de n.

12Me21
fuente
2

AnyDice , 36 bytes

Casi incorporado en el idioma:

function:f I:n{result: [explode dI]}

Para que esto sea correcto, tengo que abusar del supuesto de profundidad de recursión infinita. AnyDice limita la profundidad de recursión con una profundidad de función máxima de propiedad global. el estallido incorporado, sin embargo, usa el suyo propio; profundidad de explosión, que por defecto es 2.

set "explode depth" to 99

Agregaría otros 25 bytes; y realmente no cumpliría con los requisitos ya que es teóricamente posible que un dado explote más de 99 veces.

La salida de la función es un dado, es decir. un tipo incorporado de AnyDice que es una combinación de resultados y probabilidades para el resultado.

Taemyr
fuente
1
Creo que estoy de acuerdo con que no explote mucho, el de 36 bytes está bien para mí. No dije que no hubiera incorporado y estoy de acuerdo con tenerlos aquí, ya que no es como si tu respuesta de 1 o 0 bytes estuviera ganando. Pero bienvenido al sitio!
Rɪᴋᴇʀ
2

CJam , 19 bytes

qi{__mr)_T+:T;=}g;T

Explicación:

T is pre-set to 0

qi{__mr)_T+:T;=}g;T - whole code
qi                  - read input as integer (n) | Stack: n
  {            }    - block
   __               - Duplicate twice | Stack: n n n
     mr)            - Choose a random number from 1 to n (r). Since 'mr' picks a
                      number from 0 to n-1, the number has to be incremented with ')' 
                      Stack: n n r
        _           - Duplicate |  Stack: n n r r
         T          - push T | Stack: n n r r T
          +         - add the random number to T (t) | Stack: n n r t
           :T;      - pop the value and store in T | Stack: n n r
              =     - are the top two stack values the same (c) | Stack: n c
               }
                g   - do while loop that pops the condition from the stack after each
                      iteration | Stack: n
                 ;  - pop the top stack element and discard | Stack: T
                  T - push T | Stack: T
                    - implicit output

O en seudocódigo:

input n
var sum = 0
do {
    var random_number = pick random number from 1 to n
    sum = sum + random_number
} while (random_number == n)
output n

Como un diagrama de flujo:

Diagrama de flujo de código

Pruébalo en línea!

lolad
fuente
2

Excel VBA, 46 bytes

Gracias a @TaylorScott

Do:v=-Int(-[A1]*Rnd):t=t+v:Loop While[A1]=v:?t

Ejecutado en la ventana de comandos.

Como una función definida por el usuario.

Excel VBA, 108 67 bytes

Function z(i)
Do
v=Int((i*Rnd)+1)
z=z+v
Loop While v=i
End Function
william porter
fuente
Puede bajar esto bastante usando un bucle do.. loop whiley convirtiendo la función en una función de ventana inmediata. - Do:v=-Int(-[A1]*Rnd):t=t+v:Loop While[A1]=v:?t- 46 Bytes
Taylor Scott
1
@TaylorScott Gracias, olvidé que Do x Mientras y existía en Excel VBA.
William Porter