確率を正確に計算する


9

このタスクは、確率を正確に計算するコードを記述することです。出力は、最も縮小された形式で分数として記述された正確な確率でなければなりません。つまり、出力んです4/8けど、むしろ1/2

いくつかの正の整数についてn、1と-1の長さの一様にランダムな文字列を検討し、nそれをAと呼びます。次にA、最初の値に連結します。これはA[1] = A[n+1]、1からのインデックスAが長さを持っている場合 n+1です。ここでn、最初のn値が-1、0、または1であり、確率がそれぞれ1 / 4、1 / 2、1 / 4 である長さの2番目のランダムな文字列についても検討し、Bと呼びます。

たとえば、を検討してくださいn=3。以下のための可能な値Aとは、B可能性A = [-1,1,1,-1]B=[0,1,-1]。この場合、2つの内積は0および2です。

今の内積考えるA[1,...,n]Bとの内積をA[2,...,n+1]してB

コードは、両方の内積がゼロである確率を出力する必要があります。

以下のためにn=1、この確率明確です1/2

nコードでどのように指定されているかは問題ではありませんが、変更方法は非常に単純で明白なはずです。

言語とライブラリ

任意の言語とライブラリを使用できます。コードを実行したいので、可能であればLinuxでコードを実行/コンパイルする方法の完全な説明を含めてください。


2
最初のいくつかのテストケースはn役に立ちます。また、A、Bおよび2つの内積の明示的な例も役立つかもしれません。
マーティンエンダー2015年

整数をハーコード化することを選択した場合、0、2、n=4または3バイトとしてカウントされますか?出力は正確である a/b必要が[a b]ありますか、または許可されますか?
Dennis

@デニスそれは正確でなければなりません。あなたが整数をハードコードするならば、私はそれを変更するために一箇所でそれを変更する必要があるだけnでしょうか?そうでなければ、それは許されないと思います。

はい、私のプログラムは整数を1回だけ使用してデカルト指数を計算します。その他はすべて、結果の配列から派生します。
デニス

回答:


7

Pyth、48 47 46 44バイト

K,smlf!|Fms*Vd.>Tk2^,1_1Q^+0tM3Q^8Qj\//RiFKK

オンラインで試す:デモ

オンライン版はおそらく計算しませんn=6。私のラップトップ(オフラインバージョン)では、約45秒かかります。

ブルートフォースアプローチ。

説明:

smlf!|Fms*Vd.>Tk2^,1_1Q^+0tM3Q   implicit: Q = input number
                          tM3    the list [-1, 0, 1]
                        +0       add zero, results in [0, -1, 0, 1]
                       ^     Q   all possible lists of length Q using these elements
 m                               map each list d (B in Lembik's notation) to:
                  ,1_1              the list [1, -1]
                 ^    Q             all possible lists of length Q
   f                                filter for lists T (A in Lembik's notation),
                                    which satisfy:
       m        2                      map each k in [0, 1] to:
        s*Vd.>Tk                          scalar-product d*(shifted T by k)
    !|F                                not or (True if both scalar-products are 0)      
  l                                 determine the length                
s                                add all possibilities at the end

K,...^8QQj\//RiFKK   
 ,...^8Q             the list [result of above, 8^Q]
K                    store it in K
              iFK    determine the gcd of the numbers in K
            /R   K   divide the numbers in K by the gcd
         j\/         join the two numbers by "/" and print

ダン、gcdのことを忘れて、私が逃したものがあることを知っていた
Maltysen

+0r1_2より短いです/R2r2_2
isaacg

あなたが数えるのは89/512バージョンであるべきだと私は公平だと思います。

@Lembik Ok変更しました。
ジャクベ2015年

認めざるを得ません。これは47文字で行うことができるとは思いもしませんでした。

8

Mathematica、159 100 87 86 85バイト

n=3;1-Mean@Sign[##&@@Norm/@({1,0,0,-1}~t~n.Partition[#,2,1,1])&/@{1,-1}~(t=Tuples)~n]

変更するには、nまだ始まったばかりで、変数の定義を変更してください。

ブルートフォースなのでかなり遅いですが、最初の8つの結果は次のとおりです。

n   P(n)
1   1/2
2   3/8
3   7/32
4   89/512
5   269/2048
6   903/8192
7   3035/32768
8   169801/2097152

最後のものはすでに231秒かかり、ランタイムは恐ろしく指数関数的です。

説明

私が言ったように、それは総当たりです。基本的に、私はすべての可能性を列挙していますAB、可能なすべてのペアのための2つのドット積を計算して、得られることがペアの割合を見つけます{0, 0}。Mathematicaの組合せ論と線形代数関数はこれを行う上で非常に役立ちました:

{1,-1}~(t=Tuples)~n

これは、1or を含むすべてのnタプルを生成します。-1つまり、すべて可能Aです。以下のためにn = 3それであります:

{{1, 1, 1}, 
 {1, 1, -1}, 
 {1, -1, 1}, 
 {1, -1, -1}, 
 {-1, 1, 1}, 
 {-1, 1, -1}, 
 {-1, -1, 1}, 
 {-1, -1, -1}}

計算Bもほぼ同じです。

{1,0,0,-1}~t~n

を繰り返すことにより0、各タプル0に含まれる各タプルを複製します。これにより01またはの2倍の可能性があり-1ます。もう一度n = 3例として使用します。

{{-1, -1, -1},
 {-1, -1, 0}, {-1, -1, 0},
 {-1, -1, 1},
 {-1, 0, -1}, {-1, 0, -1},
 {-1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, {-1, 0, 0},
 {-1, 0, 1}, {-1, 0, 1},
 {-1, 1, -1},
 {-1, 1, 0}, {-1, 1, 0},
 {-1, 1, 1},
 {0, -1, -1}, {0, -1, -1},
 {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, -1, 0},
 {0, -1, 1}, {0, -1, 1},
 {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1},
 {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
 {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1},
 {0, 1, -1}, {0, 1, -1},
 {0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0},
 {0, 1, 1}, {0, 1, 1},
 {1, -1, -1},
 {1, -1, 0}, {1, -1, 0},
 {1, -1, 1},
 {1, 0, -1}, {1, 0, -1},
 {1, 0, 0}, {1, 0, 0}, {1, 0, 0}, {1, 0, 0},
 {1, 0, 1}, {1, 0, 1},
 {1, 1, -1},
 {1, 1, 0}, {1, 1, 0},
 {1, 1, 1}}

ここで、可能なAそれぞれについてB、との両方でA[1 .. n]、可能なそれぞれの内積を求めA[2 .. n+1]ます。たとえば、現在のA{1, 1, -1}である場合、両方の{1, 1, -1}とのドット積が必要です{1, -1, 1}。すべてBがすでに行列の行になっているので、の2つのサブリストAを別の行列の列として使用して、それらの間の単純なドット積を計算できるようにします。しかし、転置は{{1, 1, -1}, {1, -1, 1}}単に{{1, 1}, {1, -1}, {-1, 1}}のすべての2要素循環サブリストのリストであるを与えるだけですA。これは次のことを行います。

Partition[#,2,1,1]

したがって、それを計算し、のリストでドット積をとりBます。ネストされたリストを取得するため(可能な場合Aはそれぞれ個別のベクトルが生成されるため)、それらをでフラット化し##&@@ます。

ペアで{x, y}あるかどうかを確認するに{0, 0}は、Sign[Norm[{x,y}]] がどこでを計算するかを確認しNormます√(x²+y²)。これは0またはを与え1ます。

最後に、sとsの1リスト内のs の分数を知りたいだけなので、必要なのはリストの算術平均だけです。ただし、これにより、少なくとも1つの内積の両方が非ゼロになる確率が得られるので、それを減算して、目的の結果を得ます。011


6

Pyth- 65 55バイト

1バイトのコストで分数が減少するバグを修正しました。

ブルートフォースアプローチを使用し、非常にゴルフをすることができますが、そこに何かを出したかっただけです。非常に遅い

*F-KP/Jmms*Vked,thdPhd*makhk^,1_1Q^[1ZZ_1)Q,ZZ2/lJ^2/K2

デカルト積を使用してAとの両方を生成し、ソースリストに2回出現Bさせることにより変数確率を実行し、0その内積をゼロにカウントします。内積はVセクター化構文糖質によって容易になります。最初は分数を単純化するのは怖かったですが、Prime Factorization関数と2の累乗だけ削減すればよいという実現により、非常に簡単でした。

こちらからオンラインでお試しください


どうすれば変更できnますか?

@Lembik Pythプログラムは、2番目のテキストボックスで指定されているユーザー入力を要求します(オンラインコンパイラーを使用する場合)。
ジャクベ2015年

@Jakubeああありがとう!そして、それも実際に動作するようです:)

6

CJam、58 57 54 51 46バイト

WX]m*Zm*_{~.+2,@fm<\f.*::+0-!},,__~)&:T/'/@,T/

実行するには、目的の整数をWX]との間に挿入しますm*

ビットマジックと5バイトのゴルフをしてくれた@ jimmy23013に感謝します!

CJamインタープリターでオンラインで試してください。

考え

これらの回答のほとんどの部分は単純ですが、2つの巧妙なトリックを使用しています。

  • 代わりに、全てのベクトルのペアリングの{-1、1} n個の全てのベクトルと{-1、0、1} nは所望の確率とし、それにベクトルのトリプレットの数をカウント考慮{-1,1} N満足すること特定の条件。

    トリプレットの最後の2つのベクトルを追加すると、結果は{-2、0、2} nのベクトルになります。

    以来(-1)+ 1 = 0 = 1 +(-1) 0の2倍の頻度で起こる-2 sおよび2秒。

    各コンポーネントを2で除算すると、希望の確率を持つ{-1、0、1} nのベクトルが生成されます。

    スカラー積が0かどうかだけに関心があるので、2による除算をスキップできます。

  • 問題の条件を満たすすべてのトリプレットとトリプレットの総数を数えた後、結果として生じる割合を減らす必要があります。

    両方の数値のGCDを計算する代わりに、分母は常に2の累乗になるため、両方の数を分子を除算する2の最大の累乗で除算すれば十分です。

    xを除算する2の最高のべき乗を取得するには、xと〜x + 1のビット単位のANDを取ることができます。

    〜Xの全ビット反転さXを全ての後続ので、0秒になる1秒。追加することにより1をする〜X、それらの1秒がに戻って変わります0秒と最後の1〜のx + 1の最後の一致する1のx

    他のすべてのビットはどちらも0か異なるので、ビット単位のAND はxの最後の1とそれに続くすべての0から構成される整数を返します。これは、xを除算する2の最大べき乗です。

コード

WX]    e# Push the array [-1 1].
       e# Insert N here.
m*     e# Cartesian product: Push the array of all vectors of {-1,1}^N.
Zm*    e# Cartesian product: Push the array of all triplets of these vectors.
_      e# Copy the array.
{      e# Filter; for each triplet of vectors U, V and W in {-1,1}^N:
  ~    e#   Dump U, V and W on the stack.
  .+   e#   Compute X := V + W, a vector of {-2,0,2}^N, where each component is
       e#   zero with probability 1/2.
  2,@  e#   Push [0 1]. Rotate U on top of it.
  fm<  e#   Push [U U'], where U' is U rotated one dimension to the left.
  \f.* e#   Push [U*X and U'*X], where * denotes the vectorized product.
  ::+  e#   Add the components of both products.
  0-   e#   Remove zeroes.
       e#   Push the logical NOT of the array.
},     e#   If the array was empty, keep the triplet.
,      e# Push X, the length of the filtered array.
__~)&  e# Push X & ~X + 1.
:T     e# Save the result in T and divide X by T.
'/     e# Push a slash.
@,T/   e# Dividet he length of the unfiltered array by T.

WX]m*Zm*_{~.+2,@fm<\f.*::+0-!},,__W*&:T/'/@,T/
jimmy23013

@ jimmy23013:それは印象的なビットマジックです。ありがとう!
Dennis
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.