Probabilidad de todas las combinaciones de eventos dados

18

Dada una secuencia de eventos con probabilidades entre 0.0 y 1.0, generar y derivar la probabilidad de que ocurra cada combinación. Puede suponer que se proporciona una secuencia de números en cualquier construcción que proporcione su idioma elegido.

Aquí hay un ejemplo; puede suponer que la longitud de las combinaciones de la secuencia se ajusta a la memoria:

{ 0.55, 0.67, 0.13 }

El programa imprimirá cada combinación y la probabilidad asociada de que ocurra esa secuencia. Un 1 indicará que ocurrió el evento en ese índice de la secuencia de entrada y un 0 indicará que ese evento no ocurrió. El resultado deseado está debajo (no me importa imprimir el trabajo, eso es solo para fines informativos del 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

Este problema está relacionado tangencialmente con el cálculo de un "producto cartesiano".

Recuerde, este es el código golf, por lo que gana el código con el menor número de bytes.

Mark Johnson
fuente
3
¡Bienvenido a Programming Puzzles & Code Golf, y agradable primer desafío!
Pomo de la puerta
¿ [0.129195, 0.019305, 0.262305, ..., 0.047905]Sería suficiente como salida o son los [0,0,0], [0,0,1], ...necesarios?
Laikoni
@Laikoni Esa salida está bien. La porción de salida no es la carne del problema.
Mark Johnson el
¿Puede la salida estar en orden inverso?
Luis Mendo
@LuisMendo Claro, por qué no.
Mark Johnson el

Respuestas:

8

Haskell, 86 bytes

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

Ejemplo de uso:

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 mayoría de los bytes se gastan para el formato de salida. Si solo le interesa el vector de probabilidad, solo tiene 29 bytes:

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

Cómo funciona:

                    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
fuente
Esto es ordenado; Tenía curiosidad por saber si iba a haber una forma realmente corta y puramente funcional de hacer esto. ¿Conoces C # o F #? Tengo curiosidad por saber cómo sería el mismo algoritmo en esos idiomas, ya que no estoy completamente familiarizado con la sintaxis de Haskell.
Mark Johnson el
@ MarkJohnson: no, lo siento, no sé ni C # ni F #.
nimi
5

Mathematica, 46 45 bytes

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

Toma una lista. Incluso funciona para la lista vacía {}, para la cual es la salida {1}.

Caso de prueba:

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

Explicación

Dada una lista de probabilidades sy una lista de bits bcon 0denotando "no ocurrió" y 1denotando "ocurrió", la lista de probabilidades a multiplicar viene dada por

1 - b - s

hasta firmar. Si en cambio 0denota "ocurrió" y 1"no ocurrió", entonces esto se simplifica a

b - s

Así que nosotros:

                      {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
fuente
4

Perl, 42 40 bytes

Incluye +1 para -a

Dar números en STDIN:

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

salidas

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
fuente
4

MATL , 12 11 bytes

TF-|Z}&Z*!p

La entrada es un vector de columna, con el formato [0.55; 0.67; 0.13]

Pruébalo en línea!

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
fuente
3

Perl, 116 bytes

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

Legible:

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

Crea una lista de todas las combinaciones posibles de 0s y 1s de longitud igual al número de parámetros de entrada (por ejemplo, para el ejemplo anterior, sería de longitud 3), luego calcula cada probabilidad.

Gracias a @Dada por mostrarme lo globque puede hacer la función , aunque no estoy 100% seguro de entender cómo lo hace.

Salida de muestra:

[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
fuente
1
-aen lugar de (@a=split/ /,<>)...
Dada
3

R, 72 69 bytes

Toma información de stdin y devuelve un vector R de probabilidades.

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

Editar: se eliminó una transposición innecesaria, la matriz de permutación ahora es la versión transpuesta de la siguiente y las probabilidades se calculan como el producto en forma de columna en lugar de en forma de fila. Salida de ejemplo:

[1] 0.129195 0.157905 0.262305 0.320595 0.019305 0.023595 0.039195 0.047905

Tenga en cuenta que las probabilidades están en un orden diferente debido al hecho de que la matriz de permutación generada por expand.gridproduce lo siguiente (la generación de esta matriz probablemente se puede jugar usando paquetes externos):

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 primera probabilidad corresponde al resultado invertido de la primera fila en la matriz anterior y la segunda a la segunda fila invertida, etc. El formateo de la salida para ver esto aún más claramente hace que el programa sea más largo (164 bytes):

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

que en cambio 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
Billywob
fuente
Había estado trabajando en mi propia respuesta a esto, pero no pude encontrar una solución ordenada. Gran uso de expand.grid! Creo que applypuede funcionar tanto en marcos de datos como en matrices, por lo que su código debería funcionar sin el t(t(...)), lo que le ahorrará 6 bytes.
rturnbull
@rturnbull Tenga en cuenta que tno está relacionado con ningún marco de datos, sino para permitir la resta del vector de probabilidad de la matriz de permutación (con diferentes dimensiones). Se necesita al menos uno de ellos debido a la forma en que R maneja estas operaciones vectorizadas, pero probablemente podría eliminar la transposición externa y aplicar el producto sobre columnas. Se actualizará mañana
Billywob
2

J, 14 bytes

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

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

Explicación

-.([:,*/)/@,.]  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
millas
fuente
¿Puedes hacer |*//0.55 0.67 0.13-/0 1un tren?
Adám
2

Pyth, 10 bytes

*MaVLQ^U2l

Pruébelo en línea: demostración

Explicación:

*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
fuente
1

C, 110 bytes

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

Sin golf:

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

Funciona hasta 32 elementos, + 5 + 1 bytes para 64 elementos (declare long k;y agregue Len el primer bucle para que k<1L<<N).

Karl Napf
fuente
1
Para> 32 elementos, ¿C requiere el literal "L" en el *1*<<no es solo una cosa de C ++?
Mark Johnson el
@ Mark Johnson, sí, supongo que requeriría.
Karl Napf
1

05AB1E , 8 bytes

<Äæ¹æR+P

Pruébalo en línea!

 <Äæ¹æ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 de pulpo mágico
fuente
1

JavaScript (Firefox 30-57), 57 bytes

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

Devuelve una matriz de todas las probabilidades. Si también desea la matriz de eventos, entonces para 86 bytes:

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

Si se le permiten los eventos como una cadena, entonces solo son 80 bytes:

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

Resta dos bytes para 1/cada solución si la probabilidad nunca será cero.

Neil
fuente
¿Cómo ejecutarías esto en un <script></script>bloque? ¿Tengo problemas con el primer "para" ser inesperado?
Mark Johnson el
@MarkJohnson Mientras estés usando Firefox 30 o posterior, debería funcionar.
Neil
0

Perl 6, 24 19 bytes de latín-1

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

Código anterior:

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

Esta es una función. Úselo así:

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

Llegar:

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

Explicación del código anterior:

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

El código más nuevo es básicamente el mismo, solo que usa la sintaxis 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

El mapa genera una matriz llena de anyconstrucciones, que se multiplican en anyconstrucciones más grandes , resolviendo el problema sin necesidad de un bucle.

No es el lenguaje más corto para el programa, pero es una traducción muy directa del problema.


fuente
0

Dyalog APL , 10 bytes

Nueva solución

Indice de origen independiente. Función anónima. Toma la lista de probabilidades como argumento.

∘.×/⊢,¨1-⊢

∘.×/ La reducción del producto cartesiano sobre

los valores del argumento

cada uno emparejado con

1-⊢ los valores del argumento del complemento (literalmente uno menos los valores del argumento)

TryAPL en línea!


Antigua solución

Requiere ⎕IO←0cuál es el predeterminado en muchos sistemas. Solicita la lista de probabilidades.

|⎕∘.×.-⊂⍳2

Explicación

| valor absoluto de

la entrada, ɑ = [ ɑ ₁  ɑ ₂  ɑ ₃]

∘.×.-tensor interno modificado multiplicado, ( ɑ ₁ - b ₁) ⊗ ( ɑ ₂ - b ₂) ⊗ ( ɑ ₃ - b ₃), con

⊂⍳2la lista adjunta b = [[0 1]]

Definición matemática

Como b está encerrado, es escalar y, por lo tanto, se extiende a la longitud de ɑ , es decir, 3, por lo que toda la expresión es

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 en línea!

Notas (se aplica tanto a la solución antigua como a la nueva)

El programa y la fórmula funcionan para cualquier número ( n ) de variables y devuelve una matriz n- dimensional de longitud 2 en cada dimensión. Con tres variables, la probabilidad de un resultado específico
P ( p , q , r ) = A p , q , r
que puede seleccionarse convenientemente de la matriz con(⊃A)[p;q;r] extraído conp q r⌷⊃A

Por ejemplo, 1 1 0⌷⊃|0.55 0.67 0.13∘.×.-⊂⍳2da P (55%, 67%, ¬13%) = 1.9305%

Adán
fuente
0

PHP, 105 97 94 93 87 bytes

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

Corre así:

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

Tenga en cuenta que la salida es 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]

Explicación

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)

Ajustes

  • Se guardaron 8 bytes utilizando lógica binaria para obtener bits en lugar de convertir a cadena
  • Se guardó un byte combinando el restablecimiento de $p a 1 con el cálculo de$c
  • Se guardó un byte al agregar el resultado de print (1) a $i lugar de incrementar
  • Guardado un byte utilizando guión bajo como delimitador de salida
  • Se guardó un byte usando el signo menos como delimitador (no hay posibilidades negativas).
  • Guardado 6 bytes al usar en $clugar de$$i
aross
fuente
0

C ++ 17, 137 131 129 bytes

Ahorrando 6 bytes declarando #define A auto, la primera vez que una macro tan corta guarda algo. -2 bytes para usar #importy eliminar el espacio antes<

#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 todas las combinaciones posibles.

Sin golf:

//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);
Karl Napf
fuente