Distribusi Frekuensi Gulungan Dadu Campuran


24

Tindak lanjut dari tantangan ini

Diberikan satu set dadu campuran, output distribusi frekuensi bergulir mereka semua dan menjumlahkan angka-angka digulung pada setiap dadu.

Sebagai contoh, pertimbangkan 1d12 + 1d8(menggulung 1 dadu 12 sisi dan 1 dadu sisi 8). Gulungan maksimum dan minimum adalah 20dan 2, masing-masing, yang mirip dengan penggulungan 2d10(2 dadu 10 sisi). Namun, 1d12 + 1d8menghasilkan distribusi yang lebih rata daripada 2d10: [1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 7, 6, 5, 4, 3, 2, 1]versus [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1].

Aturan

  • Frekuensi harus terdaftar dalam urutan jumlah yang sesuai dengan frekuensi.
  • Memberi label frekuensi dengan jumlah yang sesuai diperbolehkan, tetapi tidak diperlukan (karena jumlahnya dapat disimpulkan dari urutan yang diperlukan).
  • Anda tidak harus menangani input yang outputnya melebihi kisaran integer yang representatif untuk bahasa Anda.
  • Angka nol di depan atau di belakang tidak diizinkan. Hanya frekuensi positif yang akan muncul di output.
  • Anda dapat mengambil input dalam format apa pun yang wajar (daftar dadu ( [6, 8, 8]), daftar pasangan dadu ( [[1, 6], [2, 8]]), dll.).
  • Frekuensi harus dinormalisasi sehingga GCD dari frekuensinya adalah 1 (misalnya, [1, 2, 3, 2, 1]bukan [2, 4, 6, 4, 2]).
  • Semua dadu akan memiliki setidaknya satu wajah (jadi a d1adalah minimum).
  • Ini adalah , jadi kode terpendek (dalam byte) menang. Celah standar dilarang, seperti biasa.

Uji Kasus

Kasus-kasus uji ini diberikan sebagai input: output, di mana input diberikan sebagai daftar pasangan yang [a, b]mewakili a bdadu-sisi (sehingga [3, 8]mengacu pada 3d8, dan [[1, 12], [1, 8]]mengacu pada 1d12 + 1d8).

[[2, 10]]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
[[1, 1], [1, 9]]: [1, 1, 1, 1, 1, 1, 1, 1, 1]
[[1, 12], [1, 8]]: [1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 7, 6, 5, 4, 3, 2, 1]
[[2, 4], [3, 6]]: [1, 5, 15, 35, 68, 116, 177, 245, 311, 363, 392, 392, 363, 311, 245, 177, 116, 68, 35, 15, 5, 1]
[[1, 3], [2, 13]]: [1, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 37, 36, 33, 30, 27, 24, 21, 18, 15, 12, 9, 6, 3, 1]
[[1, 4], [2, 8], [2, 20]]: [1, 5, 15, 35, 69, 121, 195, 295, 423, 579, 761, 965, 1187, 1423, 1669, 1921, 2176, 2432, 2688, 2944, 3198, 3446, 3682, 3898, 4086, 4238, 4346, 4402, 4402, 4346, 4238, 4086, 3898, 3682, 3446, 3198, 2944, 2688, 2432, 2176, 1921, 1669, 1423, 1187, 965, 761, 579, 423, 295, 195, 121, 69, 35, 15, 5, 1]
[[1, 10], [1, 12], [1, 20], [1, 50]]: [1, 4, 10, 20, 35, 56, 84, 120, 165, 220, 285, 360, 444, 536, 635, 740, 850, 964, 1081, 1200, 1319, 1436, 1550, 1660, 1765, 1864, 1956, 2040, 2115, 2180, 2235, 2280, 2316, 2344, 2365, 2380, 2390, 2396, 2399, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2399, 2396, 2390, 2380, 2365, 2344, 2316, 2280, 2235, 2180, 2115, 2040, 1956, 1864, 1765, 1660, 1550, 1436, 1319, 1200, 1081, 964, 850, 740, 635, 536, 444, 360, 285, 220, 165, 120, 84, 56, 35, 20, 10, 4, 1]

Jawaban:


7

Jelly ,  14  7 byte

-3 bytes terima kasih kepada Tn. Xcoder (penggunaan rentang implisit untuk menghindari memimpin R; penggantian pengurangan oleh produk Cartesian diad dan ratakan p/F€,, dengan produk bawaan Cartesian untuk tujuan itu Œp,.)

ŒpS€ĠL€

Tautan monadik mengambil daftar wajah dadu dan mengembalikan distribusi normal dari jumlah yang meningkat.

Cobalah online!

Bagaimana?

Menelusuri daftar "ukuran" dadu (secara implisit) membuat mereka ke dalam daftar wajah mereka, kemudian mendapatkan produk Cartesian dari daftar tersebut (semua kemungkinan gulungan set dadu), kemudian meringkas gulungan itu, mendapat kelompok-kelompok yang sama indeks (dengan nilai menaik) dan mengambil panjang masing-masing kelompok.

ŒpS€ĠL€ - Link: list of numbers, dice  e.g. [2,5,1,2]
Œp      - Cartisian product (implicit range-ification -> [[1,2],[1,2,3,4,5],[1],[1,2]])
        -                   -> [[1,1,1,1],[1,1,1,2],[1,2,1,1],[1,2,1,2],[1,3,1,1],[1,3,1,2],[1,4,1,1],[1,4,1,2],[1,5,1,1],[1,5,1,2],[2,1,1,1],[2,1,1,2],[2,2,1,1],[2,2,1,2],[2,3,1,1],[2,3,1,2],[2,4,1,1],[2,4,1,2],[2,5,1,1],[2,5,1,2]]
  S€    - sum €ach          -> [4,5,5,6,6,7,7,8,8,9,5,6,6,7,7,8,8,9,9,10]
    Ġ   - group indices     -> [[1],[2,3,11],[4,5,12,13],[6,7,14,15],[8,9,16,17],[10,18,19],[20]]
     L€ - length of €ach    -> [1,3,4,4,4,3,1]

Catatan: hanya ada satu cara untuk menggulung minimum (dengan menggulirkan satu di setiap dadu) dan kami tidak menghitung ganda setiap gulungan, sehingga tidak perlu melakukan normalisasi GCD.


Terima kasih, saya bertanya-tanya apakah kita pernah membutuhkannya ÷g/$(bukankah selalu ada satu cara untuk mendapatkan min atau maks?)
Jonathan Allan

2
Pikir ini alternatif yang layak untuk dibagikan:ŒpS€µLƙ
Mr. Xcoder

5

MATL , 8 byte

1i"@:gY+

Input adalah array ukuran die (mungkin diulang).

Cobalah online! Atau verifikasi semua kasus uji .

Penjelasan

1      % Push 1
i      % Input: numeric array
"      % For each k in that array
  @    %   Push k
  :    %   Range: gives [1 2 ... k]
  g    %   Convert to logical: gives [1 1 ... 1]
  Y+   %   Convolution, with full size
       % End (implicit). Display (implicit)

5

Sekam , 7 byte

mLkΣΠmḣ

Input adalah daftar dadu. Cobalah online!

Penjelasan

mLkΣΠmḣ  Implicit input, say x=[3,3,6].
     mḣ  Map range: [[1,2,3],[1,2,3],[1,2,3,4,5,6]]
    Π    Cartesian product: [[1,1,1],[1,1,2],..,[3,3,6]]
  kΣ     Classify by sum: [[[1,1,1]],[[1,1,2],[1,2,1],[2,1,1]],..,[[3,3,6]]]
mL       Map length: [1,3,6,8,9,9,8,6,3,1]


4

Oktaf , 88 69 58 56 byte

Seperti disebutkan dalam jawaban Haskell, ini menggunakan fakta bahwa distribusi misalnya dadu 3 sisi dan 5 sisi adalah konvolusi diskrit dari dua vektor [1,1,1]dan [1,1,1,1,1]. Terima kasih @LuisMendo untuk pandai golf -11 bytes!

function y=f(c);y=1:c;if d=c(2:end);y=conv(~~y,f(d));end

Cobalah online!

Pengajuan ini menggunakan pendekatan rekursif. Tetapi jika Anda akan menggunakan loop, itu akan menjadi sedikit lebih lama:

function y=f(c);y=1;for k=cellfun(@(x)ones(1,x),c,'Un',0);y=conv(y,k{1});end

4

Haskell , 80 78 64 byte

Solusi ini akhirnya hampir sama dengan @ Sherlock9 dalam tantangan sebelumnya dengan pendekatan yang mungkin lebih alami. @xnor memiliki solusi Haskell yang lebih pendek !

import Data.List
g x=[1..x]
map length.group.sort.map sum.mapM g

Penjelasan:

                              mapM g -- all possible outcomes
                      map sum        -- the sums of all possible outcomes
map length.group.sort                -- count the frequency of each sum

Cobalah online!

Solusi sebelumnya:

Ini menggunakan fungsi konvolusi diskret @AndersKaseorg . Pengamatan di sini adalah bahwa distribusi misalnya dadu 3 sisi dan 5 sisi adalah konvolusi diskrit dari dua vektor [1,1,1]dan [1,1,1,1,1].

foldl1(#).map(`take`l)
(a:b)#c=zipWith(+)(0:b#c)$map(a*)c++[]#b
_#c=0<$c
l=1:l

Cobalah online!


4

Bahasa Wolfram (Mathematica) , 26 byte

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

Cobalah online!

Modifikasi jawaban saya untuk tantangan sebelumnya . Ini hanya menghasilkan semua hasil yang mungkin, menambahkannya, dan menghitung hasilnya.

Untuk bersenang-senang, kita bisa menulisnya Tally@*Total@*Thread@*Tuples@*Range, tapi itu lebih lama.

Bahasa Wolfram (Mathematica) , 41 byte

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

Cobalah online!

Ini adalah pendekatan berbasis konvolusi (di sini, kami mengambil konvolusi melalui produk fungsi pembangkit - 1+x+x^2+...+x^(N-1)adalah fungsi pembangkit untuk menggulirkan dN - dan kemudian mengambil daftar koefisien). Saya memasukkannya karena solusi pertama tidak praktis untuk input besar.


4

Mathematica, 44 byte

Menghasilkan frekuensi yang diberi label dengan jumlah yang sesuai

Tally@*Fold[Join@@Table[#+i,{i,#2}]&]@*Range

Cobalah online!

-5 byte dari Martin Ender

terima kasih kepada Misha Lavrov karena memberi tahu saya bahwa "label" itu valid


3

Pyth , 12 byte

lM.gs.nk*FSM

Coba di sini!

Bagaimana?

lM.gs.nk * FSM ~ Program lengkap.

          SM ~ Peta dengan rentang bilangan bulat unary inklusif [1, N].
        * F ~ Lipat (Kurangi oleh) produk Cartesian.
  .g ~ Kelompokkan berdasarkan hasil fungsi.
    sn ~ Jumlah daftar ketika diratakan.
IM ~ Panjang masing-masing kelompok.

3

Jelly , 14 byte

R+Ѐ/FċЀSR$ḟ0

Cobalah online!

Input adalah daftar nilai mati. Saya bisa bermain golf ini dengan mencuri ĠL€dari jawaban Jelly lainnya tetapi kemudian saya juga bisa bermain golf di babak pertama dan berakhir dengan hal yang sama jadi saya akan membiarkannya seperti itu.



2

05AB1E , 11 byte

€L.«âOO{γ€g

Cobalah online!

Bagaimana itu bekerja

€ L. «âOO {γ € g - Program lengkap.

€ L - Untuk setiap N dalam daftar, dapatkan [1 .. N].
  «- Lipat fungsi diadik antara setiap elemen dalam daftar dari kanan ke kiri.
    â - Dan pilih produk cartesian sebagai fungsi itu.
     O - Ratakan masing-masing.
      O - Jumlah masing-masing.
       {γ - Urutkan, dan kelompokkan ke dalam menjalankan nilai berdekatan yang sama.
         € g - Dapatkan panjang masing-masing.

Disimpan 1 byte berkat Emigna !


Anda bisa melakukannya Odaripada€˜
Emigna

2

R , 51 byte

function(D){for(x in D)F=outer(F,1:x,"+")
table(F)}

Cobalah online!

Mengambil daftar dadu dan mengembalikan vektor frekuensi bernama; nama (nilai jumlah dadu) dicetak di atas frekuensi.

R , 59 byte

function(D)table(Reduce(function(x,y)outer(x,1:y,"+"),D,0))

Cobalah online!

Sebuah Reducependekatan daripada satu berulang di atas.

R , 62 byte

function(D)Re(convolve(!!1:D,"if"(sum(x<-D[-1]),f(x),1),,"o"))

Cobalah online!

Pendekatan konvolusi. Ini akan memberikan beberapa peringatan bahwa itu hanya menggunakan elemen pertama Duntuk ekspresi 1:Dtetapi tidak mempengaruhi output. Jika kita tidak harus mengambil bagian Real dari solusi, itu akan menjadi 58 byte.


1

APL (Dyalog Classic) , 12 10 byte

-2 Terima kasih kepada @ Adám

⊢∘≢⌸+/↑,⍳⎕

Cobalah online!

input adalah daftar N dadu

⍳⍵ adalah array N-dimensi dari vektor bersarang - semua kemungkinan lemparan mati

+/↑, meratakan array dan menjumlahkan lemparan

⊢∘≢⌸ menghitung berapa banyak dari setiap jumlah unik, yang tercantum dalam urutan penampilan pertama mereka, yang untungnya bertepatan dengan peningkatan urutan mereka


1
-2: ⊢∘≢⌸+/↑,⍳⎕
Adám



0

Bersih , 154 142 136 107 100 85 + 13 = 98 byte

Input adalah daftar dadu.

\l#t=foldr(\a-> \b=[x+y\\x<-[1..a],y<-b])[0]l
=[length[v\\v<-t|u==v]\\u<-removeDup t]

Jawabannya dalam bentuk lambda.

+13 byte dari import StdEnv, yang mengimpor modul yang diperlukan agar ini berfungsi.

Cobalah online!


0

JavaScript (ES6), 83 byte

f=(n,...a)=>n?f(...a).map((e,i)=>[...Array(n)].map(_=>r[i]=~~r[i++]+e),r=[])&&r:[1]
g=s=>o.textContent=f(...(s.match(/\d+/g)||[]).map(n=>+n)).join`, `
<input oninput=g(this.value)><p id=o>1

Mengambil input dari setiap die sebagai parameter terpisah.


0

JavaScript (ES6), 76 74 byte

Mengambil input sebagai daftar dadu.

a=>(g=k=>a.map(d=>(s+=n%d|0,n/=d),s=0,n=k)|n?x:g(k+1,x[s]=-~x[s]))(0,x=[])

Uji kasus

Memproses dua test case terakhir akan membutuhkan untuk mengaktifkan TCO atau meningkatkan batas ukuran stack standar dari mesin JS.

Diformat dan dikomentari

NB: Ini adalah versi komentar dari pengiriman awal saya yang menggunakan pengurangan (). Ini 2 byte lebih lama tetapi lebih mudah dibaca.

a =>                    // given the list of dice a
  (g = k =>             // g = recursive function taking k = counter
    a.reduce((k, d) =>  //   for each die d in a:
      (                 //     k % d represents the current face of d
        s += k % d,     //     we add it to the total s
        k / d | 0       //     and we update k to pick the face of the next die
      ),                //     initialization:
      k,                //     start with the current value of k
      s = 0             //     total = 0
    ) ?                 //   reduce() returns 1 as soon as k = product of all dice
      x                 //     in which case we're done: stop recursion and return x
    :                   //   else:
      g(                //     do a recursive call to g() with:
        k + 1,          //       k incremented
        x[s] = -~x[s]   //       x[s] incremented
      )                 //     end of recursive call
  )(0, x = [])          // initial call to g() with k = 0 and x = empty array

0

Clojure, 96 byte

#(sort-by key(frequencies(reduce(fn[R D](for[d(range D)r R](+ r d 1)))[0](mapcat repeat % %2))))

Input pertama adalah daftar jumlah dadu, dan input kedua adalah daftar jumlah sisi pada setiap dadu.


0

Perl 5 , 94 byte

map$k{$_}++,map eval,glob join'+',map'{'.(join',',1..$_).'}',<>;say$k{$_}for sort{$a-$b}keys%k

Cobalah online!

Format input adalah daftar dadu yang dipisahkan oleh baris baru. Dengan demikian, 1d10 + 2d8 akan dimasukkan sebagai:

10
8
8

0

SageMath, 46 byte

lambda*a:reduce(convolution,[x*[1]for x in a])

Cobalah online

Ini adalah adaptasi dari solusi saya untuk tantangan lain . Dibutuhkan sejumlah dadu sebagai parameter (misalnya f(4,4,6,6,6)untuk 2d4+3d6), dan mengembalikan daftar.


Python 2 + NumPy , 62 byte

lambda*a:reduce(numpy.convolve,[x*[1]for x in a])
import numpy

Cobalah online!

Seperti sebelumnya, saya sudah memasukkan solusi ini dengan yang di atas, karena mereka pada dasarnya setara. Perhatikan bahwa fungsi ini mengembalikan array NumPy dan bukan daftar Python, sehingga outputnya terlihat sedikit berbeda jika Anda printmenggunakannya.

numpy.ones(x)adalah cara yang "benar" untuk membuat array untuk digunakan dengan NumPy, dan karenanya dapat digunakan sebagai pengganti [x*[1]], tapi sayangnya jauh lebih lama.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.