Distribuzione della frequenza di rotoli di dadi multipli


23

Dati due numeri interi positivi ae b, emettere la distribuzione di frequenza del rotolamento dei tempi di bdado a alato e sommando i risultati.

Una distribuzione di frequenza elenca la frequenza di ogni possibile somma se ogni possibile sequenza di tiri di dado si verifica una volta. Pertanto, le frequenze sono numeri interi la cui somma è uguale b**a.

Regole

  • Le frequenze devono essere elencate in ordine crescente della somma a cui corrisponde la frequenza.
  • L'etichettatura delle frequenze con le somme corrispondenti è consentita, ma non richiesta (poiché le somme possono essere desunte dall'ordine richiesto).
  • Non è necessario gestire input in cui l'output supera l'intervallo rappresentabile di numeri interi per la propria lingua.
  • Gli zero iniziali o finali non sono consentiti. Nell'output dovrebbero apparire solo frequenze positive.

Casi test

Formato: 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]

Possiamo supporre che bsia almeno 2? (O in caso contrario, come dovrebbe essere la lista delle frequenze per le somme di un dado a 1 faccia?)
Misha Lavrov

Possiamo avere zero iniziali o finali?
xnor

Risposte:


9

Ottava , 38 byte

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

Provalo online!

Spiegazione

L'aggiunta di variabili casuali indipendenti corrisponde alla convoluzione delle loro funzioni di massa di probabilità (PMF) o alla moltiplicazione delle loro funzioni caratteristiche (CF). Quindi il CF della somma di avariabili indipendenti, identicamente distribuite è dato da quello di una singola variabile elevata alla potenza di a.

Il CF è essenzialmente la trasformata di Fourier del PMF e può quindi essere calcolato tramite una FFT. Il PMF di un unico bstampo a senso unico è uniforme su 1, 2, ..., b. Tuttavia, sono necessarie due modifiche:

  • 1viene utilizzato al posto dei valori di probabilità effettivi ( 1/b). In questo modo il risultato sarà de-normalizzato e conterrà numeri interi come richiesto.
  • Il riempimento con zeri è necessario affinché l'output FFT abbia le dimensioni appropriate ( a*b-a+1) e il comportamento periodico implicito assunto dall'FFT non influisce sui risultati.

Una volta ottenuta la funzione caratteristica della somma, viene utilizzato un FFT inverso per calcolare il risultato finale e viene applicato l'arrotondamento per correggere le imprecisioni in virgola mobile.

Esempio

Considerate ingressi a=2, b=6. Il codice a:a*b<a+bcrea un vettore con b=6quelli, con spaziatura zero per dimensioni a*b-a+1:

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

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

Qui si può quasi riconoscere la funzione sinc (trasformata di Fourier di un impulso rettangolare).

(...).^asolleva ogni voce ae quindi ifft(...)prende l'inverso FFT, che dà

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

Sebbene i risultati in questo caso siano esattamente numeri interi, in generale potrebbero esserci errori relativi dell'ordine di 1e-16, motivo per cui round(...)è necessario.


1
Mi ha davvero colpito!
rahnema1,

@ rahnema1 Elaborazione del segnale per la vittoria!
Luis Mendo,

8

Mathematica, 29 byte

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

Genera solo tutti i possibili tiri di dado, prende il loro totale, quindi conta. Ogni frequenza viene etichettata con il suo valore.

Mathematica, 38 byte

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

Si espande (1+x+x^2+...+x^(a-1))^be prende i coefficienti di x. Poiché 1+x+x^2+...+x^(a-1)è la funzione generatrice di un singolo tiro di dado e i prodotti corrispondono alle convoluzioni - aggiungendo valori di dadi - il risultato fornisce la distribuzione della frequenza.


6

Haskell , 90 79 77 75 byte

Grazie a Lynn per il trucco del prodotto cartesiano . -11 byte grazie a molti trucchi Haskell di Funky Computer Man, -2 byte dalla denominazione, -2 byte grazie a Laikoni. I suggerimenti sul golf sono i benvenuti! Provalo online!

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

Utilizzare $invece di ()per salvare 2 byte. TIO
Wheat Wizard




(map length$)=(length<$>)per due byte
Michael Klein,

4

Pyth - 10 byte

Prende solo tutte le possibili combinazioni di dadi prendendo il prodotto cartesiano di [1, b], atempi, somma e ottenendo la lunghezza di ciascun gruppo di somma.

lM.gksM^SE

Test Suite .


4

05AB1E , 8 byte

LIãO{γ€g

Provalo online!

Come?

LIãO {γ € g - Programma completo.

L - Range [1 ... input # 1]
 I - Ingresso n. 2.
  ã - Potenza cartesiana.
   O - Mappa con somma.
    {- Ordina.
     γ - Raggruppa elementi uguali consecutivi.
      € g - Ottieni la lunghezza di ciascuno


4

R , 52 byte

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

Provalo online!

Una porta della soluzione Octave di @Luis Mendo , fft(z, inverse=T)purtroppo restituisce l'invertito FFT non normalizzato, quindi dobbiamo dividere per la lunghezza e restituisce uncomplex vettore, quindi prendiamo solo la parte reale.


ben giocato - rimborso per la cmdscalefigura di ieri :-)
flodel

@flodel hah! In realtà ti assegnerò una taglia per quello :)
Giuseppe,

Non stavi scherzando! Così generoso da parte tua! Mi piace vedere (e imparare da) le tue risposte, le restituirò rapidamente!
flodel,

3

SageMath, 40 byte

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

Provalo online

convolutioncalcola la convoluzione discreta di due elenchi. reducefa quello che dice sulla scatola. [1]*bè un elenco di b 1s, la distribuzione di frequenza di 1db. [[1]*b]*acrea un elenco nidificato di acopie di b 1s.


Python 2 + NumPy , 56 byte

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

Provalo online!

Ho incluso questa soluzione con quella sopra, poiché sono sostanzialmente equivalenti. Nota che questa funzione restituisce un array NumPy e non un elenco Python, quindi l'output appare un po 'diverso se tuprint .

numpy.ones((a,b))è il modo "corretto" per creare un array da usare con NumPy, e quindi potrebbe essere usato al posto di [[1]*b]*a, ma purtroppo è più lungo.


3

Gelatina , 5 byte

ṗS€ĠẈ

Provalo online!

Si noti che questo prende gli argomenti in ordine inverso.

Come?

ṗS € ĠL € - Programma completo (diadico) | Esempio: 6, 2

ṗ - Potenza cartesiana (con intervallo implicito) | [[1, 1], [1, 2], ..., [6, 6]]
 S € - Somma ciascuno | [2, 3, 4, ..., 12]
   Ġ - Raggruppa gli indici per valori | [[1], [2, 7], [3, 8, 13], ..., [36]]
    L € - Lunghezza di ciascun gruppo | [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]

Soluzioni alternative:

ṗZSĠL€
ṗZSµLƙ
ṗS€µLƙ






1

JavaScript (ES6), 94 byte

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

Limitato dall'overflow di numeri interi a 32 bit, ma i float potrebbero essere utilizzati al costo di 1 byte.


Umm ... ci vuole solo un input
Herman L

@HermanLauenstein Mi dispiace, in qualche modo ho completamente ignorato quella parte della domanda ... risolverà a breve.
Neil,

1

J , 25 24 21 20 byte

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

Provalo online!

Inizialmente ho incrementato l'elenco [0..n-1] per ottenere [1..n] ma apparentemente non è necessario.


Bella risposta. Ecco una versione tacita per lo stesso numero di byte: #/.~@,@(+///)@$i.@{:. Sembra che ci dovrebbe essere un modo per raderlo un po 'di più rendendo il verbo diadico, ma non sono stato in grado di farlo.
Giona

@Jonah hai un extra /in+//
FrownyFrog

In realtà, hai ragione. Funziona in entrambi i modi. Immagino che quella soluzione salvi un byte allora :)
Giona

1

Javascript (ES6), 89 byte

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

Accetta input nella sintassi del curry in ordine inverso 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

In realtà , 13 12 byte

-1 byte grazie a Mr. Xcoder. Provalo 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

Non ti serve @, vero?
Mr. Xcoder,

Come nota a R∙♂Σ╗╜╔⌠╜c⌡M
margine

1

AWK , 191 byte

Emette le frequenze come una colonna verticale.

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

Provalo online!

L'aggiunta di altri 6 byte consente più set di input.

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

Provalo online!


1

Clojure, 86 byte

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

Un esempio:

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

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

Provalo online!


sizeof(int)? Veramente?
orlp

@orlp dipendente dall'ambiente, lo sai
Leaky Nun

2
È consentito a un programma C di assumere una particolare architettura. Finché funziona su almeno una macchina. Inoltre, 8funzionerebbe su qualsiasi architettura, sovrallocando un po 'ma va bene.
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;per -2 byte.
Kevin Cruijssen,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.