#######################################################################################################################
# Эмперические характеристики
#######################################################################################################################
def EC_1(marks_text):
    """В группе учится `N` студентов.
    Ими были получены следующие 100-балльные оценки: `marks_text`
    Найдите: 
    - A – среднюю положительную оценку в группе;
    - M – медиану положительных оценок в группе;
    - H – среднее гармоническое оценок, которые не менее M;
    - G – среднее геометрическое оценок, которые не менее M;
    - Q – медианную оценку в той части группы, в которой студенты набрали не менее M баллов;
    - N – количество студентов, оценки которых оказались между H и Q (включая границы)

    Args:
        marks_text (numerical): Строка оценок с запятыми и ковычками

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

    Returns:
        `answer` (tuple): Соответствующие величины
    """

    import numpy as np
    import scipy.stats
    
    marks_0 = np.array(marks_text.split(', ')).astype(int)
    marks = marks_0[marks_0!=0]
    
    answer = []
    
    answer.append(np.mean(marks))
    print('A = ' + rrstr(answer[0],1))
    
    answer.append(np.median(marks))
    print('M = ' + str(int(answer[1])))
    
    answer.append(scipy.stats.hmean(marks[marks >= answer[1]]))
    print('H = ' + rrstr(answer[2],1))
    
    answer.append(scipy.stats.gmean(marks[marks >= answer[1]]))
    print('G = ' + rrstr(answer[3],1))
    
    answer.append(np.median(marks[marks >= answer[1]]))
    print('Q = ' + rrstr(answer[4],0))
    
    answer.append(len(marks[[i in np.arange(min(int(answer[2]),int(answer[4])),max(int(answer[2]),int(answer[4]))+1,1) for i in marks]]))
    print('N = ' + rrstr(answer[5],0))
    
    return tuple(answer)
#######################################################################################################################
def EC_2(text):
    """Следующие `N` чисел – это умноженные на 10000 и округленные до ближайшего целого
    дневные логарифмические доходности акции компании АВС: `text`. 
    Будем называть их преобразованными доходностями (ПД).
    Финансовый аналитик Глеб предполагает, что преобразованные доходности (как и исходные)
    приближенно распределены по нормальному закону.
    Чтобы проверить свое предположение Глеб нашел нижнюю квартиль L и верхнюю квартиль H нормального распределения N(μ,σ2),
    для которого μ – это среднее арифметическое ПД,
    а σ – эмпирическое стандартное отклонение ПД.
    Затем Глеб подсчитал количество ПД, попавших в интервал от L до H 
    (надеясь, что в этот интервал попадет половина ПД).
    Результат этого вычисления показался ему недостаточно убедительным.
    Чтобы окончательно развеять сомнения относительно нормальности ПД,
    Глеб построил на одном рисунке графики функций:
    F^(x) и F(x), где F^(x) – эмпирическая функция распределения ПД,
    а F(x) – функция распределения N(μ,σ2).
    В качестве меры совпадения двух графиков Глеб решил использовать
    расстояние d между функциями F^(x) и F(x),
    которое он вычислил, исходя из определения:
    d=sup|F^(x)−F(x)|. В ответе укажите результаты вычислений Глеба: 
    - среднее арифметическое ПД; 
    - эмпирическое стандартное отклонение ПД; 
    - квартили L;
    - квартиль H 
    - количество ПД, попавших в интервал от L до H; 
    - расстояние между функциями F^(x) и F(x).

    Args:
        text (str): Строка чисел через запятую

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

    Returns:
        `answer` (tuple): Соответствующие величины
    """
    import numpy as np
    import scipy.stats
    import matplotlib.pyplot as plt
    from statsmodels.distributions.empirical_distribution import ECDF
    
    data= np.array(text.split(', ')).astype(int)
    mu=data.mean()
    sigma = data.std()

    X=scipy.stats.norm(mu,sigma)

    L = X.ppf(0.25)
    H = X.ppf(0.75)

    lenLH = len(data[np.logical_and(data>L,data<H)])


    Fexp = ECDF(data)

    fig, ax = plt.subplots(figsize=(6,5))
    xx=np.linspace(X.ppf(0.01),X.ppf(0.99),1000)
    ax.plot(xx,X.cdf(xx))
    ax.plot(xx,Fexp(xx))
    plt.show()
    data_sort=np.sort(data)

    length_ff=max([max(np.abs((i+1)/len(data)-X.cdf(data_sort[i])),np.abs((i)/len(data)-X.cdf(data_sort[i]))) for i in range(len(data))]) # equals to scipy.stats.kstest(data,X.cdf)[0]

    task = 'среднее арифметическое ПД ,эмпирическое стандартное отклонение ПД ,квартиль L,квартиль Н,количество ПД от L до H,Расстояние мужду функциями распределения'.split(',')
    answer=[mu,sigma,L,H,lenLH,length_ff]
    commas = [1,1,1,1,0,3]
    
    for i in range(6):
        print(task[i]+' = '+rrstr(answer[i],commas[i]))
        
    return tuple(answer)
#######################################################################################################################
def EC_3(text):
    """В группе Ω учатся студенты: ω1,...,ω`n`.
    Пусть X и Y – 100-балльные экзаменационные оценки
    по математическому анализу и теории вероятностей.
    Оценки студента ωi обозначаются: xi=X(ωi) и yi=Y(ωi),
    i=1,...,`n`. Все оценки известны: `text`.
    Требуется найти следующие условные эмпирические характеристики:
    - ковариацию X и Y при условии, что одновременно X⩾50 и Y⩾50;
    - коэффициент корреляции X и Y при том же условии.

    Args:
        text (str): Текст вида `xi=X(ωi), yi=Y(ωi),...` записанный в `'''_'''`

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

    Returns:
        `answer` (tuple): Соответствующие величины
    """

    import re
    import numpy as np

    x_values = list(map(int, re.findall(r'x\d+=(\d+)', text)))
    y_values = list(map(int, re.findall(r'y\d+=(\d+)', text)))

    # Отфильтровать пары (X, Y), где X >= 50 и Y >= 50
    filtered_data = [(x, y) for x, y in zip(x_values, y_values) if x >= 50 and y >= 50]
    x_filtered, y_filtered = zip(*filtered_data)  # Разделяем на списки x и y

    # Рассчитать ковариацию
    cov_xy = np.cov(x_filtered, y_filtered, ddof=0)[0, 1]

    # Рассчитать коэффициент корреляции
    corr_xy = np.corrcoef(x_filtered, y_filtered)[0, 1]

    # Вывод результатов
    print('Ковариация = ' + rrstr(cov_xy,1))
    print('Коэффициент корреляции = ' + rrstr(corr_xy,3))
    
    return (cov_xy,corr_xy)
#######################################################################################################################
def EC_4(text):
    """Поток Ω состоит из k групп: Ω1,...,Ωk, k=3.
    На потоке учатся n=n1+...+nk студентов,
    где ni – число студентов в группе Ωi, i=1,...,k.
    Пусть X(ω)– 100-балльная оценка студента ω∈Ω.
    Далее используются следующие обозначения:
    x¯i – среднее значение,
    σi – (эмпирическое) стандартное отклонение признака X на группе Ωi.
    Дано: ni=__,x¯i=__, σi=__,
    Требуется найти: 
    - среднее значение X на потоке Ω;
    - (эмпирическое) стандартное отклонение X на потоке Ω.

    Args:
        text (str): Текст всего задания записанный в `'''_'''`
        
    ## Prints
        `answer` каждое значение по очереди.<br>C запятой вместо точки и сокращением до соответствующего количества знаков после запятой

    Returns:
        `answer` (tuple): Соответствующие величины
    """
    import re
    import numpy as np

    x_values = np.array(list(map(int, re.findall(r'x[¯]{0,3}\d+=(\d+)', text))))
    s_values = np.array(list(map(int, re.findall(r'σ\d+=(\d+)', text))))
    n_values = np.array(list(map(int, re.findall(r'n\d+=(\d+)', text))))

    N = sum(n_values)
    X_ = sum(np.multiply(n_values,x_values))/N

    S = np.sqrt(np.sum(n_values*(s_values**2 + (x_values-X_)**2))/N)

    print('Среднее значение = ' + rrstr(X_,1))
    print('Стандартное отклонение = ' + rrstr(S,3))

    return (X_,S)
#######################################################################################################################
EC=[EC_1, EC_2, EC_3, EC_4]