Su tarea es hacer un programa que tome un número entero n > 1
y n
genere 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 n
y tirar el n
dado 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.
Respuestas:
Código de máquina x86 (para Intel Ivy Bridge y posterior), 17 bytes
Los bytes de código anteriores definen una función que simula un dado explosivo. Se necesita una sola entrada, pasada en el
ESI
registro, que indica el número máximo de dados. Devuelve un solo valor en elECX
registro, que es el resultado de los rollos.Internamente, utiliza la
RDRAND
instrucció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:
Estoy haciendo trampa un poco . Todas las convenciones de llamadas estándar x86 devuelven el resultado de una función en el
EAX
registro. Pero, en el verdadero código de máquina, no hay convenciones de llamadas. Puede usar cualquier registro que desee para entrada / salida. El usoECX
para el registro de salida me ahorró 1 byte. Si desea usarEAX
, inserte unaXCHG eax, ecx
instrucción de 1 byte inmediatamente antes de laret
instrucción. Esto intercambia los valores de los registrosEAX
yECX
, copiando efectivamente el resultado deECX
enEAX
, y desechandoECX
con el valor anterior deEAX
.Pruébalo en línea!
Aquí está la función equivalente transcrita en C, usando el
__builtin_ia32_rdrand32_step
intrínseco soportado por GCC, Clang e ICC para generar laRDRAND
instrucción:Curiosamente, GCC con la
-Os
bandera transforma esto en casi exactamente el mismo código de máquina . Toma la entrada enEDI
lugar deESI
, lo cual es completamente arbitrario y no cambia nada sustancial sobre el código. Debe devolver el resultadoEAX
, como mencioné anteriormente, y utiliza laMOV
instrucción más eficiente (pero más grande) para hacer esto inmediatamente antes delRET
. 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!fuente
Python 2 ,
666461 bytes-3 bytes gracias a xnor
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.c
se inicializa a cero, porc%n
lo que falsey está allí. En las próximas iteraciones, solo será falsey si se tiraron los dados explosivos.Python 2 , 55 bytes
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.
fuente
c*(c<n)
puede serc%n
.R , 39 bytes
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. Seanorte 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 unG e o m e t r i c ( 1 - 1norte) distribución (consulte lapágina de wikipedia, que define el éxito y el fracaso al revés). Cada explosión traenorte al total. La tirada final sigue unadistribuciónU n i fo r m (1,2,…,n-1) que sumamos al total.
fuente
sample
con los estándares de aleatoriedad, dado su sesgo ?sample
conduce 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í!sample
con ? ;-)Perl 6 , 26 bytes
Pruébalo en línea!
Explicación
fuente
{sum roll(*,1..$_)...$_>*}
J ,
1611 bytesPrué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:
Un tren es cuando 2 o más verbos se concatenan. Aquí, la respuesta es de la forma
f g h j
:Un llamado "tren 4" se analiza como un gancho y un tenedor:
Por lo tanto, la respuesta es equivalente a:
Ganchos:
(f g) x
yx (f g) y
Un gancho monádico (un argumento) de dos verbos, dado un argumento
x
, se cumple la siguiente equivalencia:Por ejemplo,
(* -) 5
evalúa a5 * (- 5)
, que evalúa a_25
.Esto significa que nuestro 4-tren, un gancho de
f
y(g h j)
, es equivalente a:¿Pero qué hace
f
aquí?(+$:)^:=
es una conjunción de dos verbos que usan la conjunción Power^:
: otro hook ((+$:)
) y un verbo (=
). Tenga en cuenta que estof
es diádico: tiene dos argumentos (x
y(g h j) x
). Entonces tenemos que ver cómo se^:
comporta. La conjunción de poderf^:o
toma un verbof
y un verbo o un sustantivoo
(un sustantivo es solo un dato) y aplicaf
o
tiempos. Por ejemplo, tomao = 3
. Se cumplen las siguientes equivalencias:Si
o
es un verbo, la conjunción de potencia simplemente evaluaráo
los argumentos y usará el resultado del sustantivo como recuento repetido.Para nuestro verbo,
o
es=
, el verbo de igualdad. Se evalúa0
para diferentes argumentos y1
para argumentos iguales. Repetimos el gancho(+$:)
una vez para argumentos iguales y no para los diferentes. Para facilitar la notación de la explicación, dejemosy ⇔ ((g h j) x)
. Recuerde que nuestro gancho inicial es equivalente a esto:Expandiendo la conjunción, esto se convierte en:
Si
x
yy
son lo mismo, esto se convierte en:De lo contrario, esto se convierte en:
Ahora, hemos visto tenedores monádicos. Aquí tenemos un tenedor diádico:
Entonces, cuando
x
yy
son lo mismo, obtenemos:¿Qué es
$:
? Se refiere al verbo completo y permite la recursividad. Esto significa que, cuandox
y yare the same, we apply the verb to
yand add
x`.Tenedores:
(g h j) x
Ahora, ¿qué hace la horquilla interna? Esto fue
y
en nuestro último ejemplo. Para una bifurcación monádica de tres verbos, dado un argumentox
, se cumple la siguiente equivalencia:Para el siguiente ejemplo, supongamos que hemos llamado verbos
SUM
,DIVIDE
yLENGTH
que haga lo que supongo que podría hacerlo. Si concatenamos los tres en una bifurcación, obtenemos:Esta bifurcación evalúa el promedio de
x
(suponiendo quex
sea 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:
?
Poniendolo todo junto
Dadas todas estas cosas, nuestro verbo es equivalente a:
Esto expresa la funcionalidad deseada.
fuente
(+$:)^:=1+?
Jalea , 7 bytes
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.
Aquí hay 5000 puntos de datos de n = 3 en un gráfico de semilog que muestra la distribución exponencial (¿aproximadamente?).
fuente
Pyth -
1211 bytesUtiliza funcional mientras. Siento que debería haber una respuesta más inteligente que simplemente simule la distribución.
Pruébalo en línea .
fuente
Python 3 , 80 bytes
Pruébalo en línea!
fuente
r.random()
devuelve 0.1-r.random()
debería funcionar.import ... as _
es más corto!05AB1E , 10 bytes
Pruébelo en línea o verifique las listas .
Alternativa de 10 bytes:
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:
fuente
.Γ
o algo.Wolfram Language (Mathematica) , 50 bytes
Pruébalo en línea!
fuente
R ,
4742 bytesPrué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!
fuente
if
para 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!Ruby , 35 bytes
Pruébalo en línea!
fuente
x
variable: ¡ Pruébelo en línea!APL (Dyalog Unicode) ,
1514 bytesPruébalo en línea!
fuente
Haskell ,
7776 bytesPruébalo en línea!
Gracias a killmous por un byte.
Si
<|>
estuviéramos en el preludio, podríamos mejorar conMonadComprehensions
:Haskell , no competidor, 66 bytes
Pruébalo en línea!
fuente
Python 2 , 53 bytes
Pruébalo en línea!
Utiliza la
or
idea de cortocircuito de la respuesta de ArBo . La expresiónrandom()*n//1
genera un número desde0
hastan-1
,0
tomando el lugar de un rollo den
. Elor
toma el número que, excepto si se trata de cero (Falsey-) que sigue an+f(n)
.fuente
Japt , 13 bytes
Intentalo
La respuesta del puerto de Arnauld . Descubrí cómo hacer una llamada recursiva;)
JS transpuesto:
fuente
N.g(f)
:)U
. Saltar una línea parece funcionar también. Ese es un buen truco :)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.
Intentalo
fuente
PowerShell , 49 bytes
Pruébalo en línea!
Método iterativo Ajusta la entrada
$args
a$a
y el$l
rodillo ast (hecho hasta entrar en el bucle al menos una vez). Luego, mientras el último lanzamiento sea-eq
ual a la entrada, seguimos rodando. Dentro del bucle, acumulamos en$o
el último rollo, que se actualiza creando un rango de1
entrada$a
y seleccionando unRandom
elemento del mismo. (Honestamente, estoy un poco sorprendido de que$o+=$l=
funcione). Una vez que estamos fuera del ciclo, nos vamos$o
a la tubería y la salida es implícita.fuente
Adelante (gforth) , 72 bytes
Pruébalo en línea!
Explicación del Código
fuente
Lote, 70 bytes.
Toma la entrada
n
como un parámetro de línea de comando%1
.d
es el rollo actual,t
el total acumulado. Simplemente sigue rodando hastad
que no sea igual an
.fuente
Jalea , 9 bytes
Pruébalo en línea!
Una alternativa que no tiene esta limitación es:
Jalea , 10 bytes
Pruébalo en línea!
Tenga en cuenta que ambos enlaces TIO generan 400 números para mostrar la distribución.
fuente
Python 3 ,
8172 bytesPruébalo en línea!
-9 bytes gracias a ArBo
Explicación
fuente
from random import*
lugar.TI-BASIC,
2823 bytes-5 bytes gracias a esta meta publicación!
La entrada está adentro
Ans
.La salida está en
Ans
y se imprime implícitamente.Ejemplos:
Explicación:
Notas:
fuente
startTmr
ya no es necesario, este envío ahora funcionará para versiones de TI-BASIC anteriores a la TI-84 +SmileBASIC 3, 49 bytes
La función
D N OUT R
implementa tiradas de dados explosivas de forma recursiva.Sin golf
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 var
yvar = fun(in)
son exactamente iguales, es por eso que podemos definir la función enOUT
forma y también llamarla en una expresión en el cuerpo de la función. Si hubiera definido la función comoDEF D(N)
tendría que declarar explícitamenteRETURN R
en el cuerpo de la función; mezclar ambas sintaxis me ahorró bytes.fuente
Potencia Shell , 43 bytes (método iterativo)
Pruébalo en línea!
PowerShell , 48 bytes (método recursivo)
Pruébalo en línea!
fuente
Jalea , 7 bytes
Un enlace monádico que acepta un número entero
n
, que produce un número entero.¿Cómo?
fuente
SmileBASIC, 41 bytes
Despues de leer:
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 den
.fuente
AnyDice , 36 bytes
Casi incorporado en el idioma:
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.
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.
fuente
CJam , 19 bytes
Explicación:
O en seudocódigo:
Como un diagrama de flujo:
Pruébalo en línea!
fuente
Excel VBA, 46 bytes
Gracias a @TaylorScott
Ejecutado en la ventana de comandos.
Como una función definida por el usuario.
Excel VBA,
10867 bytesfuente
do
..loop while
y 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