Simulazione di dadi esplodenti


31

Il tuo compito è creare un programma che accetta un numero intero n > 1e produca il tiro di un ndado a lato singolo . Tuttavia, questo dado segue le regole per esplodere i dadi .

Quando tiri il dado, controlla quale valore hai lanciato. Se hai ottenuto il massimo per quel tipo di dado (su un d4 standard che sarebbe 4, o 6 su un d6, ecc.), Tira di nuovo e aggiungi il nuovo lancio a quel totale. Ogni lancio continua ad aggiungersi al totale, fino a quando non ottieni più il numero massimo. Quel numero finale viene comunque aggiunto.

Il tuo programma dovrebbe prendere un singolo numero intero ne lanciare il ndado a faccia esplodere . Ecco un esempio di distribuzione per mostrare come dovrebbe essere n=4. Nota che non dovresti mai generare multipli di n, poiché esploderanno sempre.

Puoi assumere che la dimensione dello stack per qualsiasi ricorsione che fai sia infinita e la tua funzione casuale deve soddisfare i nostri standard di casualità (generatore casuale incorporato o ora / data ). La tua funzione casuale dovrebbe anche essere il più uniforme possibile, rispetto a qualcosa come una distribuzione geometrica, dal momento che questi sono dadi di cui stiamo parlando.


1
il programma deve essere perfetto? Come può la sua distribuzione essere fuori da una quantità estremamente bassa?
Maltysen,

A: Riker; RE: @ commento di Maltysen sopra; o quantità estremamente elevata?
Artemis supporta Monica il

Risposte:


36

Codice macchina x86 (per Intel Ivy Bridge e versioni successive), 17 byte

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

I suddetti byte di codice definiscono una funzione che simula un dado che esplode. Prende un singolo input, passato nel ESIregistro, indicando il numero massimo del dado. Restituisce un singolo valore nel ECXregistro, che è il risultato dei rulli.

Internamente, utilizza l' RDRANDistruzione per generare un numero casuale. Questo utilizza un generatore di numeri casuali (RNG) integrato nell'hardware dei processori Intel Ivy Bridge e versioni successive (alcune CPU AMD supportano anche queste istruzioni).

La logica della funzione è piuttosto semplice. Il numero casuale generato viene ridimensionato in modo che rientri nell'intervallo desiderato utilizzando la tecnica standard ( (rand % dieSize) + 1), quindi viene verificato per vedere se dovrebbe causare un'esplosione. Il risultato finale viene tenuto in un registro dell'accumulatore.

Ecco una versione annotata che mostra il linguaggio mnemonico dell'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

Sto barando un po ' . Tutte le convenzioni di chiamata x86 standard restituiscono il risultato di una funzione nel EAXregistro. Ma, nel vero codice macchina, non ci sono convenzioni di chiamata. È possibile utilizzare tutti i registri desiderati per l'input / output. Utilizzando ECXper il registro di uscita mi ha salvato 1 byte. Se si desidera utilizzare EAX, inserire XCHG eax, ecxun'istruzione di 1 byte immediatamente prima retdell'istruzione. Ciò scambia i valori di EAXe ECXregistri, copiando efficacemente il risultato da ECXin EAXe cancellando ECXil vecchio valore di EAX.

Provalo online!

Ecco la funzione equivalente trascritta in C, usando l' __builtin_ia32_rdrand32_stepintrinseco supportato da GCC, Clang e ICC per generare l' RDRANDistruzione:

#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;
}

È interessante notare che GCC con la -Osbandiera lo trasforma quasi esattamente nello stesso codice macchina . Prende l'input EDIinvece di ESI, che è completamente arbitrario e non cambia nulla di sostanziale sul codice. Deve restituire il risultato EAX, come ho già detto, e usa l' MOVistruzione più efficiente (ma più grande) per farlo immediatamente prima del RET. Altrimenti, samezies. È sempre divertente quando il processo è completamente reversibile: scrivi il codice nell'assembly, trascrivilo in C, eseguilo attraverso un compilatore C e riavvia l'assembly originale!


12

Python 2 , 66 64 61 byte

-3 byte grazie a xnor

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

Provalo online!

Il roll precedente è archiviato c, permettendoci di accedervi più volte senza doverlo archiviare in una variabile, cosa che non può essere eseguita in una lambda Python. Ad ogni ricorsione, controlliamo se abbiamo lanciato dadi esplosivi.

cè inizializzato a zero, quindi c%nc'è falsità lì. Nelle prossime iterazioni, sarà falso solo se i dadi che esplodono sono stati lanciati.

Python 2 , 55 byte

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

Provalo online!

L'altra mia risposta sembra essere un po 'troppo ingegnosa, dal momento che sembra funzionare anche questo ... Lascio comunque.


2
Le funzioni ricorsive in cui la condizione di rottura si basa sulla casualità avranno sempre una probabilità diversa da zero di overflow dello stack.
Probabilità

3
In genere, nella mia esperienza si presume che le dimensioni dello stack siano infinite nelle sfide del golf del codice. Man mano che le dimensioni dello stack aumentano all'infinito, la probabilità di overflow dello stack converge rapidamente a zero.
ArBo,

ArBo do @mypetlion prima di digitare il tuo commento in modo da poter eseguire il ping dell'utente
MilkyWay90

1
Penso che c*(c<n)possa essere c%n.
xnor

@xnor Certo, sono un idiota ...
ArBo

12

R , 39 byte

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

Provalo online!

Spiegazione: questa soluzione evita la ricorsione / mentre i cicli calcolando direttamente la distribuzione del numero di esplosioni che si verificheranno. Sia n il numero di lati sul dado. Se indichi il successo come il lancio di una n e il fallimento come il lancio di qualsiasi altra cosa, allora hai probabilità 1n di successo. Il numero totale di esplosioni è il numero di successi prima del primo fallimento. Ciò corrisponde a unsoleometrioc(1-1n)distribuzione (vedere lapagina di Wikipedia, che definisce il successo e il fallimento al contrario). Ogni esplosione portanal totale. Il tiro finale segue una distribuzioneUnioform(1,2,...,n-1)che aggiungiamo al totale.


molto bella! Devi amare le distribuzioni integrate per sfide casuali !
Giuseppe,

Non samplesoddisfare gli standard per casualità, data la sua pregiudizi ?
Xi'an,

@ Xi'an Abbastanza sicuro lo fa : è il built-in generatore casuale di variabili aleatorie discrete.
Robin Ryder,

Lo so, lo so, ma controlla il link che ho messo: la discretizzazione inerente a sampleporta a una mancanza di uniformità che dà un rapporto di probabilità massima e minima fino a 1,03 ... Scioccante, vero ?!
Xi'an,

Sì, è scioccante. Ma poi di nuovo, quanto spesso usi samplecon ? ;-)m231
Robin Ryder il

9

Perl 6 , 26 byte

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

Provalo online!

Spiegazione

{                        } # 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

2
Bene, la mia soluzione era{sum roll(*,1..$_)...$_>*}
Jo King,

9

J , 16 11 byte

(+$:)^:=1+?

Provalo online!

Spiegazione

TL; DR 1+? esegue il tiro di dado, si (+$:)^:=ripete solo quando è uguale all'input.


La funzione è un treno di 4 verbi:

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

Un treno è quando 2 o più verbi sono concatenati. Qui, la risposta è nella forma f g h j:

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

Un cosiddetto "4-train" viene analizzato come un gancio e una forcella:

f g h j   ⇔   f (g h j)

Pertanto, la risposta equivale a:

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

Ganci: (f g) xex (f g) y

Un hook monadico (a un argomento) di due verbi, dato un argomento x, vale la seguente equivalenza:

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

Ad esempio, (* -) 5valuta a 5 * (- 5), che valuta a _25.

Ciò significa che il nostro treno 4, un gancio di fe (g h j), equivale a:

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

Ma cosa ci ffa qui? (+$:)^:=è una congiunzione di due verbi che usano la congiunzione Power^: : un altro hook ( (+$:)) e un verbo ( =). Nota qui che fè diadico: ha due argomenti ( xe (g h j) x). Quindi dobbiamo guardare come ^:si comporta. La congiunzione del potere f^:oprende un verbo fe un verbo o un sostantivo o(un sostantivo è solo un pezzo di dati) e applica i f otempi. Ad esempio, prendi o = 3. Sono valide le seguenti equivalenze:

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

Se oè un verbo, la congiunzione di potere valuterà semplicemente ogli argomenti e utilizzerà il risultato del nome come conteggio delle ripetizioni.

Per il nostro verbo, oè =, il verbo di uguaglianza. Valuta 0per argomenti diversi e 1per argomenti uguali. Ripetiamo l'hook (+$:)una volta per argomenti uguali e nessuna volta per argomenti diversi. Per facilità di notazione per la spiegazione, let y ⇔ ((g h j) x). Ricorda che il nostro hook iniziale è equivalente a questo:

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

Espandendo la congiunzione, questo diventa:

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

Se xe ysono uguali, questo diventa:

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

Altrimenti, questo diventa:

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

Ora, abbiamo visto forchette monadiche. Qui abbiamo una forcella diadica:

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

Quindi, quando xe ysono gli stessi, otteniamo:

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

Che cosa è $:? Si riferisce all'intero verbo stesso e consente la ricorsione. Ciò significa che, quando xe y are the same, we apply the verb toy and addx`.

Forchette: (g h j) x

Ora, cosa fa la forcella interna? Questo è stato ynel nostro ultimo esempio. Per un fork monadico di tre verbi, dato un argomento x, vale la seguente equivalenza:

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

Per questo il prossimo esempio, supponiamo di avere i verbi di nome SUM, DIVIDEe LENGTHche si fa quello che si supponga che potrebbe. Se concateniamo i tre in un fork, otteniamo:

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

Questo fork valuta la media di x(supponendo che xsia un elenco di numeri). In J, scriveremmo questo esempio come +/ % #.

Un'ultima cosa sulle forcelle. Quando il "dente" più a sinistra (nel nostro caso simbolico sopra, g) è un sostantivo, viene trattato come una funzione costante che restituisce quel valore.

Con tutto questo in atto, ora possiamo capire il fork di cui sopra:

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

?[0,X)[1,X]

Mettere tutto insieme

Date tutte queste cose, il nostro verbo equivale 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

Questo esprime la funzionalità desiderata.


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

@ngn Grazie! Incorporated.
Conor O'Brien,

7

Gelatina , 7 byte

X+ß}¥=¡

Provalo online!

Usa la ricorsione. Esegue nuovamente il programma ( ß) e aggiunge ( +) se ( ¡) il numero casuale ( X) è uguale ( =) all'ingresso del programma. }marche ßagiscono sull'ingresso programma e ¥combina +ß}in un unico collegamento per ¡consumare.

Qui una distribuzione di 1000 output per n = 6 che ho raccolto usando questo programma. Tracciato con pitone / matplotlib. istogramma

Ecco un 5000 punti dati da n = 3 su un diagramma di semilogrammo che mostra la distribuzione esponenziale (approssimativamente?). inserisci qui la descrizione dell'immagine


Trame belle! La distribuzione che ottieni è una distribuzione geometrica (vedi la mia risposta R ), che è strettamente correlata alla distribuzione esponenziale.
Robin Ryder,

6

Pyth - 12 11 byte

Utilizza funzionale mentre. Sento che dovrebbe esserci una risposta più intelligente che simuli solo la distribuzione.

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

Provalo online .


4

Python 3 , 80 byte

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

Provalo online!


1
C'è una leggera possibilità di fallimento se r.random()capita di restituire 0. 1-r.random()dovrebbe funzionare, comunque.
nwellnhof,

Anche se tecnicamente quella possibilità è 0
Quintec,

1
Un raro caso in cui import ... as _è il più breve!
xnor

@xnor davvero! L'unica altra volta che ricordo che la vittoria in una mia risposta è qui
Lynn,

4

05AB1E , 10 byte

[ILΩDIÊ#}O

Provalo online o verifica gli elenchi .

Alternativa a 10 byte:

[LΩDˆÊ#}¯O

Provalo online o verifica gli elenchi .

Anche se mi piace di più quello in alto perché contiene la "parola" DIÊ, che si adatta alla sfida.

Spiegazione:

[         # 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)  

Stavo cercando di pensare a un modo di usare o qualcosa del genere.
Magic Octopus Urn il


3

R , 47 42 byte

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

Provalo online!

Credito per l'approccio di Arbo .

Ancora un byte più lungo di quello di Robin Ryder , aumenta il suo!


Interessante, ho rielaborato questo in un ricorsivo ifper 46 byte, ma ho finito per ottenere un 52 su un rotolo che non dovrebbe essere possibile con n = 4, quindi non so se sta accadendo una cosa strana con limite di ricorsione basso, ma io penso che potrebbe essere difettoso. Provalo online!
CriminallyVulgar

Ho provato un metodo ricorsivo e ho ottenuto una soluzione a 54 byte. Quindi hai provato qualcosa di simile al tuo per 44 Provalo online!
Aaron Hayman,



3

Haskell , 77 76 byte

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

Provalo online!

Grazie a killmous per un byte.

Se <|>fossimo nel preludio, potremmo fare di meglio con MonadComprehensions:

Haskell , non competitivo, 66 byte

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

Provalo online!


1
È possibile salvare un byte se si definisce g come funzione infix.
killmous

1
@killmous, grazie. A prima vista ho pensato che sarebbe stato lo stesso o peggio, ma è meglio.
lunedì

3

Python 2 , 53 byte

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

Provalo online!

Utilizza l' oridea di corto circuito dalla risposta di ArBo . L'espressione random()*n//1genera un numero da 0a n-1, 0sostituendo un rotolo di n. Il orprende il cui numero, tranne se è zero (Falsey) continua a n+f(n).


Sembra che la tua risposta fosse già pronta quando l'ho modificata nel mio più breve ... Non l'ho visto, ma se vuoi che lo elimini perché è abbastanza simile lo farò.
ArBo,


3

Japt , 13 byte

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

Provalo

La risposta di Port of Arnauld . Capito come effettuare una chiamata ricorsiva;)

Transpiled JS:

// 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
   })

1
Molto bello l'uso di N.g(f):)
Shaggy,

Ho preso una pugnalata a questo me stesso e ho finito con 12 byte ma non voglio pubblicarlo perché mi piace troppo la tua soluzione!
Shaggy,

Posta come una risposta diversa :)
dana

Potrebbe essere più corto, ma è un inferno molto più brutto del tuo: petershaggynoble.github.io/Japt-Interpreter/…
Shaggy

Capisco, sì, stavo cercando di trovare un modo per non inquinare U. Anche saltare una linea sembra funzionare. Questo è un buon trucco :)
Dana il

3

Japt , 12 byte

Potrebbe essere più breve della soluzione di Dana, ma è molto più brutta. Lo sto solo postando perché sembra che ci sia un'eternità da quando abbiamo avuto una soluzione Japt che è iniziata con una riga vuota.


ö
>°V©VªV+ß

Provalo


2

PowerShell , 49 byte

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

Provalo online!

Metodo iterativo. Imposta l'ingresso $argssu $ae il $lrullo ast (fatto così entriamo nel loop almeno una volta). Quindi, fino a quando l'ultimo lancio è -equguale all'input, continuiamo a girare . All'interno del loop ci accumuliamo $onell'ultimo roll, che viene aggiornato creando un intervallo 1dall'input $ae selezionando un Randomsuo elemento. (Onestamente, sono un po 'sorpreso che$o+=$l= funzioni .) Una volta fuori dal circuito, lasciamo $ola pipeline e l'output è implicito.


2

Forth (gforth) , 72 byte

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

Provalo online!

Spiegazione del codice

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

2

Lotto, 70 byte

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

Accetta l'input ncome parametro della riga di comando %1. dè il tiro corrente, til totale cumulativo. Continua semplicemente a rotolare fino a quando dnon è uguale a n.



2

Python 3 , 81 72 byte

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

Provalo online!

-9 byte grazie ad ArBo

Spiegazione

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

È possibile salvare 1 byte utilizzando from random import*invece.
orthoplex,

1
È possibile ottenere questo fino a 74 byte utilizzando questa soluzione ricorsiva
Ripristinare Monica

1
@squid Puoi salvare 1 byte in questo modo .
orthoplex,

1
@orthoplex e quindi puoi accorciare if / else e renderlo un one-liner . Inizia a sembrare la mia soluzione allora;)
ArBo

1
@ArBo Sì, è per questo che non sono passato a ricorsivo, non volevo solo copiarti.
Artemis supporta Monica il

2

TI-BASIC, 28 23 byte

-5 byte grazie a questo meta post!

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

L'ingresso è in Ans.
L'output è in Ansed è implicitamente stampato.

Esempi:

4
              4
prgmCDGF11
              5
6
              6
prgmCDGF11
              3

Spiegazione:

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"

Gli appunti:

  • TI-BASIC è un linguaggio tokenizzato. Il conteggio dei caratteri non equivale al conteggio dei byte.

Poiché startTmrnon è più necessario, questo invio funzionerà ora per le versioni di TI-BASIC precedenti alla TI-84 +
Tau

2

SmileBASIC 3, 49 byte

La funzione D N OUT Rimplementa in modo ricorsivo i tiri di dado esplosivi.

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

Si noti che in SmileBASIC le funzioni possono avere più valori di ritorno. Se una funzione ha un valore di ritorno allora fun in OUT vare var = fun(in)sono esattamente gli stessi, ecco perché possiamo definire la funzione nella OUTforma e anche chiamarla in un'espressione nel corpo della funzione stessa. Se avessi definito la funzione come DEF D(N)avrei dovuto dichiarare esplicitamente RETURN Rnel corpo della funzione; il missaggio di entrambe le sintassi mi ha salvato byte.



2

Gelatina , 7 byte

X=п⁸S_

Un collegamento monadico che accetta un numero intero n, che produce un numero intero.

105

Come?

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

2

SmileBASIC, 41 byte

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

Dopo aver letto:

Nota che non dovresti mai generare multipli di n, poiché esploderanno sempre.

Mi sono reso conto che invece di verificare se un tiro di dadi fosse n, puoi semplicemente ripetere mentre la somma è un multiplo di n.


2

AnyDice , 36 byte

Quasi un built-in nella lingua:

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

Perché ciò sia corretto, devo abusare dell'infinita ipotesi di profondità di ricorsione. AnyDice limita la profondità di ricorsione con una profondità di funzione massima della proprietà globale. l'esplosione incorporata usa comunque la propria; esplode la profondità, che per impostazione predefinita è 2.

set "explode depth" to 99

Aggiungerebbe altri 25 byte; e non corrisponderebbe realmente ai requisiti poiché è teoricamente possibile che un dado esploda più di 99 volte.

L'output della funzione è un dado, cioè. un tipo incorporato AnyDice che è una combinazione di risultati e probabilità per il risultato.


1
Penso di essere a posto con l'esplosione non molto, il 36 byte va bene per me. Non ho detto nessun builtin e sono d'accordo con averli qui, dal momento che non è come la tua risposta a 1 o 0 byte sta vincendo. Ma benvenuti nel sito!
Rɪᴋᴇʀ

2

CJam , 19 byte

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

Spiegazione:

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 in pseudocodice:

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

Come diagramma di flusso:

Diagramma di flusso del codice

Provalo online!


2

Excel VBA, 46 byte

Grazie a @TaylorScott

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

Eseguito nella finestra di comando.

Come una funzione definita dall'utente.

Excel VBA, 108 67 byte

Function z(i)
Do
v=Int((i*Rnd)+1)
z=z+v
Loop While v=i
End Function

Puoi farlo un bel po 'usando un ciclo do.. loop whilee convertendo la funzione in una funzione finestra immediata. - Do:v=-Int(-[A1]*Rnd):t=t+v:Loop While[A1]=v:?t- 46 byte
Taylor Scott,

1
@TaylorScott Grazie, ho dimenticato che Do x Mentre y esisteva in Excel VBA.
William Porter,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.