Probabilità di tutte le combinazioni di determinati eventi


18

Data una sequenza di eventi con probabilità tra 0,0 e 1,0, generare e derivare la probabilità che si verifichi ciascuna combinazione. Si può presumere che una sequenza di numeri sia fornita in qualunque costrutto fornito dalla lingua scelta.

Ecco un esempio; puoi presumere che la lunghezza delle combinazioni della sequenza si adatti alla memoria:

{ 0.55, 0.67, 0.13 }

Il programma stampa ogni combinazione e la probabilità associata che si verifichi tale sequenza. Un 1 indica che si è verificato l'evento in quell'indice della sequenza di input e uno 0 indica che l'evento non si è verificato. L'output desiderato è inferiore (non mi interessa stampare il lavoro, è solo a scopo informativo dell'algoritmo):

[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

Questo problema è tangenzialmente correlato al calcolo di un "prodotto cartesiano".

Ricorda, questo è code-golf, quindi vince il codice con il minor numero di byte.


3
Benvenuto in Programming Puzzles & Code Golf e la bella prima sfida!
Maniglia della porta

Sarebbe [0.129195, 0.019305, 0.262305, ..., 0.047905]sufficiente come output o sono [0,0,0], [0,0,1], ...necessari?
Laikoni,

@Laikoni Quel risultato va bene. La parte di output non è la causa del problema.
Mark Johnson,

L'output può essere in ordine inverso?
Luis Mendo,

@LuisMendo Certo, perché no.
Mark Johnson,

Risposte:


8

Haskell, 86 byte

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

Esempio di utilizzo:

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

La maggior parte dei byte viene spesa per la formattazione dell'output. Se sei interessato solo al vettore di probabilità sono solo 29 byte:

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

Come funziona:

                    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

Questo è pulito; Ero curioso di sapere se ci sarebbe stato un modo puramente funzionale per farlo. Ti capita di conoscere C # o F #? Sono curioso di sapere che aspetto avrebbe lo stesso algoritmo in quelle lingue poiché non ho familiarità con la sintassi di Haskell.
Mark Johnson,

@MarkJohnson: no, scusa non conosco né C # né F #.
nimi,

5

Mathematica, 46 45 byte

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

Prende un elenco. Funziona anche per l'elenco vuoto {}, per il quale è l'output {1}.

Caso di prova:

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

Spiegazione

Dato un elenco di probabilità se un elenco di bit bcon 0denota "non si è verificato" e 1denota "si è verificato", l'elenco di probabilità da moltiplicare è dato da

1 - b - s

fino a firmare. Se invece 0indica "si è verificato" e 1"non si è verificato", ciò semplifica

b - s

quindi noi:

                      {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

Include +1 per -a

Dai numeri su STDIN:

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

uscite

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

L'input è un vettore di colonna, con il formato [0.55; 0.67; 0.13]

Provalo 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

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"}

Leggibile:

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

Crea un elenco di tutte le possibili combinazioni di 0 e 1 di lunghezza pari al numero di parametri di input (ad esempio, per l'esempio sopra, sarebbe di lunghezza 3), quindi calcola ogni probabilità.

Grazie a @Dada per avermi mostrato cosa può fare la globfunzione , anche se non sono sicuro al 100% di capire come lo fa.

Uscita campione:

[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
-ainvece di (@a=split/ /,<>)...
Dada,

3

R, 72 69 byte

Prende input dallo stdin e restituisce un vettore R di probabilità.

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

Modifica: rimossa una trasposizione non necessaria, la matrice di permutazione è ora la versione trasposta di quella seguente e le probabilità sono calcolate come prodotto saggio a colonna piuttosto che a livello di riga. Esempio di output:

[1] 0.129195 0.157905 0.262305 0.320595 0.019305 0.023595 0.039195 0.047905

Si noti che le probabilità sono in un ordine diverso a causa del fatto che la matrice di permutazione generata da expand.grid produce quanto segue (la generazione di questa matrice può probabilmente essere giocata a golf usando pacchetti esterni):

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

La prima probabilità corrisponde al risultato invertito della prima riga nella matrice sopra e la seconda alla seconda riga invertita ecc. La formattazione dell'output per vedere ciò rende ancora più chiaramente il programma più lungo (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="")

che invece produce:

[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

Avevo lavorato sulla mia risposta a questo, ma non riuscivo a trovare una soluzione pulita. Ottimo uso di expand.grid! Penso che applypossa funzionare su frame di dati e matrici, quindi il tuo codice dovrebbe funzionare senza il t(t(...)), che ti farà risparmiare 6 byte.
rturnbull,

@rturnbull Nota che tnon è correlato ad alcun frame di dati ma per consentire la sottrazione del vettore di probabilità dalla matrice di permutazione (con dimensioni diverse). Almeno uno di questi è necessario a causa del modo in cui R gestisce queste operazioni vettorializzate ma probabilmente potrei rimuovere il trasposizione esterno e applicare invece il prodotto sulle colonne. Si aggiornerà domani
Billywob il


2

J, 14 byte

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

uso

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

Spiegazione

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

Puoi trasformarti |*//0.55 0.67 0.13-/0 1in un treno?
Adám,

2

Pyth, 10 byte

*MaVLQ^U2l

Provalo online: dimostrazione

Spiegazione:

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

Ungolfed:

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

Funziona fino a 32 elementi, + 5 + 1 byte per 64 elementi (dichiarare long k;e aggiungere Lnel primo ciclo in modo che k<1L<<N).


1
Per> 32 elementi, C richiede la "L" letterale *1*<<no è solo una cosa C ++?
Mark Johnson,

@MarkJohnson sì, credo che sarebbe necessario.
Karl Napf,

1

05AB1E , 8 byte

<Äæ¹æR+P

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

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]

Restituisce un array di tutte le probabilità. Se vuoi anche l'array di eventi, quindi per 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]]

Se gli eventi sono consentiti come stringa, sono solo 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]]

Sottrai due byte per 1/ogni soluzione se la probabilità non sarà mai zero.


Come eseguiresti questo in un <script></script>blocco? Ricevo problemi con il primo "per" essere inaspettato?
Mark Johnson,

@MarkJohnson Fintanto che usi Firefox 30 o versioni successive, dovrebbe funzionare.
Neil,

0

Perl 6, 24 19 byte di Latin-1

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

Codice precedente:

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

Questa è una funzione Usalo in questo modo:

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

ottenere:

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

Spiegazione del codice precedente:

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

Il codice più recente è sostanzialmente lo stesso, usando solo la sintassi 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

La mappa genera un array pieno di anycostrutti, che si moltiplicano in anycostrutti più grandi , risolvendo ordinatamente il problema senza nemmeno aver bisogno di un ciclo.

Non è la lingua più breve per il programma, ma è una traduzione molto diretta del problema.


0

Dyalog APL , 10 byte

Nuova soluzione

Origine dell'indice indipendente. Funzione anonima. Prende l'elenco delle probabilità come argomento.

∘.×/⊢,¨1-⊢

∘.×/ La riduzione del prodotto cartesiano è finita

i valori dell'argomento

ognuno accoppiato con

1-⊢ i valori dell'argomento del complemento (lett. uno meno i valori dell'argomento)

ProvaAPL online!


Vecchia soluzione

Richiede il ⎕IO←0valore predefinito su molti sistemi. Richiede l'elenco delle probabilità.

|⎕∘.×.-⊂⍳2

Spiegazione

| valore assoluto di

l'ingresso, ɑ = [ ɑ ₁  ɑ ₂  ɑ ₃]

∘.×.-tensore interno modificato moltiplicato, ( ɑ ₁ - b ₁) ⊗ ( ɑ ₂ - b ₂) ⊗ ( ɑ ₃ - b ₃), con

⊂⍳2l'elenco allegato b = [[0 1]]

Definizione matematica

Come b è racchiuso, è scalare e quindi esteso alla lunghezza di ɑ , ovvero 3, quindi l'intera espressione è

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

ProvaAPL online!

Note (si applica sia alla vecchia che alla nuova soluzione)

Il programma e la formula funzionano per qualsiasi numero ( n ) di variabili e restituiscono un array n- dimensionale di lunghezza 2 in ogni dimensione. Con tre variabili, la probabilità di un risultato specifico
P ( p , q , r ) = A p , q , r
che può essere comodamente selezionata dall'array con(⊃A)[p;q;r] estratto conp q r⌷⊃A

Es 1 1 0⌷⊃|0.55 0.67 0.13∘.×.-⊂⍳2P (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);

Esegui in questo modo:

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

Si noti che l'output è little 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]

Spiegazione

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)

Ritocchi

  • Salvato 8 byte usando la logica binaria per ottenere bit invece di convertirli in stringa
  • Salvataggio di un byte combinando il ripristino di $p1 con il calcolo di$c
  • Salvato un byte aggiungendo il risultato di print (1) $iinvece di incrementare
  • Salvataggio di un byte utilizzando il trattino basso come delimitatore di output
  • Ho salvato un byte usando il segno meno come delimitatore (non ci sono possibilità negative).
  • 6 byte salvati usando $cinvece di$$i

0

C ++ 17, 137 131 129 byte

Salvataggio di 6 byte dichiarando #define A auto, la prima volta che una macro così breve salva qualsiasi cosa. -2 byte per l'utilizzo #importe l'eliminazione dello spazio prima<

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

Genera tutte le possibili combinazioni.

Ungolfed:

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

Uso:

f(0.55, 0.67, 0.13);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.