Распределение частот нескольких бросков кубиков

23

Учитывая два положительных целых числа aи b, выведите частотное распределение скользящих времен bштамповки aи суммирования результатов.

Распределение частот перечисляет частоту каждой возможной суммы, если каждая возможная последовательность бросков костей происходит один раз. Таким образом, частоты являются целыми числами, сумма которых равна b**a.

правила

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

Тестовые случаи

Формат: a b: output

1 6: [1, 1, 1, 1, 1, 1]
2 6: [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]
3 6: [1, 3, 6, 10, 15, 21, 25, 27, 27, 25, 21, 15, 10, 6, 3, 1]
5 2: [1, 5, 10, 10, 5, 1]
6 4: [1, 6, 21, 56, 120, 216, 336, 456, 546, 580, 546, 456, 336, 216, 120, 56, 21, 6, 1]
10 10: [1, 10, 55, 220, 715, 2002, 5005, 11440, 24310, 48620, 92368, 167860, 293380, 495220, 810040, 1287484, 1992925, 3010150, 4443725, 6420700, 9091270, 12628000, 17223250, 23084500, 30427375, 39466306, 50402935, 63412580, 78629320, 96130540, 115921972, 137924380, 161963065, 187761310, 214938745, 243015388, 271421810, 299515480, 326602870, 351966340, 374894389, 394713550, 410820025, 422709100, 430000450, 432457640, 430000450, 422709100, 410820025, 394713550, 374894389, 351966340, 326602870, 299515480, 271421810, 243015388, 214938745, 187761310, 161963065, 137924380, 115921972, 96130540, 78629320, 63412580, 50402935, 39466306, 30427375, 23084500, 17223250, 12628000, 9091270, 6420700, 4443725, 3010150, 1992925, 1287484, 810040, 495220, 293380, 167860, 92368, 48620, 24310, 11440, 5005, 2002, 715, 220, 55, 10, 1]
5 50: [1, 5, 15, 35, 70, 126, 210, 330, 495, 715, 1001, 1365, 1820, 2380, 3060, 3876, 4845, 5985, 7315, 8855, 10626, 12650, 14950, 17550, 20475, 23751, 27405, 31465, 35960, 40920, 46376, 52360, 58905, 66045, 73815, 82251, 91390, 101270, 111930, 123410, 135751, 148995, 163185, 178365, 194580, 211876, 230300, 249900, 270725, 292825, 316246, 341030, 367215, 394835, 423920, 454496, 486585, 520205, 555370, 592090, 630371, 670215, 711620, 754580, 799085, 845121, 892670, 941710, 992215, 1044155, 1097496, 1152200, 1208225, 1265525, 1324050, 1383746, 1444555, 1506415, 1569260, 1633020, 1697621, 1762985, 1829030, 1895670, 1962815, 2030371, 2098240, 2166320, 2234505, 2302685, 2370746, 2438570, 2506035, 2573015, 2639380, 2704996, 2769725, 2833425, 2895950, 2957150, 3016881, 3075005, 3131390, 3185910, 3238445, 3288881, 3337110, 3383030, 3426545, 3467565, 3506006, 3541790, 3574845, 3605105, 3632510, 3657006, 3678545, 3697085, 3712590, 3725030, 3734381, 3740625, 3743750, 3743750, 3740625, 3734381, 3725030, 3712590, 3697085, 3678545, 3657006, 3632510, 3605105, 3574845, 3541790, 3506006, 3467565, 3426545, 3383030, 3337110, 3288881, 3238445, 3185910, 3131390, 3075005, 3016881, 2957150, 2895950, 2833425, 2769725, 2704996, 2639380, 2573015, 2506035, 2438570, 2370746, 2302685, 2234505, 2166320, 2098240, 2030371, 1962815, 1895670, 1829030, 1762985, 1697621, 1633020, 1569260, 1506415, 1444555, 1383746, 1324050, 1265525, 1208225, 1152200, 1097496, 1044155, 992215, 941710, 892670, 845121, 799085, 754580, 711620, 670215, 630371, 592090, 555370, 520205, 486585, 454496, 423920, 394835, 367215, 341030, 316246, 292825, 270725, 249900, 230300, 211876, 194580, 178365, 163185, 148995, 135751, 123410, 111930, 101270, 91390, 82251, 73815, 66045, 58905, 52360, 46376, 40920, 35960, 31465, 27405, 23751, 20475, 17550, 14950, 12650, 10626, 8855, 7315, 5985, 4845, 3876, 3060, 2380, 1820, 1365, 1001, 715, 495, 330, 210, 126, 70, 35, 15, 5, 1]
Mego
источник
Можем ли мы предположить, что bэто как минимум 2? (Или, если нет, как должен выглядеть список частот для сумм одностороннего штампа?)
Миша Лавров
Можем ли мы иметь ведущие или конечные нули?
xnor

Ответы:

9

Октава , 38 байт

@(a,b)round(ifft(fft((a:a*b<a+b)).^a))

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

объяснение

Добавление независимых случайных величин соответствует свертыванию их функций вероятности (PMF) или умножению их характеристических функций (CF). Таким образом, CF суммы aнезависимых идентично распределенных переменных определяется как значение одной переменной, возведенной в степень a.

CF является по существу преобразованием Фурье PMF и, таким образом, может быть вычислено через FFT. PMF одного bодносторонняя фильеры равномерна на 1, 2, ..., b. Однако необходимы две модификации:

  • 1используется вместо фактических значений вероятности ( 1/b). Таким образом, результат будет нормализован и при необходимости будет содержать целые числа.
  • Заполнение нулями необходимо для того, чтобы вывод FFT имел соответствующий размер (a*b-a+1 ) и неявное периодическое поведение, принятое FFT, не влияло на результаты.

Как только характеристическая функция суммы получена, для вычисления конечного результата используется обратное БПФ, а для исправления погрешностей с плавающей запятой применяется округление.

пример

Рассмотрим входы a=2, b=6. Код a:a*b<a+bстроит вектор с b=6единицами, дополненными нулями до размера a*b-a+1:

[1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]

Потом fft(...)дает

[36, -11.8-3.48i, 0.228+0.147i, -0.949-1.09i, 0.147+0.321i, -0.083-0.577i, -0.083+0.577i, 0.147-0.321i, -0.949+1.09i, 0.228-0.147i, -11.8+3.48i]

Можно почти распознать функцию Sinc (преобразование Фурье прямоугольного импульса).

(...).^aподнимает каждую запись aи затем ifft(...)принимает обратное БПФ, которое дает

[1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]

Хотя результаты в этом случае являются точно целыми числами, в общем случае могут быть относительные ошибки порядка 1e-16, поэтому round(...)это необходимо.

Луис Мендо
источник
1
Я действительно впечатлен!
rahnema1
@ rahnema1 Обработка сигналов для победы!
Луис Мендо
8

Mathematica, 29 байт

Tally[Tr/@Range@#2~Tuples~#]&

Просто генерирует все возможные броски костей, берет их итоги, а затем считает. Каждая частота помечена своим значением.

Mathematica, 38 байт

CoefficientList[((x^#2-1)/(x-1))^#,x]&

Расширяет (1+x+x^2+...+x^(a-1))^bи принимает коэффициенты x. Так 1+x+x^2+...+x^(a-1)как это функция генерации для одного броска матрицы, и продукты соответствуют извилинам - добавление значений костей - результат дает распределение частот.

Миша лавров
источник
6

Haskell , 90 79 77 75 байт

Спасибо Линн за трюк с декартовым произведением . -11 байт благодаря многим трюкам на Haskell от Funky Computer Man, -2 байта от именования, -2 байта благодаря Лайкони. Предложения по игре в гольф приветствуются! Попробуйте онлайн!

import Data.List
g x=[1..x]
a!b=map length$group$sort$map sum$mapM g$b<$g a

Ungolfed

import Data.List
rangeX x = [1..x]
-- sums of all the rolls of b a-sided dice
diceRolls a b = [sum y | y <- mapM rangeX $ fmap (const b) [1..a]]
-- our dice distribution
distrib a b = [length x | x <- group(sort(diceRolls a b))]
Sherlock9
источник
Используйте $вместо того, ()чтобы сохранить 2 байта. TIO
Wheat Wizard
И не используйтеreplicate
Волшебник Пшеницы
(map length$)=(length<$>)за два байта
Майкл Кляйн
4

Pyth - 10 байт

Просто берет все возможные комбинации костей, беря декартово произведение [1, b], aвремя, суммирование и получая длину каждой группы сумм.

lM.gksM^SE

Тестирование .

Maltysen
источник
4

05AB1E , 8 байтов

LIãO{γ€g

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

Как?

LIãO {γ € g - Полная программа.

L - диапазон [1 ... вход № 1]
 I - Вход № 2.
  ã - декартова сила.
   O - Карта с суммой.
    { - Сортировать.
     γ - группа последовательных равных элементов.
      € г - Получить длину каждого
Мистер Xcoder
источник
4

R , 52 байта

function(a,b)Re(fft(fft(a:(a*b)<a+b)^a,T)/(a*b-a+1))

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

Порт решения @Luis Mendo Octave , fft(z, inverse=T)к сожалению, возвращает ненормализованное обратное БПФ, поэтому мы должны разделить на длину, а он возвращает complexвектор, поэтому мы берем только действительную часть.

Giuseppe
источник
хорошо сыграно - окупаемость вчерашней cmdscaleфигуры :-)
flodel
@ Флодель, ха! На самом деле я собираюсь наградить вас за это
Джузеппе
Вы не шутили! Так щедро с вашей стороны! Мне нравится видеть (и учиться) ваши ответы, я быстро заплачу!
flodel
3

SageMath, 40 байт

lambda a,b:reduce(convolution,[[1]*b]*a)

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

convolutionвычисляет дискретную свертку двух списков. reduceделает то, что говорит на жестяной банке. [1]*bсписок b 1s, распределение частот 1db. [[1]*b]*aделает вложенный список aкопий b 1с.


Python 2 + NumPy , 56 байт

lambda a,b:reduce(numpy.convolve,[[1]*b]*a)
import numpy

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

Я включил это решение с вышеупомянутым, так как они по существу эквивалентны. Обратите внимание, что эта функция возвращает массив NumPy, а не список Python, поэтому выходные данные выглядят немного иначе, если вы printэто сделаете .

numpy.ones((a,b))это «правильный» способ сделать массив для использования с NumPy, и, таким образом, его можно использовать вместо него [[1]*b]*a, но, к сожалению, он дольше.

Mego
источник
3

Желе , 5 байт

ṗS€ĠẈ

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

Обратите внимание, что это принимает аргументы в обратном порядке.

Как?

€S € ĠL € - Полная программа (двоичный) | Пример: 6, 2

ṗ - декартова сила (с неявным диапазоном) | [[1, 1], [1, 2], ..., [6, 6]]
 S € - Сумма каждый | [2, 3, 4, ..., 12]
   Group - Групповые индексы по значениям | [[1], [2, 7], [3, 8, 13], ..., [36]]
    L € - длина каждой группы | [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]

Альтернативные решения:

ṗZSĠL€
ṗZSµLƙ
ṗS€µLƙ
Мистер Xcoder
источник
2

Пари / ГП , 28 байт

a->b->Vec(((x^b-1)/(x-1))^a)

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

alephalpha
источник
Насколько я могу судить, это самое короткое решение, которое определенно не исчерпывает память ни в одном из предоставленных тестовых случаев.
Миша Лавров
1

JavaScript (ES6), 94 байта

f=(n,m,a=[1],b=[])=>n?[...Array(m)].map((_,i)=>a.map((e,j)=>b[j+=i]=(b[j]|0)+e))&&f(n-1,m,b):a
<div oninput=o.textContent=f(+n.value,+m.value).join`\n`><input id=n type=number min=0 value=0><input id=m type=number min=1 value=1><pre id=o>1

Ограничено 32-разрядным целочисленным переполнением, но вместо этого можно использовать числа с плавающей запятой стоимостью 1 байт.

Нил
источник
Хм ... это только один вход
Герман L
@HermanLauenstein Извините, я почему-то полностью упустил из виду эту часть вопроса ... скоро исправлю.
Нил
1

J , 25 24 21 20 байт

3 :'#/.~,+//y$i.{:y'

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

Сначала я увеличил список [0..n-1], чтобы получить [1..n], но, видимо, в этом нет необходимости.

FrownyFrog
источник
Хороший ответ. Вот молчаливая версия для таких же количества байт: #/.~@,@(+///)@$i.@{:. Кажется, должен быть способ побрить его, сделав глагол двоичным, но я не смог этого сделать.
Иона
@Jonah у вас есть дополнительный /в+//
FrownyFrog
На самом деле, вы правы. Просто так получается, что работают в обе стороны. Я думаю, что решение экономит байт тогда :)
Иона
1

Javascript (ES6), 89 байт

b=>g=a=>a?(l=[..."0".repeat(b-1),...g(a-1)]).map((_,i)=>eval(l.slice(i,i+b).join`+`)):[1]

Принимает ввод в синтаксис карри в обратном порядке f(b)(a)

f=b=>g=a=>a>0?(l=[..."0".repeat(b-1),...g(a-1)]).map((_,i)=>eval(l.slice(i,i+b).join`+`)):[1]
r=_=>{o.innerText=f(+inb.value)(+ina.value)}
<input id=ina type=number min=0 onchange="r()" value=0>
<input id=inb type=number min=1 onchange="r()" value=1>
<pre id=o></pre>

Герман Л
источник
1

На самом деле , 13 12 байт

-1 байт благодаря мистеру Xcoder. Попробуйте онлайн!

R∙♂Σ;╗╔⌠╜c⌡M

Ungolfed

                Implicit input: b, a
R∙              ath Cartesian power of [1..b]
  ♂Σ            Get all the sums of the rolls, call them dice_rolls
    ;╗          Duplicate dice_rolls and save to register 0
      ╔         Push uniquify(dice_rolls)
       ⌠  ⌡M    Map over uniquify(dice_rolls), call the variable i
        ╜         Push dice_rolls from register 0
         c        dice_rolls.count(i)
                Implict return
Sherlock9
источник
Вам не нужно @, не так ли?
г-н Xcoder
В качестве примечания я нашел интересную альтернативу:R∙♂Σ╗╜╔⌠╜c⌡M
Mr. Xcoder
1

AWK , 191 байт

Выводит частоты в виде вертикального столбца.

func p(z){for(m in z)S[z[m]]++
for(i=$1;i<=$1*$2;i++)print S[i]}func t(a,b,z,s){if(a){if(R++)for(n in z)for(i=0;i++<b;)s[n,i]=z[n]+i
else for(i=0;i++<b;)s[i]=i
t(--a,b,s)}else p(z)}{t($1,$2)}

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

Добавление еще 6 байтов позволяет использовать несколько наборов входных данных.

func p(z,S){for(m in z)S[z[m]]++
for(i=$1;i<=$1*$2;i++)print S[i]}func t(a,b,z,s){if(a){if(R++)for(n in z)for(i=0;i++<b;)s[n,i]=z[n]+i
else for(i=0;i++<b;)s[i]=i
t(--a,b,s)}else p(z)}{R=0;t($1,$2)}

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

Роберт Бенсон
источник
1

Clojure, 86 байт

#(sort-by key(frequencies(reduce(fn[r i](for[y(range %2)x r](+ x y 1)))[0](range %))))

Пример:

(def f #(...))
(f 5 4)

([5 1] [6 5] [7 15] [8 35] [9 65] [10 101] [11 135] [12 155] [13 155] [14 135] [15 101] [16 65] [17 35] [18 15] [19 5] [20 1])
NikoNyrh
источник
0

C (gcc), 142 bytes

i,j,k;int*f(a,b){int*r=malloc(sizeof(int)*(1+a*~-b));r[0]=1;for(i=1;i<=a;i++)for(j=i*~-b;j>=0;j--)for(k=1;k<b&k<=j;k++)r[j]+=r[j-k];return r;}

Try it online!

Leaky Nun
источник
sizeof(int)? Really?
orlp
@orlp environment-dependent, you know
Leaky Nun
2
It's allowed for a C program to assume a particular architecture. As long as it works on at least one machine. Furthermore, 8 would work on any architecture, overallocating a bit but that's ok.
orlp
r[0]=1;for(i=1;i<=a;i++)for(j=i*~-b; -> for(i=r[0]=1;i<=a;)for(j=i++*~-b; for -2 bytes.
Kevin Cruijssen