Ваша задача - создать программу, которая принимает целое число n > 1
и выводит бросок n
кубика с одной стороной. Однако эта игра в кости следует правилам взрыва игры в кости .
Когда вы бросаете кубик, проверьте, какое значение вы бросили. Если вы получили максимум для этого вида кубика (на стандартном d4, который будет 4, или 6 на d6 и т. Д.), Бросьте снова и добавьте новый бросок к этому итогу. Каждый бросок продолжает добавляться к общему количеству, пока вы больше не бросаете максимальное число. Это окончательное число все еще добавляется, хотя.
Ваша программа должна взять одно целое число n
и бросить n
кубик с взрывающейся стороной. Вот пример дистрибутива, чтобы показать, как он должен выглядеть n=4
. Обратите внимание, что вы никогда не должны выводить кратные n
, так как они всегда будут взрываться.
Вы можете предположить, что размер стека для любой выполняемой вами рекурсии бесконечен, и ваша случайная функция должна соответствовать нашим стандартам случайности (встроенный генератор случайных чисел или время / дата ). Ваша случайная функция также должна быть как можно более равномерной по сравнению с чем-то вроде геометрического распределения, поскольку речь идет о кубиках.
Ответы:
Машинный код x86 (для Intel Ivy Bridge и более поздних версий), 17 байт
Вышеуказанные байты кода определяют функцию, которая имитирует взрывающийся кристалл. Требуется один вход, переданный в
ESI
регистр, указывающий максимальное количество кубиков. Он возвращает единственное значение вECX
регистре, которое является результатом бросков.Внутри она использует в
RDRAND
инструкцию , чтобы сгенерировать случайное число. При этом используется генератор случайных чисел (RNG), который встроен в аппаратное обеспечение процессоров Intel Ivy Bridge и более поздних версий (некоторые процессоры AMD также поддерживают эту инструкцию).Логика функции в остальном довольно проста. Сгенерированное случайное число масштабируется так, чтобы оно лежало в требуемом диапазоне, используя стандартную технику (
(rand % dieSize) + 1
), а затем проверяется, должно ли оно вызвать взрыв. Окончательный результат сохраняется в регистре аккумулятора.Вот аннотированная версия, показывающая мнемонику языка ассемблера:
Я немного изменяю . Все стандартные соглашения о вызовах 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
инструкции:Интересно, что GCC с
-Os
флагом преобразует это практически в тот же машинный код . Он принимает входные данныеEDI
вместоESI
, что совершенно произвольно и ничего не меняет в коде. Он должен возвращать результат вEAX
, как я упоминал ранее, и он использует более эффективную (но более крупную)MOV
инструкцию, чтобы сделать это непосредственно передRET
. В противном случае, Samezies. Всегда весело, когда процесс полностью обратим: напишите код на ассемблере, переписайте его на C, запустите через компилятор C и верните исходную сборку обратно!источник
Python 2 ,
666461 байт-3 байта благодаря xnor
Попробуйте онлайн!
Предыдущий список хранится в нем
c
, что позволяет нам обращаться к нему несколько раз, не сохраняя его в переменной, чего нельзя сделать в лямбда-выражении Python. Каждую рекурсию мы проверяем, бросали ли мы взрывающиеся кости.c
инициализируется в ноль, такc%n
что фальси там. В следующих итерациях это будет фальшиво только в том случае, если были брошены взрывающиеся кости.Python 2 , 55 байт
Попробуйте онлайн!
Мой другой ответ, кажется, немного чрезмерно силен, так как это, кажется, работает также ... Я все равно оставлю это.
источник
c*(c<n)
может бытьc%n
.R , 39 байт
Попробуйте онлайн!
Объяснение: это решение позволяет избежать циклов рекурсии / while, непосредственно вычисляя распределение числа взрывов, которые произойдут. ПустьN будет числом сторон на кристалле. Если вы обозначаете успех как бросок N а провал - как бросание чего-либо еще, то у вас есть вероятность 1N успеха. Общее количество взрывов - это количество успехов до первого отказа. Это соответствуетГ е о м е т р я с ( 1 - 1N) распространение (см.страницу википедии, которая, наоборот, определяет успех и неудачу). Каждый взрыв приноситN к итогу. Последний бросок следует распределениюU n я fo r m (1,2,…,n-1) которое мы добавляем к итогу.
источник
sample
Удовлетворяет ли она стандартам случайности, учитывая ее предвзятость ?sample
приводит к отсутствию единообразия, которое дает отношение максимальной и минимальной вероятности до 1,03 ... Шокирующее, не так ли ?!sample
с ? ;-)Perl 6 , 26 байт
Попробуйте онлайн!
объяснение
источник
{sum roll(*,1..$_)...$_>*}
J ,
1611 байтПопробуйте онлайн!
объяснение
TL; DR
1+?
выполняет бросок кубика,(+$:)^:=
повторяется только тогда, когда он равен входу.Функция представляет собой череду из 4 глаголов:
Поезд - это когда два или более глаголов соединяются. Здесь ответ имеет вид
f g h j
:Так называемый «4-поезд» разбирается как крюк и вилка:
Таким образом, ответ эквивалентен:
Крючки:
(f g) x
иx (f g) y
Монадический (с одним аргументом) хук из двух глаголов, если задан аргумент
x
, имеет место следующая эквивалентность:Например,
(* -) 5
оценивает до5 * (- 5)
, что оценивает до_25
.Это означает, что наш 4-поезд, крюк
f
и(g h j)
, эквивалентен:Но что
f
здесь делать?(+$:)^:=
это соединение двух глаголов с использованием питания конъюнкции^:
: другой крюк ((+$:)
) и глагол (=
). Обратите внимание, чтоf
это двоично - у него есть два аргумента (x
и(g h j) x
). Поэтому мы должны посмотреть, как^:
ведет себя. Силовое соединениеf^:o
принимает глаголf
и глагол или существительноеo
(существительное - просто часть данных) и применяетf
o
времена. Например, взятьo = 3
. Имеются следующие эквивалентности:Если
o
это глагол, степенное соединение просто оцениваетo
аргументы и использует результат существительного в качестве числа повторений.Для нашего глагола,
o
это=
глагол равенства. Он оценивает0
для различных аргументов и1
для равных аргументов. Мы повторяем хук(+$:)
один раз для одинаковых аргументов, а не раз для разных. Для удобства обозначения для объяснения, позвольтеy ⇔ ((g h j) x)
. Помните, что наш начальный хук эквивалентен этому:Расширяя соединение, это становится:
Если
x
иy
совпадают, это становится:В противном случае это становится:
Теперь мы видели монадические вилки. Здесь у нас есть диадическая вилка:
Итак, когда
x
иy
совпадают, мы получаем:Что такое
$:
? Это относится ко всему самому глаголу и допускает рекурсию. Это означает, что, когдаx
и yare the same, we apply the verb to
yand add
x` к нему.вилы:
(g h j) x
Теперь, что делает внутренняя вилка? Это было
y
в нашем последнем примере. Для монадической вилки из трех глаголов с заданным аргументом имеетx
место следующая эквивалентность:Для следующего примера предположим, что мы глаголы с именем
SUM
,DIVIDE
иLENGTH
, что делать то , что вы думаете , что они могли бы. Если мы объединяем три в форк, мы получаем:Эта разветвленность оценивается как среднее
x
(предположим,x
что это список чисел). В J мы бы написали это как пример как+/ % #
.Еще одна вещь о вилках. Когда крайний левый «зубец» (в нашем символическом случае выше
g
) является существительным, он обрабатывается как постоянная функция, возвращающая это значение.Имея все это на своем месте, теперь мы можем понять вышеупомянутый форк:
?
Собираем все вместе
Учитывая все эти вещи, наш глагол эквивалентен:
Это выражает желаемую функциональность.
источник
(+$:)^:=1+?
Желе , 7 байт
Попробуйте онлайн!
Использует рекурсию. Запускает программу снова (
ß
) и добавляет (+
), если (¡
) случайное число (X
) равно (=
) входу программы.}
заставляетß
действовать на входе программы и¥
объединяет+ß}
в одну ссылку для¡
потребления.Вот распределение 1000 выходов для n = 6, которые я собрал, используя эту программу. Построен с помощью python / matplotlib.
Вот 5000 точек данных с n = 3 на полулогическом графике, который показывает (приблизительно?) Экспоненциальное распределение.
источник
Пиф -
1211 байтИспользует функциональное время. Я чувствую, что должен быть более умный ответ, который просто имитирует распределение.
Попробуйте онлайн .
источник
Python 3 , 80 байт
Попробуйте онлайн!
источник
r.random()
возвращает 0.1-r.random()
Должно сработать.import ... as _
самый короткий!05AB1E , 10 байт
Попробуйте онлайн или проверьте списки .
10 байтов альтернатива:
Попробуйте онлайн или проверьте списки .
Хотя мне больше нравится верхняя часть, потому что в ней есть «слово»
DIÊ
, которое соответствует вызову.Объяснение:
источник
.Γ
или что-то.Wolfram Language (Mathematica) , 50 байтов
Попробуйте онлайн!
источник
R ,
4742 байтаПопробуйте онлайн!
Кредит на подход ArBo .
Еще байт длиннее, чем у Робина Райдера , иди голосуй!
источник
if
для 46 байт, но в итоге получил 52 на одном броске, что было бы невозможно при n = 4, поэтому я не знаю, происходит ли странная вещь с низким пределом рекурсии, но я думаю, что это может быть глючит. Попробуйте онлайн!Рубин , 35 байт
Попробуйте онлайн!
источник
x
переменную: попробуйте онлайн!APL (Dyalog Unicode) ,
1514 байтовПопробуйте онлайн!
источник
Haskell ,
7776 байтовПопробуйте онлайн!
Спасибо killmous за один байт.
Если бы
<|>
были в прелюдии, мы могли бы сделать лучше сMonadComprehensions
:Haskell , неконкурентный, 66 байт
Попробуйте онлайн!
источник
Python 2 , 53 байта
Попробуйте онлайн!
Использует
or
идею короткого замыкания из ответа ArBo . Выражениеrandom()*n//1
генерирует число от0
доn-1
с0
заменойn
. Онor
принимает это число, за исключением того, что оно равно нулю (Falsey), до которого оно продолжаетсяn+f(n)
.источник
Japt , 13 байт
Попытайся
Порт Арнаулда ответ . Разобрался, как сделать рекурсивный вызов;)
Транспилированный JS:
источник
N.g(f)
:)U
. Пропуск строки, похоже, тоже работает. Это хороший трюк :)Japt , 12 байт
Это может быть короче, чем решение Даны, но чертовски ужасно. Я только отправляю это, потому что это кажется навсегда, так как у нас было решение Japt, которое началось с пустой строки.
Попытайся
источник
PowerShell , 49 байт
Попробуйте онлайн!
Итерационный метод. Устанавливает ввод
$args
в$a
и$l
ast roll (сделано, чтобы мы вошли в цикл хотя бы один раз). Затем, пока последний бросок равен-eq
вводу, мы продолжаем катиться. Внутри цикла мы накапливаемся в$o
последнем броске, который обновляется путем создания диапазона от1
ввода$a
и выбора егоRandom
элемента. (Честно говоря, я немного удивлен, что это$o+=$l=
работает.) Как только мы вышли из цикла, мы уходим$o
на конвейер и вывод неявен.источник
Forth (gforth) , 72 байта
Попробуйте онлайн!
Код Объяснение
источник
Пакетная, 70 байт
Принимает ввод
n
как параметр командной строки%1
.d
текущий бросок,t
совокупный итог. Просто продолжает катиться, покаd
не станет равнымn
.источник
Желе , 9 байт
Попробуйте онлайн!
Монадическая ссылка, которая принимает n в качестве аргумента и возвращает число, сгенерированное взрывающимся n-сторонним кристаллом. Это генерирует 256 чисел от 1 до n и возвращает первую совокупную сумму, которая не кратна n. Теоретически это может вернуть 256n, но даже для двухстороннего кубика это может случиться только один раз2256 раз.
Альтернатива, которая не имеет этого ограничения:
Желе , 10 байт
Попробуйте онлайн!
Обратите внимание, что обе ссылки TIO генерируют 400 номеров, чтобы показать распределение.
источник
Python 3 ,
8172 байтаПопробуйте онлайн!
-9 байт благодаря ArBo
объяснение
источник
from random import*
вместо этого.TI-BASIC,
2823 байта-5 байт благодаря этому мета-посту!
Вход находится в
Ans
.Вывод в
Ans
и неявно печатается.Примеры:
Объяснение:
Заметки:
источник
startTmr
как больше нет необходимости, это представление теперь будет работать для версий TI-BASIC ранее, чем TI-84 +.SmileBASIC 3, 49 байтов
функция
D N OUT R
реализует взрывающиеся броски костей рекурсивно.Ungolfed
Обратите внимание, что в SmileBASIC функции могут иметь несколько возвращаемых значений. Если функция имеет одно возвращаемого значения , то
fun in OUT var
иvar = fun(in)
в точности то же самое, поэтому мы можем определить функцию вOUT
форме , а также назвать его в выражении в самом теле функции. Если бы я определил функцию так, какDEF D(N)
я должен был бы явно указатьRETURN R
в теле функции; смешивание обоих синтаксисов сэкономило мне байты.источник
PowerShell , 43 байта (итерационный метод)
Попробуйте онлайн!
PowerShell , 48 байт (рекурсивный метод)
Попробуйте онлайн!
источник
Желе , 7 байт
Монадическая ссылка, принимающая целое число,
n
, которое дает целое число.Попробуйте онлайн! Или увидеть количество105 работает
Как?
источник
SmileBASIC, 41 байт
После чтения:
Я понял, что вместо того, чтобы проверять, был ли бросок костей
n
, вы можете просто повторить, пока сумма кратнаn
.источник
AnyDice , 36 байт
Почти встроенный в язык:
Чтобы это было правильно, я должен злоупотреблять предположением о бесконечной глубине рекурсии. AnyDice ограничивает глубину рекурсии глобальным свойством максимальная глубина функции. встроенная функция взрыва, однако, использует свою собственную; Глубина взрыва - по умолчанию 2.
Добавил бы еще 25 байтов; и не соответствует требованиям, поскольку теоретически кости могут взорваться более 99 раз.
Выход функции - кристалл, т.е. встроенный тип AnyDice, который представляет собой соотношение результатов и вероятностей для результата.
источник
CJam , 19 байтов
Объяснение:
Или в псевдокоде:
Как блок-схема:
Попробуйте онлайн!
источник
Excel VBA, 46 байт
Благодаря @TaylorScott
Выполняется в командном окне.
Как пользовательская функция.
Excel VBA,
10867 байтисточник
do
..loop while
и преобразовав функцию в непосредственную оконную функцию. -Do:v=-Int(-[A1]*Rnd):t=t+v:Loop While[A1]=v:?t
- 46 байт