Rozkład częstotliwości wielu rzutów kości

23

Biorąc pod uwagę dwie dodatnie liczby całkowite ai bwyprowadzamy rozkład częstotliwości toczenia bjednostronnych aczasów matrycy i sumując wyniki.

Rozkład częstotliwości podaje częstotliwość każdej możliwej sumy, jeśli każda możliwa sekwencja rzutów kostką występuje raz. Tak więc częstotliwościami są liczby całkowite, których suma jest równa b**a.

Zasady

  • Częstotliwości muszą być wymienione w kolejności rosnącej od sumy, której częstotliwość odpowiada.
  • Oznaczanie częstotliwości odpowiednimi sumami jest dozwolone, ale nie wymagane (ponieważ sumy można wywnioskować z wymaganej kolejności).
  • Nie musisz obsługiwać danych wejściowych, w których dane wyjściowe przekraczają reprezentatywny zakres liczb całkowitych dla Twojego języka.
  • Zera wiodące lub końcowe są niedozwolone. Na wyjściu powinny pojawić się tylko dodatnie częstotliwości.

Przypadki testowe

Format: 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
źródło
Czy możemy założyć, że bjest to co najmniej 2? (A jeśli nie, to jak powinna wyglądać lista częstotliwości sum jednostronnej kości?)
Misha Lavrov
Czy możemy mieć zera wiodące lub końcowe?
xnor

Odpowiedzi:

9

Oktawa , 38 bajtów

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

Wypróbuj online!

Wyjaśnienie

Dodanie niezależnych zmiennych losowych odpowiada splotowi ich funkcji masy prawdopodobieństwa (PMF) lub pomnożeniu ich funkcji charakterystycznych (CF). Tak więc CF sumy aniezależnych, identycznie rozmieszczonych zmiennych jest dana przez pojedynczą zmienną podniesioną do potęgi a.

CF jest zasadniczo transformatą Fouriera PMF, a zatem można go obliczyć za pomocą FFT. PMF pojedynczego b-sided matrycy jest jednolita na 1, 2, ..., b. Wymagane są jednak dwie modyfikacje:

  • 1jest używany zamiast rzeczywistych wartości prawdopodobieństwa ( 1/b). W ten sposób wynik zostanie zdenormalizowany i będzie zawierał liczby całkowite zgodnie z wymaganiami.
  • Konieczne jest wypełnianie zerami, aby wynik FFT miał odpowiedni rozmiar ( a*b-a+1), a domniemane zachowanie okresowe przyjęte przez FFT nie wpływa na wyniki.

Po uzyskaniu funkcji charakterystycznej sumy stosuje się odwrotną FFT do obliczenia wyniku końcowego, a zaokrąglanie stosuje się w celu skorygowania niedokładności zmiennoprzecinkowych.

Przykład

Rozważmy wejść a=2, b=6. Kod a:a*b<a+bbuduje wektor z b=6zerami uzupełnionymi o zero a*b-a+1:

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

Potem fft(...)daje

[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]

Można tutaj prawie rozpoznać funkcję sinusa (transformata Fouriera impulsu prostokątnego).

(...).^apodnosi każdy wpis do, aa następnie ifft(...)przyjmuje odwrotną FFT, co daje

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

Chociaż wyniki w tym przypadku są dokładnie liczbami całkowitymi, generalnie mogą występować błędy względne rzędu 1e-16, dlatego round(...)jest potrzebne.

Luis Mendo
źródło
1
Naprawdę jestem pod wrażeniem!
rahnema1
@ rahnema1 Przetwarzanie sygnału dla wygranej!
Luis Mendo,
8

Mathematica, 29 bajtów

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

Po prostu generuje wszystkie możliwe rzuty kostkami, bierze ich sumy, a następnie się liczy. Każda częstotliwość jest oznaczona swoją wartością.

Mathematica, 38 bajtów

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

Rozszerza się (1+x+x^2+...+x^(a-1))^bi przyjmuje współczynniki x. Ponieważ 1+x+x^2+...+x^(a-1)funkcja generowania pojedynczego rzutu matrycą i produkty odpowiadają zwojom - dodając wartości kości - wynik daje rozkład częstotliwości.

Misza Ławrow
źródło
6

Haskell , 90 79 77 75 bajtów

Dzięki Lynn za sztuczkę kartezjańską . -11 bajtów dzięki wielu sztuczkom Haskell od Funky Computer Man, -2 bajty od nazewnictwa, -2 bajty dzięki Laikoni. Sugestie dotyczące gry w golfa są mile widziane! Wypróbuj online!

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

Bez golfa

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
źródło
Użyj $zamiast, ()aby zapisać 2 bajty. TIO
Wheat Wizard
I nie używajreplicate
Wheat Wizard
(map length$)=(length<$>)dla dwóch bajtów
Michael Klein
4

Pyth - 10 bajtów

Po prostu bierze wszystkie możliwe kombinacje kości, biorąc iloczyn kartezjański [1, b], aczasy, sumowanie i otrzymując długość każdej grupy sum.

lM.gksM^SE

Pakiet testowy .

Maltysen
źródło
4

05AB1E , 8 bajtów

LIãO{γ€g

Wypróbuj online!

W jaki sposób?

LIãO {γ € g - Pełny program.

L - Zakres [1 ... wejście nr 1]
 I - Wejście nr 2.
  ã - Moc kartezjańska.
   O - Mapa z sumą.
    {- Sortuj.
     γ - Grupuj kolejne równe elementy.
      € g - Uzyskaj długość każdego
Pan Xcoder
źródło
4

R , 58 bajtów

function(a,b)table(rowSums(expand.grid(rep(list(1:b),a))))

Wypróbuj online!

flodel
źródło
4

R , 52 bajty

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

Wypróbuj online!

Port rozwiązanie Octave @Luis Mendo jest , fft(z, inverse=T)niestety zwraca nieznormalizowanych odwrotną FFT, więc musimy podzielić przez długość i zwraca complexwektor, więc bierzemy tylko część rzeczywistą.

Giuseppe
źródło
dobrze zagrane - zwrot za wczorajsze cmdscaleliczby :-)
flodel
@flodel hah! Naprawdę przyznam ci nagrodę za to :)
Giuseppe,
Nie żartowałeś! Tak hojnie z twojej strony! Cieszę się, widząc (i ucząc się) twoje odpowiedzi, spłacę je szybko!
flodel
3

SageMath, 40 bajtów

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

Wypróbuj online

convolutionoblicza dyskretne splot dwóch list. reducerobi to, co jest napisane na puszce. [1]*bto lista b 1s, rozkład częstotliwości 1db. [[1]*b]*atworzy zagnieżdżoną listę akopii b 1s.


Python 2 + NumPy , 56 bajtów

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

Wypróbuj online!

Dołączyłem to rozwiązanie do powyższego, ponieważ są one zasadniczo równoważne. Zauważ, że ta funkcja zwraca tablicę NumPy, a nie listę Python, więc wynik wygląda nieco inaczej print.

numpy.ones((a,b))jest „poprawnym” sposobem na stworzenie tablicy do użycia z NumPy, a zatem może być używana zamiast [[1]*b]*a, ale niestety jest dłuższa.

Mego
źródło
3

Galaretka , 5 bajtów

ṗS€ĠẈ

Wypróbuj online!

Zauważ, że to przyjmuje argumenty w odwrotnej kolejności.

W jaki sposób?

ṗS € ĠL € - Pełny program (dyadyczny) | Przykład: 6, 2

ṗ - Moc kartezjańska (z ukrytym zakresem) | [[1, 1], [1, 2], ..., [6, 6]]
 S € - Suma każdego | [2, 3, 4, ..., 12]
   Ġ - Grupuj indeksy według wartości | [[1], [2, 7], [3, 8, 13], ..., [36]]
    L € - Długość każdej grupy | [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]

Alternatywne rozwiązania:

ṗZSĠL€
ṗZSµLƙ
ṗS€µLƙ
Pan Xcoder
źródło
2

Python 2 , 102 91 bajtów

lambda b,a:map(map(sum,product(*[range(a)]*b)).count,range(b*~-a+1))
from itertools import*

Wypróbuj online!

ovs
źródło
2

Pari / GP , 28 bajtów

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

Wypróbuj online!

alephalpha
źródło
O ile wiem, jest to najkrótsze rozwiązanie, które zdecydowanie nie zabraknie pamięci w żadnym z podanych przypadków testowych.
Misza Ławrow
1

Perl 5 , 53 bajtów

$g=join',',1..<>;map$r[eval]++,glob"+{$g}"x<>;say"@r"

Wypróbuj online!

Format wejściowy:

b
a
Xcali
źródło
1

JavaScript (ES6), 94 bajty

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

Ograniczone przez 32-bitowe przepełnienie liczb całkowitych, ale zamiast tego można użyć liczb zmiennoprzecinkowych kosztem 1 bajtu.

Neil
źródło
Umm ... to wymaga tylko jednego wejścia
Herman L
@HermanLauenstein Przepraszam, jakoś całkowicie przeoczyłem tę część pytania ... wkrótce ją naprawię.
Neil
1

J , 25 24 21 20 bajtów

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

Wypróbuj online!

Początkowo zwiększyłem listę [0..n-1], aby uzyskać [1..n], ale najwyraźniej nie jest to konieczne.

FrownyFrog
źródło
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>

Herman L
źródło
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
Sherlock9
źródło
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!

Robert Benson
źródło
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])
NikoNyrh
źródło
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
źródło
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
0

Julia, 43 bytes

f(n,d)=reduce(conv,repmat([ones(Int,d)],n))

Try it online!

LukeS
źródło