from ...forall import *
#######################################################################################################################
# Формулы полной вероятности и Байеса
#######################################################################################################################
def FPB_1(N,n,m):
    """Имеется `N` монет, из которых `n` бракованные: <br>
    вследствие заводского брака на этих монетах с обеих сторон отчеканен герб.<br>
    Наугад выбранную монету, не разглядывая, бросают несколько раз.<br>
    - Какова вероятность, что при `m` бросках она ляжет гербом вверх?
    - При `m` бросках монета легла гербом вверх. Какова вероятность того, что была выбрана монета c двумя гербами?

    Args:
        N (numerical): Монет всего
        n (numerical): Бракованных монет
        m (numerical): При стольких бросках ляжет гербом вверх
        
    ## Prints
       `answer` каждое значение по очереди.<br>C запятой вместо точки и сокращением до 3 знаков после запятой
        
    Returns:
        `answer` (tuple): Соответствующие вероятности
    """
    ''''''
    
    
    import itertools
    
    coins = [('O', 'P')]*(N-n) + [('O', 'O')]*n
    count_1 = 0
    count_2 = 0
    N = 0
    for coin in coins:
        for throws in list(itertools.product(coin, repeat=4)):
            throw = ''.join(throws)
            N += 1
            if 'O'*m in throw:
                count_1 += 1
                if coin == ('O', 'O'):
                    count_2 += 1
                    
    answer = count_1/N,count_2/count_1
    
    task = ['Вероятность "всегда гербом вверх"   = ', 'Вероятность "монета с 2-мя гербами" = ']
    for i in range(len(answer)):
        print(task[i]+rrstr(answer[i],3))
    
    return answer
#######################################################################################################################
def FPB_2(first,first1,first2,second,second1,second2,second3):
    """В первой корзине имеется `first` шаров, при этом количество белых шаров равно либо `first1`, либо `first2`.<br>
    Оба варианта равновероятны.<br>
    Во второй корзине имеется `second` шаров, а количество белых шаров равно `second1`, `second2` или `second3`.<br>
    Эти три варианта также равновероятны. <br>
    Из обеих корзин все шары перекладываются в третью корзину. <br>
    - Какова вероятность P(A), что случайно вынутый из третьей корзины шар окажется белым (событие A)?
    - Найдите условную вероятность P(H|A), того, что случайно вынутый из третьей корзины шар 
    первоначально находился в первой корзине (событие H), при условии, что он белый (событие A)?<br/>

    Args:
        first (numerical): В первой корзине имеется `first` шаров
        first1 (numerical): При этом количество белых шаров равно либо `first1`
        first2 (numerical): Либо `first2`
        second (numerical): Во второй корзине имеется `second` шаров
        second1 (numerical): Количество белых шаров равно либо `second1`
        second2 (numerical): Либо `second2`
        second3 (numerical): Либо `second3`
        
    ## Prints
       `answer` каждое значение по очереди.<br>C запятой вместо точки и сокращением до 3 знаков после запятой
        
    Returns:
        `answer` (tuple): Соответствующие вероятности
    """
    Pa = ((first1+first2)*0.5 + (second1+second2+second3)*(1/3)) / (first + second)
    answer = (Pa,((first1+first2)*0.5/first * (first/(first+second))) / Pa)
    print('Вероятность P(A)            = ' + rrstr(answer[0],3)) 
    print('Условная вероятность P(H|A) = ' + rrstr(answer[1],3))
    
    return answer
#######################################################################################################################
def FPB_3(s1,n1,p1,s2,n2,p2):
    """Имеется две корзины с белыми и черными шарами. 
    В первой корзине всего `s1` шаров, при этом количество белых шаров распределено по биномиальному закону с параметрами
    n = `n1` и p = `p1`. 
    Во второй корзине имеется всего `s2` шаров, при этом количество белых шаров распределено по биномиальному закону 
    с параметрами n = `n2` и p = `p2`. Из обеих корзин все шары перекладываются в третью корзину. 
    - Какова вероятность P(A), что случайно вынутый из третьей корзины шар окажется белым (событие A)?
    - Найдите условную вероятность P(H|A), того, что случайно вынутый из третьей корзины шар 
    первоначально находился в первой корзине (событие H), при условии, что он белый (событие A)?

    Args:
        s1 (numerical): Шаров в 1-ой корзине
        n1 (numerical): Первый параметр биномиального закона распределения белых шаров в 1-ой корзине
        p1 (numerical): Второй параметр биномиального закона распределения белых шаров в 1-ой корзине
        s2 (numerical): Шаров в 2-ой корзине
        n2 (numerical): Первый параметр биномиального закона распределения белых шаров в 2-ой корзине
        p2 (numerical): Второй параметр биномиального закона распределения белых шаров в 2-ой корзине

    ## Prints
       `answer` каждое значение по очереди.<br>C запятой вместо точки и сокращением до 3 знаков после запятой

    Returns:
        `answer` (tuple): Соответствующие вероятности
    """

    expected_white_balls1 = n1 * p1
    expected_white_balls2 = n2 * p2

    total_balls = s1 + s2

    P_A = (expected_white_balls1 + expected_white_balls2) / total_balls

    P_H = s1 / total_balls
    P_A_given_H = expected_white_balls1 / s1
    P_H_given_A = (P_A_given_H * P_H) / P_A

    answer = (P_A,P_H_given_A)
    
    print("P(A)   = " + rrstr(answer[0], 3))
    print("P(H|A) = " + rrstr(answer[1], 3))
    
    return answer
#######################################################################################################################
def FPB_4(wt1, bl1, wt2, bl2, take1, take2):
    """Имеется две корзины с белыми и черными шарами. 
    В первой корзине количество белых – `wt1`, количество черных – `bl1`.<br>
    Во второй корзине количество белых – `wt2`, количество черных – `bl2`.<br>
    Из первой корзины случайно, без возвращения, излекаются `take1` шаров, а из второй – `take2` шаров.<br>
    Отобранные из обеих корзин шары перекладываются в третью корзину. <br>
    - Какова вероятность P(A), что случайно вынутый из третьей корзины шар окажется белым (событие A)?
    - Найдите условную вероятность P(H|A), того, что случайно вынутый из третьей корзины шар 
    первоначально находился в первой корзине (событие H), при условии, что он белый (событие A)?

    Args:
        wt1 (numerical): Белых шаров в 1-ой корзине
        bl1 (numerical): Черных шаров в 1-ой корзине
        wt2 (numerical): Белых шаров в 2-ой корзине
        bl2 (numerical): Черных шаров в 2-ой корзине
        take1 (numerical): Шаров извлекается из 1-ой корзины
        take2 (numerical): Шаров извлекается из 2-ой корзины

    ## Prints
       `answer` каждое значение по очереди.<br>C запятой вместо точки и сокращением до 3 знаков после запятой

    Returns:
        `answer` (tuple): Соответствующие вероятности
    """
    balls1 = wt1 + bl1
    balls2 = wt2 + bl2

    p_h1 = take1 / (take2 + take1)
    p_h2 = take2 / (take2 + take1)

    p_ah1 = wt1 / balls1
    p_ah2 = wt2 / balls2


    p_a = p_h1 * p_ah1 + p_h2 * p_ah2
    p_ha = p_h1 * p_ah1 / p_a
    
    answer = (p_a, p_ha)
    
    print("P(A)   = " + rrstr(answer[0], 3))
    print("P(H|A) = " + rrstr(answer[1], 3))
    
    
    return answer
#######################################################################################################################
FPB = [FPB_1,FPB_2,FPB_3,FPB_4]