Xác suất của tất cả các kết hợp của các sự kiện đã cho


18

Đưa ra một chuỗi các sự kiện có xác suất từ ​​0,0 đến 1, tạo và rút ra xác suất của mỗi sự kết hợp xảy ra. Bạn có thể đoán rằng một chuỗi số được cung cấp trong bất kỳ cấu trúc nào mà ngôn ngữ bạn chọn cung cấp.

Đây là một ví dụ; bạn có thể đoán rằng độ dài của các kết hợp của chuỗi phù hợp với bộ nhớ:

{ 0.55, 0.67, 0.13 }

Chương trình sẽ in từng kết hợp và xác suất liên quan của chuỗi đó xảy ra. 1 sẽ biểu thị rằng sự kiện trong chỉ mục đó của chuỗi đầu vào xảy ra và 0 sẽ biểu thị rằng sự kiện đó đã không xảy ra. Đầu ra mong muốn ở bên dưới (Tôi không quan tâm đến việc in tác phẩm, đó chỉ nhằm mục đích thông tin của thuật toán):

[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

Vấn đề này liên quan đến việc tính toán một "sản phẩm của Cartesian".

Hãy nhớ rằng, đây là mã golf, vì vậy mã có số byte ít nhất sẽ thắng.


3
Chào mừng bạn đến với Lập trình Câu đố & Code Golf, và thử thách đầu tiên thú vị!
tay nắm cửa

Sẽ [0.129195, 0.019305, 0.262305, ..., 0.047905]là đủ như đầu ra hoặc là [0,0,0], [0,0,1], ...cần thiết?
Laikoni 6/11/2016

@Laikoni Sản lượng đó ổn. Phần đầu ra không phải là vấn đề cốt lõi.
Mark Johnson

Đầu ra có thể được theo thứ tự ngược lại?
Luis Mendo

@LuisMendo Chắc chắn, tại sao không.
Mark Johnson

Câu trả lời:


8

Haskell, 86 byte

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

Ví dụ sử dụng:

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

Hầu hết các byte được dành cho định dạng đầu ra. Nếu bạn chỉ quan tâm đến vectơ xác suất thì chỉ có 29 byte:

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

Làm thế nào nó hoạt động:

                    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

Đây là gọn gàng; Tôi tò mò liệu sẽ có một cách thực sự ngắn gọn hoàn toàn chức năng để làm việc này. Bạn có tình cờ biết C # hoặc F #? Tôi tò mò thuật toán tương tự trong các ngôn ngữ đó sẽ trông như thế nào vì tôi hoàn toàn không quen với cú pháp Haskell.
Mark Johnson

@MarkJohnson: không, xin lỗi tôi không biết C # hay F #.
nimi

5

Toán học, 46 45 byte

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

Đưa ra một danh sách. Thậm chí hoạt động cho danh sách trống {}, mà đầu ra là {1}.

Trường hợp thử nghiệm:

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

Giải trình

Đưa ra một danh sách các xác suất svà một danh sách các bit b0biểu thị "không xảy ra" và 1biểu thị "đã xảy ra", danh sách các xác suất sẽ được nhân lên được đưa ra bởi

1 - b - s

lên để ký. Nếu thay vào đó 0biểu thị "đã xảy ra" và 1"không xảy ra", thì điều này đơn giản hóa thành

b - s

vì vậy chúng tôi:

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

Bao gồm +1 cho -a

Cho số trên STDIN:

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

đầu ra

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

MATL , 12 11 byte

TF-|Z}&Z*!p

Đầu vào là một vectơ cột, với định dạng [0.55; 0.67; 0.13]

Hãy thử trực tuyến!

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 byte

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

Có thể đọc được

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

Tạo một danh sách tất cả các kết hợp có thể có 0 và 1 độ dài bằng với số lượng tham số đầu vào (ví dụ: ví dụ ở trên, nó sẽ có độ dài 3), sau đó tính toán từng xác suất.

Cảm ơn @Dada đã chỉ cho tôi những gì globchức năng có thể làm, mặc dù tôi không chắc chắn 100% tôi hiểu cách thức hoạt động của nó.

Đầu ra mẫu:

[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
-athay vì (@a=split/ /,<>)...
Dada

3

R, 72 69 byte

Lấy đầu vào từ stdin và trả về một vectơ xác suất.

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

Chỉnh sửa: Đã xóa một chuyển đổi không cần thiết, ma trận hoán vị bây giờ là phiên bản chuyển đổi của một bên dưới và xác suất được tính là sản phẩm theo cột thay vì theo hàng. Ví dụ đầu ra:

[1] 0.129195 0.157905 0.262305 0.320595 0.019305 0.023595 0.039195 0.047905

Lưu ý rằng các xác suất theo một thứ tự khác do thực tế là ma trận hoán vị được tạo ra bằng cách expand.gridtạo ra sau đây (việc tạo ra ma trận này có thể được đánh gôn bằng các gói bên ngoài):

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

Xác suất đầu tiên tương ứng với kết quả đảo ngược của hàng đầu tiên trong ma trận trên và thứ hai với hàng thứ hai đảo ngược, v.v. Định dạng đầu ra để thấy điều này thậm chí còn rõ ràng hơn làm cho chương trình dài hơn (164 byte):

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="")

mà thay vào đó tạo ra:

[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

Tôi đã làm việc với câu trả lời của riêng mình cho vấn đề này nhưng tôi không thể đưa ra một giải pháp gọn gàng. Công dụng tuyệt vời của expand.grid! Tôi nghĩ rằng nó applycó thể hoạt động trên các khung dữ liệu cũng như ma trận, vì vậy mã của bạn sẽ hoạt động mà không cần t(t(...)), điều này sẽ giúp bạn tiết kiệm 6 byte.
rturnbull

@rturnbull Lưu ý rằng tkhông liên quan đến bất kỳ khung dữ liệu nào nhưng để cho phép phép trừ của vectơ xác suất khỏi ma trận hoán vị (với các kích thước khác nhau). Ít nhất một trong số chúng là cần thiết do cách R xử lý các hoạt động được vector hóa này nhưng tôi có thể có thể loại bỏ chuyển vị bên ngoài và áp dụng sản phẩm trên các cột thay thế. Sẽ cập nhật vào ngày mai
Billywob


2

J, 14 byte

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

Sử dụng

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

Giải trình

-.([:,*/)/@,.]  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

Bạn có thể làm |*//0.55 0.67 0.13-/0 1thành một chuyến tàu?
Adám

2

Bình thường, 10 byte

*MaVLQ^U2l

Dùng thử trực tuyến: Trình diễn

Giải trình:

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

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

Ung dung:

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

Hoạt động tối đa 32 mục, + 5 + 1 byte cho 64 mục (khai báo long k;và thêm Lvào vòng lặp đầu tiên sao cho k<1L<<N).


1
Đối với> 32 mục, C có yêu cầu chữ "L" trên *1*<<nhoặc đó chỉ là một thứ C ++?
Mark Johnson

@MarkJohnson vâng tôi đoán nó sẽ yêu cầu.
Karl Napf

1

05AB1E , 8 byte

<Äæ¹æR+P

Hãy thử trực tuyến!

 <Äæ¹æ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 byte

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

Trả về một mảng của tất cả các xác suất. Nếu bạn cũng muốn mảng sự kiện, thì với 86 byte:

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

Nếu bạn cho phép các sự kiện dưới dạng một chuỗi, thì đó chỉ là 80 byte:

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

Trừ hai byte cho 1/mỗi giải pháp nếu xác suất không bao giờ bằng không.


Làm thế nào bạn sẽ chạy này trong một <script></script>khối? Tôi đang gặp vấn đề với "cho" đầu tiên là bất ngờ?
Mark Johnson

@MarkJohnson Miễn là bạn đang sử dụng Firefox 30 trở lên, nó sẽ hoạt động.
Neil

0

Perl 6, 24 19 byte tiếng Latin-1

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

Mã cũ hơn:

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

Đây là một chức năng. Sử dụng nó như thế này:

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

để có được:

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

Giải thích về mã cũ hơn:

[*]          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

Mã mới hơn về cơ bản là giống nhau, chỉ cần sử dụng cú pháp 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

Bản đồ tạo ra một mảng đầy các anycấu trúc, nhân lên thành các anycấu trúc lớn hơn , giải quyết gọn gàng vấn đề mà không cần đến một vòng lặp.

Không phải là ngôn ngữ ngắn nhất cho chương trình, nhưng đó là bản dịch trực tiếp của vấn đề.


0

APL Dyalog , 10 byte

Giải pháp mới

Chỉ số nguồn gốc độc lập. Chức năng ẩn danh. Lấy danh sách xác suất làm đối số.

∘.×/⊢,¨1-⊢

∘.×/ Việc giảm sản phẩm của Cartesian

các giá trị đối số

mỗi cặp với

1-⊢ các giá trị đối số bổ sung (một. trừ đi các giá trị đối số)

Dùng thử trực tuyến!


Giải pháp cũ

Yêu cầu ⎕IO←0mặc định trên nhiều hệ thống. Nhắc nhở cho danh sách xác suất.

|⎕∘.×.-⊂⍳2

Giải trình

| giá trị tuyệt đối của

đầu vào, ɑ = [ ɑ ₁  ɑ ₂  ɑ ₃]

∘.×.-sửa đổi tenxơ bên trong nhân, ( ɑ ₁ - b ₁) ⊗ ( ɑ ₂ - b ₂) ⊗ ( ɑ ₃ - b ₃), với

⊂⍳2danh sách kèm theo b = [[0 1]]

Định nghĩa toán học

Như b được kèm theo, nó là vô hướng, và do đó kéo dài đến chiều dài của ɑ , cụ thể là 3, vì vậy toàn bộ biểu thức là

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

Dùng thử trực tuyến!

Ghi chú (áp dụng cho cả giải pháp cũ và mới)

Chương trình và công thức hoạt động cho bất kỳ số ( n ) biến nào và trả về một mảng n chiều có chiều dài 2 ở mọi chiều. Với ba biến, xác suất của một kết quả cụ thể
P ( p , q , r ) = A p , q , r
có thể được chọn một cách thuận tiện từ mảng có (⊃A)[p;q;r]trích xuất vớip q r⌷⊃A

Ví dụ: 1 1 0⌷⊃|0.55 0.67 0.13∘.×.-⊂⍳2cho P (55%, 67%, ¬13%) = 1.9305%


0

PHP, 105 97 94 93 87 byte

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

Chạy như thế này:

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

Lưu ý rằng đầu ra là endian nhỏ:

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

Giải trình

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)

Tinh chỉnh

  • Đã lưu 8 byte bằng cách sử dụng logic nhị phân để lấy bit thay vì chuyển đổi thành chuỗi
  • Đã lưu một byte bằng cách kết hợp việc đặt lại $pthành 1 với tính toán của$c
  • Đã lưu một byte bằng cách thêm kết quả in (1) vào $ithay vì tăng
  • Đã lưu một byte bằng cách sử dụng dấu gạch dưới làm dấu phân cách đầu ra
  • Đã lưu một byte bằng cách sử dụng dấu trừ làm dấu phân cách (không có cơ hội tiêu cực).
  • Đã lưu 6 byte bằng cách sử dụng $cthay vì$$i

0

C ++ 17, 137 131 129 byte

Lưu 6 byte bằng cách khai báo #define A auto, lần đầu tiên một macro ngắn như vậy sẽ tiết kiệm mọi thứ. -2 byte để sử dụng #importvà xóa không gian trước<

#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...);}

Sinh ra tất cả các kết hợp có thể.

Ung dung:

//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...);}

Sử dụng:

f(0.55, 0.67, 0.13);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.