Имитация взрыва кости

31

Ваша задача - создать программу, которая принимает целое число n > 1и выводит бросок nкубика с одной стороной. Однако эта игра в кости следует правилам взрыва игры в кости .

Когда вы бросаете кубик, проверьте, какое значение вы бросили. Если вы получили максимум для этого вида кубика (на стандартном d4, который будет 4, или 6 на d6 и т. Д.), Бросьте снова и добавьте новый бросок к этому итогу. Каждый бросок продолжает добавляться к общему количеству, пока вы больше не бросаете максимальное число. Это окончательное число все еще добавляется, хотя.

Ваша программа должна взять одно целое число nи бросить nкубик с взрывающейся стороной. Вот пример дистрибутива, чтобы показать, как он должен выглядеть n=4. Обратите внимание, что вы никогда не должны выводить кратные n, так как они всегда будут взрываться.

Вы можете предположить, что размер стека для любой выполняемой вами рекурсии бесконечен, и ваша случайная функция должна соответствовать нашим стандартам случайности (встроенный генератор случайных чисел или время / дата ). Ваша случайная функция также должна быть как можно более равномерной по сравнению с чем-то вроде геометрического распределения, поскольку речь идет о кубиках.

Rɪᴋᴇʀ
источник
1
должна ли программа быть идеальной? Может быть, его распространение может быть ограничено каким-то чрезвычайно низким количеством?
Maltysen
Кому: Райкер; RE: @ Maltysen комментарий выше; или чрезвычайно большое количество?
Артемида поддерживает Монику

Ответы:

36

Машинный код x86 (для Intel Ivy Bridge и более поздних версий), 17 байт

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

Вышеуказанные байты кода определяют функцию, которая имитирует взрывающийся кристалл. Требуется один вход, переданный в ESIрегистр, указывающий максимальное количество кубиков. Он возвращает единственное значение в ECXрегистре, которое является результатом бросков.

Внутри она использует в RDRANDинструкцию , чтобы сгенерировать случайное число. При этом используется генератор случайных чисел (RNG), который встроен в аппаратное обеспечение процессоров Intel Ivy Bridge и более поздних версий (некоторые процессоры AMD также поддерживают эту инструкцию).

Логика функции в остальном довольно проста. Сгенерированное случайное число масштабируется так, чтобы оно лежало в требуемом диапазоне, используя стандартную технику ( (rand % dieSize) + 1), а затем проверяется, должно ли оно вызвать взрыв. Окончательный результат сохраняется в регистре аккумулятора.

Вот аннотированная версия, показывающая мнемонику языка ассемблера:

           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

Я немного изменяю . Все стандартные соглашения о вызовах x86 возвращают результат функции в EAXрегистр. Но в настоящем машинном коде нет соглашений о вызовах. Вы можете использовать любые регистры, которые вы хотите для ввода / вывода. Использование ECXдля выходного регистра сэкономило мне 1 байт. Если вы хотите использовать EAX, вставьте 1-байтовую XCHG eax, ecxинструкцию непосредственно перед retинструкцией. Это свопы значений EAXи ECXрегистров, эффективно копирование результата из ECXв EAXи громя ECXсо старым значением EAX.

Попробуйте онлайн!

Вот эквивалентная функция расшифрованы в C, используя в __builtin_ia32_rdrand32_stepхарактеристической поддерживаемый GCC, Clang и ICC для создания RDRANDинструкции:

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

Интересно, что GCC с -Osфлагом преобразует это практически в тот же машинный код . Он принимает входные данные EDIвместо ESI, что совершенно произвольно и ничего не меняет в коде. Он должен возвращать результат в EAX, как я упоминал ранее, и он использует более эффективную (но более крупную) MOVинструкцию, чтобы сделать это непосредственно перед RET. В противном случае, Samezies. Всегда весело, когда процесс полностью обратим: напишите код на ассемблере, переписайте его на C, запустите через компилятор C и верните исходную сборку обратно!

Коди Грей
источник
12

Python 2 , 66 64 61 байт

-3 байта благодаря xnor

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

Попробуйте онлайн!

Предыдущий список хранится в нем c, что позволяет нам обращаться к нему несколько раз, не сохраняя его в переменной, чего нельзя сделать в лямбда-выражении Python. Каждую рекурсию мы проверяем, бросали ли мы взрывающиеся кости.

cинициализируется в ноль, так c%nчто фальси там. В следующих итерациях это будет фальшиво только в том случае, если были брошены взрывающиеся кости.

Python 2 , 55 байт

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

Попробуйте онлайн!

Мой другой ответ, кажется, немного чрезмерно силен, так как это, кажется, работает также ... Я все равно оставлю это.

ARBO
источник
2
Рекурсивные функции, в которых условие прерывания основано на случайности, всегда будут иметь ненулевую вероятность переполнения стека. Статистически незначительный шанс, но все же ...
mypetlion
3
Как правило, размер стека считается бесконечным в моих задачах по коду. Когда размер стека увеличивается до бесконечности, вероятность переполнения стека быстро сходится к нулю.
АрБо
ArBo сделайте @mypetlion перед тем, как напечатать свой комментарий, чтобы вы могли пропинговать пользователя
MilkyWay90
1
Я думаю, что c*(c<n)может быть c%n.
xnor
@xnor Конечно, я идиот ...
АрБо
12

R , 39 байт

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

Попробуйте онлайн!

Объяснение: это решение позволяет избежать циклов рекурсии / while, непосредственно вычисляя распределение числа взрывов, которые произойдут. Пусть N будет числом сторон на кристалле. Если вы обозначаете успех как бросок N а провал - как бросание чего-либо еще, то у вас есть вероятность 1N успеха. Общее количество взрывов - это количество успехов до первого отказа. Это соответствуетгеомеTряс(1-1N)распространение (см.страницу википедии, которая, наоборот, определяет успех и неудачу). Каждый взрыв приноситNк итогу. Последний бросок следует распределениюUNяеорм(1,2,...,N-1)которое мы добавляем к итогу.

Робин Райдер
источник
очень хорошо! Должен любить встроенные распределения для случайных испытаний!
Джузеппе
sampleУдовлетворяет ли она стандартам случайности, учитывая ее предвзятость ?
Сиань
@ Xi'an Довольно уверен, что это так : это встроенный генератор случайных чисел для дискретных случайных величин.
Робин Райдер
Я знаю, я знаю, но проверьте ссылку, которую я поставил: присущая ей дискретизация sampleприводит к отсутствию единообразия, которое дает отношение максимальной и минимальной вероятности до 1,03 ... Шокирующее, не так ли ?!
Сиань
Да, это шокирует. Но опять же, как часто вы используете sampleс ? ;-)м231
Робин Райдер
9

Perl 6 , 26 байт

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

Попробуйте онлайн!

объяснение

{                        } # 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
источник
2
Хорошо, мое собственное решение было{sum roll(*,1..$_)...$_>*}
Джо Кинг
9

J , 16 11 байт

(+$:)^:=1+?

Попробуйте онлайн!

объяснение

TL; DR 1+? выполняет бросок кубика, (+$:)^:=повторяется только тогда, когда он равен входу.


Функция представляет собой череду из 4 глаголов:

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

Поезд - это когда два или более глаголов соединяются. Здесь ответ имеет вид f g h j:

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

Так называемый «4-поезд» разбирается как крюк и вилка:

f g h j   ⇔   f (g h j)

Таким образом, ответ эквивалентен:

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

Крючки: (f g) xиx (f g) y

Монадический (с одним аргументом) хук из двух глаголов, если задан аргумент x, имеет место следующая эквивалентность:

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

Например, (* -) 5оценивает до 5 * (- 5), что оценивает до _25.

Это означает, что наш 4-поезд, крюк fи (g h j), эквивалентен:

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

Но что fздесь делать? (+$:)^:=это соединение двух глаголов с использованием питания конъюнкции ^:: другой крюк ( (+$:)) и глагол ( =). Обратите внимание, что fэто двоично - у него есть два аргумента ( xи (g h j) x). Поэтому мы должны посмотреть, как ^:ведет себя. Силовое соединение f^:oпринимает глагол fи глагол или существительное o(существительное - просто часть данных) и применяет f oвремена. Например, взять o = 3. Имеются следующие эквивалентности:

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

Если oэто глагол, степенное соединение просто оценивает oаргументы и использует результат существительного в качестве числа повторений.

Для нашего глагола, oэто =глагол равенства. Он оценивает 0для различных аргументов и 1для равных аргументов. Мы повторяем хук (+$:)один раз для одинаковых аргументов, а не раз для разных. Для удобства обозначения для объяснения, позвольте y ⇔ ((g h j) x). Помните, что наш начальный хук эквивалентен этому:

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

Расширяя соединение, это становится:

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

Если xи yсовпадают, это становится:

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

В противном случае это становится:

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

Теперь мы видели монадические вилки. Здесь у нас есть диадическая вилка:

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

Итак, когда xи yсовпадают, мы получаем:

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

Что такое $:? Это относится ко всему самому глаголу и допускает рекурсию. Это означает, что, когда xи y are the same, we apply the verb toy and addx` к нему.

вилы: (g h j) x

Теперь, что делает внутренняя вилка? Это было yв нашем последнем примере. Для монадической вилки из трех глаголов с заданным аргументом имеет xместо следующая эквивалентность:

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

Для следующего примера предположим, что мы глаголы с именем SUM, DIVIDEи LENGTH, что делать то , что вы думаете , что они могли бы. Если мы объединяем три в форк, мы получаем:

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

Эта разветвленность оценивается как среднее x(предположим, xчто это список чисел). В J мы бы написали это как пример как +/ % #.

Еще одна вещь о вилках. Когда крайний левый «зубец» (в нашем символическом случае выше g) является существительным, он обрабатывается как постоянная функция, возвращающая это значение.

Имея все это на своем месте, теперь мы можем понять вышеупомянутый форк:

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

?[0,Икс)[1,Икс]

Собираем все вместе

Учитывая все эти вещи, наш глагол эквивалентен:

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

Это выражает желаемую функциональность.

Конор О'Брайен
источник
1
(+$:)^:=1+?­­
СПП
@ngn Спасибо! Incorporated.
Конор О'Брайен
7

Желе , 7 байт

X+ß}¥=¡

Попробуйте онлайн!

Использует рекурсию. Запускает программу снова ( ß) и добавляет ( +), если ( ¡) случайное число ( X) равно ( =) входу программы. }заставляет ßдействовать на входе программы и ¥объединяет +ß}в одну ссылку для ¡потребления.

Вот распределение 1000 выходов для n = 6, которые я собрал, используя эту программу. Построен с помощью python / matplotlib. гистограмма

Вот 5000 точек данных с n = 3 на полулогическом графике, который показывает (приблизительно?) Экспоненциальное распределение. введите описание изображения здесь

dylnan
источник
Хорошие участки! Распределение, которое вы получаете, является геометрическим распределением (см. Мой ответ R ), которое тесно связано с экспоненциальным распределением.
Робин Райдер
6

Пиф - 12 11 байт

Использует функциональное время. Я чувствую, что должен быть более умный ответ, который просто имитирует распределение.

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

Попробуйте онлайн .

Maltysen
источник
4

Python 3 , 80 байт

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

Попробуйте онлайн!

Линн
источник
1
Тем не менее , существует небольшая вероятность неудачи, если она r.random()возвращает 0. 1-r.random()Должно сработать.
nwellnhof
Хотя технически этот шанс равен 0
Quintec
1
Редкий случай, когда import ... as _самый короткий!
xnor
@ xnor действительно! Единственный раз, когда я помню, что победа в моем ответе здесь
Линн
4

05AB1E , 10 байт

[ILΩDIÊ#}O

Попробуйте онлайн или проверьте списки .

10 байтов альтернатива:

[LΩDˆÊ#}¯O

Попробуйте онлайн или проверьте списки .

Хотя мне больше нравится верхняя часть, потому что в ней есть «слово» DIÊ, которое соответствует вызову.

Объяснение:

[         # 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)  
Кевин Круйссен
источник
Пытался придумать способ использования или что-то.
Волшебная Урна Осьминога
3

R , 47 42 байта

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

Попробуйте онлайн!

Кредит на подход ArBo .

Еще байт длиннее, чем у Робина Райдера , иди голосуй!

Giuseppe
источник
Интересно, что я переработал это в рекурсив ifдля 46 байт, но в итоге получил 52 на одном броске, что было бы невозможно при n = 4, поэтому я не знаю, происходит ли странная вещь с низким пределом рекурсии, но я думаю, что это может быть глючит. Попробуйте онлайн!
Преступно-
Я попытался рекурсивно и получил 54-байтовое решение. Тогда попробовал что-то похожее на твое за 44 Попробуйте онлайн!
Аарон Хейман
3

Haskell , 77 76 байтов

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

Попробуйте онлайн!

Спасибо killmous за один байт.

Если бы <|>были в прелюдии, мы могли бы сделать лучше с MonadComprehensions:

Haskell , неконкурентный, 66 байт

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

Попробуйте онлайн!

dfeuer
источник
1
Вы можете сохранить байт, если определили g как инфиксную функцию.
killmous
1
@killmous, спасибо. На первый взгляд я подумал, что будет то же самое или хуже, но лучше.
dfeuer
3

Python 2 , 53 байта

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

Попробуйте онлайн!

Использует orидею короткого замыкания из ответа ArBo . Выражение random()*n//1генерирует число от 0до n-1с 0заменой n. Он orпринимает это число, за исключением того, что оно равно нулю (Falsey), до которого оно продолжается n+f(n).

XNOR
источник
Кажется, твой ответ уже был готов, когда я отредактировал свой более короткий ... Я не видел этого, но если ты хочешь, чтобы я удалил его, потому что это довольно похоже, я сделаю.
АрБо
3

Japt , 13 байт

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

Попытайся

Порт Арнаулда ответ . Разобрался, как сделать рекурсивный вызов;)

Транспилированный 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
источник
1
Очень хорошее использование N.g(f):)
Shaggy
Я попробовал сделать это сам и получил 12 байт, но я не хочу его публиковать, потому что мне слишком нравится ваше решение!
лохматый
Опубликовать как другой ответ :)
Дана
Это может быть короче, но это намного ужаснее, чем у вас: petershaggynoble.github.io/Japt-Interpreter/…
Shaggy
Я вижу - да, я пытался придумать способ не загрязнять U. Пропуск строки, похоже, тоже работает. Это хороший трюк :)
Дана
3

Japt , 12 байт

Это может быть короче, чем решение Даны, но чертовски ужасно. Я только отправляю это, потому что это кажется навсегда, так как у нас было решение Japt, которое началось с пустой строки.


ö
>°V©VªV+ß

Попытайся

мохнатый
источник
2

PowerShell , 49 байт

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

Попробуйте онлайн!

Итерационный метод. Устанавливает ввод $argsв $aи $last roll (сделано, чтобы мы вошли в цикл хотя бы один раз). Затем, пока последний бросок равен -eqвводу, мы продолжаем катиться. Внутри цикла мы накапливаемся в $oпоследнем броске, который обновляется путем создания диапазона от 1ввода $aи выбора его Randomэлемента. (Честно говоря, я немного удивлен, что это $o+=$l=работает.) Как только мы вышли из цикла, мы уходим$o на конвейер и вывод неявен.

AdmBorkBork
источник
2

Forth (gforth) , 72 байта

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

Попробуйте онлайн!

Код Объяснение

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
источник
2

Пакетная, 70 байт

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

Принимает ввод nкак параметр командной строки %1. dтекущий бросок, tсовокупный итог. Просто продолжает катиться, пока dне станет равным n.

Нил
источник
2

Желе , 9 байт

x⁹X€Ä%ƇµḢ

Попробуйте онлайн!

Монадическая ссылка, которая принимает n в качестве аргумента и возвращает число, сгенерированное взрывающимся n-сторонним кристаллом. Это генерирует 256 чисел от 1 до n и возвращает первую совокупную сумму, которая не кратна n. Теоретически это может вернуть 256n, но даже для двухстороннего кубика это может случиться только один раз2256 раз.

Альтернатива, которая не имеет этого ограничения:

Желе , 10 байт

X³X¤+¥³ḍ¥¿

Попробуйте онлайн!

Обратите внимание, что обе ссылки TIO генерируют 400 номеров, чтобы показать распределение.

Ник Кеннеди
источник
2

Python 3 , 81 72 байта

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

Попробуйте онлайн!

-9 байт благодаря ArBo

объяснение

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
Артемида поддерживает Монику
источник
Вы можете сохранить 1 байт, используя from random import*вместо этого.
ортоплекс
1
Вы можете уменьшить это до 74 байтов, используя это рекурсивное решение
Восстановите Монику
1
@squid Вы можете сохранить 1 байт, как это .
ортоплекс
1
@orthoplex, а затем вы можете сократить if / else и сделать его однострочным . Начинает выглядеть как мое решение;)
АрБо
1
@ArBo Да, именно поэтому я не стал рекурсивным, не хотел просто копировать тебя.
Артемида поддерживает Монику
2

TI-BASIC, 28 23 байта

-5 байт благодаря этому мета-посту!

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

Вход находится в Ans .
Вывод в Ansи неявно печатается.

Примеры:

4
              4
prgmCDGF11
              5
6
              6
prgmCDGF11
              3

Объяснение:

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"

Заметки:

  • TI-BASIC - это токенизированный язык. Количество символов не равно количеству байтов.
Тау
источник
Так startTmrкак больше нет необходимости, это представление теперь будет работать для версий TI-BASIC ранее, чем TI-84 +.
Тау
2

SmileBASIC 3, 49 байтов

функция D N OUT R реализует взрывающиеся броски костей рекурсивно.

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

Обратите внимание, что в SmileBASIC функции могут иметь несколько возвращаемых значений. Если функция имеет одно возвращаемого значения , то fun in OUT varи var = fun(in)в точности то же самое, поэтому мы можем определить функцию в OUTформе , а также назвать его в выражении в самом теле функции. Если бы я определил функцию так, как DEF D(N)я должен был бы явно указать RETURN Rв теле функции; смешивание обоих синтаксисов сэкономило мне байты.

snail_
источник
2

Желе , 7 байт

X=п⁸S_

Монадическая ссылка, принимающая целое число, n , которое дает целое число.

Попробуйте онлайн! Или увидеть количество105 работает

Как?

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 байт

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

После чтения:

Обратите внимание, что вы никогда не должны выводить кратные n, так как они всегда будут взрываться.

Я понял, что вместо того, чтобы проверять, был ли бросок костей n, вы можете просто повторить, пока сумма кратна n.

12Me21
источник
2

AnyDice , 36 байт

Почти встроенный в язык:

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

Чтобы это было правильно, я должен злоупотреблять предположением о бесконечной глубине рекурсии. AnyDice ограничивает глубину рекурсии глобальным свойством максимальная глубина функции. встроенная функция взрыва, однако, использует свою собственную; Глубина взрыва - по умолчанию 2.

set "explode depth" to 99

Добавил бы еще 25 байтов; и не соответствует требованиям, поскольку теоретически кости могут взорваться более 99 раз.

Выход функции - кристалл, т.е. встроенный тип AnyDice, который представляет собой соотношение результатов и вероятностей для результата.

Taemyr
источник
1
Я думаю, что я в порядке с этим, не взрывающимся много, 36-байтовый один прекрасен мной. Я не сказал, что нет встроенных функций, и я согласен, что они здесь, потому что это не значит, что ваш 1 или 0 байтовый ответ побеждает. Но добро пожаловать на сайт!
Rɪᴋᴇʀ
2

CJam , 19 байтов

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

Объяснение:

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

Или в псевдокоде:

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

Как блок-схема:

Блок-схема кода

Попробуйте онлайн!

лолад
источник
2

Excel VBA, 46 байт

Благодаря @TaylorScott

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

Выполняется в командном окне.

Как пользовательская функция.

Excel VBA, 108 67 байт

Function z(i)
Do
v=Int((i*Rnd)+1)
z=z+v
Loop While v=i
End Function
уильям портер
источник
Вы можете немного разобраться с этим, используя цикл do.. loop whileи преобразовав функцию в непосредственную оконную функцию. - Do:v=-Int(-[A1]*Rnd):t=t+v:Loop While[A1]=v:?t- 46 байт
Тейлор Скотт
1
@TaylorScott Спасибо, я забыл, что Do x в то время как y существовал в Excel VBA.
Уильям Портер