ミックスダイスロールの頻度分布


24

この課題のフォローアップ

混合サイコロのセットが与えられた場合、それらすべてをローリングし、各サイコロでローリングした数字を合計する頻度分布を出力します。

たとえば、1d12 + 1d8(1面の12面ダイスと1面の8面ダイスをローリングする)を検討してください。最大と最小のロールがある202圧延と同様であり、それぞれ、2d10(2 10両面ダイスを)。しかし、1d12 + 1d8より平坦分布の結果2d10[1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 7, 6, 5, 4, 3, 2, 1][1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

ルール

  • 周波数は、周波数が対応する合計の昇順でリストする必要があります。
  • 対応する合計で頻度にラベルを付けることは許可されていますが、必須ではありません(合計は必要な順序から推測できるため)。
  • 出力が言語の表現可能な整数の範囲を超える入力を処理する必要はありません。
  • 先頭または末尾のゼロは許可されません。出力には正の周波数のみが表示されます。
  • 任意の妥当な形式(サイコロのリスト([6, 8, 8])、サイコロのペアのリスト([[1, 6], [2, 8]])など)で入力を取得できます。
  • 周波数のGCDが1になるように、周波数を正規化する必要があります(例:の[1, 2, 3, 2, 1]代わりに[2, 4, 6, 4, 2])。
  • すべてのサイコロには少なくとも1つの面があります(a d1が最小です)。
  • これはなので、最短のコード(バイト単位)が優先されます。通常どおり、標準の抜け穴は禁止されています。

テストケース

これらのテストケースはとして与えられinput: output、入力は-sidedダイスを[a, b]表すペアのリストとして与えられますa b(を[3, 8]参照し3d8、を[[1, 12], [1, 8]]参照します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]

回答:


7

ゼリー 14  7 バイト

Xcoder氏のおかげで-3バイト(先行を回避するために暗黙の範囲を使用します。2進Rデカルト積によるreduceの置き換えとフラット化、p/F€その目的のために組み込まれたデカルト積との交換、Œp。)

ŒpS€ĠL€

サイコロの面のリストを取得し、増加する合計の正規化された分布を返すモナドリンク。

オンラインでお試しください!

どうやって?

サイコロの「サイズ」のリストを(暗黙的に)調べてそれらを顔のリストにし、次にそれらのリストのデカルト積(サイコロのセットのすべての可能なロール)を取得し、それらのロールを合計し、等しいグループを取得しますインデックス(値の昇順)で各グループの長さを取得します。

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

注:最小サイコロを振る方法は1つしかないため(サイコロごとに1つずつ振る)、ロールを二重にカウントすることはないため、GCD正規化を実行する必要はありません。


おかげで、私たちが必要なのかどうか疑問に思って÷g/$います(最小値または最大値を取得する方法は常に1つだけではありませんか?)
ジョナサンアラン

2
思想、この価値・ツー・シェア代替:ŒpS€µLƙ
氏Xcoder


5

、7バイト

mLkΣΠmḣ

入力はサイコロのリストです。 オンラインでお試しください!

説明

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

オクターブ88 69 58 56バイト

Haskellの回答で述べたように、これは、たとえば3面と5面のサイコロの分布が2つのベクトル[1,1,1]との離散畳み込みであるという事実を使用してい[1,1,1,1,1]ます。@ LuisMendo、-11バイトの賢いゴルフに感謝します!

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

オンラインでお試しください!

この送信では、再帰的なアプローチを使用しています。ただし、ループを使用する場合は、少し長くなります。

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

4

Haskell80 78 64バイト

このソリューションは、以前の課題の@ Sherlock9のソリューションとほぼ同じでしたが、より自然なアプローチかもしれません。@xnorにはさらに短いHaskellソリューションがあります!

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

説明:

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

オンラインでお試しください!

以前のソリューション:

これは、@ AndersKaseorg 離散畳み込み関数を使用しています。ここでの観察は、たとえば3面と5面のサイコロの分布は、2つのベクトル[1,1,1]との離散畳み込みであるということ[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

オンラインでお試しください!


4

Wolfram言語(Mathematica)、26バイト

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

オンラインでお試しください!

前の挑戦に対する私の答えの修正。これはすべての可能な結果を​​生成し、それらを合計し、結果を集計します。

楽しみのために、と書くこともできますTally@*Total@*Thread@*Tuples@*Rangeが、それは長くなります。

Wolfram言語(Mathematica)、41バイト

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

オンラインでお試しください!

これは畳み込みベースのアプローチです(ここでは、生成関数の積を介して畳み込みを行います1+x+x^2+...+x^(N-1)-dNをロールするための生成関数です-そして係数のリストを取得します)。最初の解決策は大規模な入力に対して実用的ではないため、これを含めます。


4

Mathematica、44バイト

対応する合計でラベル付けされた周波数を出力します

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

オンラインでお試しください!

Martin Enderから-5バイト

「ラベル」が有効であることを知らせてくれたミシャ・ラヴロフに感謝します


3

Pyth、12バイト

lM.gs.nk*FSM

ここで試してみてください!

どうやって?

lM.gs.nk * FSM〜完全なプログラム。

          SM〜包括的単項整数範囲[1、N]のマップ。
        * F〜Fold(Reduce by)デカルト積。
  .g〜関数の結果によるグループ化。
    sn〜フラット化されたときのリストの合計。
lM〜各グループの長さ。

3

ゼリー、14バイト

R+Ѐ/FċЀSR$ḟ0

オンラインでお試しください!

入力はダイの値のリストです。ĠL€他のゼリーの答えから盗むことでこれをゴルフダウンすることができますが、前半をゴルフダウンして同じもので終わることができるので、そのままにしておきます



2

05AB1E、11バイト

€L.«âOO{γ€g

オンラインでお試しください!

使い方

€L。«âOO{γ€g-完全なプログラム。

€L-リスト内の各Nについて、[1 .. N]を取得します。
  。«-リスト内の各要素間で2項関数を右から左に折ります。
    â-そして、その関数としてデカルト積を選択します。
     O-それぞれを平らにします。
      O-それぞれ合計。
       {γ-ソートし、等しい隣接値のランにグループ化します。
         €g-それぞれの長さを取得します。

Emignaのおかげで1バイト節約できました


あなたは何ができるOの代わりに€˜
Emigna

2

R、51バイト

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

オンラインでお試しください!

サイコロのリストを取得し、周波数の名前付きベクトルを返します。名前(サイコロの合計の値)は度数の上に印刷されます。

R、59バイト

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

オンラインでお試しください!

Reduceアプローチではなく、上記反復1。

R、62バイト

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

オンラインでお試しください!

畳み込みアプローチ。D式の最初の要素のみを使用している1:Dが、出力には影響しないという警告がいくつか表示されます。Reソリューションのすべての部分をとる必要がなければ、58バイトになります。


1

APL(Dyalog Classic)12 10バイト

-2 @Adámに感謝

⊢∘≢⌸+/↑,⍳⎕

オンラインでお試しください!

入力はN個のダイスのリストです

⍳⍵ ネストされたベクトルのN次元配列です-可能なすべてのダイスロー

+/↑, 配列を平坦化し、スローを合計します

⊢∘≢⌸ 幸いなことにそれらの昇順と一致する、最初の出現順にリストされた各一意の合計の数をカウントします


1
-2: ⊢∘≢⌸+/↑,⍳⎕
アダム



0

クリーン154 142 136 107 100 85 + 13 = 98バイト

入力はサイコロのリストです。

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

答えはラムダの形式です。

から+13バイトimport StdEnv。これは、これが機能するために必要なモジュールをインポートします。

オンラインでお試しください!


0

JavaScript(ES6)、83バイト

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

各ダイの入力を個別のパラメーターとして受け取ります。


0

JavaScript(ES6)、76 74バイト

サイコロのリストとして入力を受け取ります。

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

テストケース

最後の2つのテストケースを処理するには、TCOを有効にするか、JSエンジンのデフォルトのスタックサイズ制限を増やす必要があります。

書式設定およびコメント化

注意:これは、reduce()を使用していた最初の提出物のコメント付きバージョンです。2バイト長くなりますが、読みやすくなります。

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バイト

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

最初の入力はサイコロの数のリストで、2番目の入力は各サイコロの面の数のリストです。


0

Perl 5、94バイト

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

オンラインでお試しください!

入力形式は、改行で区切られたサイコロのリストです。したがって、1d10 + 2d8は次のように入力します。

10
8
8

0

SageMath、46バイト

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

オンラインで試す

これは私のソリューションを他の挑戦に適応させたものです。これは、パラメータとしてサイコロ(例えば、任意の数に取りf(4,4,6,6,6)2d4+3d6)、およびリストを返します。


Python 2 + NumPy、62バイト

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

オンラインでお試しください!

前と同じように、これらのソリューションは本質的に同等なので、このソリューションを上記のソリューションに含めました。この関数はPythonリストではなくNumPy配列を返すため、出力は少し異なって見えることに注意してくださいprint

numpy.ones(x)は、NumPyで使用する配列を作成する「正しい」方法です。したがって、の代わりに使用できますが[x*[1]]、残念ながらはるかに長くなります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.