Calcule una probabilidad exactamente

9

Esta tarea consiste en escribir código para calcular exactamente una probabilidad. El resultado debe ser una probabilidad precisa escrita como una fracción en su forma más reducida. Es decir, nunca debería salir, 4/8sino más bien 1/2.

Para un número entero positivo n, considere una cadena uniformemente aleatoria de 1s y -1s de longitud ny llámela A. Ahora concatene a Asu primer valor. Es decir, A[1] = A[n+1]si la indexación desde 1. Aahora tiene longitud n+1. Ahora también considere una segunda cadena aleatoria de longitud ncuyos primeros nvalores son -1, 0 o 1 con probabilidad 1 / 4,1 / 2, 1/4 cada uno y llámelo B.

Por ejemplo, considere n=3. Los posibles valores de Ay Bpodrían ser A = [-1,1,1,-1]y B=[0,1,-1]. En este caso, los dos productos internos son 0y 2.

Ahora considere el producto interno de A[1,...,n]y By el producto interno de A[2,...,n+1]y B.

Su código debe generar la probabilidad de que ambos productos internos sean cero.

Por n=1esta probabilidad es clara 1/2.

No me importa cómo nse especifica en el código, pero debería ser muy simple y obvio cómo cambiarlo.

Idiomas y bibliotecas

Puede usar cualquier idioma y bibliotecas que desee. Me gustaría ejecutar su código, así que incluya una explicación completa sobre cómo ejecutar / compilar su código en Linux si es posible.

Martin Ender
fuente
2
Los casos de prueba para los primeros nserían útiles. También puede ser útil un ejemplo explícito de A, B y los dos productos internos.
Martin Ender
Si elegimos codificar el entero, ¿ n=4cuenta como cero, dos o tres bytes? ¿La salida tiene que ser exactamente a/b o [a b], por ejemplo, estar permitida?
Dennis
@ Dennis Tiene que ser exacto. Si codifica el número entero, ¿solo tendré que cambiarlo en un lugar para cambiarlo n? De lo contrario, creo que eso no está permitido.
Sí, mi programa solo usa el número entero una vez para calcular un poder cartesiano. Todo lo demás se deriva de la matriz resultante.
Dennis

Respuestas:

7

Pyth, 48 47 46 44 bytes

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

Pruébelo en línea: demostración

La versión en línea probablemente no computa n=6. En mi computadora portátil (versión fuera de línea) toma alrededor de 45 segundos.

Enfoque de fuerza bruta.

Explicación:

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
Jakube
fuente
dang, se olvidó de la mcd, sabía que había algo que extrañaba
Maltysen
+0r1_2es más corto que /R2r2_2.
isaacg
Creo que para ser justos, debería ser la versión 89/512 lo que cuenta.
@Lembik Ok lo cambió.
Jakube
Debo admitir que nunca se me ocurrió que esto se podría hacer en 47 caracteres.
8

Mathematica, 159 100 87 86 85 bytes

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

Para cambiar, nsimplemente cambie la definición de la variable al principio.

Como es la fuerza bruta, es bastante lenta, pero aquí están los primeros ocho resultados:

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

El último ya tomó 231 segundos y el tiempo de ejecución es terriblemente exponencial.

Explicación

Como dije, es fuerza bruta. Esencialmente, solo enumero todos los posibles Ay B, calculo los dos productos de puntos para cada par posible y luego encuentro la fracción de pares que produjo {0, 0}. Las funciones de combinatoria y álgebra lineal de Mathematica fueron bastante útiles para jugar golf:

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

Esto genera todas las n-tuplas que contienen 1o -1, es decir, todas las posibles A. Por n = 3eso es:

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

Para calcular Bhacemos casi lo mismo:

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

Repitiendo 0, duplicamos cada tupla para cada uno 0que contiene, con lo que 0el doble de probabilidades 1o -1. Nuevamente usando n = 3como ejemplo:

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

Ahora, para cada posible A, queremos el producto escalar de cada uno de esos posibles B, con A[1 .. n]y A[2 .. n+1]. Por ejemplo, si nuestro actual Aes {1, 1, -1}, queremos el producto de punto con ambos {1, 1, -1}y con {1, -1, 1}. Como todos nuestros Bya son convenientemente las filas de una matriz, queremos que las dos sublistas sean Acomo columnas de otra matriz, para que podamos calcular un simple producto de puntos entre ellas. Pero la transposición {{1, 1, -1}, {1, -1, 1}}simplemente da {{1, 1}, {1, -1}, {-1, 1}}cuál es solo una lista de todas las sublistas cíclicas de 2 elementos A. Eso es lo que hace esto:

Partition[#,2,1,1]

Entonces calculamos eso y tomamos el producto punto con nuestra lista de B. Como ahora obtenemos una lista anidada (dado que cada posible Aproduce un vector separado), los aplanamos con ##&@@.

Para averiguar si un par {x, y}es {0, 0}, calculamos Sign[Norm[{x,y}]] dónde Normda √(x²+y²). Esto da 0o 1.

Por último, ya que ahora sólo queremos saber las fracciones de 1s en una lista de 0s y 1S Todo lo que necesitamos es la media aritmética de la lista. Sin embargo, esto produce la probabilidad de que al menos un producto de punto sea distinto de cero, por lo que lo restamos 1para obtener el resultado deseado.

Martin Ender
fuente
6

Pyth - 65 55 bytes

Error solucionado con reducción de fracción al costo de un byte.

Utiliza un enfoque de fuerza bruta, y se puede jugar mucho al golf, pero solo quería obtener algo. Muy lento

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

Utiliza productos cartesianos para generar ambos Ay B, haciendo las probabilidades variables haciendo 0aparecer dos veces en la lista fuente y luego cuenta las que ese producto interno a cero. El producto interno se hace fácil por el Vazúcar sintáctico de ectorización. Simplificar la fracción me estaba asustando inicialmente, pero fue bastante fácil con la Pfunción de Factorización de tiempo y la comprensión de que solo tenemos que reducir en potencias de 2.

Pruébelo en línea aquí .

Maltysen
fuente
¿Cómo cambio n?
@Lembik El programa Pyth solicita una entrada del usuario, que se especifica en el segundo cuadro de texto (si usa el compilador en línea).
Jakube
@Jakube ¡Oh, gracias! Y en realidad parece funcionar también :)
6

CJam, 58 57 54 51 46 bytes

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

Para ejecutarlo, inserte el número entero deseado entre WX]y m*.

¡Gracias a @ jimmy23013 por la poca magia y por jugar golf en 5 bytes!

Pruébelo en línea en el intérprete de CJam .

Idea

La mayoría de las partes de estas respuestas son sencillas, pero utiliza dos trucos geniales:

  • En lugar de emparejar todos los vectores de {-1, 1} n con todos los vectores de {-1, 0, 1} n con las probabilidades deseadas, considera el número de tripletas de vectores en {-1, 1} n que satisfacen Una cierta condición.

    Si sumamos los dos últimos vectores de un triplete, el resultado será un vector de {-2, 0, 2} n .

    Como (-1) + 1 = 0 = 1 + (-1) , 0 s ocurrirá el doble de veces que -2 sy 2 s.

    Dividir cada componente por 2 produciría un vector de {-1, 0, 1} n con las probabilidades deseadas.

    Como solo estamos interesados ​​si el producto escalar es 0 o no, podemos omitir la división por 2 .

  • Después de contar todos los trillizos que satisfacen la condición de la pregunta y el número total de trillizos, tenemos que reducir la fracción resultante.

    En lugar de calcular el MCD de ambos números, dado que el denominador siempre será una potencia de 2, es suficiente dividir ambos números por la potencia más alta de 2 que divide el numerador.

    Para obtener la mayor potencia de 2 que divide x , podemos tomar el AND bit a bit de x y ~ x + 1 .

    ~ x invierte todos los bits de x , por lo que todos los 0 s finales se convierten en 1 s. Al agregar 1 a ~ x , esos 1 s volverán a ser 0 sy el último 1 en ~ x + 1 coincidirá con el último 1 en x .

    Todos los demás bits son 0 o distintos, por lo que el bit a bit Y devuelve el entero que consiste en el último 1 de x y todos los 0 s que le siguen. Esta es la potencia más alta de 2 que divide x .

Código

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.
Dennis
fuente
WX]m*Zm*_{~.+2,@fm<\f.*::+0-!},,__W*&:T/'/@,T/.
jimmy23013
@ jimmy23013: Eso es algo impresionante de magia. ¡Gracias!
Dennis