特定のイベントのすべての組み合わせの確率


18

確率が0.0〜1.0のイベントのシーケンスを指定して、各組み合わせが発生する確率を生成および導出します。選択した言語が提供するものであれば、どのような構成でも一連の数字が提供されると想定できます。

以下に例を示します。シーケンスの組み合わせの長さがメモリに収まると仮定できます。

{ 0.55, 0.67, 0.13 }

プログラムは、各組み合わせと、そのシーケンスが発生する関連確率を出力します。1は入力シーケンスのそのインデックス内のイベントが発生したことを示し、0はそのイベントが発生しなかったことを示します。望ましい出力は以下のとおりです(作業の印刷は気にしません。これはアルゴリズムの情報提供のみを目的としています)。

[0,0,0] = (1 - 0.55) * (1-0.67) * (1-0.13) = 0.129195
[0,0,1] = (1 - 0.55) * (1-0.67) * (0.13)   = 0.019305
[0,1,0] = (1 - 0.55) * (0.67)   * (1-0.13) = 0.262305
[0,1,1] = (1 - 0.55) * (0.67)   * (0.13)   = 0.039195
[1,0,0] = (0.55)     * (1-0.67) * (1-0.13) = 0.157905
[1,0,1] = (0.55)     * (1-0.67) * (0.13)   = 0.023595
[1,1,0] = (0.55)     * (0.67)   * (1-0.13) = 0.320595
[1,1,1] = (0.55)     * (0.67)   * (0.13)   = 0.047905

この問題は、「デカルト積」の計算に正接しています。

これはコードゴルフなので、バイト数が最も少ないコードが優先されます。


3
プログラミングパズルとコードゴルフへようこそ。最初の挑戦です。
ドアノブ

考え[0.129195, 0.019305, 0.262305, ..., 0.047905]出力としては十分であるか、またはされている[0,0,0], [0,0,1], ...必要が?
ライコニ

@Laikoniその出力は問題ありません。出力部分は問題の肉ではありません。
マークジョンソン

出力を逆順にすることはできますか?
ルイスメンドー

@LuisMendoもちろんです。
マークジョンソン

回答:


8

Haskell、86バイト

unlines.map(\p->show(fst<$>p)++" = "++show(product$snd<$>p)).mapM(\x->[(0,1-x),(1,x)])

使用例:

Prelude> putStrLn $ unlines.map(\p->show(fst<$>p)++" = "++show(product$snd<$>p)).mapM(\x->[(0,1-x),(1,x)]) $ [0.55, 0.67, 0.13]
[0,0,0] = 0.12919499999999998
[0,0,1] = 1.9304999999999996e-2
[0,1,0] = 0.262305
[0,1,1] = 3.9195e-2
[1,0,0] = 0.157905
[1,0,1] = 2.3595e-2
[1,1,0] = 0.320595
[1,1,1] = 4.790500000000001e-2

ほとんどのバイトは出力フォーマットに費やされます。確率ベクトルのみに興味がある場合、たった29バイトです。

map product.mapM(\x->[1-x,x])

使い方:

                    mapM(\x->[(0,1-x),(1,x)])   -- for each number x in the input
                                                -- list make either the pair (0,1-x)
                                                -- or (1,x). Build a list with
                                                -- all combinations

    map(\p->                    )               -- for each such combination p
          show(fst<$>p)                         -- print the first elements
          ++" = "++                             -- then the string " = "
          show(product$snd<$>p)                 -- then the product of the second
                                                -- elements

unlines                                         -- joins with newlines

これはきれいです。これを行うための非常に短い純粋に機能的な方法があるかどうか興味がありました。C#またはF#を知っていますか?Haskell構文に完全に慣れていないので、これらの言語の同じアルゴリズムがどのように見えるか興味があります。
マークジョンソン

@MarkJohnson:いいえ、C#もF#もわかりません。
nimi

5

Mathematica、46 45バイト

(s=#;1##&@@Abs[#-s]&/@{1,0}~Tuples~Length@s)&

リストを取得します。でも、空のリストのために働く{}の出力があるため、{1}

テストケース:

%[{0.55, 0.67, 0.13}]
{0.129195, 0.019305, 0.262305, 0.039195, 0.157905, 0.023595, 0.320595, 0.047905}

説明

確率のリストを指定するsと、ビットのリストb0「発生しなかった」を示すと1「発生した」を示す、乗算される確率のリストは次式で与えられます。

1 - b - s

サインまで。代わりに0「発生した」と1「発生しなかった」を示す場合、これは

b - s

だから私たち:

                      {1,0}~Tuples~Length@s   (* Generate all possible bit combinations *)
              (#-s)&/@{1,0}~Tuples~Length@s   (* Generate probabilities to be multiplied
                                                  up to sign *)
     1##&@@Abs[#-s]&/@{1,0}~Tuples~Length@s   (* Correct sign and multiply;
                                                 1##& is short for Times *)
(s=#;1##&@@Abs[#-s]&/@{1,0}~Tuples~Length@s)& (* Assign s to first argument of function,
                                                 done separately to avoid clash
                                                 with inner function *)

4

Perl、42 40バイト

+1を含む -a

STDINに番号を付けます:

perl -M5.010 combi.pl <<< "0.55 0.67 0.13"

出力

0.129195
0.019305
0.262305
0.039195
0.157905
0.023595
0.320595
0.047905

combi.pl

#!/usr/bin/perl -a
$"=")\\*({1-,}";say eval for<({1-,}@F)>

4

MATL12 11バイト

TF-|Z}&Z*!p

入力は、次の形式の列ベクトルです。 [0.55; 0.67; 0.13]

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

TF    % Push [1, 0]
-     % Subtract from implicit input (column array), with broadcast. Gives a 2-col
      % matrix where the first column is the input minus 1 and the second is the input
|     % Absolute value
Z}    % Split the matrix into its rows
&Z*   % Cartesian product of all resulting. This gives a matrix as result, with each
      % "combination" on a different row
!p    % Product of each row. Implicitly display

3

Perl、116バイト

for(glob"{0,1}"x(@a=split/ /,<>)){@c=split//;$d=1;$d*=@c[$_]?$a[$_]:1-$a[$_]for 0..$#a;say"[".join(",",@c)."] = $d"}

読みやすい:

for(glob"{0,1}"x(@a=split/ /,<>)){
    @c=split//;
    $d=1;$d*=@c[$_]?$a[$_]:1-$a[$_]for 0..$#a;
    say"[".join(",",@c)."] = $d"
}

入力パラメーターの数に等しい長さの0と1のすべての可能な組み合わせのリストを作成し(たとえば、上記の例では、長さ3になります)、各確率を計算します。

ものを私を示すため@Dadaのおかげでglob機能ませんが、私は100%じゃないにもかかわらず、必ず私は理解してどのようにそれはそれを行います。

サンプル出力:

[0,0,0] = 0.129195
[0,0,1] = 0.019305
[0,1,0] = 0.262305
[0,1,1] = 0.039195
[1,0,0] = 0.157905
[1,0,1] = 0.023595
[1,1,0] = 0.320595
[1,1,1] = 0.047905

1
-a代わりに(@a=split/ /,<>)...
ダダ

3

R、72 69バイト

stdinから入力を受け取り、確率のRベクトルを返します。

apply(abs(t(expand.grid(rep(list(1:0),length(x<-scan())))-x)),1,prod)

編集:不要な転置を1つ削除しました。置換行列は下の転置行列になり、確率は行単位ではなく列単位の積として計算されます。 出力例:

[1] 0.129195 0.157905 0.262305 0.320595 0.019305 0.023595 0.039195 0.047905

によってexpand.grid生成された順列行列は以下を生成するため、確率は異なる順序になっていることに注意してください(この行列の生成は、おそらく外部パッケージを使用して行うことができます)。

1    1    1    1
2    0    1    1
3    1    0    1
4    0    0    1
5    1    1    0
6    0    1    0
7    1    0    0
8    0    0    0

最初の確率は、上記のマトリックスの最初の行の反転結果に対応し、2番目は反転した2行目などに対応します。これを確認するために出力をフォーマットすると、プログラムがさらに長くなります(164バイト):

m=expand.grid(rep(list(1:0),length(x<-scan())))
cat(paste0("[",apply(abs(m-1),1,function(x)paste0(x,collapse=",")),"] = ",apply(abs(t(t(m)-x)),1,prod),"\n"),sep="")

代わりに生成されます:

[0,0,0] = 0.129195
[1,0,0] = 0.157905
[0,1,0] = 0.262305
[1,1,0] = 0.320595
[0,0,1] = 0.019305
[1,0,1] = 0.023595
[0,1,1] = 0.039195
[1,1,1] = 0.047905

私はこれに対する自分の答えに取り組んでいましたが、きちんとした解決策を思い付くことができませんでした。の素晴らしい使用expand.grid!私はそれapplyが行列だけでなくデータフレームでも動作できると思うので、あなたのコードはt(t(...))6バイトを節約するなしで動作するはずです。
-rturnbull

@rturnbull tデータフレームとは関係ありませんが、順列行列(異なる次元)から確率ベクトルを減算できることに注意してください。Rがこれらのベクトル化された演算を処理する方法のため、少なくともそれらの1つが必要ですが、おそらく外側の転置を削除し、代わりに列に積を適用できます。明日更新
ビリーウォブ


2

J、14バイト

-.([:,*/)/@,.]

使用法

   f =: -.([:,*/)/@,.]
   f 0.55 0.67 0.13
0.129195 0.019305 0.262305 0.039195 0.157905 0.023595 0.320595 0.047905

説明

-.([:,*/)/@,.]  Input: array P
-.              Complement (1-x) for each x in P
             ]  Identity, get P
           ,.   Interleave to make pairs [(1-x), x]
  (     )/@     Reduce from right-to-left by
      */          Forming the multiplication table
   [:,            Flattening the result

|*//0.55 0.67 0.13-/0 1電車に乗れますか?
アダム

2

Pyth、10バイト

*MaVLQ^U2l

オンラインで試してください: デモンストレーション

説明:

*MaVLQ^U2lQ   implicit Q at the end (Q = input list)
      ^U2lQ   repeated Cartesian product of [0, 1] with itself length(Q)-times
              this gives all combinations of 0s and 1s
  aVLQ        absolute difference between these 0-1-vectors with Q
*M            fold the vectors by multiplication

1

C、110バイト

i,k;f(float* a,int n){for(k=0;k<1<<n;++k){float p=1;for(i=0;i<n;++i)p*=k&(1<<i)?a[i]:1-a[i];printf("%f,",p);}}

ゴルフをしていない:

i,k;f(float* a,int n){ 
 for(k=0; k<1<<n; ++k){
  float p=1;
  for (i=0; i<n; ++i)
   p*=k&(1<<i)?a[i]:1-a[i];
  printf("%f,",p);
 }
}

最大32個のアイテム、64個のアイテムに対して+ 5 + 1バイトまで動作します(最初のループで宣言long k;して追加Lしますk<1L<<N)。


1
32を超えるアイテムの場合、Cは「L」リテラルを*1*<<n必要としますか、それともC ++のものですか?
マークジョンソン

@MarkJohnsonはい、必要だと思います。
カールナップ

1

05AB1E、8バイト

<Äæ¹æR+P

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

 <Äæ¹æR+P  # Main link (Input is [.1,.2])
 ###########
 <Ä        # Invert input, take the abs value.
           # Stack is [.9,.8]
   æ¹æ     # Powerset of both inverted and original arrays.
           # Stack is [[],[.1],[.2],[.1,.2]],[[],[.9],[.8],[.9,.8]]
      R+   # Reverse original array, add arrays together.
           # Stack is [.9,.8],[.1,.8],[.2,.9],[.1,.2]
        P  # For each sub array, push product.
           # Final Result: [0.02, 0.18, 0.08, 0.72]
           # E.G.          [  11,   10,   01,   00]

1

JavaScript(Firefox 30-57)、57バイト

f=([p,...a])=>1/p?[for(q of[1-p,p])for(b of f(a))q*b]:[1]

すべての確率の配列を返します。イベントの配列も必要な場合は、86バイトの場合:

f=([p,...a])=>1/p?[for(e of'01')for(b of f(a))[[+e,...b[0]],(+e?p:1-p)*b[1]]]:[[[],1]]

イベントを文字列として許可している場合、たった80バイトです。

f=([p,...a])=>1/p?[for(e of'01')for(b of f(a))[e+b[0],(+e?p:1-p)*b[1]]]:[['',1]]

1/確率がゼロにならない場合は、ソリューションごとに2バイトを減算します。


これを<script></script>ブロックでどのように実行しますか?最初の「for」が予期しない問題が発生していますか?
マークジョンソン

@MarkJohnson Firefox 30以降を使用している限り、動作するはずです。
ニール

0

Perl 6の、24のラテン-1の19バイト

{[*] 1 «-»@_ «|»@_}

古いコード:

{[*] map {1-$^a|$^a},@_}

これは機能です。次のように使用します。

{[*] 1 «-»@_ «|»@_}(0.55, 0.67, 0.13)

取得するため:

any(any(any(0.129195, 0.019305), any(0.262305, 0.039195)), any(any(0.157905, 0.023595), any(0.320595, 0.047905)))

古いコードの説明:

[*]          multiply together all array elements
map          but first transform each element via
{1-$^a|$^a}  considering both 1 minus the value and the value
,@_          of the function input

新しいコードは基本的に同じで、terser構文を使用します:

[*]          multiply together all array elements
1 «-»@_      of the array formed by subtracting the argument from 1
«|»@_        pointwise considering both that and the original array

マップは、anyより大きなany構造に乗算する構造でいっぱいの配列を生成し、ループを必要とせずに問題をきれいに解決します。

プログラムの最短言語ではありませんが、それは問題の非常に直接的な翻訳です。


0

Dyalog APL、10 バイト

新しいソリューション

インデックスの起源は独立しています。匿名関数。確率リストを引数として取ります。

∘.×/⊢,¨1-⊢

∘.×/ デカルト積の削減

引数値

各ペア

1-⊢ 補数の引数値(1から引数値を引いた値)

TryAPLオンライン!


古いソリューション

⎕IO←0多くのシステムでデフォルトである必要があります。確率のリストのプロンプト。

|⎕∘.×.-⊂⍳2

説明

| の絶対値

入力、ɑ = [ ɑ ₁  ɑ ₂  ɑ ₃]

∘.×.-(修飾されたインナーテンソルは、乗算ɑ - ₁ B ₁)⊗(ɑ ₂ - B ₂)⊗(ɑ - ₃ Bを用いて、₃)

⊂⍳2囲まれたリストb = [[0 1]]

数学的定義

Bが封入され、それはスカラーであるための長さに延長ɑ全体式であるので、すなわち3

A =│(ɑ - ₁ B ⊗()ɑ ₂ - B)⊗(ɑ ₃ - B)│ =

 │(ɑ ₁ - [0,1])⊗(ɑ ₂ - [0,1])⊗(ɑ ₃ - [0,1])│=

 │[ ɑ ₁、ɑ ₁ - 1]⊗[ ɑ ₂ 、ɑ ₂ - 1]⊗[ ɑ ₃、ɑ ₃ - 1]│=

 ⎢⎡⎡   ɑɑɑ₃⎤⎡  ɑ ɑ₃-1)⎦⎦⎥₂(ɑ ₃-1)⎤⎤⎥
 ⎢⎢⎣  ɑ ₁(ɑ ₂-1)ɑ ₃⎦⎣  ɑ ₁(ɑ ₂-1)(ɑ ₃-1)⎦⎥⎥
 ⎢⎢⎡(ɑ ₁-1 )ɑɑ ₃⎤⎡(ɑ ₁-1)ɑ ₂(ɑ ₃-1)⎥⎥⎤
 ⎢⎣⎣(ɑ ₁-1)(ɑ ₂-1)ɑ ₃⎦⎣(ɑ ₁-1)(₂₂ -1)(ɑ

TryAPLオンライン!

注(古いソリューションと新しいソリューションの両方に適用)

プログラムと式は、任意の数(n)の変数に対して機能し、次元で長さ2のn次元配列を。3つの変数を使用すると、特定の結果の確率
Ppqr)= A pqr
は、配列から便利に選択できます。(⊃A)[p;q;r]で抽出p q r⌷⊃A

例えば1 1 0⌷⊃|0.55 0.67 0.13∘.×.-⊂⍳2P(55%、67%、¬13%)= 1.9305%を与えます


0

PHP、105 97 94 93 87バイト

for(;$i<2**$c=count($a=$argv)-$p=1;$i+=print-abs($p))for(;$c;)$p*=$a[$c--]-!($i>>$c&1);

次のように実行します:

php -r 'for(;$i<2**$c=count($a=$argv)-$p=1;$i+=print-abs($p))for(;$c;)$p*=$a[$c--]-!($i>>$c&1);' -- .55 .67 .13 2>/dev/null;echo
> -0.129195-0.157905-0.262305-0.320595-0.019305-0.023595-0.039195-0.047905

出力はリトルエンディアンであることに注意してください。

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

説明

for(
  ;
  $i<2**$c=                 # Iterate over possible combinations: 2^c,
    count($a=$argv)-$p=1;   #   where c is input length -p (set p to 1)
  $i+=print-abs($p)         # Increment i and print product after each
)                           #   iteration, dash separated
  for(
     ;
     $c;                    # Iterate over input ($c..0)
  )
    $p*=                    # Multiply the product by difference between:
      $a[$c--]-             # - The $c-th item of the input.
      !($i>>$c&1);          # - The $c-th bit of `$i`, negated (1 or 0)

微調整

  • 文字列に変換する代わりにバイナリロジックを使用してビットを取得することで8バイトを節約
  • $p1へのリセットと以下の計算を組み合わせて1 バイトを保存しました$c
  • $iインクリメントする代わりにprint(1)の結果を追加することにより、バイトを保存しました
  • アンダースコアを出力区切り文字として使用してバイトを保存しました
  • 区切り記号としてマイナス記号を使用してバイトを保存しました(負の可能性はありません)。
  • $c代わりにを使用して6バイトを保存しました$$i

0

C ++ 17、137 131 129バイト

を宣言して6バイトを#define A auto節約します。そのような短いマクロが初めて何かを保存するのは初めてです。- #importスペースを使用および削除する前に2バイト<

#import<iostream>
#define A auto
A g(A r){std::cout<<r<<",";}A g(A r,A x,A...p){g(x*r,p...);g(r-x*r,p...);}A f(A...p){g(1,p...);}

可能なすべての組み合わせを生成します。

ゴルフをしていない:

//base case to print the result
int g(auto r){std::cout << r << ",";}

//extract item from parameter pack
int g(auto r, auto x, auto... p) {
 g(x*r,p...);    //multiply with temp result and call with tail
 g(r-x*r,p...);  //same as above for (1-x)
}

//start of recursion, setting temp result to 1
int f(auto...p){g(1,p...);}

使用法:

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