Частотний розподіл кількох рулонів кісток


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, не впливає на результати.

Після отримання характерної функції суми, для обчислення кінцевого результату використовується обернена 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(...)приймає зворотний FFT, який дає

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

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


1
Я справді вражений!
rahnema1

@ rahnema1 Обробка сигналу на виграш!
Луїс Мендо

8

Математика, 29 байт

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

Просто генерує всі можливі рулони кісток, бере їх підсумки, а потім підраховує. Кожна частота позначається своїм значенням.

Математика, 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 байт

Завдяки Lynn за декартовий трюк продукту . -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

Безумовно

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
Пшеничний майстер




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

4

Pyth - 10 байт

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

lM.gksM^SE

Тестовий сюїт .


4

05AB1E , 8 байт

LIãO{γ€g

Спробуйте в Інтернеті!

Як?

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

L - Діапазон [1 ... вхід №1]
 Я - Введення №2.
  ã - декартові сили.
   O - Карта з сумою.
    {- Сортувати.
     γ - Групуйте послідовні рівні елементи.
      € г - Отримайте довжину кожного


4

R , 52 байти

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

Спробуйте в Інтернеті!

Порт рішення @Luis Mendo's Octave , fft(z, inverse=T)на жаль, повертає ненормалізовану обернену FFT, тому ми повинні ділити на довжину, і він повертає 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 1s.


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]
   Ġ - Групові індекси за значеннями | [[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], але, мабуть, це не потрібно.


Nice answer. Here's a tacit version for same number of bytes: #/.~@,@(+///)@$i.@{:. Seems like there should be a way to shave it down a bit more making the verb dyadic, but I wasn't able to do it.
Jonah

@Jonah you have an extra / in +//
FrownyFrog

Actually, you're right. It just happens to work both ways. I guess that solution saves a byte then :)
Jonah

1

Javascript (ES6), 89 bytes

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

Takes input in currying syntax in reverse order 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

Actually, 13 12 bytes

-1 byte thanks to Mr. Xcoder. Try it online!

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

You do not need the @, do you?
Mr. Xcoder

As a side note, I found an interesting alternative: R∙♂Σ╗╜╔⌠╜c⌡M
Mr. Xcoder

1

AWK, 191 bytes

Outputs frequencies as a vertical column.

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

Try it online!

Adding 6 more bytes allows for multiple sets of inputs.

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

Try it online!


1

Clojure, 86 bytes

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

An example:

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