Sua tarefa é criar um programa que receba um número inteiro n > 1
e n
produza o rolo de um dado de um lado. No entanto, este dado segue as regras para explodir dados .
Quando você rolar o dado, verifique qual valor você rolou. Se você obteve o máximo para esse tipo de dado (em um d4 padrão que seria 4 ou 6 em um d6, etc.), role novamente e adicione o novo teste a esse total. Cada rolo continua adicionando ao total, até que você não role mais o número máximo. Esse número final ainda é adicionado.
Seu programa deve coletar um único número inteiro n
e rolar o dado explosivo n
. Aqui está um exemplo de distribuição para mostrar como deve ser n=4
. Observe que você nunca deve produzir múltiplos de n
, pois eles sempre explodirão.
Você pode assumir que o tamanho da pilha para qualquer recursão é infinito e sua função aleatória deve atender aos nossos padrões de aleatoriedade (gerador aleatório embutido ou hora / data ). Sua função aleatória também deve ser o mais uniforme possível, em comparação com uma distribuição geométrica, já que estamos falando de dados.
Respostas:
Código da máquina x86 (para Intel Ivy Bridge e posterior), 17 bytes
Os bytes de código acima definem uma função que simula um dado explosivo. É preciso uma única entrada, passada no
ESI
registro, indicando o número máximo de dados. Ele retorna um único valor noECX
registro, que é o resultado dos rolos.Internamente, ele usa a
RDRAND
instrução para gerar um número aleatório. Isso usa um gerador de números aleatórios (RNG) que é incorporado ao hardware dos processadores Intel Ivy Bridge e posteriores (alguns processadores AMD também suportam esta instrução).A lógica da função é bastante direta. O número aleatório gerado é redimensionado para ficar dentro do intervalo desejado usando a técnica padrão (
(rand % dieSize) + 1
) e, em seguida, é verificado para ver se deve causar uma explosão. O resultado final é mantido em um registro acumulador.Aqui está uma versão anotada mostrando os mnemônicos da linguagem assembly:
Estou trapaceando um pouco . Todas as convenções de chamada x86 padrão retornam o resultado de uma função no
EAX
registro. Mas, no código de máquina verdadeiro, não há convenções de chamada. Você pode usar qualquer registrador que desejar para entrada / saída. A utilizaçãoECX
do registro de saída me salvou 1 byte. Se você deseja usarEAX
, insira umaXCHG eax, ecx
instrução de 1 byte imediatamente antes daret
instrução. Isso troca os valores dos registradoresEAX
eECX
, copiando efetivamente o resultado deECX
paraEAX
e descartandoECX
o valor antigo deEAX
.Experimente online!
Aqui está a função equivalente transcrita em C, usando o
__builtin_ia32_rdrand32_step
intrínseco suportado pelo GCC, Clang e ICC para gerar aRDRAND
instrução:Curiosamente, o GCC com o
-Os
sinalizador transforma isso quase exatamente no mesmo código de máquina . Ele recebe a entrada emEDI
vez deESI
, que é completamente arbitrária e não altera nada de substância no código. Ele deve retornar o resultadoEAX
, como mencionei anteriormente, e usa aMOV
instrução mais eficiente (mas maior) para fazer isso imediatamente antes doRET
. Caso contrário, samezies. É sempre divertido quando o processo é totalmente reversível: escreva o código em assembly, transcreva-o em C, execute-o em um compilador C e recupere seu assembly original!fonte
Python 2 ,
666461 bytes-3 bytes graças ao xnor
Experimente online!
O rolo anterior é armazenado
c
, permitindo acessar várias vezes sem precisar armazená-lo em uma variável, o que não pode ser feito em uma lambda Python. A cada recursão, verificamos se lançamos dados explosivos.c
é inicializado como zero, assimc%n
como o falsey lá. Nas próximas iterações, somente será falsey se dados explodidos forem lançados.Python 2 , 55 bytes
Experimente online!
Minha outra resposta parece ter um pouco de engenharia, já que parece funcionar bem ... deixarei assim mesmo.
fonte
c*(c<n)
pode serc%n
.R , 39 bytes
Experimente online!
Explicação: esta solução evita loops de recursão / while, calculando diretamente a distribuição do número de explosões que ocorrerão. Sejan o número de lados no dado. Se você denota sucesso como rolar um n e falha como rolar qualquer outra coisa, então você tem probabilidade 1n de sucesso. O número total de explosões é o número de sucessos antes da primeira falha. Isso corresponde a umL um e o m e t r i c ( 1 - 1n) distribuição (veja apáginadaWikipedia, que define sucesso e fracasso ao contrário). Cada explosão trazn ao total. O rolo final segue umU n i fou r m (1,2,…,n-1) de distribuição que se juntam ao total.
fonte
sample
aos padrões de aleatoriedade, dado seu viés ?sample
leva a uma falta de uniformidade que fornece uma razão entre a probabilidade máxima e a mínima de 1,03 ... Chocante, não é ?!sample
com ? ;-)Perl 6 , 26 bytes
Experimente online!
Explicação
fonte
{sum roll(*,1..$_)...$_>*}
J ,
1611 bytesExperimente online!
Explicação
TL; DR
1+?
executa o rolo de matriz,(+$:)^:=
reitera apenas quando é igual à entrada.A função é um trem de 4 verbos:
Um trem é quando 2 ou mais verbos são concatenados. Aqui, a resposta é da seguinte forma
f g h j
:Um chamado "trem de 4" é analisado como um gancho e um garfo:
Assim, a resposta é equivalente a:
Ganchos:
(f g) x
ex (f g) y
Um gancho monádico (um argumento) de dois verbos, dado um argumento
x
, mantém a seguinte equivalência:Por exemplo,
(* -) 5
avalia como5 * (- 5)
, que avalia como_25
.Isso significa que nosso trem de 4, um gancho de
f
e(g h j)
, é equivalente a:Mas o que
f
faz aqui?(+$:)^:=
é uma conjunção de dois verbos usando a conjunção Power^:
: outro hook ((+$:)
) e um verbo (=
). Observe aqui quef
é diádico - ele tem dois argumentos (x
e(g h j) x
). Então, temos que ver como^:
se comporta. A conjunção de poderf^:o
usa um verbof
e um verbo ou um substantivoo
(um substantivo é apenas um dado) e aplica osf
o
tempos. Por exemplo, pegueo = 3
. As seguintes equivalências são válidas:Se
o
for um verbo, a conjunção de poder simplesmente avaliaráo
os argumentos e usará o resultado do substantivo como a contagem de repetição.Para o nosso verbo,
o
é=
, o verbo da igualdade. Ele avalia0
para argumentos diferentes e1
para argumentos iguais. Repetimos o gancho(+$:)
uma vez para argumentos iguais e não há tempos para argumentos diferentes. Para facilitar a notação da explicação, deixey ⇔ ((g h j) x)
. Lembre-se de que nosso gancho inicial é equivalente a isso:Expandindo a conjunção, isso se torna:
Se
x
ey
são iguais, isso se torna:Caso contrário, isso se tornará:
Agora, vimos garfos monádicos. Aqui, temos um garfo diádico:
Então, quando
x
ey
são os mesmos, obtemos:O que é
$:
? Refere-se ao verbo inteiro em si e permite recursão. Isso significa que, quandox
e yare the same, we apply the verb to
yand add
x` a ele.Forquilhas:
(g h j) x
Agora, o que o garfo interno faz? Este foi o
y
nosso último exemplo. Para um garfo monádico de três verbos, dado um argumentox
, a seguinte equivalência é válida:Para esta próxima exemplo, suponha que temos verbos chamado
SUM
,DIVIDE
eLENGTH
, que faça o que você acha que eles podem. Se concatenarmos os três em um garfo, obteremos:Essa bifurcação é avaliada como a média de
x
(assumindo quex
seja uma lista de números). Em J, escreveríamos isso como exemplo como+/ % #
.Uma última coisa sobre garfos. Quando o "dente" mais à esquerda (no nosso caso simbólico acima
g
) é um substantivo, ele é tratado como uma função constante retornando esse valor.Com tudo isso no lugar, agora podemos entender o garfo acima:
?
Juntando tudo
Dadas todas essas coisas, nosso verbo é equivalente a:
Isso expressa a funcionalidade desejada.
fonte
(+$:)^:=1+?
Geléia , 7 bytes
Experimente online!
Usa recursão. Executa o programa novamente (
ß
) e adiciona (+
) se (¡
) o número aleatório (X
) é igual (=
) à entrada do programa.}
marcasß
agir sobre a entrada de programa e¥
combina+ß}
em um único link para¡
a consumir.Aqui está uma distribuição de 1000 saídas para n = 6, que eu coletei usando este programa. Traçado com python / matplotlib.
Aqui estão 5000 pontos de dados de n = 3 em um gráfico semilog que mostra a distribuição exponencial (aproximadamente?).
fonte
Pitão -
1211 bytesUsa enquanto funcional. Eu sinto que deveria haver uma resposta mais inteligente que simule a distribuição.
Experimente online .
fonte
Python 3 , 80 bytes
Experimente online!
fonte
r.random()
retornar 0.1-r.random()
deve funcionar, no entanto.import ... as _
é o mais curto!05AB1E , 10 bytes
Experimente online ou verifique as listas .
Alternativa de 10 bytes:
Experimente online ou verifique as listas .
Embora eu goste mais do top porque ele tem a 'palavra'
DIÊ
, o que combina com o desafio.Explicação:
fonte
.Γ
ou algo assim.Wolfram Language (Mathematica) , 50 bytes
Experimente online!
fonte
R ,
4742 bytesExperimente online!
Crédito à abordagem da ArBo .
Ainda um byte mais longo do que o de Robin Ryder , faça um voto positivo!
fonte
if
para 46 bytes, mas acabei obtendo um 52 em um rolo, o que não seria possível com n = 4, então não sei se há algo estranho com limite de recursão baixo, mas eu acho que pode ser buggy. Experimente online!Ruby , 35 bytes
Experimente online!
fonte
x
variável: Experimente online!APL (Dyalog Unicode) ,
1514 bytesExperimente online!
fonte
Haskell ,
7776 bytesExperimente online!
Graças a killmous por um byte.
Se
<|>
estivéssemos no prelúdio, poderíamos fazer melhor comMonadComprehensions
:Haskell , não concorrente, 66 bytes
Experimente online!
fonte
Python 2 , 53 bytes
Experimente online!
Usa a
or
idéia de curto-circuito da resposta do ArBo . A expressãorandom()*n//1
gera um número de0
paran-1
,0
substituindo um rolo den
. Eleor
pega esse número, exceto se for zero (Falsey) e continuan+f(n)
.fonte
Japonês , 13 bytes
Tente
Resposta do porto de Arnauld . Descobri como fazer uma chamada recursiva;)
JS transpilado:
fonte
N.g(f)
:)U
. Pular uma linha parece funcionar também. Isso é um bom truque :)Japonês , 12 bytes
Pode ser mais curto que a solução da dana, mas é muito mais feio. Só estou postando porque parece que sempre, desde que tivemos uma solução Japt que começou com uma linha vazia.
Tente
fonte
PowerShell , 49 bytes
Experimente online!
Método iterativo. Define a entrada
$args
como$a
e o$l
ast roll (feito para inserir o loop pelo menos uma vez). Então, enquanto o último rolo for-eq
ual para a entrada, continuamos rolando. Dentro do loop, acumulamos$o
o último rolo, que é atualizado criando um intervalo de1
entrada$a
e escolhendo umRandom
elemento do mesmo. (Honestamente, estou um pouco surpreso que$o+=$l=
funcione.) Quando estamos fora do circuito, deixamos$o
o pipeline e a saída está implícita.fonte
Quarto (gforth) , 72 bytes
Experimente online!
Código Explicação
fonte
Lote, 70 bytes
Recebe a entrada
n
como um parâmetro da linha de comando%1
.d
é o rolo atual,t
o total acumulado. Simplesmente continua rolando até qued
não seja igual an
.fonte
Geléia , 9 bytes
Experimente online!
Um link monádico que toma n como argumento e retorna um número gerado por um dado explodindo em frente e verso. Isso gera 256 números de 1 a n e retorna a primeira soma cumulativa que não é um múltiplo de n. Em teoria, isso poderia retornar 256n, mas mesmo para um dado de dois lados isso aconteceria apenas um a cada2256 vezes.
Uma alternativa que não tem essa limitação é:
Gelatina , 10 bytes
Experimente online!
Observe que os dois links TIO geram 400 números para mostrar a distribuição.
fonte
Python 3 ,
8172 bytesExperimente online!
-9 bytes graças ao ArBo
Explicação
fonte
from random import*
.TI-BASIC,
2823 bytes-5 bytes graças a este meta post!
A entrada é no
Ans
.A saída está inserida
Ans
e é impressa implicitamente.Exemplos:
Explicação:
Notas:
fonte
startTmr
não é mais necessário, este envio agora funcionará para versões do TI-BASIC anteriores ao TI-84 +SmileBASIC 3, 49 bytes
A função
D N OUT R
implementa dados explosivos rolando recursivamente.Ungolfed
Observe que, no SmileBASIC, as funções podem ter vários valores de retorno. Se uma função tem um valor de retorno
fun in OUT var
evar = fun(in)
é exatamente o mesmo, é por isso que podemos definir a função naOUT
forma e também chamá-la em uma expressão no próprio corpo da função. Se eu tivesse definido a função,DEF D(N)
teria que declarar explicitamenteRETURN R
no corpo da função; misturar as duas sintaxes me salvou em bytes.fonte
PowerShell , 43 bytes (método iterativo)
Experimente online!
PowerShell , 48 bytes (método recursivo)
Experimente online!
fonte
Geléia , 7 bytes
Um link monádico que aceita um número inteiro
n
, que gera um número inteiro.Experimente online! Ou veja as contagens de105 corre
Quão?
fonte
SmileBASIC, 41 bytes
Depois de ler:
Percebi que, em vez de verificar se houve uma rolagem de dados
n
, você pode apenas repetir enquanto a soma é um múltiplo den
.fonte
AnyDice , 36 bytes
Quase um built-in no idioma:
Para que isso esteja correto, tenho de abusar da suposição de profundidade de recursão infinita. AnyDice limita a profundidade de recursão com uma profundidade de função máxima da propriedade global. a explosão incorporada, no entanto, usa a sua; profundidade de explosão - o padrão é 2.
Adicionaria outros 25 bytes; e não corresponderia realmente aos requisitos, já que é teoricamente possível que um dado exploda mais de 99 vezes.
A saída da função é um dado, ie. um tipo interno do AnyDice que é um pareamento de resultados e probabilidades para o resultado.
fonte
CJam , 19 bytes
Explicação:
Ou no pseudocódigo:
Como um fluxograma:
Experimente online!
fonte
Excel VBA, 46 bytes
Obrigado a @TaylorScott
Executado na janela de comando.
Como uma função definida pelo usuário.
Excel VBA,
10867 bytesfonte
do
..loop while
e convertendo a função em uma função imediata da janela. -Do:v=-Int(-[A1]*Rnd):t=t+v:Loop While[A1]=v:?t
- 46 bytes