Simulando Dados Explosivos

31

Sua tarefa é criar um programa que receba um número inteiro n > 1e nproduza 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 ne 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.

Rɪᴋᴇʀ
fonte
1
o programa precisa ser perfeito? Como sua distribuição pode ser reduzida em uma quantidade extremamente baixa?
Maltysen
Para: Riker; RE: @ comentário de Maltysen acima; ou quantidade extremamente alta?
Artemis apoia Monica em
2
@ArtemisFowl Veja nossos padrões de aleatoriedade. Também aqui .
Rɪᴋᴇʀ 12/04

Respostas:

36

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

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

Os bytes de código acima definem uma função que simula um dado explosivo. É preciso uma única entrada, passada no ESIregistro, indicando o número máximo de dados. Ele retorna um único valor noECX registro, que é o resultado dos rolos.

Internamente, ele usa a RDRANDinstruçã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:

           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

Estou trapaceando um pouco . Todas as convenções de chamada x86 padrão retornam o resultado de uma função no EAXregistro. 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ção ECXdo registro de saída me salvou 1 byte. Se você deseja usar EAX, insira uma XCHG eax, ecxinstrução de 1 byte imediatamente antes da retinstrução. Isso troca os valores dos registradores EAXe ECX, copiando efetivamente o resultado de ECXpara EAXe descartando ECXo valor antigo de EAX.

Experimente online!

Aqui está a função equivalente transcrita em C, usando o __builtin_ia32_rdrand32_stepintrínseco suportado pelo GCC, Clang e ICC para gerar a RDRANDinstrução:

#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, o GCC com o -Ossinalizador transforma isso quase exatamente no mesmo código de máquina . Ele recebe a entrada em EDIvez de ESI, que é completamente arbitrária e não altera nada de substância no código. Ele deve retornar o resultado EAX, como mencionei anteriormente, e usa a MOVinstrução mais eficiente (mas maior) para fazer isso imediatamente antes do RET. 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!

Cody Gray
fonte
12

Python 2 , 66 64 61 bytes

-3 bytes graças ao xnor

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

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, assim c%ncomo o falsey lá. Nas próximas iterações, somente será falsey se dados explodidos forem lançados.

Python 2 , 55 bytes

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

Experimente online!

Minha outra resposta parece ter um pouco de engenharia, já que parece funcionar bem ... deixarei assim mesmo.

ArBo
fonte
2
Funções recursivas em que a condição de quebra é baseada na aleatoriedade sempre terão uma chance diferente de zero de estourar a pilha. Chance estatisticamente insignificante, mas ainda assim ...
mypetlion
3
Normalmente, presume-se que o tamanho da pilha seja infinito nos desafios do código de golfe na minha experiência. À medida que o tamanho da pilha aumenta para o infinito, a probabilidade de excesso de pilha converge rapidamente para zero.
ArBo 12/04
ArBo do @mypetlion antes de você digitar seu comentário para poder executar ping no usuário
MilkyWay90 13/04
1
Eu acho que c*(c<n)pode ser c%n.
xnor 13/04
@xnor Claro, eu sou um idiota ...
ArBo 13/04
12

R , 39 bytes

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

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. Seja n 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 umGeometrEuc(1-1n)distribuição (veja apáginadaWikipedia, que define sucesso e fracasso ao contrário). Cada explosão traznao total. O rolo final segue umvocênEuform(1,2,...,n-1)de distribuição que se juntam ao total.

Robin Ryder
fonte
muito agradável! Conseguiu amar as distribuições internas para desafios aleatórios !
Giuseppe
Atende sampleaos padrões de aleatoriedade, dado seu viés ?
Xian
@ Xi'an Certamente que sim : é o gerador aleatório embutido para variáveis ​​aleatórias discretas.
Robin Ryder
Eu sei, eu sei, mas verifique o link que coloquei: a discretização inerente a sampleleva 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 é ?!
Xian
Sim, é chocante. Mas, novamente, quantas vezes você usar samplecom ? ;-)m231
Robin Ryder
9

Perl 6 , 26 bytes

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

Experimente online!

Explicação

{                        } # 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
fonte
2
Bom, minha própria solução foi{sum roll(*,1..$_)...$_>*}
Jo King
9

J , 16 11 bytes

(+$:)^:=1+?

Experimente online!

Explicação

TL; DR 1+? executa o rolo de matriz, (+$:)^:=reitera apenas quando é igual à entrada.


A função é um trem de 4 verbos:

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

Um trem é quando 2 ou mais verbos são concatenados. Aqui, a resposta é da seguinte forma f g h j:

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

Um chamado "trem de 4" é analisado como um gancho e um garfo:

f g h j   ⇔   f (g h j)

Assim, a resposta é equivalente a:

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

Ganchos: (f g) xex (f g) y

Um gancho monádico (um argumento) de dois verbos, dado um argumento x, mantém a seguinte equivalência:

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

Por exemplo, (* -) 5avalia como 5 * (- 5), que avalia como _25.

Isso significa que nosso trem de 4, um gancho de fe (g h j), é equivalente a:

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

Mas o que ffaz aqui? (+$:)^:=é uma conjunção de dois verbos usando a conjunção Power^: : outro hook ( (+$:)) e um verbo ( =). Observe aqui que fé diádico - ele tem dois argumentos ( xe (g h j) x). Então, temos que ver como ^:se comporta. A conjunção de poder f^:ousa um verbo fe um verbo ou um substantivo o(um substantivo é apenas um dado) e aplica os f otempos. Por exemplo, pegue o = 3. As seguintes equivalências são válidas:

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

Se ofor um verbo, a conjunção de poder simplesmente avaliará oos argumentos e usará o resultado do substantivo como a contagem de repetição.

Para o nosso verbo, oé =, o verbo da igualdade. Ele avalia 0para argumentos diferentes e 1para 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, deixe y ⇔ ((g h j) x). Lembre-se de que nosso gancho inicial é equivalente a isso:

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

Expandindo a conjunção, isso se torna:

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

Se xe ysão iguais, isso se torna:

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

Caso contrário, isso se tornará:

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

Agora, vimos garfos monádicos. Aqui, temos um garfo diádico:

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

Então, quando xe ysão os mesmos, obtemos:

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

O que é $:? Refere-se ao verbo inteiro em si e permite recursão. Isso significa que, quando xe y are the same, we apply the verb toy and addx` a ele.

Forquilhas: (g h j) x

Agora, o que o garfo interno faz? Este foi o ynosso último exemplo. Para um garfo monádico de três verbos, dado um argumento x, a seguinte equivalência é válida:

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

Para esta próxima exemplo, suponha que temos verbos chamado SUM, DIVIDEe LENGTH, que faça o que você acha que eles podem. Se concatenarmos os três em um garfo, obteremos:

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

Essa bifurcação é avaliada como a média de x(assumindo que xseja 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:

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

?[0 0,x)[1,x]

Juntando tudo

Dadas todas essas coisas, nosso verbo é 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

Isso expressa a funcionalidade desejada.

Conor O'Brien
fonte
1
(+$:)^:=1+?­­
ngn 13/04
@ngn Obrigado! Incorporado.
Conor O'Brien
7

Geléia , 7 bytes

X+ß}¥=¡

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

Aqui estão 5000 pontos de dados de n = 3 em um gráfico semilog que mostra a distribuição exponencial (aproximadamente?). insira a descrição da imagem aqui

dylnan
fonte
Parcelas agradáveis! A distribuição que você recebe é uma distribuição geométrica (veja minha resposta R ), que está intimamente relacionada à distribuição exponencial.
Robin Ryder
6

Pitão - 12 11 bytes

Usa enquanto funcional. Eu sinto que deveria haver uma resposta mais inteligente que simule a distribuição.

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

Experimente online .

Maltysen
fonte
4

Python 3 , 80 bytes

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

Experimente online!

Lynn
fonte
1
Há uma pequena chance de falha se r.random()retornar 0. 1-r.random()deve funcionar, no entanto.
nwellnhof 12/04
Embora tecnicamente essa chance seja 0
Quintec
1
Um caso raro, onde import ... as _é o mais curto!
xnor 13/04
@xnor de fato! A única outra vez que lembro que vencer em uma resposta minha é aqui
Lynn
4

05AB1E , 10 bytes

[ILΩDIÊ#}O

Experimente online ou verifique as listas .

Alternativa de 10 bytes:

[LΩDˆÊ#}¯O

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:

[         # 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
fonte
Estava tentando pensar em uma maneira de usar ou algo assim.
Magic Octopus Urn
3

R , 47 42 bytes

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

Experimente online!

Crédito à abordagem da ArBo .

Ainda um byte mais longo do que o de Robin Ryder , faça um voto positivo!

Giuseppe
fonte
Interessante, refiz isso de forma recursiva ifpara 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!
CriminallyVulgar
Tentei uma recursiva e obtive uma solução de 54 bytes. Tentei algo semelhante ao seu para 44 Experimente online!
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

Experimente online!

Graças a killmous por um byte.

Se <|>estivéssemos no prelúdio, poderíamos fazer melhor com MonadComprehensions:

Haskell , não concorrente, 66 bytes

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

Experimente online!

dfeuer
fonte
1
Você pode salvar um byte se definir g como uma função infix.
killmous 12/04
1
@killmous, obrigado. À primeira vista, imaginei que seria o mesmo ou pior, mas é melhor.
dfeuer 12/04
3

Python 2 , 53 bytes

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

Experimente online!

Usa a oridéia de curto-circuito da resposta do ArBo . A expressão random()*n//1gera um número de 0para n-1, 0substituindo um rolo de n. Ele orpega esse número, exceto se for zero (Falsey) e continua n+f(n).

xnor
fonte
Parece que sua resposta já estava correta quando eu editei na minha mais curta ... Eu não vi isso, mas se você quiser que eu a exclua porque é bem parecida, eu irei.
ArBo 13/04
@ArBo De maneira alguma, respostas duplicadas independentemente são boas .
xnor 13/04
3

Japonês , 13 bytes

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

Tente

Resposta do porto de Arnauld . Descobri como fazer uma chamada recursiva;)

JS transpilado:

// 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
fonte
1
Muito bom uso de N.g(f):)
Shaggy
Fiz uma punhalada nesse assunto e acabei com 12 bytes, mas não quero publicá-la porque gosto demais da sua solução!
Shaggy
Postá-lo como uma resposta diferente :)
dana
Pode ser mais curto, mas é muito mais feio que o seu: petershaggynoble.github.io/Japt-Interpreter/…
Shaggy
Entendo - sim, eu estava tentando encontrar uma maneira de não poluir U. Pular uma linha parece funcionar também. Isso é um bom truque :)
dana
3

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.


ö
>°V©VªV+ß

Tente

Shaggy
fonte
2

PowerShell , 49 bytes

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

Experimente online!

Método iterativo. Define a entrada $argscomo $ae o $last roll (feito para inserir o loop pelo menos uma vez). Então, enquanto o último rolo for -equal para a entrada, continuamos rolando. Dentro do loop, acumulamos $oo último rolo, que é atualizado criando um intervalo de 1entrada $ae escolhendo um Randomelemento do mesmo. (Honestamente, estou um pouco surpreso que $o+=$l=funcione.) Quando estamos fora do circuito, deixamos $oo pipeline e a saída está implícita.

AdmBorkBork
fonte
2

Quarto (gforth) , 72 bytes

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

Experimente online!

Código Explicação

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
fonte
2

Lote, 70 bytes

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

Recebe a entrada ncomo um parâmetro da linha de comando %1. dé o rolo atual, to total acumulado. Simplesmente continua rolando até que dnão seja igual a n.

Neil
fonte
2

Geléia , 9 bytes

x⁹X€Ä%ƇµḢ

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

X³X¤+¥³ḍ¥¿

Experimente online!

Observe que os dois links TIO geram 400 números para mostrar a distribuição.

Nick Kennedy
fonte
2

Python 3 , 81 72 bytes

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

Experimente online!

-9 bytes graças ao ArBo

Explicação

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
Artemis apoia Monica
fonte
Você pode salvar 1 byte usando from random import*.
orthoplex
1
Você pode reduzir isso para 74 bytes usando esta solução recursiva
Reinstate Monica
1
@squid Você pode salvar 1 byte como este .
orthoplex
1
@orthoplex e, em seguida, você pode encurtar o if / else e torná-lo único . Começa a parecer com a minha solução;)
ArBo 12/04
1
@ArBo Sim, é por isso que não mudei para recursivo, não queria apenas copiar você.
Artemis apoia Monica em
2

TI-BASIC, 28 23 bytes

-5 bytes graças a este meta post!

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

A entrada é no Ans.
A saída está inserida Anse é impressa implicitamente.

Exemplos:

4
              4
prgmCDGF11
              5
6
              6
prgmCDGF11
              3

Explicação:

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 é uma linguagem tokenizada. Contagem de caracteres não é igual à contagem de bytes.
Tau
fonte
Como startTmrnão é mais necessário, este envio agora funcionará para versões do TI-BASIC anteriores ao TI-84 +
Tau
2

SmileBASIC 3, 49 bytes

A função D N OUT Rimplementa dados explosivos rolando recursivamente.

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

Ungolfed

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

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 vare var = fun(in)é exatamente o mesmo, é por isso que podemos definir a função na OUTforma 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 explicitamente RETURN Rno corpo da função; misturar as duas sintaxes me salvou em bytes.

Caracol_
fonte
2

Geléia , 7 bytes

X=п⁸S_

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?

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
fonte
2

SmileBASIC, 41 bytes

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

Depois de ler:

Observe que você nunca deve gerar múltiplos de n, pois eles sempre explodirão.

Percebi que, em vez de verificar se houve uma rolagem de dados n, você pode apenas repetir enquanto a soma é um múltiplo de n.

12Me21
fonte
2

AnyDice , 36 bytes

Quase um built-in no idioma:

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

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.

set "explode depth" to 99

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.

Taemyr
fonte
1
Eu acho que estou bem com isso não explodindo muito, o de 36 bytes é bom para mim. Eu não disse nenhum builtins e estou bem em tê-los aqui, já que não é como se sua resposta de 1 ou 0 byte estivesse ganhando. Mas seja bem-vindo ao site!
Rɪᴋᴇʀ
2

CJam , 19 bytes

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

Explicação:

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

Ou no pseudocó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 um fluxograma:

Fluxograma de código

Experimente online!

lolad
fonte
2

Excel VBA, 46 bytes

Obrigado a @TaylorScott

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

Executado na janela de comando.

Como uma função definida pelo usuário.

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
fonte
Você pode resolver isso bastante usando um loop do.. loop whilee 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
Taylor Scott
1
@ TaylorScott Obrigado, esqueci que Do x Enquanto y existia no Excel VBA.
william porter