Prawdopodobieństwo wszystkich kombinacji danych zdarzeń

18

Biorąc pod uwagę sekwencje zdarzeń o prawdopodobieństwach od 0,0 do 1,0, generuj i wyprowadzaj prawdopodobieństwo wystąpienia każdej kombinacji. Możesz założyć, że podana jest ciąg liczb w dowolnej konstrukcji wybranego przez ciebie języka.

Oto przykład; możesz założyć, że długość kombinacji sekwencji pasuje do pamięci:

{ 0.55, 0.67, 0.13 }

Program wydrukuje każdą kombinację i związane z nią prawdopodobieństwo wystąpienia tej sekwencji. 1 oznacza, że ​​zdarzenie w tym indeksie sekwencji wejściowej miało miejsce, a 0 oznacza, że ​​to zdarzenie nie miało miejsca. Pożądane dane wyjściowe są poniżej (nie dbam o drukowanie pracy, to tylko w celach informacyjnych algorytmu):

[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

Problem ten jest stycznie związany z obliczaniem „produktu kartezjańskiego”.

Pamiętaj, to jest kodowanie w golfa, więc wygrywa kod z najmniejszą liczbą bajtów.

Mark Johnson
źródło
3
Witamy w Programowaniu łamigłówek i Code Golf i miłym pierwszym wyzwaniu!
Klamka
Czy [0.129195, 0.019305, 0.262305, ..., 0.047905]wystarczyłoby jako wyjście, czy jest [0,0,0], [0,0,1], ...konieczne?
Laikoni
@Laikoni To wyjście jest w porządku. Część wyjściowa nie jest sednem problemu.
Mark Johnson
Czy wyjście może być w odwrotnej kolejności?
Luis Mendo,
@LuisMendo Pewnie, dlaczego nie.
Mark Johnson

Odpowiedzi:

8

Haskell, 86 bajtów

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

Przykład użycia:

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

Większość bajtów jest przeznaczona na formatowanie wyjściowe. Jeśli interesuje Cię tylko wektor prawdopodobieństwa, to tylko 29 bajtów:

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

Jak to działa:

                    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
nimi
źródło
To jest miłe; Byłem ciekawy, czy istniałby naprawdę krótki, czysto funkcjonalny sposób na zrobienie tego. Czy znasz C # lub F #? Jestem ciekawy, jak mógłby wyglądać ten sam algorytm w tych językach, ponieważ zupełnie nie znam składni Haskella.
Mark Johnson
@MarkJohnson: nie, przepraszam, nie znam ani C #, ani F #.
nimi
5

Mathematica, 46 45 bajtów

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

Pobiera listę. Działa nawet dla pustej listy {}, dla której jest wyjście {1}.

Przypadek testowy:

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

Wyjaśnienie

Biorąc pod uwagę listę prawdopodobieństw soraz listę bitów bz 0oznaczający „nie występuje” i 1oznaczające „doszło”, listę prawdopodobieństw być mnożona jest przez daną

1 - b - s

do podpisania. Jeśli zamiast tego 0oznacza „wystąpił” i 1„nie wystąpił”, upraszcza to

b - s

więc my:

                      {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 *)
u54112
źródło
4

Perl, 42 40 bajtów

Obejmuje +1 dla -a

Podaj liczby na STDIN:

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

wyjścia

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)>
Ton Hospel
źródło
4

MATL , 12 11 bajtów

TF-|Z}&Z*!p

Dane wejściowe to wektor kolumny o formacie [0.55; 0.67; 0.13]

Wypróbuj online!

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
Luis Mendo
źródło
3

Perl, 116 bajtów

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

Czytelny:

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

Tworzy listę wszystkich możliwych kombinacji zer i 1 długości równych liczbie parametrów wejściowych (np. Dla powyższego przykładu będzie to długość 3), a następnie oblicza każde prawdopodobieństwo.

Dzięki @Dada za pokazanie mi, co potrafi taglob funkcja , mimo że nie jestem w 100% pewien, że rozumiem, jak to robi.

Przykładowe dane wyjściowe:

[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
Gabriel Benamy
źródło
1
-azamiast (@a=split/ /,<>)...
Dada
3

R, 72 69 bajtów

Pobiera dane wejściowe ze standardowego wejścia i zwraca wektor R prawdopodobieństw.

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

Edycja: Usunięto jedną niepotrzebną transpozycję, macierz permutacji jest teraz transponowaną wersją poniższej, a prawdopodobieństwa są obliczane jako iloczyn kolumnowy, a nie wierszowy. Przykładowe dane wyjściowe:

[1] 0.129195 0.157905 0.262305 0.320595 0.019305 0.023595 0.039195 0.047905

Zauważ, że prawdopodobieństwa są w innej kolejności ze względu na fakt, że macierz permutacji generowana przez expand.gridpowoduje: (generowanie tej macierzy można prawdopodobnie zagrać w golfa za pomocą zewnętrznych pakietów):

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

Pierwsze prawdopodobieństwo odpowiada odwróconemu wynikowi pierwszego wiersza w powyższej macierzy, a drugie odwróconemu drugiemu wierszowi itp. Formatowanie wyniku, aby zobaczyć to jeszcze wyraźniej, powoduje, że program jest dłuższy (164 bajty):

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

który zamiast tego wytwarza:

[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
Billywob
źródło
Pracowałem nad własną odpowiedzią na to pytanie, ale nie mogłem znaleźć zgrabnego rozwiązania. Świetne wykorzystanie expand.grid! Myślę, że to applymoże działać zarówno na ramkach danych, jak i macierzach, więc twój kod powinien działać bez t(t(...)), co pozwoli ci zaoszczędzić 6 bajtów.
rturnbull
@rturnbull Uwaga, która tnie jest powiązana z żadną ramką danych, ale umożliwia odjęcie wektora prawdopodobieństwa od macierzy permutacji (o różnych wymiarach). Co najmniej jedna z nich jest potrzebna ze względu na sposób, w jaki R obsługuje te wektoryzowane operacje, ale prawdopodobnie mógłbym usunąć zewnętrzną transpozycję i zastosować produkt zamiast kolumn. Zaktualizuje jutro
Billywob
2

J, 14 bajtów

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

Stosowanie

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

Wyjaśnienie

-.([:,*/)/@,.]  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
mile
źródło
Czy potrafisz wsiąść |*//0.55 0.67 0.13-/0 1do pociągu?
Adám
2

Pyth, 10 bajtów

*MaVLQ^U2l

Wypróbuj online: Demonstracja

Wyjaśnienie:

*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
Jakube
źródło
1

C, 110 bajtów

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

Nie golfowany:

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

Działa do 32 elementów, + 5 + 1 bajtów dla 64 elementów (zadeklaruj long k;i dodaj Lw pierwszej pętli, aby k<1L<<N).

Karl Napf
źródło
1
Czy dla> 32 pozycji C wymaga literału „L” na, *1*<<nczy jest to po prostu C ++?
Mark Johnson
@MarkJohnson tak, myślę, że będzie to wymagać.
Karl Napf,
1

05AB1E , 8 bajtów

<Äæ¹æR+P

Wypróbuj online!

 <Äæ¹æ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]
Urna Magicznej Ośmiornicy
źródło
1

JavaScript (Firefox 30-57), 57 bajtów

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

Zwraca tablicę wszystkich prawdopodobieństw. Jeśli chcesz także tablicę zdarzeń, to dla 86 bajtów:

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

Jeśli dozwolone są zdarzenia jako ciąg, to tylko 80 bajtów:

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

Odejmij dwa bajty dla 1/każdego rozwiązania, jeśli prawdopodobieństwo nigdy nie będzie wynosić zero.

Neil
źródło
Jak prowadziłbyś to w <script></script>bloku? Mam problemy z pierwszym niespodziewanym „za”?
Mark Johnson
@MarkJohnson Jeśli używasz przeglądarki Firefox 30 lub nowszej, powinna działać.
Neil,
0

Perl 6, 24 19 bajtów Latin-1

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

Starszy kod:

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

To jest funkcja. Użyj tego w ten sposób:

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

uzyskać:

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

Objaśnienie starszego kodu:

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

Nowszy kod jest w zasadzie taki sam, używając tylko składni 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

Mapa generuje tablicę pełną anykonstrukcji, które mnożą się w większe anykonstrukcje, starannie rozwiązując problem, nawet nie potrzebując pętli.

Nie jest to najkrótszy język programu, ale jest to bardzo bezpośrednie tłumaczenie problemu.


źródło
0

Dyalog APL , 10 bajtów

Nowe rozwiązanie

Niezależne pochodzenie indeksu. Funkcja anonimowa. Jako argument przyjmuje listę prawdopodobieństw.

∘.×/⊢,¨1-⊢

∘.×/ Zmniejszenie produktu kartezjańskiego

wartości argumentów

każdy w połączeniu z

1-⊢ uzupełniające wartości argumentów (lit. jeden minus wartości argumentów)

Wypróbuj APL online!


Stare rozwiązanie

Wymaga ⎕IO←0ustawienia domyślnego w wielu systemach. Monity o listę prawdopodobieństw.

|⎕∘.×.-⊂⍳2

Wyjaśnienie

| wartość bezwzględna

wejście, ɑ = [ ɑ ₁  ɑ ₂  ɑ ₃]

∘.×.-zmodyfikowany tensor wewnętrzny pomnożony, ( ɑ ₁ - b ₁) ⊗ ( ɑ ₂ - b ₂) ⊗ ( ɑ ₃ - b ₃), z

⊂⍳2załączona lista b = [[0 1]]

Definicja matematyczna

Jak ₃ ⎤ ⎡   ɑ b jest ujęte, jest skalarne, a zatem rozszerzone do długości ɑ , a mianowicie 3, więc całe wyrażenie to

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

Wypróbuj APL online!

Uwagi (dotyczy zarówno starego, jak i nowego rozwiązania)

Program i formuła działają dla dowolnej liczby ( n ) zmiennych i zwracają n- wymiarową tablicę o długości 2 w każdym wymiarze. Przy trzech zmiennych prawdopodobieństwo określonego wyniku
P ( p , q , r ) = A p , q , r,
które można wygodnie wybrać z tablicy za pomocą (⊃A)[p;q;r]wyodrębnionego za pomocąp q r⌷⊃A

Np. 1 1 0⌷⊃|0.55 0.67 0.13∘.×.-⊂⍳2Daje P (55%, 67%, ¬13%) = 1,9305%

Adám
źródło
0

PHP, 105 97 94 93 87 bajtów

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

Uruchom tak:

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

Zauważ, że wyjście to mały endian:

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

Wyjaśnienie

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)

Poprawki

  • Zaoszczędzono 8 bajtów przy użyciu logiki binarnej, aby uzyskać bit zamiast konwersji na ciąg
  • Zapisano bajt, łącząc resetowanie $pdo 1 z obliczeniem$c
  • Zapisano bajt, dodając wynik print (1) do $izamiast zwiększania
  • Zapisano bajt, używając podkreślnika jako separatora wyjściowego
  • Zapisano bajt za pomocą znaku minus jako separatora (nie ma żadnych szans ujemnych).
  • Zapisano 6 bajtów, używając $czamiast$$i
aross
źródło
0

C ++ 17, 137 131 129 bajtów

Oszczędność 6 bajtów poprzez oświadczenie #define A auto, że tak krótkie makro po raz pierwszy zapisuje wszystko. -2 bajty do używania #importi usuwania spacji wcześniej<

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

Odradza wszystkie możliwe kombinacje.

Nie golfowany:

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

Stosowanie:

f(0.55, 0.67, 0.13);
Karl Napf
źródło