import numpy as np

import pandas as pd

import gc

import time

from contextlib import contextmanager

from lightgbm import LGBMClassifier

from sklearn.metrics import roc_auc_score

from sklearn.model_selection import KFold, StratifiedKFold

from sklearn.preprocessing import LabelEncoder

import matplotlib.pyplot as plt

import seaborn as sns

import warnings

warnings.simplefilter(action='ignore', category=FutureWarning)
"""

Input should be a dataframe (df) and the function reduces data sizes of the df

Note: If you have problems with this function try to discard Float16 part as

there might be errors because of this data type:

https://github.com/pandas-dev/pandas/issues/9220

"""

def reduce_mem_usage(df, verbose=True):

    numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']

    start_mem = df.memory_usage().sum() / 1024**2

    for col in df.columns:

        col_type = df[col].dtypes

        if col_type in numerics:

            c_min = df[col].min()

            c_max = df[col].max()

            if str(col_type)[:3] == 'int':

                if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:

                    df[col] = df[col].astype(np.int8)

                elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:

                    df[col] = df[col].astype(np.int16)

                elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:

                    df[col] = df[col].astype(np.int32)

                elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:

                    df[col] = df[col].astype(np.int64)

            else:

                if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:

                    df[col] = df[col].astype(np.float16)

                elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:

                    df[col] = df[col].astype(np.float32)

                else:

                    df[col] = df[col].astype(np.float64)

    end_mem = df.memory_usage().sum() / 1024**2

    print('Memory usage after optimization is: {:.2f} MB'.format(end_mem))

    print('Decreased by {:.1f}%'.format(100 * (start_mem - end_mem) / start_mem))

    return df
@contextmanager

def timer(title):

    t0 = time.time()

    yield

    print("{} - done in {:.0f}s".format(title, time.time() - t0))

def one_hot_encoder(df, nan_as_category = True):

    original_columns = list(df.columns) # col names as string in a list

    categorical_columns = [col for col in df.columns if df[col].dtype == 'object'] #categorical col names

    df = pd.get_dummies(df, columns = categorical_columns, dummy_na = nan_as_category) #creating dummies

    new_columns = [c for c in df.columns if c not in original_columns] #new col names

    return df, new_columns

def label_encoder(df):

    # Create a label encoder object

    le = LabelEncoder()

    le_count = 0

    # Iterate through the columns

    for col in df:

        if df[col].dtype == 'object':

            # If 2 or fewer unique categories

            if len(list(df[col].unique())) <= 2:

                # Train on the training data

                le.fit(df[col])

                # Transform both training and testing data

                df[col] = le.transform(df[col])

                # Keep track of how many columns were label encoded

                le_count += 1

    print('%d columns were label encoded.' % le_count)

    return df
# Preprocess application_train.csv and application_test.csv

def application_train_test(num_rows = None, nan_as_category = False):

    df = pd.read_csv("../input/home-credit-default-risk/application_train.csv", nrows = num_rows)

    test_df = pd.read_csv("../input/home-credit-default-risk/application_test.csv", nrows = num_rows)

    df = df.append(test_df).reset_index()

    del df["index"]

    df = df[df['CODE_GENDER'] != 'XNA']

    df['DAYS_EMPLOYED'].replace(365243, np.nan, inplace= True)

    df['APP_NEW_AGE'] = df['DAYS_BIRTH'] / (- 365.25)

    # Some simple new features (percentages)

    df['APP_NEW_DAYS_EMPLOYED_PERC'] = df['DAYS_EMPLOYED'] / df['DAYS_BIRTH']

    df['APP_NEW_INCOME_CREDIT_PERC'] = df['AMT_INCOME_TOTAL'] / df['AMT_CREDIT']

    df['APP_NEW_INCOME_PER_PERSON'] = df['AMT_INCOME_TOTAL'] / df['CNT_FAM_MEMBERS']

    df['APP_NEW_ANNUITY_INCOME_PERC'] = df['AMT_ANNUITY'] / df['AMT_INCOME_TOTAL']

    df['APP_NEW_PAYMENT_RATE'] = df['AMT_ANNUITY'] / df['AMT_CREDIT']

    df["APP_NEW_CREDIT_GOODS_PRICE_RATIO"] = df["AMT_CREDIT"] / df["AMT_GOODS_PRICE"]

    df["APP_NEW_CREDIT_DOWNPAYMENT"] = df["AMT_GOODS_PRICE"] - df["AMT_CREDIT"]

    df.loc[(df.AMT_INCOME_TOTAL < 30000),'APP_NEW_INCOME_BAND'] = 1

    df.loc[(df.AMT_INCOME_TOTAL >= 30000)&(df.AMT_INCOME_TOTAL < 65000),'APP_NEW_INCOME_BAND'] = 2

    df.loc[(df.AMT_INCOME_TOTAL >= 65000)&(df.AMT_INCOME_TOTAL < 95000),'APP_NEW_INCOME_BAND'] = 3

    df.loc[(df.AMT_INCOME_TOTAL >= 95000)&(df.AMT_INCOME_TOTAL < 130000),'APP_NEW_INCOME_BAND'] = 4

    df.loc[(df.AMT_INCOME_TOTAL >= 130000)&(df.AMT_INCOME_TOTAL < 160000),'APP_NEW_INCOME_BAND'] = 5

    df.loc[(df.AMT_INCOME_TOTAL >= 160000)&(df.AMT_INCOME_TOTAL < 190000),'APP_NEW_INCOME_BAND'] = 6

    df.loc[(df.AMT_INCOME_TOTAL >= 190000)&(df.AMT_INCOME_TOTAL < 220000),'APP_NEW_INCOME_BAND'] = 7

    df.loc[(df.AMT_INCOME_TOTAL >= 220000)&(df.AMT_INCOME_TOTAL < 275000),'APP_NEW_INCOME_BAND'] = 8

    df.loc[(df.AMT_INCOME_TOTAL >= 275000)&(df.AMT_INCOME_TOTAL < 325000),'APP_NEW_INCOME_BAND'] = 9

    df.loc[(df.AMT_INCOME_TOTAL >= 325000),'APP_NEW_INCOME_BAND'] = 10

    APP_NEW_AGE_CAT = pd.Series(["Young", "Adult 1","Adult 2","Adult 3", "Adult 4"], dtype = "object")

    df["APP_NEW_AGE_CAT"] = APP_NEW_AGE_CAT

    df.loc[(df["APP_NEW_AGE"] > 20.0) & (df["APP_NEW_AGE"] <= 30.0), "APP_NEW_AGE_CAT"] = APP_NEW_AGE_CAT[0]

    df.loc[(df["APP_NEW_AGE"] > 30.0) & (df["APP_NEW_AGE"] <= 40.0), "APP_NEW_AGE_CAT"] = APP_NEW_AGE_CAT[1]

    df.loc[(df["APP_NEW_AGE"] > 40.0) & (df["APP_NEW_AGE"] <= 50.0), "APP_NEW_AGE_CAT"] = APP_NEW_AGE_CAT[2]

    df.loc[(df["APP_NEW_AGE"] > 50.0) & (df["APP_NEW_AGE"] <= 60.0), "APP_NEW_AGE_CAT"] = APP_NEW_AGE_CAT[3]

    df.loc[df["APP_NEW_AGE"] > 60 ,"APP_NEW_AGE_CAT"] = APP_NEW_AGE_CAT[4]

    df["APP_NEW_AGE_DAYS_EMP"] = df["DAYS_EMPLOYED"] / (- 365.25)

    df["APP_NEW_AGE_WORK_PERCENT"] = (df["APP_NEW_AGE_DAYS_EMP"] / df['APP_NEW_AGE']) * 100

    df['APP_NEW_CREDIT_INCOME_PERCENT'] = df['AMT_CREDIT'] / df['AMT_INCOME_TOTAL']

    df['APP_NEW_ANNUITY_INCOME_PERCENT'] = df['AMT_ANNUITY'] / df['AMT_INCOME_TOTAL']

    df['APP_NEW_DAYS_EMPLOYED_PERCENT'] = df['DAYS_EMPLOYED'] / df['DAYS_BIRTH']

    df['APP_NEW_INCOME_PER_PERSON'] = df['AMT_INCOME_TOTAL'] / df['CNT_FAM_MEMBERS']

    df['APP_NEW_INCOME_CREDIT_PERC'] = df['AMT_INCOME_TOTAL'] / df['AMT_CREDIT']

    df['APP_NEW_PAYMENT_RATE'] = df['AMT_ANNUITY'] / df['AMT_CREDIT']

    df['APP_NEW_AMT_PAY_YEAR'] = df['AMT_CREDIT'] / df['AMT_ANNUITY']

    df['APP_NEW_AGE_PAYOFF'] = df['APP_NEW_AGE'] + df['APP_NEW_AMT_PAY_YEAR']

    df['APP_NEW_AMT_DIFF_CREDIT_GOODS'] = df['AMT_CREDIT'] - df['AMT_GOODS_PRICE']

    df['APP_NEW_AMT_CREDIT_GOODS_PERC'] = ((df['AMT_GOODS_PRICE'] / df['AMT_CREDIT']) * 100)

    df['APP_NEW_CNT_ADULT'] = df['CNT_FAM_MEMBERS'] - df['CNT_CHILDREN']

    df['APP_NEW_EXT_SOURCES_MEAN'] = df[['EXT_SOURCE_1', 'EXT_SOURCE_2', 'EXT_SOURCE_3']].mean(axis=1)

    df['APP_NEW_EXT_SOURCES_MAX'] = df[['EXT_SOURCE_1', 'EXT_SOURCE_2', 'EXT_SOURCE_3']].max(axis=1)

    df['APP_NEW_EXT_SOURCES_SUM'] = df[['EXT_SOURCE_1', 'EXT_SOURCE_2', 'EXT_SOURCE_3']].sum(axis=1)

    df = label_encoder(df)

    # Categorical features with One-Hot encode

    df, cat_cols = one_hot_encoder(df, nan_as_category) #returns: encoded new df and cat col names

    del test_df

    gc.collect()

    return df
# Preprocess bureau.csv and bureau_balance.csv

def bureau_and_balance(num_rows = None, nan_as_category = True):

    bureau = pd.read_csv('../input/home-credit-default-risk/bureau.csv', nrows = num_rows)

    bureau_balance = pd.read_csv('../input/home-credit-default-risk/bureau_balance.csv', nrows = num_rows)

    # Bureau balance: Perform aggregations and merge with bureau.csv

    def _status_to_int(status):

        if status in ['X', 'C']:

            return 0

        if pd.isnull(status):

            return np.nan

        return int(status)

    bureau_balance['NEW_BUREAU_BALANCE_DPD_LEVEL'] = bureau_balance['STATUS'].apply(_status_to_int)

    bureau_balance['NEW_BUREAU_BALANCE_STATUS_UNKNOWN'] = (bureau_balance['STATUS'] == 'X').astype(int)

    bureau_balance["MONTHS_BALANCE"] = (-1*bureau_balance["MONTHS_BALANCE"])+1

    bb_aggregations = {'MONTHS_BALANCE': ["max"],

                    'NEW_BUREAU_BALANCE_DPD_LEVEL':['sum', 'mean', 'max', 'std', 'skew'],

                    'NEW_BUREAU_BALANCE_STATUS_UNKNOWN':['sum', 'mean']}

    bb_agg = bureau_balance.groupby('SK_ID_BUREAU').agg(bb_aggregations)

    bb_agg.columns = pd.Index([e[0] + "_" + e[1].upper() for e in bb_agg.columns.tolist()])

    bureau = bureau.join(bb_agg, how='left', on='SK_ID_BUREAU')

    bureau.drop(['SK_ID_BUREAU'], axis=1, inplace= True)

    del bureau_balance, bb_agg

    gc.collect()

     # Bureau new features

    bureau.drop(["AMT_CREDIT_SUM_LIMIT","AMT_CREDIT_SUM_OVERDUE","CREDIT_DAY_OVERDUE","AMT_CREDIT_SUM_OVERDUE"],axis=1,inplace=True)

    bureau['BUREAU_CREDIT_TYPE_CONSUMER'] = (bureau['CREDIT_TYPE'] == 'Consumer credit').astype(int)

    bureau['BUREAU_CREDIT_TYPE_CAR'] = (bureau['CREDIT_TYPE'] == 'Car loan').astype(int)

    bureau['BUREAU_CREDIT_TYPE_MORTGAGE'] = (bureau['CREDIT_TYPE'] == 'Mortgage').astype(int)

    bureau['BUREAU_CREDIT_TYPE_CREDIT_CARD'] = (bureau['CREDIT_TYPE'] == 'Credit card').astype(int)

    bureau['BUREAU_CREDIT_TYPE_OTHER'] = (~(bureau['CREDIT_TYPE'].isin(['Consumer credit', 'Car loan', 'Mortgage', 'Credit card']))).astype(int)

    bureau['BUREAU_UNUSUAL_CURRENCY'] = (~(bureau['CREDIT_CURRENCY'] == 'currency 1')).astype(int)

    bureau['NEW_PAYMENT_RATE_SUM'] = bureau['AMT_ANNUITY'] / bureau['AMT_CREDIT_SUM']

    bureau['NEW_PAYMENT_RATE_SUM_DEBT'] = bureau['AMT_ANNUITY'] / bureau['AMT_CREDIT_SUM_DEBT']

    bureau['NEW_PAYMENT_RATE_AMT_CREDIT_MAX_OVERDUE'] = bureau['AMT_ANNUITY'] / bureau['AMT_CREDIT_MAX_OVERDUE']

    bureau.drop(["CREDIT_TYPE","CREDIT_CURRENCY"],axis=1,inplace=True)

    bureau.loc[(bureau["CREDIT_ACTIVE"]=="Active")&(bureau["DAYS_CREDIT_ENDDATE"]>-42056.001)&(bureau["DAYS_CREDIT_ENDDATE"]<=-1773.0),"BUREAU_NEW_ACTIVE_EARLY_PAYERS_SCORE"] = 1

    bureau.loc[(bureau["CREDIT_ACTIVE"]=="Active")&(bureau["DAYS_CREDIT_ENDDATE"]>-1773.0)&(bureau["DAYS_CREDIT_ENDDATE"]<=-1273.0),"BUREAU_NEW_ACTIVE_EARLY_PAYERS_SCORE"] = 2

    bureau.loc[(bureau["CREDIT_ACTIVE"]=="Active")&(bureau["DAYS_CREDIT_ENDDATE"]>-1273.0)&(bureau["DAYS_CREDIT_ENDDATE"]<=-777.0),"BUREAU_NEW_ACTIVE_EARLY_PAYERS_SCORE"] = 3

    bureau.loc[(bureau["CREDIT_ACTIVE"]=="Active")&(bureau["DAYS_CREDIT_ENDDATE"]>-777.0)&(bureau["DAYS_CREDIT_ENDDATE"]<=-474.0),"BUREAU_NEW_ACTIVE_EARLY_PAYERS_SCORE"] = 4

    bureau.loc[(bureau["CREDIT_ACTIVE"]=="Active")&(bureau["DAYS_CREDIT_ENDDATE"]>-474.0)&(bureau["DAYS_CREDIT_ENDDATE"]<=-268.0),"BUREAU_NEW_ACTIVE_EARLY_PAYERS_SCORE"] = 5

    bureau.loc[(bureau["CREDIT_ACTIVE"]=="Active")&(bureau["DAYS_CREDIT_ENDDATE"]>-268.0)&(bureau["DAYS_CREDIT_ENDDATE"]<=-133.0),"BUREAU_NEW_ACTIVE_EARLY_PAYERS_SCORE"] = 6

    bureau.loc[(bureau["CREDIT_ACTIVE"]=="Active")&(bureau["DAYS_CREDIT_ENDDATE"]>-133.0)&(bureau["DAYS_CREDIT_ENDDATE"]<=-38.0),"BUREAU_NEW_ACTIVE_EARLY_PAYERS_SCORE"] = 7

    bureau.loc[(bureau["CREDIT_ACTIVE"]=="Active")&(bureau["DAYS_CREDIT_ENDDATE"]>-38.0)&(bureau["DAYS_CREDIT_ENDDATE"]<=-1.0),"BUREAU_NEW_ACTIVE_EARLY_PAYERS_SCORE"] = 8

    bureau.loc[(bureau["CREDIT_ACTIVE"]=="Closed")&(bureau["DAYS_ENDDATE_FACT"]<bureau["DAYS_CREDIT_ENDDATE"])&(bureau["DAYS_ENDDATE_FACT"]>-42023.001)&(bureau["DAYS_ENDDATE_FACT"]<=-2145.0),"BUREAU_NEW_CLOSED_EARLY_PAYERS_SCORE"] = 1

    bureau.loc[(bureau["CREDIT_ACTIVE"]=="Closed")&(bureau["DAYS_ENDDATE_FACT"]<bureau["DAYS_CREDIT_ENDDATE"])&(bureau["DAYS_ENDDATE_FACT"]>-2145.0)&(bureau["DAYS_ENDDATE_FACT"]<=-1598.0),"BUREAU_NEW_CLOSED_EARLY_PAYERS_SCORE"] = 2

    bureau.loc[(bureau["CREDIT_ACTIVE"]=="Closed")&(bureau["DAYS_ENDDATE_FACT"]<bureau["DAYS_CREDIT_ENDDATE"])&(bureau["DAYS_ENDDATE_FACT"]>-1598.0)&(bureau["DAYS_ENDDATE_FACT"]<=-1191.0),"BUREAU_NEW_CLOSED_EARLY_PAYERS_SCORE"] = 3

    bureau.loc[(bureau["CREDIT_ACTIVE"]=="Closed")&(bureau["DAYS_ENDDATE_FACT"]<bureau["DAYS_CREDIT_ENDDATE"])&(bureau["DAYS_ENDDATE_FACT"]>-1191.0)&(bureau["DAYS_ENDDATE_FACT"]<=-902.),"BUREAU_NEW_CLOSED_EARLY_PAYERS_SCORE"] = 4

    bureau.loc[(bureau["CREDIT_ACTIVE"]=="Closed")&(bureau["DAYS_ENDDATE_FACT"]<bureau["DAYS_CREDIT_ENDDATE"])&(bureau["DAYS_ENDDATE_FACT"]>-902.)&(bureau["DAYS_ENDDATE_FACT"]<=-656.0),"BUREAU_NEW_CLOSED_EARLY_PAYERS_SCORE"] = 5

    bureau.loc[(bureau["CREDIT_ACTIVE"]=="Closed")&(bureau["DAYS_ENDDATE_FACT"]<bureau["DAYS_CREDIT_ENDDATE"])&(bureau["DAYS_ENDDATE_FACT"]>-656.0)&(bureau["DAYS_ENDDATE_FACT"]<=-439.0),"BUREAU_NEW_CLOSED_EARLY_PAYERS_SCORE"] = 6

    bureau.loc[(bureau["CREDIT_ACTIVE"]=="Closed")&(bureau["DAYS_ENDDATE_FACT"]<bureau["DAYS_CREDIT_ENDDATE"])&(bureau["DAYS_ENDDATE_FACT"]>-439.0)&(bureau["DAYS_ENDDATE_FACT"]<=-229.0),"BUREAU_NEW_CLOSED_EARLY_PAYERS_SCORE"] = 7

    bureau.loc[(bureau["CREDIT_ACTIVE"]=="Closed")&(bureau["DAYS_ENDDATE_FACT"]<bureau["DAYS_CREDIT_ENDDATE"])&(bureau["DAYS_ENDDATE_FACT"]>-229.0)&(bureau["DAYS_ENDDATE_FACT"]<=0.0),"BUREAU_NEW_CLOSED_EARLY_PAYERS_SCORE"] = 8

    bureau.loc[(bureau["CREDIT_ACTIVE"]=="Closed")&(bureau["DAYS_ENDDATE_FACT"]>bureau["DAYS_CREDIT_ENDDATE"])&(bureau["DAYS_ENDDATE_FACT"]>-2876.001)&(bureau["DAYS_ENDDATE_FACT"]<=-2046.0),"BUREAU_NEW_CLOSED_LATE_PAYERS_SCORE"] = 1

    bureau.loc[(bureau["CREDIT_ACTIVE"]=="Closed")&(bureau["DAYS_ENDDATE_FACT"]>bureau["DAYS_CREDIT_ENDDATE"])&(bureau["DAYS_ENDDATE_FACT"]>-2046.0)&(bureau["DAYS_ENDDATE_FACT"]<=-1501.0),"BUREAU_NEW_CLOSED_LATE_PAYERS_SCORE"] = 2

    bureau.loc[(bureau["CREDIT_ACTIVE"]=="Closed")&(bureau["DAYS_ENDDATE_FACT"]>bureau["DAYS_CREDIT_ENDDATE"])&(bureau["DAYS_ENDDATE_FACT"]>-1501.0)&(bureau["DAYS_ENDDATE_FACT"]<=-1182.0),"BUREAU_NEW_CLOSED_LATE_PAYERS_SCORE"] = 3

    bureau.loc[(bureau["CREDIT_ACTIVE"]=="Closed")&(bureau["DAYS_ENDDATE_FACT"]>bureau["DAYS_CREDIT_ENDDATE"])&(bureau["DAYS_ENDDATE_FACT"]>-1182.0)&(bureau["DAYS_ENDDATE_FACT"]<=-1012.0),"BUREAU_NEW_CLOSED_LATE_PAYERS_SCORE"] = 4

    bureau.loc[(bureau["CREDIT_ACTIVE"]=="Closed")&(bureau["DAYS_ENDDATE_FACT"]>bureau["DAYS_CREDIT_ENDDATE"])&(bureau["DAYS_ENDDATE_FACT"]>-1012.0)&(bureau["DAYS_ENDDATE_FACT"]<=-878.0),"BUREAU_NEW_CLOSED_LATE_PAYERS_SCORE"] = 5

    bureau.loc[(bureau["CREDIT_ACTIVE"]=="Closed")&(bureau["DAYS_ENDDATE_FACT"]>bureau["DAYS_CREDIT_ENDDATE"])&(bureau["DAYS_ENDDATE_FACT"]>-878.0)&(bureau["DAYS_ENDDATE_FACT"]<=-615.0),"BUREAU_NEW_CLOSED_LATE_PAYERS_SCORE"] = 6

    bureau.loc[(bureau["CREDIT_ACTIVE"]=="Closed")&(bureau["DAYS_ENDDATE_FACT"]>bureau["DAYS_CREDIT_ENDDATE"])&(bureau["DAYS_ENDDATE_FACT"]>-615.0)&(bureau["DAYS_ENDDATE_FACT"]<=-307.0),"BUREAU_NEW_CLOSED_LATE_PAYERS_SCORE"] = 7

    bureau.loc[(bureau["CREDIT_ACTIVE"]=="Closed")&(bureau["DAYS_ENDDATE_FACT"]>bureau["DAYS_CREDIT_ENDDATE"])&(bureau["DAYS_ENDDATE_FACT"]>-307.0)&(bureau["DAYS_ENDDATE_FACT"]<=0.0),"BUREAU_NEW_CLOSED_LATE_PAYERS_SCORE"] = 8

    bureau['BUREAU_NEW_DAYS_CREDIT_SCORE'] = pd.qcut(bureau['DAYS_CREDIT'],10,labels=[10.0,9.0,8.0,7.0,6.0,5.0,4.0,3.0,2.0,1.0])

    bureau.loc[(bureau["CREDIT_ACTIVE"]=="Active")&(bureau["BUREAU_NEW_DAYS_CREDIT_SCORE"] == 10),"BUREAU_NEW_LAST_ACTIVE_DAYS_CREDIT"] = 1

    # Bureau and bureau_balance numeric features

    num_aggregations = {

        "DAYS_CREDIT": ['min', 'max', 'mean', 'var', 'sum'],

        'DAYS_CREDIT_ENDDATE': ['min', 'max', 'mean'],

        'DAYS_CREDIT_UPDATE': ['mean'],

        'AMT_CREDIT_SUM': ['max', 'mean', 'sum'],

        'AMT_CREDIT_SUM_DEBT': ['max', 'mean', 'sum'],

        'AMT_CREDIT_MAX_OVERDUE': ['mean'],

        'DAYS_ENDDATE_FACT': ['mean', 'sum'],

        'AMT_ANNUITY': ['min', 'max', 'mean', 'var', 'sum'],

        'CNT_CREDIT_PROLONG': ['sum','std'],

        'MONTHS_BALANCE_MAX': ['max'],

        "NEW_BUREAU_BALANCE_DPD_LEVEL_SUM" :['max',"sum"],

        "NEW_BUREAU_BALANCE_DPD_LEVEL_MEAN" :['max',"sum","mean"],

        "NEW_BUREAU_BALANCE_DPD_LEVEL_MAX" :['max',"sum"],

        "NEW_BUREAU_BALANCE_DPD_LEVEL_STD" :['max',"sum","std"],

        "NEW_BUREAU_BALANCE_DPD_LEVEL_SKEW" :['max',"sum","skew"],

        "NEW_BUREAU_BALANCE_STATUS_UNKNOWN_SUM" :['max',"sum"],

        "NEW_BUREAU_BALANCE_STATUS_UNKNOWN_MEAN" :['max',"sum","mean"],

        'BUREAU_CREDIT_TYPE_CONSUMER': ['mean', 'sum'],

        'BUREAU_CREDIT_TYPE_CAR': ['mean', 'sum'],

        'BUREAU_CREDIT_TYPE_MORTGAGE': ['mean', 'sum'],

        'BUREAU_CREDIT_TYPE_CREDIT_CARD': ['mean', 'sum'],

        'BUREAU_CREDIT_TYPE_OTHER': ['mean', 'sum'],

        'BUREAU_UNUSUAL_CURRENCY': ['mean', 'sum'],

        'NEW_PAYMENT_RATE_SUM':['max',"mean","sum"],

        'NEW_PAYMENT_RATE_SUM_DEBT':['max',"mean","sum"],

        'NEW_PAYMENT_RATE_AMT_CREDIT_MAX_OVERDUE':['max',"mean","sum",'min'],

        'BUREAU_NEW_ACTIVE_EARLY_PAYERS_SCORE':['mean','sum','max','min'],

        'BUREAU_NEW_CLOSED_EARLY_PAYERS_SCORE':['mean','sum','max','min'],

        'BUREAU_NEW_CLOSED_LATE_PAYERS_SCORE':['mean','sum','max','min'],

    }

    # Bureau and bureau_balance categorical features

    bureau, bureau_cat = one_hot_encoder(bureau, nan_as_category)

    cat_aggregations = {}

    for cat in bureau_cat: cat_aggregations[cat] = ['mean']

    bureau_agg = bureau.groupby('SK_ID_CURR').agg({**num_aggregations, **cat_aggregations})

    bureau_agg.columns = pd.Index(['BURO_' + e[0] + "_" + e[1].upper() for e in bureau_agg.columns.tolist()])

    # Bureau: Active credits - using only numerical aggregations

    active = bureau[bureau['CREDIT_ACTIVE_Active'] == 1]

    active_agg = active.groupby('SK_ID_CURR').agg(num_aggregations)

    active_agg.columns = pd.Index(['ACTIVE_' + e[0] + "_" + e[1].upper() for e in active_agg.columns.tolist()])

    bureau_agg = bureau_agg.join(active_agg, how='left', on='SK_ID_CURR')

    del active, active_agg

    gc.collect()

    # Bureau: Closed credits - using only numerical aggregations

    closed = bureau[bureau['CREDIT_ACTIVE_Closed'] == 1]

    closed_agg = closed.groupby('SK_ID_CURR').agg(num_aggregations)

    closed_agg.columns = pd.Index(['CLOSED_' + e[0] + "_" + e[1].upper() for e in closed_agg.columns.tolist()])

    bureau_agg = bureau_agg.join(closed_agg, how='left', on='SK_ID_CURR')

    del closed, closed_agg, bureau

    gc.collect()

    return bureau_agg
# Preprocess previous_applications.csv

def previous_applications(num_rows = None, nan_as_category = True):

    df = pd.read_csv("../input/home-credit-default-risk/previous_application.csv", nrows = num_rows)

    df.replace(365243,np.nan,inplace = True)

    df.replace("XNA",np.nan,inplace = True)

    df['NEW_RETURN_DAY'] = df['DAYS_DECISION'] + df['CNT_PAYMENT'] * 30

    df['NEW_DAYS_TERMINATION_diff'] = df['DAYS_TERMINATION'] - df['NEW_RETURN_DAY']

    df['NEW_AMT_DOWN_PAYMENT_rate'] = df['AMT_DOWN_PAYMENT'] / (df['AMT_CREDIT'] + 0.01)

    df['NEW_AMT_SPEND_TO_PRODUCT'] = df['AMT_GOODS_PRICE'] / df['AMT_CREDIT']

    df['NEW_DAYS_DUE']=df['DAYS_FIRST_DUE'] - df['DAYS_LAST_DUE_1ST_VERSION']

    df['NEW_APP_CREDIT_PERC'] = df['AMT_APPLICATION'] / df['AMT_CREDIT']

    df["NAME_PAYMENT_TYPE"].replace(["Non-cash from your account","Cashless from the account of the employer"],np.nan,inplace=True)

    a = ["Channel of corporate sales","Car dealer"]

    df["CHANNEL_TYPE"].replace(a,"Others_Type",inplace=True)

    b = ['Family', 'Spouse, partner', 'Children', 'Other_B', 'Other_A', 'Group of people']

    df["NAME_TYPE_SUITE"] = df["NAME_TYPE_SUITE"].replace(b, 'not_alone')

    df["WEEKDAY_APPR_PROCESS_START"] = df["WEEKDAY_APPR_PROCESS_START"].replace(['MONDAY','TUESDAY', 'WEDNESDAY','THURSDAY','FRIDAY'], 'WEEK_DAY')

    df["WEEKDAY_APPR_PROCESS_START"] = df["WEEKDAY_APPR_PROCESS_START"].replace(['SATURDAY', 'SUNDAY'], 'WEEKEND')

    a = ['Auto technology', 'Jewelry', 'MLM partners', 'Tourism']

    df["NAME_SELLER_INDUSTRY"] = df["NAME_SELLER_INDUSTRY"].replace(a, 'Other_Ind')

    a = ['Auto Accessories', 'Jewelry', 'Homewares', 'Medical Supplies', 'Vehicles', 'Sport and Leisure','Gardening', 'Other', 'Office Appliances', 'Tourism', 'Medicine', 'Direct Sales', 'Fitness', 'Additional Service','Education', 'Weapon', 'Insurance', 'House Construction', 'Animals']

    df["NAME_GOODS_CATEGORY"] = df["NAME_GOODS_CATEGORY"].replace(a, 'Other_Cat')

    a = ['Buying a used car','Building a house or an annex','Everyday expenses','Medicine','Payments on other loans','Education','Journey', 'Purchase of electronic equipment','Buying a new car','Wedding / gift / holiday','Buying a home','Car repairs','Furniture','Buying a holiday home / land', 'Business development','Gasification / water supply','Buying a garage','Hobby','Money for a third person','Refusal to name the goal','Urgent needs','Other']

    df['NAME_CASH_LOAN_PURPOSE']= df['NAME_CASH_LOAN_PURPOSE'].replace(a,'Others')

    df["NAME_PORTFOLIO"].replace("cars",np.nan,inplace=True)

    a = [8,9,10,11,12,13,14,15,16,17]

    df["HOUR_APPR_PROCESS_START"] = df["HOUR_APPR_PROCESS_START"].replace(a, 'Working_Hours')

    b = [18,19,20,21,22,23,0,1,2,3,4,5,6,7]

    df["HOUR_APPR_PROCESS_START"] = df["HOUR_APPR_PROCESS_START"].replace(b, 'Off_Hours')

    drops = ["RATE_INTEREST_PRIMARY","RATE_INTEREST_PRIVILEGED","FLAG_LAST_APPL_PER_CONTRACT","NFLAG_LAST_APPL_IN_DAY","NAME_PRODUCT_TYPE","SELLERPLACE_AREA"]

    df.drop(drops,inplace=True,axis=1)

    df["NFLAG_INSURED_ON_APPROVAL"] = df["NFLAG_INSURED_ON_APPROVAL"].astype("object")

    cat_features = list(df.select_dtypes(['object']).columns)

    df = pd.get_dummies(df, columns= cat_features, dummy_na= True,drop_first=True)

    agg1 = {'SK_ID_CURR': ['size'],

    'AMT_ANNUITY': ['max', 'min', 'mean','std', 'sum'],

    'AMT_APPLICATION':['max', 'min', 'mean','std', 'sum'],

    'AMT_CREDIT':['max', 'min', 'mean','std', 'sum'],

    'AMT_DOWN_PAYMENT': ['max', 'min', 'mean','std', 'sum'],

    'AMT_GOODS_PRICE': ['max', 'min', 'mean','std', 'sum'],

    'RATE_DOWN_PAYMENT': ['max', 'min', 'mean','std'],

    'DAYS_DECISION': ['max', 'min', 'mean', 'sum'],

    'CNT_PAYMENT': ['max', 'min', 'mean','std', 'sum'],

    'DAYS_FIRST_DRAWING': ['max','mean', 'sum'],

    'DAYS_FIRST_DUE': ['max', 'min', 'mean', 'sum'],

    'DAYS_LAST_DUE_1ST_VERSION': ['max', 'min', 'mean', 'sum'],

    'DAYS_LAST_DUE': ['max', 'min', 'mean', 'sum'],

    'DAYS_TERMINATION': ['max', 'min', 'mean','std', 'sum'],

    'NEW_RETURN_DAY': ['max', 'min', 'mean','std', 'sum'],

    'NEW_DAYS_TERMINATION_diff': ['max', 'mean','std', 'sum'],

    'NEW_AMT_DOWN_PAYMENT_rate': ['max','mean','std'],

    'NEW_AMT_SPEND_TO_PRODUCT': ['max', 'mean','std', 'sum'],

    'NEW_APP_CREDIT_PERC': ['max', 'min', 'mean'],

    'NAME_CONTRACT_TYPE_Consumer loans': ['max', 'min','sum'],

    'NAME_CONTRACT_TYPE_Revolving loans': ['max', 'min','sum'],

    'NAME_CONTRACT_TYPE_nan': ['max', 'min','sum'],

    'WEEKDAY_APPR_PROCESS_START_WEEK_DAY': ['max', 'min', 'sum'],

    'WEEKDAY_APPR_PROCESS_START_nan': ['max', 'sum'],

    'HOUR_APPR_PROCESS_START_Working_Hours': ['max', 'min', 'sum'],

    'HOUR_APPR_PROCESS_START_nan': ['max','sum'],

    'NAME_CASH_LOAN_PURPOSE_Repairs': ['max', 'min', 'sum'],

    'NAME_CASH_LOAN_PURPOSE_XAP': ['max', 'sum'],

    'NAME_CASH_LOAN_PURPOSE_nan': ['max', 'sum'],

    'NAME_CONTRACT_STATUS_Canceled': ['max','sum'],

    'NAME_CONTRACT_STATUS_Refused': ['max','sum'],

    'NAME_CONTRACT_STATUS_Unused offer': ['max','sum'],

    'NAME_CONTRACT_STATUS_nan': ['max', 'sum'],

    'NAME_PAYMENT_TYPE_nan': ['max', 'sum'],

    'CODE_REJECT_REASON_HC': ['max', 'min','sum'],

    'CODE_REJECT_REASON_LIMIT': ['max', 'min','sum'],

    'CODE_REJECT_REASON_SCO': ['max', 'min','sum'],

    'CODE_REJECT_REASON_SCOFR': ['max', 'sum'],

    'CODE_REJECT_REASON_VERIF': ['max',  'sum'],

    'CODE_REJECT_REASON_XAP': ['max',  'sum'],

    'CODE_REJECT_REASON_nan': ['max','sum'],

    'NAME_TYPE_SUITE_not_alone': ['max', 'min','sum'],

    'NAME_TYPE_SUITE_nan': ['max', 'min', 'sum'],

    'NAME_CLIENT_TYPE_Refreshed': ['max', 'min','sum'],

    'NAME_CLIENT_TYPE_Repeater': ['max', 'min', 'sum'],

    'NAME_CLIENT_TYPE_nan': ['max', 'min','sum'],

    'NAME_GOODS_CATEGORY_Clothing and Accessories': ['max', 'min', 'sum'],

    'NAME_GOODS_CATEGORY_Computers': ['max', 'min','sum'],

    'NAME_GOODS_CATEGORY_Construction Materials': ['max', 'min', 'sum'],

    'NAME_GOODS_CATEGORY_Consumer Electronics': ['max', 'min', 'sum'],

    'NAME_GOODS_CATEGORY_Furniture': ['max', 'min', 'sum'],

    'NAME_GOODS_CATEGORY_Mobile': ['max', 'min', 'sum'],

    'NAME_GOODS_CATEGORY_Other_Cat': ['max', 'min', 'sum'],

    'NAME_GOODS_CATEGORY_Photo / Cinema Equipment': ['max', 'min', 'sum'],

    'NAME_GOODS_CATEGORY_nan': ['max', 'min', 'sum'],

    'NAME_PORTFOLIO_Cars': ['max', 'min', 'sum'],

    'NAME_PORTFOLIO_Cash': ['max', 'min', 'sum'],

    'NAME_PORTFOLIO_POS': ['max', 'min','sum'],

    'NAME_PORTFOLIO_nan': ['max', 'min', 'sum'],

    'CHANNEL_TYPE_Contact center': ['max', 'min', 'sum'],

    'CHANNEL_TYPE_Country-wide': ['max', 'min', 'sum'],

    'CHANNEL_TYPE_Credit and cash offices': ['max', 'min', 'sum'],

    'CHANNEL_TYPE_Others_Type': ['max', 'min', 'sum'],

    'CHANNEL_TYPE_Regional / Local': ['max', 'min','sum'],

    'CHANNEL_TYPE_Stone': ['max', 'min','sum'],

    'CHANNEL_TYPE_nan': ['max', 'min', 'sum'],

    'NAME_SELLER_INDUSTRY_Connectivity': ['max', 'min','sum'],

    'NAME_SELLER_INDUSTRY_Construction': ['max', 'min', 'sum'],

    'NAME_SELLER_INDUSTRY_Consumer electronics': ['max', 'min',  'sum'],

    'NAME_SELLER_INDUSTRY_Furniture': ['max', 'min', 'sum'],

    'NAME_SELLER_INDUSTRY_Industry': ['max', 'min', 'sum'],

    'NAME_SELLER_INDUSTRY_Other_Ind': ['max', 'min','sum'],

    'NAME_SELLER_INDUSTRY_nan': ['max', 'min','sum'],

    'NAME_YIELD_GROUP_low_action': ['max', 'min', 'sum'],

    'NAME_YIELD_GROUP_low_normal': ['max', 'min', 'sum'],

    'NAME_YIELD_GROUP_middle': ['max', 'min','sum'],

    'NAME_YIELD_GROUP_nan': ['max', 'min','sum'],

    'PRODUCT_COMBINATION_Card X-Sell': ['max', 'min', 'sum'],

    'PRODUCT_COMBINATION_Cash': ['max', 'min', 'sum'],

    'PRODUCT_COMBINATION_Cash Street: high': ['max', 'min', 'sum'],

    'PRODUCT_COMBINATION_Cash Street: low': ['max', 'min','sum'],

    'PRODUCT_COMBINATION_Cash Street: middle': ['max', 'min','sum'],

    'PRODUCT_COMBINATION_Cash X-Sell: high': ['max', 'min','sum'],

    'PRODUCT_COMBINATION_Cash X-Sell: low': ['max', 'min','sum'],

    'PRODUCT_COMBINATION_Cash X-Sell: middle': ['max', 'min','sum'],

    'PRODUCT_COMBINATION_POS household with interest': ['max', 'min','sum'],

    'PRODUCT_COMBINATION_POS household without interest': ['max', 'min','sum'],

    'PRODUCT_COMBINATION_POS industry with interest': ['max', 'min','sum'],

    'PRODUCT_COMBINATION_POS industry without interest': ['max', 'min','sum'],

    'PRODUCT_COMBINATION_POS mobile with interest': ['max', 'min','sum'],

    'PRODUCT_COMBINATION_POS mobile without interest': ['max', 'min','sum'],

    'PRODUCT_COMBINATION_POS other with interest': ['max', 'min','sum'],

    'PRODUCT_COMBINATION_POS others without interest': ['max', 'min','sum'],

    'PRODUCT_COMBINATION_nan': ['max', 'min','sum'],

    'NFLAG_INSURED_ON_APPROVAL_1.0': ['max', 'min','sum'],

    'NFLAG_INSURED_ON_APPROVAL_nan': ['max', 'min','sum']}

    df = df.groupby(['SK_ID_CURR']).agg(agg1)

    df.columns = pd.Index(['PREV_' + e[0] + "_" + e[1].upper() for e in df.columns.tolist()])

    return df
# Preprocess POS_CASH_balance.csv

def pos_cash(num_rows = None, nan_as_category = True):

    df=pd.read_csv('../input/home-credit-default-risk/POS_CASH_balance.csv',nrows = num_rows)

    df['NEW_ADJOURNMENT']=df['SK_DPD']-df['SK_DPD_DEF']

    b = ["Demand","Returned to the store","Approved","Amortized debt","Canceled","XNA"]

    df["NAME_CONTRACT_STATUS"].replace(b, 'Others',inplace=True)

    cat_features = list(df.select_dtypes(['object']).columns)

    df = pd.get_dummies(df, columns= cat_features, dummy_na= True)

    agg={

    'MONTHS_BALANCE': ['max'],

    'SK_DPD': ['max', 'mean',"std"],

    'SK_DPD_DEF': ['max', 'mean',"std"],

    'CNT_INSTALMENT':['min','mean','max'],

    'CNT_INSTALMENT_FUTURE':['mean','min','max'],

    'SK_ID_CURR':['max','size'],

    'NEW_ADJOURNMENT':['max','mean',"std"],

    'NAME_CONTRACT_STATUS_Active':['sum'],

    'NAME_CONTRACT_STATUS_Completed':['sum'],

    'NAME_CONTRACT_STATUS_Signed':['sum'],

    'NAME_CONTRACT_STATUS_Others':['sum']

    }

    pos_agg = df.groupby(['SK_ID_PREV']).agg(agg)

    pos_agg.columns = pd.Index([e[0] + "_" + e[1].upper() for e in pos_agg.columns.tolist()])

    pos_agg["NEW_PAID_MONTH"] = pos_agg["CNT_INSTALMENT_MAX"] - pos_agg["CNT_INSTALMENT_FUTURE_MIN"]

    agg2={

        "MONTHS_BALANCE_MAX":["max","mean"],

        "SK_DPD_MAX":["max","mean"],

        "SK_DPD_MEAN":["max","mean"],

        "SK_DPD_STD":["max","mean","min","std"],

        "SK_DPD_DEF_MAX":["max","mean"],

        "SK_DPD_DEF_MEAN":["max","mean"],

        "SK_DPD_DEF_STD":["max","mean"],

        "CNT_INSTALMENT_MIN":["max","mean","min"],

        "CNT_INSTALMENT_MEAN":["max","mean"],

        "CNT_INSTALMENT_MAX":["max","mean"],

        "CNT_INSTALMENT_FUTURE_MEAN":["max","mean"],

        "CNT_INSTALMENT_FUTURE_MIN":["max","mean"],

        "CNT_INSTALMENT_FUTURE_MAX":["max","mean"],

        "SK_ID_CURR_MAX":["max"],

        "SK_ID_CURR_SIZE":["max","min"],

        "NEW_ADJOURNMENT_MAX":["max","mean"],

        "NEW_ADJOURNMENT_MEAN":["max","mean"],

        "NEW_ADJOURNMENT_STD":["max","mean","min"],

        "NAME_CONTRACT_STATUS_Active_SUM":["max","sum"],

        'NAME_CONTRACT_STATUS_Signed_SUM':["max","sum"],

        'NAME_CONTRACT_STATUS_Completed_SUM':["max","sum"],

        'NAME_CONTRACT_STATUS_Others_SUM':["max","sum"]

    }

    pos_agg2 = pos_agg.groupby(["SK_ID_CURR_MAX"]).agg(agg2)

    pos_agg2.index.names = ['SK_ID_CURR']

    pos_agg2.columns = pd.Index(["POS" + "_" + e[0] + "_" + e[1].upper() for e in pos_agg2.columns.tolist()])

    del df

    gc.collect()

    return pos_agg2
# Preprocess installments_payments.csv

def installments_payments(num_rows=None, nan_as_category = True):

    pd.options.mode.chained_assignment = None

    df = pd.read_csv("../input/home-credit-default-risk/installments_payments.csv", nrows = num_rows)

    df["NEW_DELAY"] = df["DAYS_INSTALMENT"] - df["DAYS_ENTRY_PAYMENT"]

    df['NEW_FLAG_DELAY'] = df['NEW_DELAY'].apply(lambda x : 1 if x < 0 else 0)

    df['NEW_RATIO_DELAY'] = df[['SK_ID_PREV','NEW_FLAG_DELAY']].groupby('SK_ID_PREV')['NEW_FLAG_DELAY'].transform(lambda x : x.sum() / x.count())

    df["NEW_PAYMENT_DIFF"] = df["AMT_INSTALMENT"] - df["AMT_PAYMENT"]

    df["IP_NEW_PAYMENT_INSTALMENT_DIFF"] = df["AMT_PAYMENT"] - df["AMT_INSTALMENT"]

    df["NUM_INSTALMENT_VERSION"] = df["NUM_INSTALMENT_VERSION"].astype("object")

    df[(df["NUM_INSTALMENT_VERSION"] != 1) & (df["NUM_INSTALMENT_VERSION"] != 0) & (df["NUM_INSTALMENT_VERSION"] != 2) & (df["NUM_INSTALMENT_VERSION"] != 3)]['NUM_INSTALMENT_VERSION'] = 4

    cat_features = list(df.select_dtypes(['object']).columns)

    df = pd.get_dummies(df, columns= cat_features,drop_first=True)

    agg1 = {'SK_ID_CURR': ['count','max'],

           'NEW_DELAY': ['max', 'min', 'mean','std', 'sum'],

           'NUM_INSTALMENT_NUMBER':['min','max'],

           'DAYS_INSTALMENT':['max','min','std'],

           'NEW_PAYMENT_DIFF': ['max', 'mean', 'std', 'min','sum'],

           'IP_NEW_PAYMENT_INSTALMENT_DIFF': ['max', 'mean', 'std', 'min','sum'],

           'AMT_INSTALMENT': ['max', 'mean', 'sum', 'min', 'std'],

           'AMT_PAYMENT': ['min', 'max', 'mean', 'sum', 'std'],

           'DAYS_ENTRY_PAYMENT': ['max', 'min', 'std'],

           "NUM_INSTALMENT_VERSION_1.0":["sum"],

           "NUM_INSTALMENT_VERSION_2.0":["sum"],

           "NUM_INSTALMENT_VERSION_3.0":["sum"],

           "NUM_INSTALMENT_VERSION_4.0":["sum"]

            }

    Installments_agg = df.groupby(['SK_ID_PREV']).agg(agg1)

    Installments_agg.columns = pd.Index([e[0] + "_" + e[1].upper() for e in Installments_agg.columns.tolist()])

    del df

    gc.collect()

    return Installments_agg
# Preprocess credit_card_balance.csv

def credit_card_balance(num_rows = None, nan_as_category = True):

    cc = pd.read_csv('../input/home-credit-default-risk/credit_card_balance.csv', nrows = num_rows)

    cc, cat_cols = one_hot_encoder(cc, nan_as_category= True)

    # General aggregations

    cc.drop(['SK_ID_PREV'], axis= 1, inplace = True)

    cc['number_of_instalments'] = cc.groupby(

    by=['SK_ID_CURR'])['CNT_INSTALMENT_MATURE_CUM'].agg('max').reset_index()[

    'CNT_INSTALMENT_MATURE_CUM']

    cc['AMT_DRAWINGS_ATM_CURRENT'][cc['AMT_DRAWINGS_ATM_CURRENT'] < 0] = np.nan

    cc['AMT_DRAWINGS_CURRENT'][cc['AMT_DRAWINGS_CURRENT'] < 0] = np.nan

    cc_agg = cc.groupby('SK_ID_CURR').agg(['min', 'max', 'mean', 'sum', 'var'])

    cc_agg.columns = pd.Index(['CC_' + e[0] + "_" + e[1].upper() for e in cc_agg.columns.tolist()])

    # Count credit card lines

    cc_agg['CC_COUNT'] = cc.groupby('SK_ID_CURR').size()

    del cc

    gc.collect()

    return cc_agg
# LightGBM GBDT with KFold or Stratified KFold

# Parameters from Tilii kernel: https://www.kaggle.com/tilii7/olivier-lightgbm-parameters-by-bayesian-opt/code

def kfold_lightgbm(df, num_folds, stratified = False, debug= False):

    import re

    df = df.rename(columns = lambda x:re.sub('[^A-Za-z0-9_]+', '', x))

    # Divide in training/validation and test data

    train_df = df[df['TARGET'].notnull()]

    test_df = df[df['TARGET'].isnull()]

    print("Starting LightGBM. Train shape: {}, test shape: {}".format(train_df.shape, test_df.shape))

    del df

    gc.collect()

    # Cross validation model

    if stratified:

        folds = StratifiedKFold(n_splits= num_folds, shuffle=True, random_state=1001)

    else:

        folds = KFold(n_splits= num_folds, shuffle=True, random_state=1001)

    # Create arrays and dataframes to store results

    oof_preds = np.zeros(train_df.shape[0])

    sub_preds = np.zeros(test_df.shape[0])

    feature_importance_df = pd.DataFrame()

    feats = [f for f in train_df.columns if f not in ['TARGET','SK_ID_CURR','SK_ID_BUREAU','SK_ID_PREV','index']]

    for n_fold, (train_idx, valid_idx) in enumerate(folds.split(train_df[feats], train_df['TARGET'])):

        train_x, train_y = train_df[feats].iloc[train_idx], train_df['TARGET'].iloc[train_idx]

        valid_x, valid_y = train_df[feats].iloc[valid_idx], train_df['TARGET'].iloc[valid_idx]

        # LightGBM parameters found by Bayesian optimization

        clf = LGBMClassifier(

            njobs = -1,

            n_estimators=10000,

            learning_rate=0.02,

            num_leaves=34,

            colsample_bytree=0.9497036,

            subsample=0.8715623,

            max_depth=8,

            reg_alpha=0.041545473,

            reg_lambda=0.0735294,

            min_split_gain=0.0222415,

            min_child_weight=39.3259775,

            silent=-1,

            verbose=-1, )

        clf.fit(train_x, train_y, eval_set = [(train_x, train_y), (valid_x, valid_y)],

            eval_metric = 'auc', verbose = 300, early_stopping_rounds = 200)

        oof_preds[valid_idx] = clf.predict_proba(valid_x, num_iteration=clf.best_iteration_)[:, 1]

        sub_preds += clf.predict_proba(test_df[feats], num_iteration=clf.best_iteration_)[:, 1] / folds.n_splits

        fold_importance_df = pd.DataFrame()

        fold_importance_df["feature"] = feats

        fold_importance_df["importance"] = clf.feature_importances_

        fold_importance_df["fold"] = n_fold + 1

        feature_importance_df = pd.concat([feature_importance_df, fold_importance_df], axis=0)

        print('Fold %2d AUC : %.6f' % (n_fold + 1, roc_auc_score(valid_y, oof_preds[valid_idx])))

        del clf, train_x, train_y, valid_x, valid_y

        gc.collect()

    print('Full AUC score %.6f' % roc_auc_score(train_df['TARGET'], oof_preds))

    # Write submission file and plot feature importance

    if not debug:

        test_df['TARGET'] = sub_preds

        test_df[['SK_ID_CURR', 'TARGET']].to_csv(submission_file_name, index= False)

    display_importances(feature_importance_df)

    return feature_importance_df

# Display/plot feature importance

def display_importances(feature_importance_df_):

    cols = feature_importance_df_[["feature", "importance"]].groupby("feature").mean().sort_values(by="importance", ascending=False)[:40].index

    best_features = feature_importance_df_.loc[feature_importance_df_.feature.isin(cols)]

    plt.figure(figsize=(8, 10))

    sns.barplot(x="importance", y="feature", data=best_features.sort_values(by="importance", ascending=False))

    plt.title('LightGBM Features (avg over folds)')

    plt.tight_layout()

    plt.savefig('lgbm_importances01.png')
def main(debug = False):

    num_rows = 10000 if debug else None

    df = application_train_test(num_rows)

    with timer("Process bureau and bureau_balance"):

        bureau = bureau_and_balance(num_rows)

        print("Bureau df shape:", bureau.shape)

        df = df.join(bureau, how='left', on='SK_ID_CURR')

        del bureau

        gc.collect()

    with timer("Process previous_applications"):

        prev = previous_applications(num_rows)

        print("Previous applications df shape:", prev.shape)

        df = df.join(prev, how='left', on='SK_ID_CURR')

        del prev

        gc.collect()

    with timer("Process POS-CASH balance"):

        pos = pos_cash(num_rows)

        print("Pos-cash balance df shape:", pos.shape)

        df = df.join(pos, how='left', on='SK_ID_CURR')

        del pos

        gc.collect()

    with timer("Process installments payments"):

        ins = installments_payments(num_rows)

        print("Installments payments df shape:", ins.shape)

        df = df.join(ins, how='left', on='SK_ID_CURR')

        del ins

        gc.collect()

    with timer("Process credit card balance"):

        cc = credit_card_balance(num_rows)

        print("Credit card balance df shape:", cc.shape)

        df = df.join(cc, how='left', on='SK_ID_CURR')

        del cc

        gc.collect()

    with timer("Run LightGBM with kfold"):

        feat_importance = kfold_lightgbm(df, num_folds= 10, stratified= False, debug= debug)

if __name__ == "__main__":

    submission_file_name = "submission.csv"

    with timer("Full model run"):

        main()


# -*- coding: utf-8 -*-
"""
Created on Sun Dec  6 19:07:38 2020

@author: LMJ
"""

import sys

f=open('input.txt','r')
f=sys.stdin
#print(f.readline())
n, m=map(int,f.readline().split())

'''
#method1
n, m=min(n,m), max(n ,m)

if n==m:
    print(n+1)
else:
    for i in range(n+1,m+2):
        print(i, end=' ')

'''

#method2
cnt=[0]*(n+m+3)
for i in range(1,n+1):
    for j in range(1,m+1):
        cnt[i+j]+=1

cnt_max=max(cnt)
for i in range(n+m+3):
    if cnt[i]==cnt_max:
        print(i, end=' ')


from typing import Dict

import requests

BASE_URL = 'https://api.mailgun.net'

class MailGunAPI():
    def __init__(self, config: Dict[str, str]):
        domain: str = config['MAILGUN_DOMAIN']
        self.endpoints = {
            'send': f'{BASE_URL}/v3/{domain}/messages',
            'validate': f'{BASE_URL}/v4/address/validate'
        }
        self.sender = f'{config["MAILGUN_SENDER"]} <no-reply@{domain}>'
        self.auth = ('api', config['MAILGUN_API_KEY'])
        if not self.auth[1]:
            raise Exception('no mailgun key supplied')

    def send(self, maildata: Dict[str, str]):
        maildata['from'] = self.sender
        response = requests.post(self.endpoints['send'],
                                 auth=self.auth,
                                 data=maildata)
        return response

    def validate_adr(self, address: str):
        return requests.get(self.endpoints['validate'],
                            auth=self.auth,
                            params={'address': address})


from typing import Any
from typing import Dict
from typing import List
from typing import Tuple
from typing import Union
from typing import Optional
import logging
import math
import random
import signal

import attr

from .annealing import AdaptiveSimulatedAnnealing
from ..state import State

_LOGGER = logging.getLogger(__name__)
_INSTANCE = None

def _sigusr1_handler(sig_num: int, _: Any) -> None:
    """Handle SIGUSR1 that switches the predictor to exploitation (soon resolution timeout)."""
    global _INSTANCE

    _LOGGER.debug("Switching to exploitation phase based on a signal")
    _INSTANCE._temperature = 0.0  # type: ignore

@attr.s(slots=True)
class TemporalDifference(AdaptiveSimulatedAnnealing):
    """Implementation of Temporal Difference (TD) based predictor with adaptive simulated annealing schedule."""

    step = attr.ib(type=int, default=1, kw_only=True)
    trace = attr.ib(type=bool, default=True, kw_only=True)
    _policy = attr.ib(type=Dict[Tuple[str, str, str], List[Union[float, int]]], factory=dict, init=False)
    _steps_reward = attr.ib(type=float, default=0.0, init=False)
    _steps_taken = attr.ib(type=int, default=0, init=False)
    _next_state = attr.ib(type=Optional[State], default=None, init=False)
    _old_handler = attr.ib(type=Any, init=False, default=None)

    @step.validator
    def _step_validator(self, _: str, value: int) -> None:
        """Validate step parameter for n-step TD-learning."""
        if not isinstance(value, int):
            raise ValueError(f"Unknown type for TD n-step: {type(value)}")

        if value < 1:
            raise ValueError(f"Step set to {value} is not valid for n-step TD-learning")

    def pre_run(self) -> None:
        """Initialize pre-running of this predictor."""
        global _INSTANCE

        super().pre_run()
        self._policy.clear()
        self._temperature = float(self.context.limit)
        self._steps_taken = 0
        self._steps_reward = 0.0
        self._next_state = None

        # Setup handler that responds to SIGUSR1 and switches to exploitation phase.
        self._old_handler = signal.getsignal(signal.SIGUSR1)
        signal.signal(signal.SIGUSR1, _sigusr1_handler)
        _INSTANCE = self

    def post_run(self) -> None:
        """De-initialize resources used by this predictor."""
        global _INSTANCE

        signal.signal(signal.SIGUSR1, self._old_handler)
        self._old_handler = None
        _INSTANCE = None

    def set_reward_signal(self, state: State, package_tuple: Tuple[str, str, str], reward: float) -> None:
        """Note down reward signal of the last action performed."""
        trajectory_end = math.isnan(reward) or math.isinf(reward)
        if trajectory_end:
            self._next_state = None
            reward = 0.0

        self._steps_reward += reward
        if self._steps_taken < self.step and not trajectory_end:
            return

        if self.trace:
            for package_tuple in state.iter_resolved_dependencies():
                record = self._policy.setdefault(package_tuple, [0.0, 0])
                record[0] += self._steps_reward
                record[1] += 1
        else:
            record = self._policy.setdefault(package_tuple, [0.0, 0])
            record[0] += self._steps_reward
            record[1] += 1

        self._steps_taken = 0  # Set back to zero as we update policy.
        self._steps_reward = 0.0

    def run(self) -> Tuple[State, Tuple[str, str, str]]:
        """Run Temporal Difference (TD) with adaptive simulated annealing schedule."""
        if self._next_state is not None:
            unresolved_dependency_tuple = self._next_state.get_random_unresolved_dependency(prefer_recent=True)
            if self.keep_history:
                self._temperature_history.append((None, None, None, self.context.accepted_final_states_count))
            return self._next_state, unresolved_dependency_tuple

        if self._temperature > 0.0:
            self._temperature = self._temperature_function(self._temperature, self.context)
            self._next_state = self.context.beam.max()

            # Pick a random state to be expanded if accepted.
            probable_state_idx = random.randrange(1, self.context.beam.size) if self.context.beam.size > 1 else 0
            probable_state = self.context.beam.get(probable_state_idx)
            acceptance_probability = self._compute_acceptance_probability(
                self._next_state.score, probable_state.score, self._temperature
            )

            if acceptance_probability >= random.random():
                # Perform exploration.
                unresolved_dependency_tuple = probable_state.get_random_unresolved_dependency(prefer_recent=True)
                self._next_state = probable_state
            else:
                unresolved_dependency_tuple = self._do_exploitation(self._next_state)

            if self.keep_history:
                self._temperature_history.append(
                    (
                        self._temperature,
                        self._next_state is self.context.beam.max(),
                        acceptance_probability,
                        self.context.accepted_final_states_count,
                    )
                )

            self._steps_taken += 1
            return self._next_state, unresolved_dependency_tuple

        self._steps_taken += 1
        self._next_state = self.context.beam.max()
        if self.keep_history:
            self._temperature_history.append(
                (
                    self._temperature,
                    True,
                    0.0,
                    self.context.accepted_final_states_count,
                )
            )

        return self._next_state, self._do_exploitation(self._next_state)

    def _do_exploitation(self, state: State) -> Tuple[str, str, str]:
        """Perform expansion of a highest rated stack with action that should yield highest reward."""
        to_resolve_average = None
        to_resolve_package_tuple = None
        for package_tuple in state.iter_unresolved_dependencies():
            reward_records = self._policy.get(package_tuple)
            if reward_records is None:
                continue

            # Compute average - we want to be skewed based on the reward signal
            # we aggregate (so for example median of medians is not that suitable).
            average = reward_records[0] / reward_records[1]
            if to_resolve_average is None or to_resolve_average < average:
                to_resolve_average = average
                to_resolve_package_tuple = package_tuple

        # Make sure we found a candidate based on rewards marked. If not, pick a random one.
        return to_resolve_package_tuple or state.get_random_unresolved_dependency(prefer_recent=True)


from fastapi import APIRouter, Depends, HTTPException, status
from fastapi_users import FastAPIUsers
from beanie.odm.fields import PydanticObjectId
from ..models import User
from ..auth.backend import auth_backend
from ..users.user_manager import get_user_manager
from ..permissions import check_reporter, check_author_or_admin
from .schemas import CommentOut, CommentUpdate
from .utils import read_comment, edit_comment, remove_comment

router = APIRouter(prefix="/comments", tags=["comments"])
fastapi_users = FastAPIUsers[User, PydanticObjectId](get_user_manager, [auth_backend])
current_active_verified_user = fastapi_users.current_user(active=True, verified=True)

@router.patch(
    "/{comment_id}", response_model=CommentOut, status_code=status.HTTP_200_OK
)
async def update_comment(
    comment_id: str,
    comment: CommentUpdate,
    user: User = Depends(current_active_verified_user),
):
    """A route to update a comment"""
    try:
        db_comment = await read_comment(comment_id)
        if not db_comment:
            raise Exception("Comment not found")
        await check_reporter(user, db_comment.author)
        return await edit_comment(db_comment, comment)
    except Exception as e:
        if str(e) == "You cannot edit this bug":
            raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=str(e))
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))

@router.delete("/{comment_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_comment(
    comment_id: str, user: User = Depends(current_active_verified_user)
):
    """A route to delete a comment"""
    try:
        comment = await read_comment(comment_id)
        if not comment:
            raise Exception("Comment not found")
        await check_author_or_admin(user, comment)
        return await remove_comment(comment)
    except Exception as e:
        if str(e) == "You cannot edit this bug":
            raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=str(e))
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))


"""
Geeks for geeks - Find pair with maximum product
http://www.geeksforgeeks.org/return-a-pair-with-maximum-product-in-array-of-integers/
"""

def find_max_pair(num_list):
    max_index = abs_max_in_list(num_list)
    max_elt = num_list[max_index]
    num_list[max_index] = 0
    second_max_index = abs_max_in_list(num_list)
    second_max = num_list[second_max_index]
    return (max_elt, second_max)

def abs_max_in_list(num_list):
    max, max_index = num_list[0], 0
    for index, num in enumerate(num_list[1:]):
        if abs(num) > max:
            max, max_index = abs(num), (index+1)
    return max_index

def main():
    num_list = [int(i) for i in input().strip().split(", ")]
    print(find_max_pair(num_list))

if __name__ == '__main__':
    main()


N = int(input())

allOddNumbersSum = []

for numb in range(0, N):
    X, Y = input().split()
    X, Y = int(X), int(Y)

    oddNumbers = []

    if X > Y:
        X1 = Y
        X2 = X
    else:
        X1 = X
        X2 = Y

    if X1 % 2 != 0:
        for number in range(X1, X2, 2)[1:]:
            oddNumbers.append(number)
    else:
        for number in range(X1 + 1, X2, 2):
            oddNumbers.append(number)

    allOddNumbersSum.append(sum(oddNumbers))

for oddNumber in allOddNumbersSum:
    print(oddNumber)

URI 1099 - Sum of Consecutive Odd Numbers II.py


# @author: Gautam Patel
# Problem Description URL: https://www.hackerrank.com/ProjectEuler+/project-euler-39-integer-right-triangles/problem
import math

mn_ub = 1201
p_ub = 5000000
pl = [0]*(p_ub+1)
ans = [0]*(p_ub+1)
def init():
    for m in range(2, mn_ub):
        for n in range(1, m):
            if (m+n) % 2 != 0 and math.gcd(m,n) == 1:
                p = 2 * m * (m + n)
                k = 1
                while k*p <= p_ub:
                    pl[k*p] += 1
                    k += 1
    for i in range(1, p_ub+1):
        if pl[i] > pl[ans[i-1]]:
            ans[i] = i
        else:
            ans[i] = ans[i-1]

init()
for _ in range(int(input())):
    n = int(input())
    print(ans[n])


import streamlit as st
from dotenv import load_dotenv
from PyPDF2 import PdfReader
from langchain.text_splitter import CharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings, HuggingFaceInstructEmbeddings
from langchain.vectorstores import FAISS, Chroma
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationalRetrievalChain
from langchain.chat_models import ChatOpenAI
from langchain.llms import HuggingFaceHub
from constants import *
import click
import torch
from htmlTemplates import *

def pdf_to_text(pdfs):
    text = ""
    for pdf in pdfs:
        reader = PdfReader(pdf)
        for page in reader.pages:
            text += page.extract_text()
    return text

def text_to_chunks(text):
    splitter = CharacterTextSplitter(
        separator="\n",
        chunk_size=1000,
        chunk_overlap=200,
        length_function=len
        )
    chunks = splitter.split_text(text=text)
    return chunks

def get_vector_store(chunks, device_type):
    # embeddings = OpenAIEmbeddings()
    model_name = "hkunlp/instructor-xl"
    model_kwargs = {'device': device_type}
    encode_kwargs = {'normalize_embeddings': True}
    embeddings = HuggingFaceInstructEmbeddings(
            model_name=model_name,
            model_kwargs=model_kwargs,
            encode_kwargs=encode_kwargs
        )

    # db = Chroma.from_documents(
    #     chunks,
    #     embeddings,
    #     persist_directory=PERSIST_DIRECTORY,
    #     client_settings=CHROMA_SETTINGS,
    # )
    # db.persist()
    # db = None
    vector_store = FAISS.from_texts(texts=chunks, embedding=embeddings)
    print("embeddings done")
    return vector_store, True

def get_conv_chain(vector_store):
    # llm = ChatOpenAI()
    llm = HuggingFaceHub(repo_id="google/flan-t5-xxl", model_kwargs={"temperature":0.5, "max_length":512})

    memory = ConversationBufferMemory(
        memory_key='chat_history', return_messages=True
    )
    conversation_chain = ConversationalRetrievalChain.from_llm(
        llm = llm,
        retriever= vector_store.as_retriever(),
        memory = memory
    )
    return conversation_chain

# @click.command()
# @click.option(
#     "--device_type",
#     default="cuda" if torch.cuda.is_available() else "cpu",
#     type=click.Choice(
#         [
#             "cpu",
#             "cuda",
#             "ipu",
#             "xpu",
#             "mkldnn",
#             "opengl",
#             "opencl",
#             "ideep",
#             "hip",
#             "ve",
#             "fpga",
#             "ort",
#             "xla",
#             "lazy",
#             "vulkan",
#             "mps",
#             "meta",
#             "hpu",
#             "mtia",
#         ],
#     ),
#     help="Device to run on. (Default is cuda)",
# )

def handle_userinput(question):
    res = st.session_state.conversation({'question': question})
    st.session_state.chat_history = res['chat_history']
    # st.write(res)
    for i,msg in enumerate(st.session_state.chat_history):
        if i % 2==0:
            st.write(user_template.replace("{{MSG}}", msg.content), unsafe_allow_html=True)
        else:
            st.write(bot_template.replace("{{MSG}}", msg.content), unsafe_allow_html=True)

def main(device_type="cuda"):
    load_dotenv()
    st.set_page_config(page_title="Anubhab's Chatting", page_icon=":books:")

    st.write(css, unsafe_allow_html=True)

    # initialise session states
    if "conversation" not in st.session_state:
        st.session_state.conversation = None
    if "chat_history" not in st.session_state:
        st.session_state.chat_history = None
    if "knowledge_base" not in st.session_state:
        st.session_state.knowledge_base = False

    st.header("Chat with multiple pdfs :books:")
    question = st.text_input("Ask a question about your documents:")
                            #  disabled=not st.session_state.knowledge_base )
    # if not st.session_state.knowledge_base :
    #     st.write("First train the KB on your pdfs")

    if question :
        print("user Q is " , question)
        # if st.session_state.conversation == None:
        #     st.write("No Knowledge base yet")
        # else:
        #     handle_userinput(question)
        if st.session_state.knowledge_base  :
            handle_userinput(question)
        else:
            st.write("No Knowledge base yet")

    # st.write(user_template.replace("{{MSG}}", "hello Robot"), unsafe_allow_html=True)
    # st.write(bot_template.replace("{{MSG}}", "hello Human"), unsafe_allow_html=True)

    with st.sidebar:
        st.subheader("your documents")
        pdfs = st.file_uploader("Upload pdfs here ",
                         accept_multiple_files=True,
                         type=['pdf'])
        if st.button("Process"):
            with st.spinner("Processing"):
                # 1. get pdf text extracted
                raw_text = pdf_to_text(pdfs)
                print("raw text size : ", len(raw_text))

                # 2. get text embedings
                text_chunks = text_to_chunks(raw_text)

                print("Raw text divided into ", len(text_chunks), " chunks ")

                # 3. create vector store
                print("Now creating embeddings & vector storage ... ")
                vector_store, st.session_state.knowledge_base = get_vector_store(text_chunks, "cpu")
                print("Knowlwdge base is ready : address of vectorSpace ", vector_store)

                # conversation chain
                st.session_state.conversation = get_conv_chain(vector_store)

if __name__ == '__main__':
    main()


def readForSlope(x_slope, y_slope, line, line_num):
    if line_num > 0 and line_num % y_slope == 0:
        x = int(line_num * (x_slope / y_slope))
        line_diff = 0

        val = line[x % line_size]
        if val == '#': return 1
    return 0

with open('./input.txt') as file:
    trees1 = trees2 = trees3 = trees4 = trees5 = 0
    line_num = 0
    trees = 0
    line = file.readline()
    line_size = len(line)-1
    while line:
        trees1 += readForSlope(1,1, line, line_num)
        trees2 += readForSlope(3,1, line, line_num)
        trees3 += readForSlope(5,1, line, line_num)
        trees4 += readForSlope(7,1, line, line_num)
        trees5 += readForSlope(1,2, line, line_num)

        line = file.readline()
        line_num += 1

print(trees1 * trees2 * trees3 * trees4 * trees5)


import bisturi.codegen
import copy, pprint

__trace_enabled = False
__trace_indent = 0

def _trace(pargs=[], pattrs=[], presult=False):
    def decorator(method):
        def wrapper(self, *args, **kargs):
            global __trace_indent

            who = getattr(self, '__name__', self.__class__.__name__)
            indent = " " * __trace_indent
            print(
                "{i}{who} {method}".format(
                    i=indent, who=who, method=method.__name__
                )
            )

            if pargs:
                print("{i}Args:".format(i=indent))
                for p in pargs:
                    try:
                        val = args[p]
                    except:
                        val = kargs[p]

                    print(
                        "{i}{arg}: {val}".format(
                            i=indent, arg=p, val=pprint.pformat(val)
                        )
                    )

            __trace_indent += 1
            try:
                result = method(self, *args, **kargs)
            finally:
                __trace_indent -= 1

            if pattrs:
                print("{i}Attrs post-call:".format(i=indent))
                for p in pattrs:
                    val = getattr(self, p)
                    print(
                        "{i}{arg}: {val}".format(
                            i=indent, arg=p, val=pprint.pformat(val)
                        )
                    )

            if presult:
                print(
                    "{i}Result: {val}".format(
                        i=indent, val=pprint.pformat(val)
                    )
                )

            return result

        if __trace_enabled:
            return wrapper
        else:
            return method

    return decorator

class PacketClassBuilder:
    def __init__(self, metacls, name, bases, attrs):
        self.metacls = metacls
        self.name = name
        self.bases = bases
        self.attrs = attrs

    def bisturi_configuration_default(self):
        return {}

    @_trace(pattrs=['bisturi_conf'])
    def make_configuration(self):
        defaults = self.bisturi_configuration_default()
        self.bisturi_conf = self.attrs.get('__bisturi__', defaults)

    def create_field_name_from_subpacket_name(self, subpacket_name):
        '''Helper method to transform names like CamelCase into camel_case'''
        name = subpacket_name[0].lower() + subpacket_name[1:]
        return "".join((c if c.islower() else "_" + c.lower()) for c in name)

    @_trace(pattrs=['fields_in_class', 'original_fields_in_class'])
    def collect_the_fields_from_class_definition(self):
        ''' Collect the fields of the packet and make new Ref fields
            from Packets "fields".

            Take something like this:

            class A(Packet):
                a = 1
                b = Int(2)
                c = Int(2)
                d = B       # B is a Packet subclass
                e = B()

            and collect [
                b->Int(2), c->Int(2),
                d->Ref(B), e->Ref(B()),
                ]
        '''
        from bisturi.packet import Packet
        from bisturi.field import Field
        from bisturi.field import Ref
        import inspect

        def make_a_field(name_and_field):
            name, field = name_and_field
            if isinstance(field, Field):
                return name, field  # return as it

            is_a_pkt_instance = isinstance(field, Packet)
            is_a_pkt_class = (
                inspect.isclass(field) and issubclass(field, Packet)
            )
            if is_a_pkt_class or is_a_pkt_instance:
                # make a Ref field from it
                newfield = Ref(prototype=field)
                newname = name

                return newname, newfield

            # anything else it is not a field so it should be filtered
            # out
            return None

        # Since Python 3.6 self.attrs (coming from the Metaclass
        # __new__) will be already ordered following the order in the
        # Packet class definition
        names_and_field = map(make_a_field, self.attrs.items())

        # Filter out non-field like objects (marked as None by the
        # previous step)
        names_and_field = filter(None, names_and_field)

        # Save the values from the iterator
        self.fields_in_class = list(names_and_field)

        # Preserve a copy because self.fields_in_class may be modified
        # later
        self.original_fields_in_class = list(self.fields_in_class)

    @_trace(pattrs=['fields'])
    def ask_to_each_field_to_describe_itself(self):
        ''' Ask to each field to describe itself. This should return for each
            field a list of names and fields which represent that original field.
            In most cases one field is described by only one field (itself) but
            there are cases where multiple field are needed.

            class A(Packet):
                a = Int(1)
                b = Int(2).at(0)

            The original list of fields should be [a->Int(1), b->Int(2)]
            but after the description of both fields we have a new list of fields:
                [a->Int(1), _shift_b_->Move(0), b->Int(2)]

            How each field is describe will depend of each field instance.
            See the method _describe_yourself of each Field subclass.
        '''
        self.fields = sum([field._describe_yourself(name, self.bisturi_conf) \
                            for name, field in self.fields_in_class], [])

    @_trace(pattrs=['slots'])
    def compile_fields_and_create_slots(self):
        ''' Compile each field, allowing them to optimize their pack/unpack
            methods.
            Also collect them and create the necessary slots to optimize the
            memory usage, then extend the slot list with the slots given by
            the user.
        '''
        def compile_field(position, name_and_field):
            _, field = name_and_field
            return field._compile(position, self.fields, self.bisturi_conf)

        additional_slots = self.bisturi_conf.get('additional_slots', [])
        self.slots = sum(
            map(compile_field, *zip(*enumerate(self.fields))), additional_slots
        )

    @_trace(pattrs=['slots'])
    def compile_descriptors_and_extend_slots(self):
        ''' Compile each field's descriptor if any and add their slots to the
            slot list.
        '''
        def has_descriptor(field):
            return field.descriptor is not None and hasattr(
                field.descriptor, '_compile'
            )

        self.slots += sum(
            (
                field.descriptor._compile(
                    name, field.descriptor_name, self.bisturi_conf
                ) for name, field in self.fields if has_descriptor(field)
            ), []
        )

    @_trace()
    def lookup_pack_unpack_methods(self):
        ''' The list of fields is transformed in a list of tuples with the
            pack/unpack methods of each field ready to be called avoiding a
            further lookup.

            Take this [a->Int(1), b->Int(2)] into
                [(a, Int(1), a.pack, a.unpack),
                 (b, Int(2), b.pack, b.unpack),
                 ]
        '''
        self.fields = [
            (name, field, field.pack, field.unpack)
            for name, field in self.fields
        ]

    @_trace(pattrs=['attrs'])
    def remove_fields_from_class_definition(self):
        ''' Remove from the class definition any field.
            Take this:
                class A(Packet):
                    a = 1
                    b = Int(2)

            and transform it into:
                class A(Packet):
                    a = 1
        '''
        for name, _ in self.original_fields_in_class:
            del self.attrs[name]

    @_trace(pattrs=['attrs', 'slots'])
    def add_descriptors_to_class_definition(self):
        ''' Add to the class definition any field's descriptor.
            It will replace a field by its descriptor.
            Take this:
                class A(Packet):
                    a = 1
                    b = Int(2).describe(Foo)

            and transform it into:
                class A(Packet):
                    a = 1
                    b = Foo()
        '''
        for name, field in self.fields:
            if field.descriptor:
                self.attrs[field.descriptor_name] = field.descriptor
                self.slots.remove(field.descriptor_name)

    @_trace()
    def collect_sync_methods_from_field_descriptors(self):
        self.sync_before_pack_methods = []
        self.sync_after_unpack_methods = []
        for name, field in self.fields:
            if field.descriptor:
                try:
                    self.sync_before_pack_methods.append(
                        field.descriptor.sync_before_pack
                    )
                except AttributeError:
                    pass

                try:
                    self.sync_after_unpack_methods.append(
                        field.descriptor.sync_after_unpack
                    )
                except AttributeError:
                    pass

    @_trace(pattrs=['metacls', 'name', 'bases', 'attrs', 'cls'])
    def create_class(self):
        ''' Create the class with the correct attributes and slots.
            If it is necessary, the original attributes (fields) can be access
            via the dictionary __bisturi__, key original_fields_in_class.
        '''
        self.bisturi_conf['original_fields_in_class'
                          ] = self.original_fields_in_class

        self.attrs['__slots__'] = self.slots
        self.attrs['__bisturi__'] = self.bisturi_conf

        self.cls = type.__new__(
            self.metacls, self.name, self.bases, self.attrs
        )

    @_trace()
    def add_get_fields_class_method(self):
        @classmethod
        def get_fields(cls):
            return self.fields

        self.cls.get_fields = get_fields

    @_trace()
    def add_sync_descriptor_class_methods(self):
        @classmethod
        def get_sync_before_pack_methods(cls):
            return self.sync_before_pack_methods

        @classmethod
        def get_sync_after_unpack_methods(cls):
            return self.sync_after_unpack_methods

        self.cls.get_sync_before_pack_methods = get_sync_before_pack_methods
        self.cls.get_sync_after_unpack_methods = get_sync_after_unpack_methods

    @_trace(pattrs=['am_in_debug_mode'])
    def check_if_we_are_in_debug_mode(self):
        ''' A class creation is in debug mode if one of its fields is
            a breakpoint (Bkpt).
        '''
        from bisturi.field import Bkpt
        self.am_in_debug_mode = any(
            (isinstance(field, Bkpt) for _, field in self.fields)
        )

    @_trace()
    def create_optimized_code(self):
        ''' Generate the optimized code for the pack and unpack methods and
            replace the original version for the optimized ones.

            The generation can be disabled partially with the configuration
            flags generate_for_pack/generate_for_unpack.
            And it is totally disabled if the class is in debug mode
            (see check_if_we_are_in_debug_mode)
        '''
        generate_by_default = True if not self.am_in_debug_mode else False

        generate_for_pack = self.cls.__bisturi__.get(
            'generate_for_pack', generate_by_default
        )
        generate_for_unpack = self.cls.__bisturi__.get(
            'generate_for_unpack', generate_by_default
        )

        vectorize = self.cls.__bisturi__.get('vectorize', True)
        annotate = self.cls.__bisturi__.get('annotate', True)

        bisturi.codegen.CodeGenerator(
            [
                (i, name_f[0], name_f[1])
                for i, name_f in enumerate(self.fields)
            ],
            self.cls,
            generate_for_pack,
            generate_for_unpack,
            sourcecode_by_field_name=self.sourcecode_by_field_name,
            vectorize=vectorize,
            annotate=annotate
        ).generate_code()

    @_trace()
    def get_packet_class(self):
        return self.cls

    @_trace()
    def create_collect_and_describe_the_field_list(self):
        ''' Given a class definition create any extra field necessary,
            then collect all of them and at last ask to each field to
            describe itself returning a final list of fields.
        '''
        self.collect_the_fields_from_class_definition()
        self.ask_to_each_field_to_describe_itself()

    @_trace()
    def compile_fields_and_descriptors_and_create_slots(self):
        ''' Each field and each descriptor is compiled, optimized and
            added to the list of slots.
        '''
        self.compile_fields_and_create_slots()
        self.compile_descriptors_and_extend_slots()

    @_trace()
    def collect_fields_sourcecode(self):
        import inspect, textwrap
        try:
            sourcelines, _ = inspect.getsourcelines(self.cls)
        except TypeError:
            self.sourcecode_by_field_name = {}
            return

        fields_names = [name for name, f in self.original_fields_in_class
                        ] + ["@@@@@@@@@@@@@@"]

        tmp = []
        last_field_name = None
        self.sourcecode_by_field_name = {}
        for name in fields_names:
            while sourcelines:
                line = sourcelines.pop(0)
                if line.strip().startswith(name
                                           ) or line.strip().startswith('#'):
                    tmp = textwrap.dedent(''.join(tmp))
                    tmp = textwrap.indent(tmp, '# ')
                    self.sourcecode_by_field_name[last_field_name] = tmp
                    tmp = [line]
                    last_field_name = name
                    break

                tmp.append(line)

        tmp = textwrap.dedent(''.join(tmp))
        tmp = textwrap.indent(tmp, '# ')
        self.sourcecode_by_field_name[last_field_name] = tmp

    @_trace()
    def create_packet_class_and_add_its_special_methods(self):
        self.create_class()
        self.collect_fields_sourcecode()
        self.add_get_fields_class_method()
        self.add_sync_descriptor_class_methods()

    @_trace()
    def remove_fields_from_and_add_descriptors_to_class_definition(self):
        self.remove_fields_from_class_definition()
        self.add_descriptors_to_class_definition()

    @_trace()
    def optimize_methods(self):
        self.check_if_we_are_in_debug_mode()
        self.lookup_pack_unpack_methods()
        self.create_optimized_code()

class PacketSpecializationClassBuilder(PacketClassBuilder):
    def __init__(self, metacls, name, bases, attrs):
        from bisturi.packet import Packet

        self.super_class = attrs['__bisturi__']['specialization_of']
        assert isinstance(self.super_class, Packet)

        original_fields_in_superclass = self.super_class.__bisturi__[
            'original_fields_in_class']
        specialized_fields = self.specialize_fields(
            attrs, original_fields_in_superclass
        )

        PacketClassBuilder.__init__(
            self, metacls, name, bases, specialized_attrs
        )

    def bisturi_configuration_default(self):
        return copy.deepcopy(self.super_class.__bisturi__)

    def specialize_fields(
        self, specialization_attrs, original_fields_in_superclass
    ):
        specialized_fields = copy.deepcopy(original_fields_in_superclass)
        for attrname, attrvalue in specialization_attrs:
            if isinstance(
                attrvalue, Field
            ) and attrname not in original_fields_in_superclass:
                raise Exception(
                    "You cannot add new fields like '%s'." % attrname
                )

            if isinstance(
                attrvalue, (
                    int,
                    bytes,
                )
            ) and attrname in original_fields_in_superclass:
                specialized_fields[
                    attrname
                ].default = attrvalue  # TODO the default or a constant??

            if isinstance(
                attrvalue, Field
            ) and attrname in original_fields_in_superclass:
                # TODO remove?
                #attrvalue.ctime = original_fields_in_superclass[
                #    attrname
                #].ctime  # override the creation time to keep the same order
                specialized_fields[attrname] = attrvalue

        return specialized_fields

class MetaPacket(type):
    def __new__(metacls, name, bases, attrs):
        if name == 'Packet' and bases == (object, ):
            attrs['__slots__'] = []
            return type.__new__(
                metacls, name, bases, attrs
            )  # Packet base class

        specialization_of = attrs.get('__bisturi__',
                                      {}).get('specialization_of', None)
        if specialization_of:
            builder = PacketSpecializationClassBuilder(
                metacls, name, bases, attrs
            )

        else:
            builder = PacketClassBuilder(metacls, name, bases, attrs)

        builder.make_configuration()

        builder.create_collect_and_describe_the_field_list()
        builder.compile_fields_and_descriptors_and_create_slots()

        builder.collect_sync_methods_from_field_descriptors()

        builder.remove_fields_from_and_add_descriptors_to_class_definition()
        builder.create_packet_class_and_add_its_special_methods()

        builder.optimize_methods()

        cls = builder.get_packet_class()
        return cls


import random

class Number():
    def __init__(self, sigFigs, power):
        self.sigFigs = sigFigs
        self.power = power
        self.value = MakeNumber(sigFigs, power)

def MakeNumber(sigFigs, power):
    allDigits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
    firstDigit = ['1', '2', '3', '4', '5', '6', '7', '8', '9']

    if power < 0:
        value = "0."+ -(power+1)*"0" + random.choice(firstDigit)
        for digit in range(sigFigs-1):
            value += random.choice(allDigits)
        return value
    elif sigFigs - power < 2:
        value = random.choice(firstDigit)
        for digit in range(sigFigs-1):
            if digit == sigFigs-2:
                value += random.choice(firstDigit)
            else:
                value += random.choice(allDigits)
        value += (power-sigFigs+1)*"0"
        return value
    else:
        value = random.choice(firstDigit)
        decimalLocation = power +1
        for digit in range(1, sigFigs+1):
            if digit == decimalLocation:
                value += "."
            else:
                value += random.choice(allDigits)
        return value

def RoundValue(value, sigFigs):
    decimalIndex = value.find('.')
    if decimalIndex < 0:
        decimalIndex = len(value)

    if float(value)<1:
        placeholders = 0
        for x in range(2,len(value)):
            if value[x] == "0":
                placeholders += 1
            else:
                break

        roundToSigFigs = round(float(value)*10**placeholders,sigFigs)
        addPlaceholders = round(roundToSigFigs/10**placeholders,sigFigs+placeholders)

        if len(str(roundToSigFigs))-sigFigs < 3:
            result = str(addPlaceholders)+"0"*(2-(len(str(roundToSigFigs))-sigFigs))
        else:
            result = str(addPlaceholders)
        return result
    else:
        roundToSigFigs = round(float(value)/10**decimalIndex,sigFigs)
        addZeros = round(roundToSigFigs*10**decimalIndex,sigFigs-decimalIndex)

        if sigFigs <= decimalIndex:
            result = str(int(addZeros))
        elif len(str(addZeros))-sigFigs <= 0:
            result = str(addZeros)+"0"*(sigFigs-len(str(addZeros))+1)
        else:
            result = str(addZeros)

        return result

def CheckAnswer(result, answer):
    if answer == '':        #Check for null result.
        return False

    if answer[0] == ".":    #Convert '.xx' to '0.xx'.
        answer = "0"+answer

    if result == answer:    #Check for exact result.
        return True
    else:
        return False

def CheckRounding(result, sigFigs):
    if float(result)>=10 and sigFigs <= len(result):
        if result[sigFigs-1] == "0" and result.find('.') == -1:
            return True
        else:
            return False

def ApplySciNotation(result, sigFigs):
    if result[0] == "0":
        for x in range(2, len(result)):
            if result[x] != "0":
                startHere = x
                if sigFigs > 1:
                    sciNot = result[x]+"."
                else:
                    sciNot = result[x]
                break
        for digit in range(startHere+1,len(result)):
            sciNot += result[digit]
    elif result.find(".") >= 0:
        decimalIndex = result.find(".")
        sciNot = result[0]+"."
        for x in range(1,sigFigs+1):
            if result[x] != ".":
                sciNot += result[x]
    else:
        sciNot = result[0]
        if sigFigs > 1:
            sciNot += "."
        for x in range(1,sigFigs):
            sciNot += result[x]
    return sciNot

def Main():
    for x in range(4):
        sigFigs = random.randrange(1,7)
        power = random.randrange(-5,9)
        value = MakeNumber(sigFigs,power)
        text = "How many sig figs are in the value: "+ str(value)+"?\n"
        answer = int(input(text))
        if answer == sigFigs:
            print("Correct!")
        else:
            print("Sorry,",value,"has",sigFigs,"sig figs.")


from nose.tools import *
import gzip
from cStringIO import StringIO
from acoustid.server import GzipRequestMiddleware

def test_gzip_request_middleware():
    def app(environ, start_response):
        assert_equal('Hello world!', environ['wsgi.input'].read(int(environ['CONTENT_LENGTH'])))
    gzcontent = StringIO()
    f = gzip.GzipFile(fileobj=gzcontent, mode='w')
    f.write('Hello world!')
    f.close()
    data = gzcontent.getvalue()
    environ = {
        'HTTP_CONTENT_ENCODING': 'gzip',
        'CONTENT_LENGTH': len(data),
        'wsgi.input': StringIO(data),
    }
    mw = GzipRequestMiddleware(app)
    mw(environ, None)


import random
import typing as tp
from collections import deque
from string import ascii_letters

from custom_data_structures.splay_tree.node import Node
from custom_data_structures.splay_tree.splay_tree_implicit_keys import SplayTreeImplicitKeys

def main():
    # S: str = input()
    # tree: SplayTreeImplicitKeys = SplayTreeImplicitKeys()
    # for letter in S:
    #     new_tree = SplayTreeImplicitKeys(Node(letter))
    #     SplayTreeImplicitKeys.merge(tree, new_tree)
    #
    # q: int = int(input())
    #
    # for _ in range(q):
    #     i, j, k = map(int, input().split(" "))
    #     tree = SplayTreeImplicitKeys.rope(tree, i+1, j+1, k)
    # print(tree.in_order_traversal())

    tree = SplayTreeImplicitKeys(Node("a"))

    current_string: str = "a"
    cmds = ['merge', 'rope', 'search']

    for _ in range(1000):
        cmd_idx = random.randint(0, len(cmds) - 1)
        rand_cmd = cmds[cmd_idx]
        if rand_cmd == 'merge':
            letter: str = random.choice(ascii_letters)
            print(f'merge letter {letter}')
            new_tree = SplayTreeImplicitKeys(Node(letter))
            tree = SplayTreeImplicitKeys.merge(tree, new_tree)
            current_string += letter
            tree_string = tree.in_order_traversal()

            assert tree_string == current_string

        if rand_cmd == 'rope':
            try:
                i: int = random.randint(0, len(current_string)-1)
                j: int = random.randint(i, len(current_string)-1)
                k: int = random.randint(0, len(current_string) - (j - i + 1))
                print(f'rope {i} {j} {k}')
                tree = SplayTreeImplicitKeys.rope(tree, i+1, j+1, k)
                substr_ij: str = current_string[i:j+1]
                left_str: str = current_string[0:i] + current_string[j+1:]
                if k == 0:
                    current_string = substr_ij + left_str
                else:
                    current_string = left_str[0:k] + substr_ij + left_str[k:]
                tree_string = tree.in_order_traversal()
                print(f'current_string={current_string}')
                print(f'tree_string={tree_string}')
                assert current_string == tree_string
            except KeyError:
                pass

        if rand_cmd == 'search':
            rand_int = random.randint(0, len(current_string) - 1)
            print(f'finding value with idx={rand_int}')
            found_node = tree.search(rand_int + 1)
            assert current_string[rand_int] == found_node.value

        if tree.root:
            print('tree after operation:')
            tree.root.display()
            print(f'true string: {current_string}')
            print('=======')

        result_ = tree.in_order_traversal()
        assert len(result_) == len(current_string)

    tree = SplayTreeImplicitKeys(Node("a"))
    r = SplayTreeImplicitKeys(Node("r"))
    u = SplayTreeImplicitKeys(Node("u"))
    tree = SplayTreeImplicitKeys.merge(tree, r)
    tree = SplayTreeImplicitKeys.merge(tree, u)
    tree = SplayTreeImplicitKeys.rope(tree, 1, 1, 1)

    result_ = tree.in_order_traversal()
    print(result_)
    assert "rau" == result_

if __name__ == "__main__":
    main()


from collections import deque

def debug(pixels):
    return '\n'.join(''.join('\x1b[32m#\x1b[0m' if cell else '.' for cell in row) for row in pixels)

def display(instructions, width=50, height=6, sync_rate=0.1):
    pixels = [deque(None for _ in range(width))
              for _ in range(height)
              ]

    lit_count = 0
    print(debug(pixels), end='')
    for instruction in instructions:
        op, _, rest = instruction.partition(' ')
        if op == 'rect':
            width, height = [int(val) for val in rest.split('x')]
            for x in range(width):
                for y in range(height):
                    pixels[y][x] = True
        elif op == 'rotate':
            if rest.startswith('column'):
                col, amount = (int(val) for val in rest.split('=')[-1].split(' by '))
                pixels = list(deque(z) for z in zip(*pixels[::-1]))
                pixels[col].rotate(-amount)
                pixels = list(reversed(list(deque(z) for z in zip(*pixels))))

            elif rest.startswith('row'):
                row, amount = (int(val) for val in rest.split('=')[-1].split(' by '))
                pixels[row].rotate(amount)
            else:
                assert False, 'Unknown direction '+rest
        else:
            assert False, 'Unknown instruction '+op
        lit_count = sum(sum(1 for x in row if x) for row in pixels)
        print('\x1b[5A', end='\r')
        print(debug(pixels), end='\r')
        print('\n{:*<50}'.format('*** {:>3} '.format(lit_count)), end='\x1b[1A')
        import time; time.sleep(sync_rate)

    return lit_count

if __name__ == '__main__':
    with open('input.txt') as f:
        instructions = f.readlines()
        for _ in range(8):
            print('*'*50)
        print('\x1b[7A', end='\r')
        pixels_lit = display(instructions, sync_rate=0.1)
        print()


import numpy as np
from scipy import linalg

if __name__ == "__main__":

    a = np.array(
        [[3, 1],
         [2, 4]]
    )
    a_eig = np.linalg.eig(a)

    x = a_eig[1][:, 0]
    l = a_eig[0][0]
    print(l, x)

    print(np.dot(a, x))
    print(l * x)

    x_1 = np.array(
        [2, 5]
    )

    print(x_1*a)


from django.db import models
from django.contrib.auth.models import User

class FriendRequest(models.Model):
    from_user = models.ForeignKey(
        User, on_delete=models.CASCADE, related_name='sent_friend_requests')
    to_user = models.ForeignKey(
        User, on_delete=models.CASCADE, related_name='received_friend_requests')
    created_at = models.DateTimeField(auto_now_add=True)
    accepted = models.BooleanField(default=False)

class UserFriends(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    friends = models.ManyToManyField(
        User, related_name='my_friends', blank=True)

class Group(models.Model):
    name = models.CharField(max_length=255)
    members = models.ManyToManyField(User, related_name='group_members')
    creator = models.ForeignKey(User, on_delete=models.SET_DEFAULT, default=1)

    def __str__(self):
        return self.name

class GroupInvitation(models.Model):
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    inviter = models.ForeignKey(User, on_delete=models.CASCADE)
    invitee = models.ForeignKey(
        User, on_delete=models.CASCADE, related_name='invitations')
    accepted = models.BooleanField(default=False)

    def __str__(self):
        return self.group.name

class Expense(models.Model):
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    description = models.CharField(max_length=255)
    amount = models.DecimalField(max_digits=10, decimal_places=2)
    payer = models.ForeignKey(User, on_delete=models.CASCADE)
    date = models.DateField(auto_now_add=True)
    isEvenlySplit = models.BooleanField(default=False)
    isTypeSettle = models.BooleanField(default=False)

    def __str__(self):
        return f"{self.group.name} => {self.description} => {self.payer.username} payed ${self.amount}"

class ExpenseDetail(models.Model):
    expense = models.ForeignKey(Expense, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    amount_owed = models.DecimalField(max_digits=10, decimal_places=2)

    def __str__(self):
        return f"{self.user.username} owes {self.expense.payer.username} ${self.amount_owed}"

class Debt(models.Model):
    debtor = models.ForeignKey(
        User, on_delete=models.CASCADE, related_name='debts_created')
    creditor = models.ForeignKey(
        User, on_delete=models.CASCADE, related_name='debts_received')
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    amount = models.DecimalField(max_digits=10, decimal_places=2)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.debtor} owes {self.creditor} ${self.amount} in group {self.group}"


from scipy.spatial import distance as dist
import face_recognition
from threading import Thread
import cv2
import numpy as np
import playsound

min_ear=0.28
Eye_Frames=10
counter=0
ALARM_ON=False
def alarm(soundfile):
    playsound.playsound(soundfile)
    playsound.PlaysoundException()
def eye_aspect_ratio(eye):
    A=dist.euclidean(eye[1],eye[5])
    B=dist.euclidean(eye[2],eye[4])
    C=dist.euclidean(eye[0],eye[3])
    EyeAspectRatio=(A+B)/(2*C)
    return EyeAspectRatio

def main():
    global counter,ALARM_ON
    video_capture=cv2.VideoCapture(0)
    video_capture.set(3,640)
    video_capture.set(4,480)
    while True:
        ret,frame=video_capture.read()
        face_landmarks_list=face_recognition.face_landmarks(frame)
        for face_landmark in face_landmarks_list:

            leftEye=face_landmark['left_eye']
            rightEye=face_landmark['right_eye']
            left_EAR=eye_aspect_ratio(leftEye)
            right_EAR=eye_aspect_ratio(rightEye)

            ear=(left_EAR+right_EAR)/2

            lpts=np.array(leftEye)
            rpts=np.array(rightEye)

            cv2.polylines(frame,[lpts],True,(255,255,0),1)
            cv2.polylines(frame,[rpts],True,(255,255,0),1)
            if ear<min_ear:
                counter +=1
                if counter>=Eye_Frames:
                    if not ALARM_ON:
                        ALARM_ON=True
                        t=Thread(target=alarm,args=('Alarm.mp3',))
                        t.daemon=True
                        t.start()
                cv2.putText(frame,"!!!!ALERT!!!!,you are feeling asleep",(5,10),cv2.FONT_HERSHEY_SIMPLEX,0.4,(0,0,255),1)

            else:
                counter=0
                ALARM_ON=False
        cv2.putText(frame,"EAR: {:.2f}".format(ear),(300,10),cv2.FONT_HERSHEY_SIMPLEX,0.4,(0,0,255),1)
        cv2.imshow("@@@ Drowsiness Detector Window @@@",frame)
        if cv2.waitKey(1)==ord('q'):
            break
    video_capture.release()
    cv2.destroyAllWindows()

if __name__=='__main__':
    main()


from ctypes import pointer

class Solution:

    def shiftRight(self, nums, indexOfZero):
        temp = nums[indexOfZero-1]
        nums[indexOfZero - 1] = nums[indexOfZero]
        nums[indexOfZero] = temp

    def shiftLeft(self, nums, startIndex, endIndex):

        while endIndex != startIndex:
            temp = nums[endIndex-1]
            nums[endIndex-1] = nums[endIndex]
            nums[endIndex] = temp
            endIndex -= 1

    def merge(self, nums1, m, nums2, n) -> None:
        """
        Do not return anything, modify nums1 in-place instead.
        """

        firstPointer = 0
        secondPointer = 0
        indexOfZero = m

        # self.shiftLeft(nums1, firstPointer, indexOfZero)
        # # self.shiftLeft(nums1, firstPointer+1, indexOfZero+1)
        # print(nums1)

        if len(nums1) == 1:
            nums1[0] = nums2[0]
            return nums1
        elif n == 0:
            return nums1

        while firstPointer < len(nums1) and secondPointer < len(nums2):
            if nums1[firstPointer] == nums2[secondPointer]:
                self.shiftRight(nums1, indexOfZero)
                indexOfZero += 1
                nums1[firstPointer+1] = nums2[secondPointer]
                firstPointer += 1
                secondPointer += 1
            elif nums1[firstPointer] > nums2[secondPointer]:
                self.shiftLeft(nums1, firstPointer, indexOfZero)
                indexOfZero += 1
                nums1[firstPointer] = nums2[secondPointer]
                firstPointer += 1
                secondPointer += 1
            elif nums1[firstPointer] == 0:
                nums1[firstPointer] = nums2[secondPointer]
                indexOfZero += 1
                firstPointer += 1
                secondPointer += 1
            else:
                firstPointer += 1
        print(nums1)

ss = Solution()
# rs = ss.merge([1, 2, 3, 0, 0, 0], 3, [2, 5, 6], 3)
# rs = ss.merge([1], 1, [], 0)
# rs = ss.merge([0], 0, [1], 1)
# rs = ss.merge([1, 2, 3, 0, 0, 0], 3, [2, 2, 2], 3)
# rs = ss.merge([1, 2, 3, 0, 0, 0], 3, [5, 5, 5], 3)
# rs = ss.merge([2, 2, 3, 0, 0, 0], 3, [1, 1, 1], 3)
# rs = ss.merge([2, 2, 3, 0, 0, 0], 3, [1, 2, 3], 3)
# rs = ss.merge([2, 0], 1, [1], 1)
rs = ss.merge([0, 0, 0, 0, 0], 0, [1, 2, 3, 4, 5], 5)
print(rs)