Simulation de dés explosant

31

Votre tâche consiste à créer un programme qui accepte un nombre entier n > 1et génère le jet d'un ndé simple face. Cependant, ce dé suit les règles pour exploser les dés .

Lorsque vous lancez le dé, vérifiez quelle valeur vous avez lancée. Si vous avez obtenu le maximum pour ce type de dé (sur un d4 standard qui serait 4, ou 6 sur un d6, etc.), relancez et ajoutez le nouveau jet à ce total. Chaque jet continue à s'ajouter au total, jusqu'à ce que vous n'obteniez plus le nombre maximum. Ce nombre final est encore ajouté cependant.

Votre programme doit prendre un seul entier net lancer le ndé à explosion . Voici un exemple de distribution pour montrer à quoi cela devrait ressembler n=4. Notez que vous ne devez jamais sortir de multiples n, car ils exploseront toujours.

Vous pouvez supposer que la taille de la pile pour toute récursion que vous faites est infinie, et votre fonction aléatoire doit répondre à nos normes d'aléatoire (générateur aléatoire intégré ou heure / date ). Votre fonction aléatoire devrait également être aussi uniforme que possible, par rapport à quelque chose comme une distribution géométrique, car ce sont des dés dont nous parlons.

Rɪᴋᴇʀ
la source
1
le programme doit-il être parfait? Comme sa distribution peut-elle être coupée d'une quantité extrêmement faible?
Maltysen
À: Riker; RE: @ Commentaire de Maltysen ci-dessus; ou un montant extrêmement élevé?
Artemis prend en charge Monica le
2
@ArtemisFowl Voir nos normes d'aléatoire. En outre, ici .
Rɪᴋᴇʀ

Réponses:

36

Code machine x86 (pour Intel Ivy Bridge et versions ultérieures), 17 octets

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

Les octets de code ci-dessus définissent une fonction qui simule une matrice qui explose. Il faut une seule entrée, passée dans le ESIregistre, indiquant le nombre maximum de dé. Il renvoie une seule valeur dans le ECXregistre, qui est le résultat des rouleaux.

En interne, il utilise l' RDRANDinstruction pour générer un nombre aléatoire. Celui-ci utilise un générateur de nombres aléatoires (RNG) intégré au matériel des processeurs Intel Ivy Bridge et ultérieurs (certains processeurs AMD prennent également en charge cette instruction).

La logique de la fonction est par ailleurs assez simple. Le nombre aléatoire généré est mis à l'échelle pour se situer dans la plage souhaitée à l'aide de la technique standard ( (rand % dieSize) + 1), puis il est vérifié pour voir s'il doit provoquer une explosion. Le résultat final est conservé dans un registre accumulateur.

Voici une version annotée montrant les mnémoniques du langage assembleur:

           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

Je triche un peu . Toutes les conventions d'appel x86 standard renvoient le résultat d'une fonction dans le EAXregistre. Mais, dans le vrai code machine, il n'y a pas de convention d'appel. Vous pouvez utiliser tous les registres que vous souhaitez pour les entrées / sorties. L'utilisation ECXdu registre de sortie m'a sauvé 1 octet. Si vous souhaitez utiliser EAX, insérez une XCHG eax, ecxinstruction de 1 octet juste avant l' retinstruction. Cela permute les valeurs des registres EAXet ECX, copiant efficacement le résultat de ECXdans EAXet supprimant ECXl'ancienne valeur de EAX.

Essayez-le en ligne!

Voici la fonction équivalente transcrite en C, utilisant l' __builtin_ia32_rdrand32_stepintrinsèque pris en charge par GCC, Clang et ICC pour générer l' RDRANDinstruction:

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

Fait intéressant, GCC avec le -Osdrapeau transforme cela en presque exactement le même code machine . Il prend l'entrée au EDIlieu de ESI, ce qui est complètement arbitraire et ne change rien de fond sur le code. Il doit retourner le résultat dans EAX, comme je l'ai mentionné précédemment, et il utilise l' MOVinstruction plus efficace (mais plus grande) pour le faire immédiatement avant le RET. Sinon, samezies. C'est toujours amusant lorsque le processus est entièrement réversible: écrivez le code dans l'assembly, transcrivez-le en C, exécutez-le via un compilateur C et récupérez votre assembly d'origine!

Cody Grey
la source
12

Python 2 , 66 64 61 octets

-3 octets grâce à xnor

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

Essayez-le en ligne!

Le rouleau précédent est stocké dans c, ce qui nous permet d'y accéder plusieurs fois sans avoir à le stocker dans une variable, ce qui ne peut pas être fait dans un lambda Python. À chaque récursivité, nous vérifions si nous avons lancé des dés explosifs.

cest initialisé à zéro, il en c%nest de même pour Falsey. Dans les prochaines itérations, ce ne sera falsey que si des dés explosifs étaient lancés.

Python 2 , 55 octets

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

Essayez-le en ligne!

Mon autre réponse semble être un peu trop technique, car cela semble fonctionner aussi bien ... Je vais le laisser quand même.

ArBo
la source
2
Les fonctions récursives où la condition de rupture est basée sur l'aléatoire auront toujours une chance non nulle de débordement de pile.
Chance
3
En règle générale, la taille de la pile est supposée infinie dans les défis de golf de code selon mon expérience. Lorsque la taille de la pile augmente à l'infini, la probabilité d'un débordement de pile converge rapidement vers zéro.
ArBo
ArBo do @mypetlion avant de taper votre commentaire pour pouvoir envoyer une requête ping à l'utilisateur
MilkyWay90
1
Je pense que c'est c*(c<n)possible c%n.
xnor
@xnor Bien sûr, je suis un idiot ...
ArBo
12

R , 39 octets

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

Essayez-le en ligne!

Explication: cette solution évite les boucles recursion / while en calculant directement la distribution du nombre d'explosions qui se produiront. Soit le nombre de faces du dé. Si vous dénotez le succès comme un et l'échec comme quoi que ce soit d'autre, alors vous avez une probabilité de succès. Le nombre total d'explosions est le nombre de succès avant le premier échec. Cela correspond à une distribution (voir la page wikipedia , qui définit le succès et l'échec dans l'autre sens). Chaque explosion porte au total. Le jet final suit unnn1nGeometric(11n)nUniform(1,2,,n-1)nUniform(1,2,,n1) distribution que nous ajoutons au total.

Robin Ryder
la source
très agréable! Je dois aimer les distributions intégrées pour des défis aléatoires !
Giuseppe
Répond-il sampleaux normes de hasard, étant donné son biais ?
Xi'an
@ Xi'an Je suis sûr que c'est le cas : c'est le générateur aléatoire intégré pour les variables aléatoires discrètes.
Robin Ryder
Je sais, je sais, mais vérifiez le lien que j'ai mis: la discrétisation inhérente à sampleconduit à un manque d'uniformité qui donne un rapport de probabilité max / min aussi élevé que 1,03 ... Choc, n'est-ce pas?!
Xi'an
Oui, c'est choquant. Mais encore une fois, à quelle fréquence utilisez-vous sampleavec ? ;-)m231
Robin Ryder
9

Perl 6 , 26 octets

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

Essayez-le en ligne!

Explication

{                        } # 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
la source
2
Agréable, ma propre solution était{sum roll(*,1..$_)...$_>*}
Jo King
9

J , 16 11 octets

(+$:)^:=1+?

Essayez-le en ligne!

Explication

TL; DR 1+? effectue le jet de dé, (+$:)^:=réitère uniquement lorsqu'il est égal à l'entrée.


La fonction est un train de 4 verbes:

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

Un train, c'est quand 2 verbes ou plus sont concaténés. Ici, la réponse est de la forme f g h j:

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

Un soi-disant "4-train" est analysé comme un crochet et une fourchette:

f g h j   ⇔   f (g h j)

Ainsi, la réponse équivaut à:

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

Crochets: (f g) xetx (f g) y

Un crochet monadique (un argument) de deux verbes, étant donné un argument x, l'équivalence suivante est valable:

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

Par exemple, (* -) 5évalue à 5 * (- 5), qui évalue à _25.

Cela signifie que notre 4-train, un crochet de fet (g h j), équivaut à:

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

Mais que fait f-on ici? (+$:)^:=est une conjonction de deux verbes utilisant la conjonction Power^: : un autre hook ( (+$:)) et un verbe ( =). Notez ici que fc'est dyadique - il a deux arguments ( xet (g h j) x). Nous devons donc regarder comment ^:se comporte. La conjonction de puissance f^:oprend un verbe fet soit un verbe soit un nom o(un nom n'est qu'un élément de données) et applique des f otemps. Par exemple, prenez o = 3. Les équivalences suivantes sont valables:

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

Si oest un verbe, la conjonction de puissance évaluera simplement oles arguments et utilisera le résultat du nom comme nombre de répétitions.

Pour notre verbe, oest =, le verbe d'égalité. Il évalue à 0des arguments différents et à 1des arguments égaux. Nous répétons le crochet (+$:)une fois pour des arguments égaux et pas de temps pour des arguments différents. Pour faciliter la notation de l'explication, let y ⇔ ((g h j) x). N'oubliez pas que notre crochet initial est équivalent à ceci:

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

En élargissant la conjonction, cela devient:

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

Si xet ysont les mêmes, cela devient:

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

Sinon, cela devient:

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

Maintenant, nous avons vu des fourches monadiques. Ici, nous avons une fourche dyadique:

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

Donc, quand xet ysont les mêmes, nous obtenons:

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

Qu'est-ce que c'est $:? Il fait référence à l'ensemble du verbe lui-même et permet la récursivité. Cela signifie que, quand xet y are the same, we apply the verb toy and addx` à elle.

Fourches: (g h j) x

Maintenant, que fait la fourche intérieure? C'était ydans notre dernier exemple. Pour une fourche monadique de trois verbes, étant donné un argument x, l'équivalence suivante est vérifiée:

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

Pour cet exemple suivant, supposons que nous avons des verbes du nom SUM, DIVIDEet LENGTHqui font ce que vous supposez qu'ils pourraient. Si nous concaténons les trois en une fourchette, nous obtenons:

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

Cette fourchette est évaluée à la moyenne de x(en supposant qu'il xs'agit d'une liste de nombres). En J, nous écrivions en fait ceci comme exemple +/ % #.

Une dernière chose à propos des fourches. Lorsque la "dent" la plus à gauche (dans notre cas symbolique ci-dessus, g) est un nom, elle est traitée comme une fonction constante renvoyant cette valeur.

Avec tout cela en place, nous pouvons maintenant comprendre la fourchette ci-dessus:

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

?donne ici un entier aléatoire dans la plage , nous devons donc transformer la plage pour représenter les dés; l'incrémentation donne la plage .[0,x)[1,x]

Mettre tous ensemble

Compte tenu de toutes ces choses, notre verbe équivaut à:

((+$:)^:=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

Cela exprime la fonctionnalité souhaitée.

Conor O'Brien
la source
1
(+$:)^:=1+?­­
ngn
@ngn Merci! Incorporé.
Conor O'Brien le
7

Gelée , 7 octets

X+ß}¥=¡

Essayez-le en ligne!

Utilise la récursivité. Exécute à nouveau le programme ( ß) et ajoute ( +) si ( ¡) le nombre aléatoire ( X) est égal ( =) à l'entrée du programme. }fait ßagir sur l'entrée du programme et se ¥combine +ß}en un seul lien pour ¡consommer.

Voici une distribution de 1000 sorties pour n = 6 que j'ai collectées à l'aide de ce programme. Tracé avec python / matplotlib. histogramme

Voici 5000 points de données de n = 3 sur un graphique semi-journal qui montre la distribution exponentielle (approximativement?). entrez la description de l'image ici

dylnan
la source
Belles parcelles! La distribution que vous obtenez est une distribution géométrique (voir ma réponse R ), qui est étroitement liée à la distribution exponentielle.
Robin Ryder
6

Pyth - 12 11 octets

Utilise tout fonctionnel. Je pense qu'il devrait y avoir une réponse plus intelligente qui simule simplement la distribution.

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

Essayez-le en ligne .

Maltysen
la source
4

Python 3 , 80 octets

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

Essayez-le en ligne!

Lynn
la source
1
Il y a une légère chance d'échec s'il r.random()arrive de retourner 0. 1-r.random()devrait fonctionner, cependant.
nwellnhof
Bien que techniquement cette chance soit de 0
Quintec
1
Un cas rare où import ... as _est le plus court!
xnor
@xnor en effet! La seule autre fois où je me souviens que gagner dans une de mes réponses est ici
Lynn
4

05AB1E , 10 octets

[ILΩDIÊ#}O

Essayez-le en ligne ou vérifiez les listes .

Alternative de 10 octets:

[LΩDˆÊ#}¯O

Essayez-le en ligne ou vérifiez les listes .

Bien que j'aime encore le top parce qu'il contient le «mot» DIÊ, ce qui convient au défi.

Explication:

[         # 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
la source
J'essayais de penser à une façon d'utiliser ou quelque chose.
Urne de poulpe magique
3

R , 47 42 octets

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

Essayez-le en ligne!

Crédit à l'approche d' ArBo .

Encore un octet de plus que celui de Robin Ryder , votez pour le sien!

Giuseppe
la source
Intéressant, j'ai retravaillé ceci pour un récursif ifpour 46 octets, mais j'ai fini par obtenir un 52 sur un rouleau qui ne devrait pas être possible avec n = 4, donc je ne sais pas s'il se passe une chose étrange avec une limite de récursivité basse, mais je pense qu'il peut être buggé. Essayez-le en ligne!
CriminallyVulgar
J'ai essayé un récursif et j'ai obtenu une solution de 54 octets. Essayez
Aaron Hayman
3

Haskell , 77 76 octets

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

Essayez-le en ligne!

Merci à killmous pour un octet.

Si nous <|>étions dans le prélude, nous pourrions faire mieux avec MonadComprehensions:

Haskell , non concurrent, 66 octets

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

Essayez-le en ligne!

dfeuer
la source
1
Vous pouvez enregistrer un octet si vous définissez g comme une fonction d'infixe.
killmous
1
@killmous, merci. À première vue, j'ai pensé que ce serait le même ou pire, mais c'est mieux.
dfeuer
3

Python 2 , 53 octets

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

Essayez-le en ligne!

Utilise l' oridée de court-circuit de la réponse d' ArBo . L'expression random()*n//1génère un nombre de 0à n-1, en 0prenant la place d'un rouleau de n. Le orprend ce nombre, sauf s'il est nul (Falsey), il continue n+f(n).

Xnor
la source
Il semble que votre réponse était déjà en place lorsque j'ai édité dans ma version la plus courte ... Je ne l'ai pas vue, mais si vous voulez que je la supprime parce qu'elle est assez similaire, je le ferai.
ArBo
3

Japt , 13 octets

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

L'essayer

Réponse du port d' Arnauld . Compris comment passer un appel récursif;)

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
   })
Dana
la source
1
Très belle utilisation de N.g(f):)
Shaggy
J'ai essayé ce moi et je me suis retrouvé avec 12 octets mais je ne veux pas le poster parce que j'aime trop votre solution!
Shaggy
Postez-le comme une réponse différente :)
dana
Il peut être plus court, mais c'est beaucoup plus laid que le vôtre: petershaggynoble.github.io/Japt-Interpreter/…
Shaggy
Je vois - ouais j'essayais de trouver un moyen de ne pas polluer U. Sauter une ligne semble également fonctionner. C'est une bonne astuce :)
dana
3

Japt , 12 octets

C'est peut-être plus court que la solution de Dana, mais c'est beaucoup plus laid. Je ne le poste que parce que cela semble éternel car nous avions une solution Japt qui commençait avec une ligne vide.


ö
>°V©VªV+ß

L'essayer

Hirsute
la source
2

PowerShell , 49 octets

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

Essayez-le en ligne!

Méthode itérative. Définit l'entrée $argspour $aet le $lrouleau ast (fait pour que nous entrons dans la boucle au moins une fois). Ensuite, tant que le dernier rouleau est -equal à l'entrée, nous continuons à rouler. À l'intérieur de la boucle, nous nous accumulons dans $ole dernier rouleau, qui est mis à jour en créant une plage de 1à l'entrée $aet en sélectionnant un Randomélément de celle-ci. (Honnêtement, je suis un peu surpris que cela $o+=$l=fonctionne.) Une fois que nous sommes hors de la boucle, nous partons $osur le pipeline et la sortie est implicite.

AdmBorkBork
la source
2

Forth (gforth) , 72 octets

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

Essayez-le en ligne!

Explication du code

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
la source
2

Lot, 70 octets

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

Prend l'entrée ncomme paramètre de ligne de commande %1. dest le rôle actuel, tle total cumulé. Continue simplement à rouler jusqu'à ce qu'il dne soit pas égal à n.

Neil
la source
2

Python 3 , 81 72 octets

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

Essayez-le en ligne!

-9 octets grâce à ArBo

Explication

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 soutient Monica
la source
Vous pouvez enregistrer 1 octet en utilisant à la from random import*place.
orthoplex
1
Vous pouvez le réduire à 74 octets en utilisant cette solution récursive
Réinstallez Monica le
1
@squid Vous pouvez enregistrer 1 octet comme celui-ci .
orthoplex
1
@orthoplex et puis vous pouvez raccourcir le if / else, et en faire un one-liner . Commence alors à ressembler à ma solution;)
ArBo
1
@ArBo Oui, c'est pourquoi je ne suis pas passé à récursif, je ne voulais pas simplement vous copier.
Artemis prend en charge Monica le
2

TI-BASIC, 28 23 octets

-5 octets grâce à ce meta post!

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

L'entrée est en Ans.
La sortie est en Anset est implicitement imprimée.

Exemples:

4
              4
prgmCDGF11
              5
6
              6
prgmCDGF11
              3

Explication:

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"

Remarques:

  • TI-BASIC est un langage tokenisé. Le nombre de caractères n'est pas égal au nombre d'octets.
Tau
la source
Puisqu'il startTmrn'est plus nécessaire, cette soumission fonctionnera désormais pour les versions de TI-BASIC antérieures à la TI-84 +
Tau
2

SmileBASIC 3, 49 octets

La fonction D N OUT Rimplémente récursivement les jets de dés explosifs.

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

Notez que dans SmileBASIC, les fonctions peuvent avoir plusieurs valeurs de retour. Si une fonction a une valeur de retour alors fun in OUT varet var = fun(in)sont exactement les mêmes, c'est pourquoi nous pouvons définir la fonction sous OUTforme et également l'appeler dans une expression dans le corps de la fonction elle-même. Si j'avais défini la fonction comme DEF D(N)je l'aurais dit explicitement RETURN Rdans le corps de la fonction; le mélange des deux syntaxes m'a fait gagner des octets.

escargot_
la source
2

Gelée , 7 octets

X=п⁸S_

Un lien monadique acceptant un entier n, ce qui donne un entier.

105

Comment?

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
la source
2

SmileBASIC, 41 octets

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

Après avoir lu:

Notez que vous ne devez jamais sortir de multiples de n, car ils exploseront toujours.

J'ai réalisé que plutôt que de vérifier si un lancer de dés était n, vous pouvez simplement répéter alors que la somme est un multiple de n.

12Me21
la source
2

AnyDice , 36 octets

Presque intégré dans la langue:

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

Pour que cela soit correct, je dois abuser de l'hypothèse de profondeur de récursion infinie. AnyDice limite la profondeur de récursivité avec une profondeur de fonction maximale de propriété globale. la fonction explode intégrée utilise cependant la sienne; profondeur d'explosion - par défaut 2.

set "explode depth" to 99

Ajouterait encore 25 octets; et ne correspondrait pas vraiment aux exigences car il est théoriquement possible qu'un dé explose plus de 99 fois.

La sortie de la fonction est un dé, c'est-à-dire. un type intégré AnyDice qui est une comparaison des résultats et des probabilités du résultat.

Taemyr
la source
1
Je pense que je suis d'accord avec ça n'explose pas beaucoup, celui de 36 octets me convient. Je n'ai pas dit non intégré et je suis d'accord avec les avoir ici, car ce n'est pas comme si votre réponse à 1 ou 0 octet gagnait. Mais bienvenue sur le site!
Rɪᴋᴇʀ
2

CJam , 19 octets

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

Explication:

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 en pseudocode:

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

En tant qu'organigramme:

Organigramme du code

Essayez-le en ligne!

lolade
la source
2

Excel VBA, 46 octets

Merci à @TaylorScott

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

Exécuté dans la fenêtre de commande.

En tant que fonction définie par l'utilisateur.

Excel VBA, 108 67 octets

Function z(i)
Do
v=Int((i*Rnd)+1)
z=z+v
Loop While v=i
End Function
William Porter
la source
Vous pouvez obtenir cela un peu en utilisant une boucle do.. loop whileet en convertissant la fonction en une fonction de fenêtre immédiate. - Do:v=-Int(-[A1]*Rnd):t=t+v:Loop While[A1]=v:?t- 46 octets
Taylor Scott
1
@TaylorScott Merci, j'ai oublié que Do x While y existait dans Excel VBA.
william porter