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


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]

Можем ли мы предположить, что 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))]

Используйте $вместо того, ()чтобы сохранить 2 байта. TIO
Wheat Wizard




(map length$)=(length<$>)за два байта
Майкл Кляйн

4

Pyth - 10 байт

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

lM.gksM^SE

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


4

05AB1E , 8 байтов

LIãO{γ€g

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

Как?

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

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


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вектор, поэтому мы берем только действительную часть.


хорошо сыграно - окупаемость вчерашней 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, но, к сожалению, он дольше.


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ƙ






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], но, видимо, в этом нет необходимости.


Хороший ответ. Вот молчаливая версия для таких же количества байт: #/.~@,@(+///)@$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

Вам не нужно @, не так ли?
г-н 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])

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!


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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.