import collections
import math
import fractions
import ast
import random
import re
from functools import reduce
from itertools import count
from difflib import SequenceMatcher

letters = "abcdefghijklmnopqrstuvwxyz"
numbers = "0123456789"

def apply_safe(function, *args):
    try:
        return function(*args)
    except:
        return args[0]

def ast_int_eval(number):
    a = str(number)
    try:
        a = ast.literal_eval(a)

        # prevents conversion to a tuple, dict, set, and so on
        if type(a) is not list and type(a) is not str and type(a) is not int and type(a) is not float:
            a = str(number)
    except:
        a = int(a)

    return a

def is_digit_value(value):
    value = str(value)
    try:
        int(value)
        return 1
    except:
        return 0

def flatten(x):
    if type(x) is list:
        return [a for i in x for a in flatten(i)]
    return [x]

def deep_flatten(S):
    if type(S) is not list or not S:
        return S

    buf = []
    for i in S:
        if type(i) is list:
            buf += deep_flatten(i)
        else:
            buf.append(i)

    return buf

def is_alpha_value(value):
    value = str(value)

    if len(value) == 0:
        return 0

    try:
        for X in value:
            if not X.lower() in letters:
                return 0
        return 1
    except:
        return 0

def convert_to_base(n, base):
    """
    convert positive decimal integer n to equivalent in another base(1-255)
    """

    digits = "\u0030\u0031\u0032\u0033\u0034\u0035\u0036\u0037\u0038\u0039" \
             "\u0041\u0042\u0043\u0044\u0045\u0046\u0047\u0048\u0049\u004A" \
             "\u004B\u004C\u004D\u004E\u004F\u0050\u0051\u0052\u0053\u0054" \
             "\u0055\u0056\u0057\u0058\u0059\u005A\u0061\u0062\u0063\u0064" \
             "\u0065\u0066\u0067\u0068\u0069\u006A\u006B\u006C\u006D\u006E" \
             "\u006F\u0070\u0071\u0072\u0073\u0074\u0075\u0076\u0077\u0078" \
             "\u0079\u007A\u01DD\u0292\u03B1\u03B2\u03B3\u03B4\u03B5\u03B6" \
             "\u03B7\u03B8\u0432\u0438\u043C\u043D\u0442\u000A\u0393\u0394" \
             "\u0398\u03B9\u03A3\u03A9\u2260\u220A\u220D\u221E\u2081\u2082" \
             "\u2083\u2084\u2085\u2086\u0020\u0021\u0022\u0023\u0024\u0025" \
             "\u0026\u0027\u0028\u0029\u002A\u002B\u002C\u002D\u002E\u002F" \
             "\u003A\u003B\u003C\u003D\u003E\u003F\u0040\u005B\u005C\u005D" \
             "\u005E\u005F\u0060\u007B\u007C\u007D\u007E\u01B5\u20AC\u039B" \
             "\u201A\u0192\u201E\u2026\u2020\u2021\u02C6\u2030\u0160\u2039" \
             "\u0152\u0106\u017D\u01B6\u0100\u2018\u2019\u201C\u201D\u2013" \
             "\u2014\u02DC\u2122\u0161\u203A\u0153\u0107\u017E\u0178\u0101" \
             "\u00A1\u00A2\u00A3\u00A4\u00A5\u00A6\u00A7\u00A8\u00A9\u00AA" \
             "\u00AB\u00AC\u03BB\u00AE\u00AF\u00B0\u00B1\u00B2\u00B3\u00B4" \
             "\u00B5\u00B6\u00B7\u00B8\u00B9\u00BA\u00BB\u00BC\u00BD\u00BE" \
             "\u00BF\u00C0\u00C1\u00C2\u00C3\u00C4\u00C5\u00C6\u00C7\u00C8" \
             "\u00C9\u00CA\u00CB\u00CC\u00CD\u00CE\u00CF\u00D0\u00D1\u00D2" \
             "\u00D3\u00D4\u00D5\u00D6\u00D7\u00D8\u00D9\u00DA\u00DB\u00DC" \
             "\u00DD\u00DE\u00DF\u00E0\u00E1\u00E2\u00E3\u00E4\u00E5\u00E6" \
             "\u00E7\u00E8\u00E9\u00EA\u00EB\u00EC\u00ED\u00EE\u00EF\u00F0" \
             "\u00F1\u00F2\u00F3\u00F4\u00F5\u00F6\u00F7\u00F8\u00F9\u00FA" \
             "\u00FB\u00FC\u00FD\u00FE\u00FF"

    n = int(n)
    base = int(base)

    if n == 0:
        return "0"

    if n < 0 or base < 2 or base > 255:
        if n > 0 and base == 1:
            return "0" * n
        return str(n)

    s = ""
    while True:
        r = n % base
        s = digits[int(r)] + s
        n = n // base
        if n == 0:
            break

    try:
        while s[0] == "0":
            s = s[1:]
    except:
        pass

    return s

def convert_to_base_arbitrary(n, base):
    n = int(n)
    base = int(base)

    if n == 0:
        return [0]

    if n > 0 and base == 1:
        return [0] * n

    s = []
    if base > 0:
        while 1:
            r = n % base
            s = [int(r)] + s
            n = n // base
            if n == 0:
                break
    else:
        while True:
            n, remainder = divmod(n, base)

            if remainder < 0:
                n, remainder = n + 1, remainder - base

            s = [remainder] + s
            if n == 0:
                break

    try:
        while s[0] == "0":
            s = s[1:]
    except:
        pass

    return s

def convert_from_base(n, base):
    digits = "\u0030\u0031\u0032\u0033\u0034\u0035\u0036\u0037\u0038\u0039" \
             "\u0041\u0042\u0043\u0044\u0045\u0046\u0047\u0048\u0049\u004A" \
             "\u004B\u004C\u004D\u004E\u004F\u0050\u0051\u0052\u0053\u0054" \
             "\u0055\u0056\u0057\u0058\u0059\u005A\u0061\u0062\u0063\u0064" \
             "\u0065\u0066\u0067\u0068\u0069\u006A\u006B\u006C\u006D\u006E" \
             "\u006F\u0070\u0071\u0072\u0073\u0074\u0075\u0076\u0077\u0078" \
             "\u0079\u007A\u01DD\u0292\u03B1\u03B2\u03B3\u03B4\u03B5\u03B6" \
             "\u03B7\u03B8\u0432\u0438\u043C\u043D\u0442\u000A\u0393\u0394" \
             "\u0398\u03B9\u03A3\u03A9\u2260\u220A\u220D\u221E\u2081\u2082" \
             "\u2083\u2084\u2085\u2086\u0020\u0021\u0022\u0023\u0024\u0025" \
             "\u0026\u0027\u0028\u0029\u002A\u002B\u002C\u002D\u002E\u002F" \
             "\u003A\u003B\u003C\u003D\u003E\u003F\u0040\u005B\u005C\u005D" \
             "\u005E\u005F\u0060\u007B\u007C\u007D\u007E\u01B5\u20AC\u039B" \
             "\u201A\u0192\u201E\u2026\u2020\u2021\u02C6\u2030\u0160\u2039" \
             "\u0152\u0106\u017D\u01B6\u0100\u2018\u2019\u201C\u201D\u2013" \
             "\u2014\u02DC\u2122\u0161\u203A\u0153\u0107\u017E\u0178\u0101" \
             "\u00A1\u00A2\u00A3\u00A4\u00A5\u00A6\u00A7\u00A8\u00A9\u00AA" \
             "\u00AB\u00AC\u03BB\u00AE\u00AF\u00B0\u00B1\u00B2\u00B3\u00B4" \
             "\u00B5\u00B6\u00B7\u00B8\u00B9\u00BA\u00BB\u00BC\u00BD\u00BE" \
             "\u00BF\u00C0\u00C1\u00C2\u00C3\u00C4\u00C5\u00C6\u00C7\u00C8" \
             "\u00C9\u00CA\u00CB\u00CC\u00CD\u00CE\u00CF\u00D0\u00D1\u00D2" \
             "\u00D3\u00D4\u00D5\u00D6\u00D7\u00D8\u00D9\u00DA\u00DB\u00DC" \
             "\u00DD\u00DE\u00DF\u00E0\u00E1\u00E2\u00E3\u00E4\u00E5\u00E6" \
             "\u00E7\u00E8\u00E9\u00EA\u00EB\u00EC\u00ED\u00EE\u00EF\u00F0" \
             "\u00F1\u00F2\u00F3\u00F4\u00F5\u00F6\u00F7\u00F8\u00F9\u00FA" \
             "\u00FB\u00FC\u00FD\u00FE\u00FF"

    n = str(n)[::-1]
    base = int(base)
    r = 0
    range_v = 0

    for Q in n:
        r += digits.index(Q) * base ** range_v
        range_v += 1

    return r

def convert_from_base_arbitrary(n, base):
    if type(n) is not list:
        n = str(n)

    base = int(base)

    n = n[::-1]
    r = 0
    range_v = 0

    for Q in n:
        r += int(Q) * base ** range_v
        range_v += 1

    return r

def is_prime(n):
    try:
        n = int(n)
    except:
        return 0

    if n == 2 or n == 3:
        return 1
    if n < 2 or n % 2 == 0 or n % 3 == 0:
        return 0
    if n < 9:
        return 1
    r = int(n ** 0.5)
    f = 5
    while f <= r:
        if n % f == 0:
            return 0
        if n % (f + 2) == 0:
            return 0
        f += 6

    return 1

def first_n_primes(n):
    prime_list = []
    primes = prime_sieve()
    for x in range(n):
        prime_list.append(next(primes))
    return prime_list

def primes_upto_n(n):
    prime_list = []
    primes = prime_sieve()
    while True:
        current_prime = next(primes)
        if current_prime > n:
            break
        prime_list.append(current_prime)
    return prime_list

def prime_sieve():
    yield 2
    yield 3
    yield 5
    yield 7
    sieve = {}
    ps = prime_sieve()
    p = next(ps) and next(ps)
    q = p * p
    for c in count(9, 2):
        if c in sieve:
            s = sieve.pop(c)
        elif c < q:
            yield c
            continue
        else:
            s = count(q + 2 * p, 2 * p)
            p = next(ps)
            q = p * p
        for m in s:
            if m not in sieve:
                break
        sieve[m] = s

def combinations(n, r):
    n = int(n)
    r = int(r)
    if r > n:
        return 0
    return int(
        math.factorial(n) // (math.factorial(r) * math.factorial(n - r))
    )

def permutations(n, r):
    n = int(n)
    r = int(r)
    if r > n:
        return 0
    return int(math.factorial(n) // math.factorial(n - r))

def prime_factorization(n):
    n = int(n)

    if n < 2:
        return []
    if n == 2:
        return [2]

    list_of_factors = []
    for Q in range(2, n + 1):
        if is_prime(Q):
            if n % Q == 0:
                list_of_factors.append(Q)
    return list_of_factors

def get_letter(n):
    n = int(n)
    if n in range(1, 27):
        return chr(64 + n)

def prime_factorization_duplicates(n):
    n = int(n)

    if n < 2:
        return []
    if n == 2:
        return [2]
    list_of_factors = []

    for Q in range(2, n + 1):
        if is_prime(Q):
            while n % Q == 0:
                list_of_factors.append(Q)
                n = int(int(n) // int(Q))
        if n == 1:
            break

    return list_of_factors

def prime_factorization_powers(n):
    n = int(n)

    if n < 2:
        return []
    if n == 2:
        return [1]

    list_of_factors = []

    for Q in range(2, n + 1):
        if is_prime(Q):
            value = 0
            while n % Q == 0:
                value += 1
                n = int(int(n) // int(Q))
            list_of_factors.append(value)

    try:
        while list_of_factors[len(list_of_factors) - 1] == 0:
            list_of_factors.pop()
    except:
        pass

    return list_of_factors

def get_nth_prime(n):
    n = int(n) + 1
    current_prime = 2
    while n > 0:
        if is_prime(current_prime):
            n -= 1
            if n > 0:
                current_prime += 1
        else:
            current_prime += 1
    return current_prime

def get_index_of_prime(n):
    from itertools import takewhile
    n = int(n)
    g = prime_sieve()
    return len(list(takewhile(lambda x: x <= n, g)))-1

def get_all_substrings(input_string):
    if type(input_string) is not list:
        input_string = str(input_string)

    length = len(input_string)
    return [
        input_string[i:j+1] for i in range(length) for j in range(i, length)
    ]

def floatify(string):
    # force an exception if not a number
    ast_int_eval(string)

    a = str(string).lower()
    is_neg = False

    # handling scientific notation
    if "e" in a:
        if "e-" in a:
            dec = re.search("e-([0-9]+)", a)
            a = ("%." + dec.group(1) + "f") % float(a)
        else:
            a = "%f" % float(a)

    if a[0] == "-":
        is_neg = True
        a = a[1:]

    if not str(a).__contains__("."):
        a += "."
    while a[0] == "0":
        a = a[1:]
    while a[-1] == "0":
        a = a[0:-1]
    if a[0] == ".":
        a = "0" + a
    if a[-1] == ".":
        a += "0"

    if is_neg:
        a = "-" + a

    return a

def trim_float(string):
    if str(string)[-2:] == ".0":
        return int(string)
    return floatify(string)

def is_float_value(string):
    number_of_dots = str(string).count(".")
    string = str(string).replace(".", "")

    if is_digit_value(string) and number_of_dots < 2:
        return 1
    return 0

def euler_totient(n):
    n = int(n)
    if is_prime(n):
        return n - 1

    amount = 0

    for k in range(1, n + 1):
        if fractions.gcd(n, k) == 1:
            amount += 1

    return amount

def chunk_divide(seq, num):
    num = ast_int_eval(num)
    avg = len(seq) / float(num)
    is_list = type(seq) is list

    if not is_list:
        seq = str(seq)

    if avg < 1:
        return seq
    # special case: there are more parts than possible groupings
    elif avg < 2:
        seq = [[x] for x in seq]

        idx = 0
        while len(seq) > num:
            seq.insert(idx, seq.pop(idx) + seq.pop(idx))
            idx = idx + 1 if idx < len(seq) - 1 else 0

        if not is_list:
            seq = [''.join(x) for x in seq]
        return seq
    else:
        seq = seq[::-1]
        out = []
        last = 0.0

        while last < len(seq):
            out.append(seq[int(last):int(last + avg)][::-1])
            last += avg

        return out[::-1]

def minimum_edit_distance(s1, s2):
    s1 = str(s1)
    s2 = str(s2)
    if len(s1) > len(s2):
        s1, s2 = s2, s1

    distances = range(len(s1) + 1)
    for index2, char2 in enumerate(s2):
        newDistances = [index2 + 1]
        for index1, char1 in enumerate(s1):
            if char1 == char2:
                newDistances.append(distances[index1])
            else:
                newDistances.append(1 + min((distances[index1],
                                             distances[index1 + 1],
                                             newDistances[-1])))
        distances = newDistances
    return distances[-1]

def infinite_replace(object1, object2, object3):

    if type(object1) is list:
        object1 = [str(x) for x in object1]
    elif type(object1) is not list:
        object1 = str(object1)

    if type(object2) is list:
        object2 = [str(x) for x in object2]
    elif type(object2) is not list:
        object2 = str(object2)

    if type(object3) is list:
        object3 = [str(x) for x in object3]
    elif type(object3) is not list:
        object3 = str(object3)

    type1 = type(object1)
    type2 = type(object2)
    type3 = type(object3)

    # [String String String]
    if type1 is str and type2 is str and type3 is str:
        while object1.replace(object2, object3) != object1:
            object1 = object1.replace(object2, object3)
        return object1

    # [String List String]
    elif type1 is str and type2 is list and type3 is str:
        previous_object = ""
        while previous_object != object1:
            previous_object = object1
            for element in object2:
                while object1.replace(element, object3) != object1:
                    object1 = object1.replace(element, object3)
        return object1

    # [String List List]
    elif type1 is str and type2 is list and type3 is list:
        previous_object = ""
        while previous_object != object1:
            previous_object = object1
            for index in range(0, len(object2)):
                while object1.replace(object2[index], object3[index])\
                        != object1:
                    object1 = object1.replace(object2[index], object3[index])
        return object1

    # [List String String]
    elif type1 is list and type2 is str and type3 is str:
        result_list = []
        for sub_element in object1:
            while sub_element.replace(object2, object3) != sub_element:
                sub_element = sub_element.replace(object2, object3)

            result_list.append(sub_element)
        return result_list

    # [List List String]
    elif type1 is list and type2 is list and type3 is str:
        result_list = []
        for sub_element in object1:
            previous_object = ""
            while previous_object != sub_element:
                previous_object = sub_element
                for sub_start in object2:
                    while sub_element.replace(sub_start, object3)\
                            != sub_element:
                        sub_element = sub_element.replace(sub_start, object3)
            result_list.append(sub_element)
        return result_list

    # [List List List]
    elif type1 is list and type2 is list and type3 is list:
        result_list = []
        for sub_element in object1:
            previous_object = ""
            while previous_object != sub_element:
                previous_object = sub_element
                for sub_index in range(0, len(object2)):
                    while sub_element.replace(
                            object2[sub_index], object3[sub_index])\
                            != sub_element:
                        sub_element = sub_element.replace(
                            object2[sub_index], object3[sub_index])
            result_list.append(sub_element)
        return result_list

    raise Exception

def single_replace(object1, object2, object3):

    if type(object1) is list:
        object1 = [str(x) for x in object1]
    else:
        object1 = str(object1)

    if type(object2) is list:
        object2 = [str(x) for x in object2]
    else:
        object2 = str(object2)

    if type(object3) is list:
        object3 = [str(x) for x in object3]
    else:
        object3 = str(object3)

    type1 = type(object1)
    type2 = type(object2)
    type3 = type(object3)

    # [String String String]
    if type1 is str and type2 is str and type3 is str:
        object1 = object1.replace(object2, object3)
        return object1

    # [String List String]
    elif type1 is str and type2 is list and type3 is str:
        for element in object2:
            object1 = object1.replace(str(element), object3)
        return object1

    # [String List List]
    elif type1 is str and type2 is list and type3 is list:
        for index in range(0, len(object2)):
            object1 = object1.replace(str(object2[index]), str(object3[index]))
        return object1

    # [List String String]
    elif type1 is list and type2 is str and type3 is str:
        result_list = []
        for sub_element in object1:
            sub_element = sub_element.replace(object2, object3)
            result_list.append(sub_element)
        return result_list

    # [List List String]
    elif type1 is list and type2 is list and type3 is str:
        result_list = []
        for sub_element in object1:
            for old in object2:
                sub_element = sub_element.replace(str(old), str(object3))
            result_list.append(sub_element)
        return result_list

    # [List List List]
    elif type1 is list and type2 is list and type3 is list:
        result_list = []
        for current in object1:
            for index in range(0, len(object2)):
                current = current.replace(object2[index], object3[index])
            result_list.append(current)
        return result_list

    raise Exception

def first_replace(object1, object2, object3):

    if type(object1) is list:
        object1 = [str(x) for x in object1]
    elif type(object1) is not list:
        object1 = str(object1)

    if type(object2) is list:
        object2 = [str(x) for x in object2]
    elif type(object2) is not list:
        object2 = str(object2)

    if type(object3) is list:
        object3 = [str(x) for x in object3]
    elif type(object3) is not list:
        object3 = str(object3)

    type1 = type(object1)
    type2 = type(object2)
    type3 = type(object3)

    # [String String String]
    if type1 is str and type2 is str and type3 is str:
        object1 = object1.replace(object2, object3, 1)
        return object1

    # [String List String]
    elif type1 is str and type2 is list and type3 is str:
        for element in object2:
            object1 = object1.replace(str(element), object3, 1)
        return object1

    # [String List List]
    elif type1 is str and type2 is list and type3 is list:
        for index in range(0, len(object2)):
            object1 = object1.replace(
                str(object2[index]), str(object3[index]), 1)
        return object1

    # [List String String]
    elif type1 is list and type2 is str and type3 is str:
        result_list = []
        for sub_element in object1:
            sub_element = sub_element.replace(object2, object3, 1)
            result_list.append(sub_element)
        return result_list

    # [List List String]
    elif type1 is list and type2 is list and type3 is str:
        result_list = []
        for sub_element in object1:
            for old in object2:
                sub_element = sub_element.replace(str(old), str(object3), 1)
            result_list.append(sub_element)
        return result_list

    # [List List List]
    elif type1 is list and type2 is list and type3 is list:
        result_list = []
        for current in object1:
            for index in range(0, len(object2)):
                current = current.replace(object2[index], object3[index], 1)
            result_list.append(current)
        return result_list

    raise Exception

def divisors_of_number(n):

    temp_list = []
    for N in range(1, int(n) + 1):
        if int(n) % N == 0:
            temp_list.append(N)

    return temp_list

def insert(object1, character, location):
    if type(object1) is not list:
        object1 = str(object1)

    location = int(location)

    if location > len(object1):
        return object1

    if type(object1) is list:
        return object1[0:location] + [character] + object1[location + 1:]

    return object1[0:location] + str(character) + object1[location + 1:]

def mirror(a):
    if type(a) is not list:
        a = str(a).split("\n")

    result = []
    for element in a:
        reversed_element = transliterate(
            element[::-1], "<>{}()[]\\/", "><}{)(][/\\")
        result.append(element + reversed_element)

    return '\n'.join(result)

def vertical_mirror(a):
    if type(a) is not list:
        a = str(a).split("\n")

    result = []
    for element in a:
        result.append(element)

    for element in a[::-1]:
        reversed_element = transliterate(element,  "\\/", "/\\")
        result.append(reversed_element)

    return '\n'.join(result)

def vertical_intersected_mirror(a):
    if type(a) is not list:
        a = str(a).split("\n")

    result = []
    for element in a:
        result.append(element)

    for element in a[::-1][1:]:
        reversed_element = transliterate(element,  "\\/", "/\\")
        result.append(reversed_element)

    return '\n'.join(result)

def intersected_mirror(a):
    if type(a) is not list:
        a = str(a).split("\n")

    result = []
    for element in a:
        reversed_element = transliterate(
            element[::-1], "<>{}()[]\\/", "><}{)(][/\\")
        result.append(element[:-1] + reversed_element)

    return '\n'.join(result)

def transliterate(string: str, prev, next):
    processed = ""

    for character in string:
        has_replaced = False
        for Q in range(min(len(prev), len(next))):
            if character == prev[Q]:
                processed += next[Q]
                has_replaced = True
                break

        if not has_replaced:
            processed += character

    return processed

def string_multiplication(a, b):
    if type(a) is not list and type(b) is not list:
        try:
            try:
                return ast_int_eval(b) * str(a)
            except:
                return ast_int_eval(a) * str(b)
        except:
            result = []
            for x in a:
                temp_list = []
                for y in b:
                    temp_list.append(str(x) + str(y))
                result.append(temp_list)
            return result
    elif type(a) is not list and type(b) is list:
        try:
            return [str(a) * ast_int_eval(x) for x in b]
        except:
            return [str(x) * ast_int_eval(a) for x in b]
    elif type(b) is not list and type(a) is list:
        try:
            return [str(x) * ast_int_eval(b) for x in a]
        except:
            return [str(b) * ast_int_eval(x) for x in a]
    else:
        try:
            result = []
            for x in range(0, len(a)):
                result.append(str(a[x]) * ast_int_eval(b[x]))
            return result
        except:
            try:
                result = []
                for x in range(0, len(a)):
                    result.append(str(b[x]) * ast_int_eval(a[x]))
                return result
            except:
                result = []
                for x in a:
                    temp_list = []
                    for y in b:
                        temp_list.append(str(x) + str(y))
                    result.append(temp_list)
                return result

def even_divide(a, b):
    b = int(ast_int_eval(b))

    if type(a) is not list:
        a = str(a)

    result = []
    temp_list = []

    for index in range(0, len(a)):
        temp_list.append(a[index])
        if len(temp_list) == b:
            result.append(temp_list)
            temp_list = []

    if temp_list:
        result.append(temp_list)

    if type(a) is str:
        return list(map(''.join, result))

    return result

def get_hash(string):
    string = "filler for the string" + str(string)

    hash_num = 0
    for index in range(0, len(string)):
        hash_num += ord(string[index]) * (index + 1) ** 8
        hash_num %= 2**32

    return hash_num

def closest_to(a, b):
    if type(b) is list:
        return a

    try:
        b = ast_int_eval(b)
    except:
        # if a is not a list, applies char difference
        # otherwise we can use string distances
        if type(a) is not list:
            b = ord(b)
        pass

    if type(a) is list:
        a = deep_flatten(a)

        if type(b) is not str:
            try:
                a = [ast_int_eval(x) for x in a]
            except:
                # fallback to string distances if there is a string in a
                b = str(b)
    else:
        a = str(a)

    closest = a
    distance = float('inf')

    for element in a:
        if type(a) is str:
            if abs(ord(element) - b) < distance:
                distance = abs(ord(element) - b)
                closest = element
        elif type(b) is str:
            element_dist = 1 - SequenceMatcher(None, str(element), b).ratio()

            if element_dist < distance:
                distance = element_dist
                closest = str(element)
        elif abs(element - b) < distance:
            distance = abs(element - b)
            closest = element

    return closest

def zip_with(a, b):
    temp = a

    if type(temp) is not list:
        temp = str(temp)

    if type(temp) is str:
        temp = temp.split("\n")

    maximum_length = max([len(x) for x in temp])

    if type(a[0]) is list:
        temp_list = []
        for element in temp:
            temp_list.append(element + [str(b)] * (maximum_length - len(element)))
        filled_list = temp_list[:]
    else:
        filled_list = [str(x) + (str(b) * (maximum_length - len(x))) for x in temp]

    zipped_list = [list(x) for x in zip(*filled_list)]
    result = []

    if type(a) is not list:
        for element in zipped_list:
            result.append(''.join(element))
        result = '\n'.join(result)

    elif type(a[0]) is str:
        for element in zipped_list:
            result.append(''.join(element))

    else:
        result = zipped_list[:]

    return result

def multi_split(a, b: list):
    if type(a) is not list:
        a = str(a)

    delimiter = ''.join(
        random.choice(" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLM"
                      "NOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~")
        for _ in range(10))
    while delimiter in a:
        delimiter = ''.join(
            random.choice(" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLM"
                          "NOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~")
            for _ in range(10))

    a = transliterate(a, b, [delimiter] * len(b))

    return [i for i in a.split(delimiter) if i]

def shape_like(a, b):

    if type(b) is str:
        b = int(ast_int_eval(b))

    if type(a) is list and type(b) is list:
        result = []
        for element in b:
            result.append(shape_like(a, element))
        return result

    elif type(a) is list and type(b) is int:
        return (a * b)[:b]

    elif type(a) is not list and type(b) is list:
        result = []
        for element in b:
            result.append(shape_like(a, element))
        return result

    elif type(a) is not list and type(b) is not list:
        return (str(a) * b)[:b]

def sentence_case(a):
    a = str(a)
    temp_string = ""
    begin_sentence = True
    for Q in a:
        if begin_sentence:
            temp_string += Q.upper()
            if not Q == " ":
                begin_sentence = False
        else:
            temp_string += Q
        if Q == "." or Q == "?" or Q == "!":
            begin_sentence = True
    return temp_string

def list_multiply(a, b, recur=True):

    try:
        if type(a) is not list:
            a = [a]

        if type(b) is list:
            result = []

            for element in b:
                try:
                    result.append(a * int(element))
                except:
                    result.append(list_multiply(a, element, False))

            return result
        else:
            return a * int(b)

    except Exception as e:

        if recur:
            return list_multiply(b, a, False)

        else:
            raise e

def deltaify(a):
    if type(a) is not list:
        a = str(a)

    sublists = []
    values = []

    for i in a:
        if type(i) is list:
            sublists.append(i)
        else:
            try:
                values.append(ast_int_eval(i))
            except:
                pass

    result = []
    for Q in range(len(values) - 1):
        result.append(values[Q+1] - values[Q])

    if len(sublists):
        result += [deltaify(l) for l in sublists]

    return result

def filtered_to_the_front(a, b):
    if type(a) is not list:
        a = str(a)

    filtered = []
    remaining = []

    for i in a:
        if type(i) is list:
            remaining.append(filtered_to_the_front(i, b))
        elif str(i) == str(b):
            filtered.append(str(i))
        else:
            remaining.append(str(i))

    result = filtered + remaining

    return result if type(a) is list else ''.join([str(x) for x in result])

def bijective_base_conversion(a, to_base):
    a = int(a)

    number = ""
    while a:
        a -= 1
        r = a % to_base
        a = a // to_base
        r += 1
        if r < 0:
            a += 1
            r -= to_base
        number += str(r)
    return number[::-1]

def bijective_decimal_conversion(a, from_base):
    a = str(int(a))

    number = 0
    for Q in a:
        number = number * from_base + int(Q)
    return number

def uniquify(a, connected=False):
    buf = []

    if type(a) is not list:
        a = str(a)

    for item in a:
        if type(item) is not list:
            item = str(item)

        if item not in buf:
            buf.append(item)
        elif connected and len(buf) and buf[-1] != item:
            buf.append(item)

    return buf if type(a) is list else ''.join(buf)


from pathlib import Path
from typing import Literal, Optional

import soundfile as sf
from telegram import Update
from telegram.ext import CallbackContext, MessageHandler, filters

from assistantbot.ai.text.prompts.pronunciation import (
    GLOBAL_PRONUNCIATION_ASSESSMENT,
    WORD_PRONUNCIATION_ASSESSMENT_PARTICULAR,
    WORDS_PRONUNCIATION_ASSESSMENT_BASE,
)
from assistantbot.ai.voice.pronunciation import PronunciationAssessment
from assistantbot.ai.voice.synthesizer import VoiceSynthesizer
from assistantbot.ai.voice.whisper import transcript_audio
from assistantbot.conversation.base import ConversationHandler
from assistantbot.conversation.chains import (
    get_conversation_chain,
    update_memory,
)
from assistantbot.logs.configuration import logger

class VoiceHandler(ConversationHandler):
    def __init__(
        self,
        grading_system: Optional[
            Literal["hundred_mark", "five_points"]
        ] = "hundred_mark",
        granularity: Optional[
            Literal["phoneme", "word", "full"]
        ] = "phoneme",
    ):
        """
        This class handles the voice messages sent to the bot.

        Parameters
        ----------
        grading_system : Optional[Literal["hundred_mark", "five_points"]]
            The grading system to use for the pronunciation assessment,

        granularity : Optional[Literal["phoneme", "word", "full"]], optional
            The granularity to use for the pronunciation assessment,
        """
        super().__init__(filters.VOICE)
        self.pronuntiation_assessment = PronunciationAssessment(
            grading_system=grading_system, granularity=granularity
        )

    def handler(self) -> MessageHandler:
        """
        This function returns the message handler.

        Returns
        -------
        MessageHandler
            The message handler.
        """
        return MessageHandler(self._type, self.callback, block=False)

    async def callback(
        self, update: Update, context: CallbackContext
    ) -> None:
        """
        This function is called when a voice message is sent to the bot.

        Parameters
        ----------
        update : Update
            The update object from Telegram.
        context : _type_
            The context object from Telegram.
        """
        # Get the message text
        response_message = """
🚀 Hey there, folks!
We're moving to @lingolearn_bot for an even better English learning experience!
While this direction will no longer be available, rest assured that everything remains the same, just in a new direction.
See you there! 🌟📚😊
"""

        # Send the start message to the user
        await context.bot.send_message(
            chat_id=update.effective_chat.id,
            text=response_message,
        )

    @staticmethod
    def _process_incoming_audio(input_file: str, output_file: str) -> None:
        """
        This function converts an audio file to .wav format and saves it in
        the specified output file.

        Parameters
        ----------
        input_file : str
            The input audio file.
        output_file : str
            The output audio file.
        """
        # Convert the audio file to .wav
        data, samplerate = sf.read(input_file)
        sf.write(output_file, data, samplerate)

        # Delete the input file
        Path(input_file).unlink()

    @staticmethod
    async def _transcript_voice_message(input_file: str) -> str:
        """
        This function transcripts the voice message and returns the text
        using Whisper API.

        Parameters
        ----------
        input_file : str
            The input audio file.

        Returns
        -------
        str
            The text of the voice message.
        """
        transcription = await transcript_audio(input_file)
        return transcription

    async def _create_text_response(
        self, user_id: int, entry_message: str
    ) -> str:
        """
        This function creates the text response using the handler of the
        text conversation.

        Parameters
        ----------
        entry_message : str
            The text of the voice message.

        Returns
        -------
        str
            The text response.
        """
        # Get the conversation chain
        conversation_chain = get_conversation_chain(user_id)

        response_message = await conversation_chain.apredict(
            input=entry_message
        )

        # Update the memory
        update_memory(user_id, conversation_chain)

        return response_message

    async def _get_pronuntiation_assessment_response(
        self, reference_text: str, input_audio_path: str
    ) -> str:
        """
        This function performs the pronunciation assessment of a given audio
        file and returns the assessment.

        Parameters
        ----------
        reference_text : str
            The reference text to use for the assessment.
        input_audio_path : str
            The path of the input audio file.

        Returns
        -------
        str
            The string with the assessment of the pronunciation.
        """
        (
            json_recognition_result,
            assessment_result,
        ) = await self.pronuntiation_assessment.get_assessment(
            reference_text, input_audio_path
        )

        # Get the global assessment result
        global_assessment = self.pronuntiation_assessment.get_global_scores(
            assessment_result
        )

        # Get the word assessment result
        word_assessment = self.pronuntiation_assessment.get_words_scores(
            json_recognition_result
        )

        # Create the assessment string for word assessment
        assessment_words_string = WORDS_PRONUNCIATION_ASSESSMENT_BASE
        tagged_text = ""

        for word in word_assessment:
            # If there is a word with a bad pronunciation, add it to the
            # assessment string
            if word.accuracy_score <= 95:
                # Get the string of the syllabes
                syllabes_string = "".join(
                    f"{s.syllabe} ({s.accuracy_score})"
                    + f"{'❗' if s.accuracy_score <= 85 else '✅'}"
                    for s in word.syllabes
                )

                assessment_words_string += (
                    WORD_PRONUNCIATION_ASSESSMENT_PARTICULAR.format(
                        word=word.word, syllabes_string=syllabes_string
                    )
                )

            # Add the word to the colored text
            if word.accuracy_score >= 95:
                tag = "i"
            elif word.accuracy_score >= 90:
                tag = "u"
            else:
                tag = "s"
            tagged_text += f"<{tag}>{word.word}</{tag}> "

        def __create_score_assessment(score: int) -> str:
            """
            This function creates a string with the score and the emoji
            depending on the score.

            Parameters
            ----------
            score : int
                The score.

            Returns
            -------
            str
                The string with the score and the emoji.
            """
            return str(score) + f"{'❗' if score <= 85 else '✅'}"

        # Create the assessment string for global assessment
        assessment_global_string = GLOBAL_PRONUNCIATION_ASSESSMENT.format(
            phrase=tagged_text,
            pronunciation_score=__create_score_assessment(
                global_assessment.pronunciation_score
            ),
            accuracy_score=__create_score_assessment(
                global_assessment.accuracy_score
            ),
            fluency_score=__create_score_assessment(
                global_assessment.fluency_score
            ),
        )

        if assessment_words_string == WORDS_PRONUNCIATION_ASSESSMENT_BASE:
            # If there are no words with a bad pronunciation, return only the
            # global assessment
            assessment_words_string = (
                "\n Nice! You pronounced all" " the words correctly!"
            )

        return assessment_global_string + assessment_words_string


from django.conf.urls import url, include
from core.views import (
    home,
    lista_pessoas,
    nova_pessoa,
    pessoa_update,
    pessoa_delete,
    lista_veiculos,
    novo_veiculo,
    veiculo_update,
    veiculo_delete,
    lista_mov_rot,
    novo_mov_rot,
    mov_rot_update,
    mov_rot_delete,
    lista_mensalista,
    novo_mensalista,
    mensalista_update,
    mensalista_delete,
    lista_mov_mens,
    mov_mensalista_novo,
    mov_mensalista_update,
    mov_mensalista_delete
)

urlpatterns = [
    url(r'^mov-mensalista-delete/(?P<id>\d+)/$', mov_mensalista_delete, name='core_mov_mensalista_delete'),
    url(r'^mov-mensalista-update/(?P<id>\d+)/$', mov_mensalista_update, name='core_mov_mensalista_update'),
    url('mov-mensalista-novo', mov_mensalista_novo, name='core_mov_mensalista_novo'),
    url('mov_mens', lista_mov_mens, name='core_lista_mov_mens'),
    url(r'^mensalista-delete/(?P<id>\d+)/$', mensalista_delete, name='core_mensalista_delete'),
    url(r'^mensalista-update/(?P<id>\d+)/$', mensalista_update, name='core_mensalista_update'),
    url('novo-mensalista', novo_mensalista, name='core_novo_mensalista'),
    url('mensalista', lista_mensalista, name='core_lista_mensalista'),
    url(r'^mov-rot-delete/(?P<id>\d+)/$', mov_rot_delete, name='core_mov_rot_delete'),
    url(r'^mov-rot-update/(?P<id>\d+)/$', mov_rot_update, name='core_mov_rot_update'),
    url('mov_rot', lista_mov_rot, name='core_lista_mov_rot'),
    url('novo_mov_rot', novo_mov_rot, name='core_novo_mov_rot'),
    url(r'^veiculo-delete/(?P<id>\d+)/$', veiculo_delete, name='core_veiculo_delete'),
    url(r'^veiculo-update/(?P<id>\d+)/$', veiculo_update, name='core_veiculo_update'),
    url('veiculos', lista_veiculos, name='core_lista_veiculos'),
    url('novo-veiculo', novo_veiculo, name='core_novo_veiculo'),
    url(r'^pessoa-delete/(?P<id>\d+)/$', pessoa_delete, name='core_pessoa_delete'),
    url(r'^pessoa-update/(?P<id>\d+)/$', pessoa_update, name='core_pessoa_update'),
    url('pessoas', lista_pessoas, name='core_lista_pessoas'),
    url('nova-pessoa', nova_pessoa, name='core_nova_pessoa'),
    url('', home, name='core_home'),
]


import random

class TicToe:

    def __init__(self, player1, player2) -> None:
        self.player1 = player1
        self.player2 = player2
        self.mark = None
        self.y = 0
        self.x = 0
        self.my_map = [list(' ' * 3) for _ in range(3)]
        self.op_mark = None

    def opposite_mark(self):
        if self.mark == 'X':
            self.op_mark = 'O'
        else:
            self.op_mark = 'X'

    def if_draw(self):
        for row in self.my_map:
            if any([i == ' ' for i in row]):
                return 0
        return 1

    def define_mark(self):
        x_mark = 0
        o_mark = 0
        for row in self.my_map:
            x_mark += row.count('X')
            o_mark += row.count('O')
        return 'X' if x_mark == o_mark else 'O'

    def who_win(self, sign):
        # Horizontal win
        for row in self.my_map:
            if all([i == sign for i in row]):
                return 1

        # Vertical win
        for x in range(3):
            if all([self.my_map[y][x] == sign for y in range(3)]):
                return 1

        # First diagonal win
        if (self.my_map[0][0] == sign and
                self.my_map[1][1] == sign and self.my_map[2][2] == sign):
            return 1
        # Second diagonal win
        elif (self.my_map[0][2] == sign and
              self.my_map[1][1] == sign and self.my_map[2][0] == sign):
            return 1
        else:
            return 0

    def user_move(self):
        while True:
            try:
                x, y = map(int, input('Enter the coordinates: > ').split())
            except ValueError:
                print('You should enter numbers!')
                continue
            else:
                if x not in range(1, 4) or y not in range(1, 4):
                    print("Coordinates should be from 1 to 3!")
                    continue
                elif self.my_map[y - 1][x - 1] == ' ':
                    self.y, self.x = y, x
                    return
                else:
                    print("This cell is occupied! Choose another one!")

    def ai_move(self):
        print('Making move level "easy"')
        while True:
            y = random.randint(1, 3)
            x = random.randint(1, 3)
            if self.my_map[y - 1][x - 1] == ' ':
                self.y, self.x = y, x
                return

    def start_game(self):
        print(self)  # drawing the map
        while True:
            self.mark = self.define_mark()
            if self.player1 == 'user' and self.mark == 'X' or self.player2 == 'user' and self.mark == 'O':
                self.user_move()
            else:
                self.ai_move()
            self.my_map[self.y - 1][self.x - 1] = self.mark
            print(self)  # updating the map
            if self.who_win(self.mark):
                print(f"{self.mark} wins")
                return
            elif self.if_draw():
                print('Draw')
                return

    def __str__(self) -> str:
        cells = '---------\n'
        for i in range(3):
            cells += f"| {' '.join(self.my_map[i])} |\n"
        cells += '---------\n'
        return cells

class MediumLevel(TicToe):

    def opposite_mark(self):
        if self.mark == 'X':
            self.op_mark = 'O'
        else:
            self.op_mark = 'X'

    def check_move(self, sign):
        y = 0
        x = 0
        diagonal_cells = [self.my_map[i][i] for i in range(3)]
        diagonal_cells1 = [self.my_map[i][2 - i] for i in range(3)]
        vertical_cells = [[row[i] for row in self.my_map] for i in range(3)]

        # checking the horizontal potential win or lose
        for row in self.my_map:
            y += 1
            if row.count(sign) == 2 and row.count(' ') == 1:
                x = row.index(' ')
                self.y, self.x = y, x + 1
                return 1
        # checking the vertical potential win or lose
        for row in vertical_cells:
            x += 1
            if row.count(sign) == 2 and row.count(' ') == 1:
                y = row.index(' ')
                self.y, self.x = y + 1, x
                return 1
        # checking the diagonal potential win or lose
        if diagonal_cells.count(sign) == 2 and diagonal_cells.count(' ') == 1:
            y = diagonal_cells.index(' ')
            self.y, self.x = y + 1, y + 1
            return 1
        if diagonal_cells1.count(sign) == 2 and diagonal_cells1.count(' ') == 1:
            y = diagonal_cells1.index(' ')
            self.y, self.x = y + 1, 3 - y
            return 1
        return 0

    def ai_move(self):
        print('Making move level "medium"')
        self.opposite_mark()
        if self.check_move(self.mark):
            return
        elif self.check_move(self.op_mark):
            return
        else:
            while True:
                y = random.randint(1, 3)
                x = random.randint(1, 3)
                if self.my_map[y - 1][x - 1] == ' ':
                    self.y, self.x = y, x
                    return

class HardLevel(TicToe):

    # using the minimax algorithm

    # predicting the scenario of every move pc can make
    def max_score(self):
        max_v = -2

        y = None
        x = None

        if self.who_win(self.mark):
            return 1
        elif self.who_win(self.op_mark):
            return -1
        elif self.if_draw():
            return 0

        for i in range(3):
            for j in range(3):
                if self.my_map[i][j] == ' ':
                    self.my_map[i][j] = self.mark
                    m = self.min_score()
                    if m > max_v:
                        max_v = m
                        y = i + 1
                        x = j + 1
                    self.my_map[i][j] = ' '
        self.y, self.x = y, x
        return max_v

    # predicting the scenario of every move opponent can make
    def min_score(self):
        min_v = 2

        y = None
        x = None
        if self.who_win(self.mark):
            return 1
        elif self.who_win(self.op_mark):
            return -1
        elif self.if_draw():
            return 0

        for i in range(3):
            for j in range(3):
                if self.my_map[i][j] == ' ':
                    self.my_map[i][j] = self.op_mark
                    m = self.max_score()
                    if m < min_v:
                        min_v = m
                    self.my_map[i][j] = ' '
        return min_v

    def ai_move(self):
        self.opposite_mark()
        print('Making move level "hard"')
        self.max_score()

class MenuBar:

    def menu_bar(self):
        cmd = []
        while True:
            try:
                cmd = input("Input command: > ").split()
            except IndexError:
                print("Bad parameters!")
            else:
                if cmd[0] == "exit":
                    exit()
                elif cmd[0] == "start" and len(cmd) != 3:
                    print("Bad parameters!")
                    continue
                elif cmd[0] == 'start' and 'medium' in cmd:
                    MediumLevel(cmd[1], cmd[2]).start_game()
                elif cmd[0] == 'start' and 'hard' in cmd:
                    HardLevel(cmd[1], cmd[2]).start_game()
                else:
                    TicToe(cmd[1], cmd[2]).start_game()

if __name__ == '__main__':
    play = MenuBar()
    play.menu_bar()


from gevent import sleep
from collections import deque
from mrkt.framework.role.task import Task
from mrkt.framework.role import Cluster
from mrkt.common.consts import *

class Pool(Cluster):
    def __init__(self, *args, **kwargs):
        super(Pool, self).__init__(*args, **kwargs)
        self.task_queue = deque()

    def schedule(self):
        while True:
            for worker in self.workers:
                if self.need_sync(worker):
                    self.sync_worker(worker)
                else:
                    while worker.utilization() < 1:
                        if self.task_queue:
                            task = self.task_queue.popleft()
                            self.processing_tasks.append(task)
                            task.assign_to(worker)
                        else:
                            break
            sleep(CLUSTER_SCHEDULE_INTERVAL)

    def submit(self, func, *args, **kwargs):
        task = Task(func, args, kwargs)
        self.task_queue.append(task)
        return task

    def map(self, func, *iterables):
        tasks = [self.submit(func, *args) for args in zip(*iterables)]
        for task in tasks:
            task.join()
            yield task.ret


import pandas as pd
from typing import Dict, Any, Optional
from datetime import timedelta

class MotuPayloadGenerator:

    def __init__(self, data: pd.DataFrame, payload: Dict[str, Any], output_filename: str,
                 days_offset: Optional[int] = 1):
        self.data = data
        self.payload = payload
        self.output_filename = output_filename
        self.area_details = []
        self.days_offset = days_offset

    def _process_row(self, row):
        tokens = self.output_filename.split(".")
        product_details = {
            'latitude_min': row["lat"],
            'longitude_min': row["lon"],
            'latitude_max': row["lat"],
            'longitude_max': row["lon"],
            'depth_min': row["depth"],
            'depth_max': row["depth"],
            'out_name': f"{row['ID']}-{tokens[0]}.{tokens[-1]}",
            'date_min': row['time'].strftime('%Y-%m-%d %H:%M:%S'),
            'date_max': (row['time'] + timedelta(days=self.days_offset)).strftime('%Y-%m-%d %H:%M:%S'),
        }
        product_details.update(self.payload)
        return product_details

    def run(self):
        return [self._process_row(row) for _, row in self.data.iterrows()]


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations

class Migration(migrations.Migration):

    dependencies = [
        ('jtx_video', '0004_auto_20150805_2247'),
    ]

    operations = [
        migrations.CreateModel(
            name='BaseFile',
            fields=[
                ('id', models.AutoField(verbose_name='ID', auto_created=True, serialize=False, primary_key=True)),
                ('filename', models.CharField(max_length=254)),
                ('extension', models.CharField(blank=True, max_length=10)),
            ],
        ),
        migrations.CreateModel(
            name='Folder',
            fields=[
                ('basefile_ptr', models.OneToOneField(primary_key=True, parent_link=True, serialize=False, auto_created=True, to='jtx_video.BaseFile')),
            ],
            bases=('jtx_video.basefile',),
        ),
        migrations.CreateModel(
            name='SubtitleFile',
            fields=[
                ('basefile_ptr', models.OneToOneField(primary_key=True, parent_link=True, serialize=False, auto_created=True, to='jtx_video.BaseFile')),
                ('video', models.OneToOneField(blank=True, to='jtx_video.Video', related_name='subtitles')),
            ],
            bases=('jtx_video.basefile',),
        ),
        migrations.CreateModel(
            name='VideoFile',
            fields=[
                ('basefile_ptr', models.OneToOneField(primary_key=True, parent_link=True, serialize=False, auto_created=True, to='jtx_video.BaseFile')),
                ('bitrate', models.FloatField(blank=True)),
                ('width', models.IntegerField(blank=True)),
                ('height', models.IntegerField(blank=True)),
                ('video', models.ForeignKey(blank=True, to='jtx_video.Video', related_name='files')),
            ],
            bases=('jtx_video.basefile',),
        ),
        migrations.AddField(
            model_name='basefile',
            name='parent',
            field=models.ForeignKey(blank=True, to='jtx_video.BaseFile', null=True),
        ),
    ]


def remove_floating_ip(self, floating_ip):
        """Register a floating ip with Unicorn

        :param floating_ip: The quark.db.models.IPAddress to remove
        :return: None
        """
        url = "%s/%s" % (CONF.QUARK.floating_ip_base_url,
                         floating_ip.address_readable)
        timeout = CONF.QUARK.unicorn_api_timeout_seconds

        try:
            LOG.info("Calling unicorn to remove floating ip: %s" % url)
            r = requests.delete(url, timeout=timeout)
        except Exception as e:
            LOG.error("Unhandled Exception caught when trying to un-register "
                      "floating ip %s with the unicorn API.  Error: %s"
                      % (floating_ip.id, e.message))
            raise ex.RemoveFloatingIpFailure(id=floating_ip.id)

        if r.status_code == 404:
            LOG.warn("The floating IP %s does not exist in the unicorn system."
                     % floating_ip.address_readable)
        elif r.status_code != 204:
            msg = "Unexpected status from unicorn API: Status Code %s, " \
                  "Message: %s" % (r.status_code, r.json())
            LOG.error("remove_floating_ip: %s" % msg)
            raise ex.RemoveFloatingIpFailure(id=floating_ip.id)


from allennlp.data import Vocabulary

from mylib.legal_reader import *
from mylib.vectorf1 import *

# there are two files.
# open each file

def score(gold, pred, debug=False):

    ldr = LegalDatasetReader()

    gold_insts = []
    all_insts = []
    for gi in ldr._read(gold):
        gold_insts.append(gi)
        all_insts.append(gi)

    pred_insts = []
    for pi in ldr._read(pred):
        pred_insts.append(pi)
        all_insts.append(pi)

    vocab = Vocabulary.from_instances(all_insts)

    for gi,pi in zip(gold_insts, pred_insts):
        gi["label"].index(vocab)
        pi["label"].index(vocab)

    f1metric = VectorF1(unmatched_index=vocab.get_token_index("unmatched", "labels"))

    for gi,pi in zip(gold_insts, pred_insts):
        gtens = gi["label"].as_tensor(None)
        ptens = pi["label"].as_tensor(None)

        if debug and (not set(gi["label"].labels) == set(pi["label"].labels)):
            print(" ".join(map(str, gi["graf"].tokens)))
            print(gi["label"].labels, pi["label"].labels)

        # predicted first, then gold!!!
        f1metric(ptens, gtens)

    for n,m in zip(["P", "R", "F1"], f1metric.get_metric()):
        print("{}: {}".format(n,m))

if __name__ == "__main__":
    import argparse

    parser = argparse.ArgumentParser(description='Process some rules.')
    parser.add_argument('--gold', '-g', help='Gold')
    parser.add_argument('--pred', '-p', help='Predictions')
    parser.add_argument('--debug', action="store_true", default=False)

    args = parser.parse_args()
    score(args.gold, args.pred, args.debug)


import os
import re
import csv

mapa = 'podatki'
datoteka_html = 'igralci.html'
datoteka_csv = 'sahisti.csv'

def pretvori_datoteko_v_niz(directory, filename):
    path = os.path.join(directory, filename)
    with open(path, encoding='utf-8') as dat:
        return dat.read()

def razbij_na_igralce(vsebina_strani):
    pattern = re.compile(r'
.*?
',
                         re.DOTALL)
    igralci = re.findall(pattern, vsebina_strani)
    return igralci

def slovar_od_igralca(igralec):
    pattern = re.compile(r'.+?(?P<ime>.*?)'
                         r'.*?"title">(?P<naslov>.*?)	'
                         r'.*?alt=".{3}">(?P<drzava>.{3}).*?	'
                         r'.*?"Rtg">(?P<standard_rating>.*?)	'
                         r'.*?"Rtg">(?P<rapid_rating>.*?)	'
                         r'.*?"Rtg">(?P<blitz_rating>.*?)	'
                         r'.*?B-Year">(?P<leto_rojstva>\d*?)	',
                         re.DOTALL)
    podatki = re.search(pattern, igralec)
    igralec_dict = podatki.groupdict()
    return igralec_dict

def igralci_iz_datoteke(directory, filename):
    stran = pretvori_datoteko_v_niz(directory, filename)
    igralci = razbij_na_igralce(stran)
    slovar_igralcev = [slovar_od_igralca(igralec) for igralec in igralci]
    return slovar_igralcev

def write_csv(fieldnames, rows, directory, filename):
    os.makedirs(directory, exist_ok=True)
    path = os.path.join(directory, filename)
    with open(path, 'w', encoding='utf-8') as csv_file:
        writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
        writer.writeheader()
        for row in rows:
            writer.writerow(row)
    return None

def zapisi_igralce_v_csv(igralci, directory, filename):
    write_csv(igralci[0].keys(), igralci, directory, filename)

def main(redownload=True, reparse=True):
    igralci = igralci_iz_datoteke(mapa, datoteka_html)
    zapisi_igralce_v_csv(igralci, mapa, datoteka_csv)

main()


import random

print("""A Lv.100 Pidgeot (Normal/Flying, Sp. Atk: 220)
attacks a Lv. 110  Marowak (Ground, Sp. Def: 250) with Brave Bird,
a Flying-type move with a Power of 95 and gains a same-type attack bonus.
It hits the target and deals a very effective damage. The weather on the field is normal.
Given the following conditions, determine how much damage Pidgeot's attack will deal. \n""")

#damage
Level = 100
Power = 95
A = 220
D = 250

#modifier
Target = 1
Weather = 1.5
Badge = 1
Critical = random.randint(1,2)
Random_number = round(random.uniform(0.85 , 1.00),2)
STAB = 1
Type = 2
other = 1

Modifier = round(Target*Weather*Badge*Critical*Random_number*STAB*Type*other)
Damage = round((((((2*Level)/5)+2)*Power*A/D)/50)+2)*Modifier

print("Target: ",Target)
print("Weather: ", Weather)
print("Badge: ",Badge)
print("Critical: ",Critical)
print("Random: ",Random_number)
print("STAB: ",STAB)
print("Type: ", Type)
print("Other: ",other)
print("\nModifiers: ", Modifier)
print("\nPidgeot deals ",Damage,"to Marowak ")

Recoil_Dam = round(Damage*0.333)
Recoil = random.randint(1,500)
if Recoil >= Recoil_Dam:
	print("As well as Marowak is recoiling.")
else:
	print("However, Marowak is not recoiling..")


#!/usr/bin/env python
# coding: utf-8

# # Model

# In[2]:

#%load_ext autotime

# ## Directory Settings

# In[3]:

# ====================================================
# Directory settings
# ====================================================
import os

OUTPUT_DIR = './'
if not os.path.exists(OUTPUT_DIR):
    os.makedirs(OUTPUT_DIR)

PREPROCESS_DIR = 'input/inchi-preprocess'
if not os.path.exists(PREPROCESS_DIR):
    os.makedirs(PREPROCESS_DIR)

#if os.path.isfile('train.log'):
#    os.remove('train.log')

# ## Data Loading

# In[4]:

import numpy as np
import pandas as pd
import dill
import torch

train = pd.read_json(f'{PREPROCESS_DIR}/train.json')

def get_train_file_path(image_id):
    return "input/train/{}/{}/{}/{}.png".format(
        image_id[0], image_id[1], image_id[2], image_id
    )

train['file_path'] = train['image_id'].apply(get_train_file_path)

print(f'train.shape: {train.shape}')
print(train.head())

# In[5]:

class Tokenizer(object):

    def __init__(self):
        self.stoi = {}
        self.itos = {}

    def __len__(self):
        return len(self.stoi)

    def fit_on_texts(self, texts):
        vocab = set()
        for text in texts:
            vocab.update(text.split(' '))
        vocab = sorted(vocab)
        vocab.append('<sos>')
        vocab.append('<eos>')
        vocab.append('<pad>')
        for i, s in enumerate(vocab):
            self.stoi[s] = i
        self.itos = {item[1]: item[0] for item in self.stoi.items()}

    def text_to_sequence(self, text):
        sequence = []
        sequence.append(self.stoi['<sos>'])
        for s in text.split(' '):
            sequence.append(self.stoi[s])
        sequence.append(self.stoi['<eos>'])
        return sequence

    def texts_to_sequences(self, texts):
        sequences = []
        for text in texts:
            sequence = self.text_to_sequence(text)
            sequences.append(sequence)
        return sequences

    def sequence_to_text(self, sequence):
        return ''.join(list(map(lambda i: self.itos[i], sequence)))

    def sequences_to_texts(self, sequences):
        texts = []
        for sequence in sequences:
            text = self.sequence_to_text(sequence)
            texts.append(text)
        return texts

    def predict_caption(self, sequence):
        caption = ''
        for i in sequence:
            if i == self.stoi['<eos>'] or i == self.stoi['<pad>']:
                break
            caption += self.itos[i]
        return caption

    def predict_captions(self, sequences):
        captions = []
        for sequence in sequences:
            caption = self.predict_caption(sequence)
            captions.append(caption)
        return captions

tokenizer = torch.load(f'{PREPROCESS_DIR}/tokenizer.pth', pickle_module=dill)
print(f"tokenizer.stoi: {tokenizer.stoi}")

# ## CFG

# In[6]:

# ====================================================
# CFG
# ====================================================
class CFG:
    debug=False
    max_len=275
    print_freq=1000
    num_workers=16 if os.cpu_count() >= 16 else os.cpu_count()
    model_name='resnet34'
    size=224
    scheduler='CosineAnnealingLR' # ['ReduceLROnPlateau', 'CosineAnnealingLR', 'CosineAnnealingWarmRestarts']
    epochs=8 # not to exceed 9h
    #factor=0.2 # ReduceLROnPlateau
    #patience=4 # ReduceLROnPlateau
    #eps=1e-6 # ReduceLROnPlateau
    T_max=4 # CosineAnnealingLR
    #T_0=4 # CosineAnnealingWarmRestarts
    encoder_lr=1e-4
    decoder_lr=4e-4
    min_lr=1e-6
    batch_size=64
    weight_decay=1e-6
    gradient_accumulation_steps=1
    max_grad_norm=5
    attention_dim=256
    embed_dim=256
    decoder_dim=512
    dropout=0.5
    seed=42
    n_fold=2
    trn_fold=[0] # [0, 1, 2, 3, 4]
    train=True

print(f'Using {CFG.num_workers} workers.')

# In[7]:

if CFG.debug:
    CFG.epochs = 1
    train = train[:10000]

# ## Library

# In[8]:

# ====================================================
# Library
# ====================================================
import sys
sys.path.append('input/pytorch-image-models/pytorch-image-models-master')

import os
import gc
import re
import math
import time
import random
import shutil
import pickle
import argparse
from pathlib import Path
from contextlib import contextmanager
from collections import defaultdict, Counter

import scipy as sp
import numpy as np
import pandas as pd
from tqdm.auto import tqdm

import Levenshtein
from sklearn import preprocessing
from sklearn.model_selection import StratifiedKFold, GroupKFold, KFold

from functools import partial

import cv2
from PIL import Image

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.optim import Adam, SGD
import torchvision.models as models
from torch.nn.parameter import Parameter
from torch.utils.data import DataLoader, Dataset
from torch.nn.utils.rnn import pad_sequence, pack_padded_sequence
from torch.optim.lr_scheduler import CosineAnnealingWarmRestarts, CosineAnnealingLR, ReduceLROnPlateau
import torch.multiprocessing as mp
import torch.distributed as dist
from torch.nn.parallel import DistributedDataParallel as DDP
from adabound import AdaBound

from albumentations import (
    Compose, OneOf, Normalize, Resize, RandomResizedCrop, RandomCrop, HorizontalFlip, VerticalFlip,
    RandomBrightness, RandomContrast, RandomBrightnessContrast, Rotate, ShiftScaleRotate, Cutout,
    IAAAdditiveGaussianNoise, Transpose, Blur
    )
from albumentations.pytorch import ToTensorV2
from albumentations import ImageOnlyTransform

import timm

import warnings
warnings.filterwarnings('ignore')

cuda_available = torch.cuda.is_available()

device = torch.device('cuda' if cuda_available else 'cpu')

if (cuda_available):
    torch.cuda.init()
    print(f'CUDA available: {cuda_available}')
    print(f'Number of available devices: {torch.cuda.device_count()}')
    print(f'Using device: {torch.cuda.get_device_name(torch.cuda.current_device())}')

# ## Utils

# In[9]:

# ====================================================
# Utils
# ====================================================

def get_score(y_true, y_pred):
    scores = []
    for true, pred in zip(y_true, y_pred):
        score = Levenshtein.distance(true, pred)
        scores.append(score)
    avg_score = np.mean(scores)
    return avg_score, scores

def init_logger(log_file=OUTPUT_DIR+'train.log'):
    from logging import getLogger, INFO, FileHandler,  Formatter,  StreamHandler
    logger = getLogger(__name__)
    logger.setLevel(INFO)
    handler1 = StreamHandler()
    handler1.setFormatter(Formatter("%(message)s"))
    #handler2 = FileHandler(filename=log_file)
    #handler2.setFormatter(Formatter("%(message)s"))
    logger.addHandler(handler1)
    #logger.addHandler(handler2)
    return logger

LOGGER = init_logger()

def seed_torch(seed=42):
    random.seed(seed)
    os.environ['PYTHONHASHSEED'] = str(seed)
    np.random.seed(seed)
    torch.manual_seed(seed)
    torch.cuda.manual_seed(seed)
    torch.backends.cudnn.deterministic = True

seed_torch(seed=CFG.seed)

# ## CV Split

# In[10]:

folds = train.copy()
Fold = StratifiedKFold(n_splits=CFG.n_fold, shuffle=True, random_state=CFG.seed)
for n, (train_index, val_index) in enumerate(Fold.split(folds, folds['InChI_length'])):
    folds.loc[val_index, 'fold'] = int(n)
folds['fold'] = folds['fold'].astype(int)
print(folds.groupby(['fold']).size())

# ## Dataset

# In[11]:

# ====================================================
# Dataset
# ====================================================
class TrainDataset(Dataset):
    def __init__(self, df, tokenizer, transform=None):
        super().__init__()
        self.df = df
        self.tokenizer = tokenizer
        self.file_paths = df['file_path'].values
        self.labels = df['InChI_text'].values
        self.transform = transform

    def __len__(self):
        return len(self.df)

    def __getitem__(self, idx):
        file_path = self.file_paths[idx]
        image = cv2.imread(file_path)
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB).astype(np.float32)
        if self.transform:
            augmented = self.transform(image=image)
            image = augmented['image']
        label = self.labels[idx]
        label = self.tokenizer.text_to_sequence(label)
        label_length = len(label)
        label_length = torch.LongTensor([label_length])
        return image, torch.LongTensor(label), label_length

class TestDataset(Dataset):
    def __init__(self, df, transform=None):
        super().__init__()
        self.df = df
        self.file_paths = df['file_path'].values
        self.transform = transform

    def __len__(self):
        return len(self.df)

    def __getitem__(self, idx):
        file_path = self.file_paths[idx]
        image = cv2.imread(file_path)
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB).astype(np.float32)
        if self.transform:
            augmented = self.transform(image=image)
            image = augmented['image']
        return image

# In[12]:

def bms_collate(batch):
    imgs, labels, label_lengths = [], [], []
    for data_point in batch:
        imgs.append(data_point[0])
        labels.append(data_point[1])
        label_lengths.append(data_point[2])
    labels = pad_sequence(labels, batch_first=True, padding_value=tokenizer.stoi["<pad>"])
    return torch.stack(imgs), labels, torch.stack(label_lengths).reshape(-1, 1)

# ## Transforms

# In[13]:

def get_transforms(*, data):

    if data == 'train':
        return Compose([
            Resize(CFG.size, CFG.size),
            Normalize(
                mean=[0.485, 0.456, 0.406],
                std=[0.229, 0.224, 0.225],
            ),
            ToTensorV2(),
        ])

    elif data == 'valid':
        return Compose([
            Resize(CFG.size, CFG.size),
            Normalize(
                mean=[0.485, 0.456, 0.406],
                std=[0.229, 0.224, 0.225],
            ),
            ToTensorV2(),
        ])

# In[14]:

from matplotlib import pyplot as plt

train_dataset = TrainDataset(train, tokenizer, transform=get_transforms(data='train'))

for i in range(1):
    image, label, label_length = train_dataset[i]
    text = tokenizer.sequence_to_text(label.numpy())
    #plt.imshow(image.transpose(0, 1).transpose(1, 2))
    plt.title(f'label: {label}  text: {text}  label_length: {label_length}')
    plt.show()

# ## MODEL

# In[15]:

class Encoder(nn.Module):
    def __init__(self, model_name='resnet18', pretrained=False):
        super().__init__()
        self.cnn = timm.create_model(model_name, pretrained=pretrained)
        self.n_features = self.cnn.fc.in_features
        self.cnn.global_pool = nn.Identity()
        self.cnn.fc = nn.Identity()

    def forward(self, x):
        bs = x.size(0)
        features = self.cnn(x)
        features = features.permute(0, 2, 3, 1)
        return features

# In[16]:

class Attention(nn.Module):
    """
    Attention network for calculate attention value
    """
    def __init__(self, encoder_dim, decoder_dim, attention_dim):
        """
        :param encoder_dim: input size of encoder network
        :param decoder_dim: input size of decoder network
        :param attention_dim: input size of attention network
        """
        super(Attention, self).__init__()
        self.encoder_att = nn.Linear(encoder_dim, attention_dim)  # linear layer to transform encoded image
        self.decoder_att = nn.Linear(decoder_dim, attention_dim)  # linear layer to transform decoder's output
        self.full_att = nn.Linear(attention_dim, 1)  # linear layer to calculate values to be softmax-ed
        self.relu = nn.ReLU()
        self.softmax = nn.Softmax(dim=1)  # softmax layer to calculate weights

    def forward(self, encoder_out, decoder_hidden):
        att1 = self.encoder_att(encoder_out)  # (batch_size, num_pixels, attention_dim)
        att2 = self.decoder_att(decoder_hidden)  # (batch_size, attention_dim)
        att = self.full_att(self.relu(att1 + att2.unsqueeze(1))).squeeze(2)  # (batch_size, num_pixels)
        alpha = self.softmax(att)  # (batch_size, num_pixels)
        attention_weighted_encoding = (encoder_out * alpha.unsqueeze(2)).sum(dim=1)  # (batch_size, encoder_dim)
        return attention_weighted_encoding, alpha

class DecoderWithAttention(nn.Module):
    """
    Decoder network with attention network used for training
    """

    def __init__(self, attention_dim, embed_dim, decoder_dim, vocab_size, device, encoder_dim=512, dropout=0.5):
        """
        :param attention_dim: input size of attention network
        :param embed_dim: input size of embedding network
        :param decoder_dim: input size of decoder network
        :param vocab_size: total number of characters used in training
        :param encoder_dim: input size of encoder network
        :param dropout: dropout rate
        """
        super(DecoderWithAttention, self).__init__()
        self.encoder_dim = encoder_dim
        self.attention_dim = attention_dim
        self.embed_dim = embed_dim
        self.decoder_dim = decoder_dim
        self.vocab_size = vocab_size
        self.dropout = dropout
        self.device = device
        self.attention = Attention(encoder_dim, decoder_dim, attention_dim)  # attention network
        self.embedding = nn.Embedding(vocab_size, embed_dim)  # embedding layer
        self.dropout = nn.Dropout(p=self.dropout)
        self.decode_step = nn.LSTMCell(embed_dim + encoder_dim, decoder_dim, bias=True)  # decoding LSTMCell
        self.init_h = nn.Linear(encoder_dim, decoder_dim)  # linear layer to find initial hidden state of LSTMCell
        self.init_c = nn.Linear(encoder_dim, decoder_dim)  # linear layer to find initial cell state of LSTMCell
        self.f_beta = nn.Linear(decoder_dim, encoder_dim)  # linear layer to create a sigmoid-activated gate
        self.sigmoid = nn.Sigmoid()
        self.fc = nn.Linear(decoder_dim, vocab_size)  # linear layer to find scores over vocabulary
        self.init_weights()  # initialize some layers with the uniform distribution

    def init_weights(self):
        self.embedding.weight.data.uniform_(-0.1, 0.1)
        self.fc.bias.data.fill_(0)
        self.fc.weight.data.uniform_(-0.1, 0.1)

    def load_pretrained_embeddings(self, embeddings):
        self.embedding.weight = nn.Parameter(embeddings)

    def fine_tune_embeddings(self, fine_tune=True):
        for p in self.embedding.parameters():
            p.requires_grad = fine_tune

    def init_hidden_state(self, encoder_out):
        mean_encoder_out = encoder_out.mean(dim=1)
        h = self.init_h(mean_encoder_out)  # (batch_size, decoder_dim)
        c = self.init_c(mean_encoder_out)
        return h, c

    def forward(self, encoder_out, encoded_captions, caption_lengths):
        """
        :param encoder_out: output of encoder network
        :param encoded_captions: transformed sequence from character to integer
        :param caption_lengths: length of transformed sequence
        """
        batch_size = encoder_out.size(0)
        encoder_dim = encoder_out.size(-1)
        vocab_size = self.vocab_size
        encoder_out = encoder_out.view(batch_size, -1, encoder_dim)  # (batch_size, num_pixels, encoder_dim)
        num_pixels = encoder_out.size(1)
        caption_lengths, sort_ind = caption_lengths.squeeze(1).sort(dim=0, descending=True)
        encoder_out = encoder_out[sort_ind]
        encoded_captions = encoded_captions[sort_ind]
        # embedding transformed sequence for vector
        embeddings = self.embedding(encoded_captions)  # (batch_size, max_caption_length, embed_dim)
        # initialize hidden state and cell state of LSTM cell
        h, c = self.init_hidden_state(encoder_out)  # (batch_size, decoder_dim)
        # set decode length by caption length - 1 because of omitting start token
        decode_lengths = (caption_lengths - 1).tolist()
        predictions = torch.zeros(batch_size, max(decode_lengths), vocab_size).to(self.device)
        alphas = torch.zeros(batch_size, max(decode_lengths), num_pixels).to(self.device)
        # predict sequence
        for t in range(max(decode_lengths)):
            batch_size_t = sum([l > t for l in decode_lengths])
            attention_weighted_encoding, alpha = self.attention(encoder_out[:batch_size_t], h[:batch_size_t])
            gate = self.sigmoid(self.f_beta(h[:batch_size_t]))  # gating scalar, (batch_size_t, encoder_dim)
            attention_weighted_encoding = gate * attention_weighted_encoding
            h, c = self.decode_step(
                torch.cat([embeddings[:batch_size_t, t, :], attention_weighted_encoding], dim=1),
                (h[:batch_size_t], c[:batch_size_t]))  # (batch_size_t, decoder_dim)
            preds = self.fc(self.dropout(h))  # (batch_size_t, vocab_size)
            predictions[:batch_size_t, t, :] = preds
            alphas[:batch_size_t, t, :] = alpha
        return predictions, encoded_captions, decode_lengths, alphas, sort_ind

    def predict(self, encoder_out, decode_lengths, tokenizer):
        batch_size = encoder_out.size(0)
        encoder_dim = encoder_out.size(-1)
        vocab_size = self.vocab_size
        encoder_out = encoder_out.view(batch_size, -1, encoder_dim)  # (batch_size, num_pixels, encoder_dim)
        num_pixels = encoder_out.size(1)
        # embed start tocken for LSTM input
        start_tockens = torch.ones(batch_size, dtype=torch.long).to(self.device) * tokenizer.stoi["<sos>"]
        embeddings = self.embedding(start_tockens)
        # initialize hidden state and cell state of LSTM cell
        h, c = self.init_hidden_state(encoder_out)  # (batch_size, decoder_dim)
        predictions = torch.zeros(batch_size, decode_lengths, vocab_size).to(self.device)
        # predict sequence
        for t in range(decode_lengths):
            attention_weighted_encoding, alpha = self.attention(encoder_out, h)
            gate = self.sigmoid(self.f_beta(h))  # gating scalar, (batch_size_t, encoder_dim)
            attention_weighted_encoding = gate * attention_weighted_encoding
            h, c = self.decode_step(
                torch.cat([embeddings, attention_weighted_encoding], dim=1),
                (h, c))  # (batch_size_t, decoder_dim)
            preds = self.fc(self.dropout(h))  # (batch_size_t, vocab_size)
            predictions[:, t, :] = preds
            if np.argmax(preds.detach().cpu().numpy()) == tokenizer.stoi["<eos>"]:
                break
            embeddings = self.embedding(torch.argmax(preds, -1))
        return predictions

# ## Helper functions

# In[17]:

# ====================================================
# Helper functions
# ====================================================
class AverageMeter(object):
    """Computes and stores the average and current value"""
    def __init__(self):
        self.reset()

    def reset(self):
        self.val = 0
        self.avg = 0
        self.sum = 0
        self.count = 0

    def update(self, val, n=1):
        self.val = val
        self.sum += val * n
        self.count += n
        self.avg = self.sum / self.count

def asMinutes(s):
    m = math.floor(s / 60)
    s -= m * 60
    return '%dm %ds' % (m, s)

def timeSince(since, percent):
    now = time.time()
    s = now - since
    es = s / (percent)
    rs = es - s
    return '%s (remain %s)' % (asMinutes(s), asMinutes(rs))

def train_fn(train_loader, encoder, decoder, criterion,
             encoder_optimizer, decoder_optimizer, epoch,
             encoder_scheduler, decoder_scheduler, device):
    batch_time = AverageMeter()
    data_time = AverageMeter()
    losses = AverageMeter()
    # switch to train mode
    LOGGER.info('Switching to train mode ..')
    encoder.train()
    decoder.train()
    start = end = time.time()
    global_step = 0
    #LOGGER.info('Enumerating train loader ..')
    for step, (images, labels, label_lengths) in enumerate(tqdm(train_loader)):
        LOGGER.info(f'Step: {step}')
        #LOGGER.info('Training - Measuring data loading time ..')
        # measure data loading time
        data_time.update(time.time() - end)
        #LOGGER.info('Training - loading data ..')
        images = images.to(device)
        labels = labels.to(device)
        label_lengths = label_lengths.to(device)
        batch_size = images.size(0)
        #LOGGER.info('Training - encoding ..')
        features = encoder(images)
        #LOGGER.info('Training - decoding ..')
        predictions, caps_sorted, decode_lengths, alphas, sort_ind = decoder(features, labels, label_lengths)
        targets = caps_sorted[:, 1:]
        predictions = pack_padded_sequence(predictions, decode_lengths, batch_first=True).data
        targets = pack_padded_sequence(targets, decode_lengths, batch_first=True).data
        loss = criterion(predictions, targets)
        # record loss
        #LOGGER.info('Training - recording ..')
        losses.update(loss.item(), batch_size)
        if CFG.gradient_accumulation_steps > 1:
            loss = loss / CFG.gradient_accumulation_steps
        loss.backward()
        encoder_grad_norm = torch.nn.utils.clip_grad_norm_(encoder.parameters(), CFG.max_grad_norm)
        decoder_grad_norm = torch.nn.utils.clip_grad_norm_(decoder.parameters(), CFG.max_grad_norm)
        if (step + 1) % CFG.gradient_accumulation_steps == 0:
            encoder_optimizer.step()
            decoder_optimizer.step()
            encoder_optimizer.zero_grad()
            decoder_optimizer.zero_grad()
            global_step += 1
        # measure elapsed time
        batch_time.update(time.time() - end)
        end = time.time()
        if step % CFG.print_freq == 0 or step == (len(train_loader)-1):
            print('Epoch: [{0}][{1}/{2}] '
                  'Data {data_time.val:.3f} ({data_time.avg:.3f}) '
                  'Elapsed {remain:s} '
                  'Loss: {loss.val:.4f}({loss.avg:.4f}) '
                  'Encoder Grad: {encoder_grad_norm:.4f}  '
                  'Decoder Grad: {decoder_grad_norm:.4f}  '
                  #'Encoder LR: {encoder_lr:.6f}  '
                  #'Decoder LR: {decoder_lr:.6f}  '
                  .format(
                   epoch+1, step, len(train_loader), batch_time=batch_time,
                   data_time=data_time, loss=losses,
                   remain=timeSince(start, float(step+1)/len(train_loader)),
                   encoder_grad_norm=encoder_grad_norm,
                   decoder_grad_norm=decoder_grad_norm,
                   #encoder_lr=encoder_scheduler.get_lr()[0],
                   #decoder_lr=decoder_scheduler.get_lr()[0],
                   ))
    return losses.avg

def valid_fn(valid_loader, encoder, decoder, tokenizer, criterion, device):
    batch_time = AverageMeter()
    data_time = AverageMeter()
    # switch to evaluation mode
    LOGGER.info('Switching to evaluation mode ..')
    encoder.eval()
    decoder.eval()
    text_preds = []
    start = end = time.time()
    for step, (images) in enumerate(tqdm(valid_loader)):
        LOGGER.info(f'Step: {step}')
        # measure data loading time
        #LOGGER.info('Evaluation - loading data ..')
        data_time.update(time.time() - end)
        images = images.to(device)
        batch_size = images.size(0)
        with torch.no_grad():
            #LOGGER.info('Evaluation - encoding ..')
            features = encoder(images)
            #LOGGER.info('Evaluation - decoding ..')
            predictions = decoder.predict(features, CFG.max_len, tokenizer)
        predicted_sequence = torch.argmax(predictions.detach().cpu(), -1).numpy()
        _text_preds = tokenizer.predict_captions(predicted_sequence)
        text_preds.append(_text_preds)
        # measure elapsed time
        batch_time.update(time.time() - end)
        end = time.time()
        if step % CFG.print_freq == 0 or step == (len(valid_loader)-1):
            print('EVAL: [{0}/{1}] '
                  'Data {data_time.val:.3f} ({data_time.avg:.3f}) '
                  'Elapsed {remain:s} '
                  .format(
                   step, len(valid_loader), batch_time=batch_time,
                   data_time=data_time,
                   remain=timeSince(start, float(step+1)/len(valid_loader)),
                   ))
    text_preds = np.concatenate(text_preds)
    return text_preds

# ## Train loop

# In[18]:

# ====================================================
# Train loop
# ====================================================
def train_loop(gpu, folds, fold, args):

    LOGGER.info(f"========== fold: {fold} training ==========")

    LOGGER.info('Initializing process group ..')

    rank = args.nr * args.gpus + gpu
    dist.init_process_group(
        backend='nccl',
        init_method='env://',
        world_size=args.world_size,
        rank=rank
    )

    # ====================================================
    # loader
    # ====================================================

    LOGGER.info('Loading ..')

    trn_idx = folds[folds['fold'] != fold].index
    val_idx = folds[folds['fold'] == fold].index

    train_folds = folds.loc[trn_idx].reset_index(drop=True)
    valid_folds = folds.loc[val_idx].reset_index(drop=True)
    valid_labels = valid_folds['InChI'].values

    train_dataset = TrainDataset(train_folds, tokenizer, transform=get_transforms(data='train'))
    valid_dataset = TestDataset(valid_folds, transform=get_transforms(data='valid'))

    train_sampler = torch.utils.data.distributed.DistributedSampler(
        train_dataset,
        num_replicas=args.world_size,
        rank=rank
    )

    train_loader = DataLoader(train_dataset,
                              batch_size=CFG.batch_size,
                              #shuffle=True,
                              num_workers=0,
                              pin_memory=True,
                              drop_last=True,
                              collate_fn=bms_collate,
                              sampler=train_sampler)
    valid_loader = DataLoader(valid_dataset,
                              batch_size=CFG.batch_size,
                              shuffle=False,
                              num_workers=0,
                              pin_memory=True,
                              drop_last=False)

    # ====================================================
    # scheduler
    # ====================================================
    def get_scheduler(optimizer):
        if CFG.scheduler=='ReduceLROnPlateau':
            scheduler = ReduceLROnPlateau(optimizer, mode='min', factor=CFG.factor, patience=CFG.patience, verbose=True, eps=CFG.eps)
        elif CFG.scheduler=='CosineAnnealingLR':
            scheduler = CosineAnnealingLR(optimizer, T_max=CFG.T_max, eta_min=CFG.min_lr, last_epoch=-1)
        elif CFG.scheduler=='CosineAnnealingWarmRestarts':
            scheduler = CosineAnnealingWarmRestarts(optimizer, T_0=CFG.T_0, T_mult=1, eta_min=CFG.min_lr, last_epoch=-1)
        return scheduler

    # ====================================================
    # model & optimizer
    # ====================================================

    torch.cuda.set_device(gpu)

    LOGGER.info('Creating encoder ..')

    encoder = Encoder(CFG.model_name, pretrained=True)
    encoder.to(device)
    encoder_optimizer = Adam(encoder.parameters(), lr=CFG.encoder_lr, weight_decay=CFG.weight_decay, amsgrad=False)
    encoder_scheduler = get_scheduler(encoder_optimizer)

    encoder = DDP(encoder, device_ids=[gpu])

    LOGGER.info('Creating decoder ..')

    decoder = DecoderWithAttention(attention_dim=CFG.attention_dim,
                                   embed_dim=CFG.embed_dim,
                                   decoder_dim=CFG.decoder_dim,
                                   vocab_size=len(tokenizer),
                                   dropout=CFG.dropout,
                                   device=device)
    decoder.to(device)
    decoder_optimizer = Adam(decoder.parameters(), lr=CFG.decoder_lr, weight_decay=CFG.weight_decay, amsgrad=False)
    decoder_scheduler = get_scheduler(decoder_optimizer)

    # ====================================================
    # loop
    # ====================================================
    criterion = nn.CrossEntropyLoss(ignore_index=tokenizer.stoi["<pad>"]).cuda(gpu)

    best_score = np.inf
    best_loss = np.inf

    LOGGER.info('Starting loop ..')

    for epoch in range(CFG.epochs):
        LOGGER.info(f'Epoch: {epoch}')

        start_time = time.time()

        LOGGER.info('Starting training ..')

        # train
        avg_loss = train_fn(train_loader, encoder, decoder, criterion,
                            encoder_optimizer, decoder_optimizer, epoch,
                            encoder_scheduler, decoder_scheduler, device)

        LOGGER.info('Evaluating ..')

        # eval
        text_preds = valid_fn(valid_loader, encoder, decoder, tokenizer, criterion, device)
        text_preds = [f"InChI=1S/{text}" for text in text_preds]
        LOGGER.info(f"labels: {valid_labels[:5]}")
        LOGGER.info(f"preds: {text_preds[:5]}")

        LOGGER.info('Scoring ..')

        # scoring
        score, scores = get_score(valid_labels, text_preds)
        LOGGER.info(f'Average levenshtein distance: {score}')

        image_keys = pd.read_csv('train_labels.csv')

        LOGGER.info('Writing output csv')

        LOGGER.info(f'Num scores: {len(scores)}')
        LOGGER.info(f'Num preds: {len(text_preds)}')

        scores_computed = pd.DataFrame({
            'predicted_inchi': text_preds,
            'score': scores
        })

        LOGGER.info(f"Num image ids: {len(valid_folds['image_id'])}")
        LOGGER.info(f"Num actual inchis: {len(valid_folds['InChI'])}")

        scores_actual = pd.DataFrame({
            'image_id': valid_folds['image_id'],
            'actual_inchi': valid_folds['InChI']
        })

        scores_out = pd.concat([scores_actual, scores_computed], axis=1)

        scores_out.sort_values('score', ascending=False).to_csv('output.csv', index=False)

        if isinstance(encoder_scheduler, ReduceLROnPlateau):
            encoder_scheduler.step(score)
        elif isinstance(encoder_scheduler, CosineAnnealingLR):
            encoder_scheduler.step()
        elif isinstance(encoder_scheduler, CosineAnnealingWarmRestarts):
            encoder_scheduler.step()

        if isinstance(decoder_scheduler, ReduceLROnPlateau):
            decoder_scheduler.step(score)
        elif isinstance(decoder_scheduler, CosineAnnealingLR):
            decoder_scheduler.step()
        elif isinstance(decoder_scheduler, CosineAnnealingWarmRestarts):
            decoder_scheduler.step()

        elapsed = time.time() - start_time

        LOGGER.info(f'Epoch {epoch+1} - avg_train_loss: {avg_loss:.4f}  time: {elapsed:.0f}s')
        LOGGER.info(f'Epoch {epoch+1} - Score: {score:.4f}')

        if score < best_score:
            best_score = score
            LOGGER.info(f'Epoch {epoch+1} - Save Best Score: {best_score:.4f} Model')
            torch.save({'encoder': encoder.state_dict(),
                        'encoder_optimizer': encoder_optimizer.state_dict(),
                        'encoder_scheduler': encoder_scheduler.state_dict(),
                        'decoder': decoder.state_dict(),
                        'decoder_optimizer': decoder_optimizer.state_dict(),
                        'decoder_scheduler': decoder_scheduler.state_dict(),
                        'text_preds': text_preds,
                       },
                        OUTPUT_DIR+f'{CFG.model_name}_fold{fold}_best.pth')

# ## Main

# In[19]:

# ====================================================
# main
# ====================================================
def main():

    """
    Prepare: 1.train  2.folds
    """

    LOGGER.info(f"Using CUDA: {torch.cuda.is_available()}")
    LOGGER.info(f"Using {CFG.num_workers} workers")

    if CFG.train:
        # train
        oof_df = pd.DataFrame()
        for fold in range(CFG.n_fold):
            if fold in CFG.trn_fold:
                parser = argparse.ArgumentParser()
                parser.add_argument('-n', '--nodes', default=1, type=int, metavar='N')
                parser.add_argument('-g', '--gpus', default=1, type=int, help='number of gpus per node')
                parser.add_argument('-nr', '--nr', default=0, type=int, help='ranking within the nodes')
                parser.add_argument('--epochs', default=2, type=int, metavar='N', help='number of total epochs to run')
                args = parser.parse_args()

                args.world_size = args.gpus * args.nodes
                os.environ['MASTER_ADDR'] = '127.0.0.1'
                os.environ['MASTER_PORT'] = '8888'
                mp.spawn(train_loop, nprocs=args.gpus, args=(folds, fold, args,))

# In[20]:

if __name__ == '__main__':
    main()


# https://school.programmers.co.kr/learn/courses/30/lessons/12981
def solution(n, words):
    """
    1부터 n까지 번호가 붙은 n명의 사람이 영어 끝말잇기를 한다.
    1. 1번부터 순서대로 차례대로 단어를 말함
    2. 마지막 사람 다음 다시 1번
    3. 이전에 등장한 단어 사용x
    4. 한 글자x
    사람 수 n과 사람들이 순서대로 말한 단어 words가 매개변수로 주어질 때,
    가장 먼저 탈락하는 사람 번호와 그 사람이 자신의 몇 번째 차례에 탈락하는지
    return [번호, 차례]
    2 <= n <= 10, 2 <= len(words) <= 100
    2 <= len(단어) <= 50, 모든 단어는 알파벳 소문자
    탈락자 없으면 [0, 0] return
    """
    log = set()
    for i, word in enumerate(words):
        if word in log or (i > 0 and words[i-1][-1] != word[0]):
            return [(i%n) + 1, (i//n) + 1]
        log.add(word)
    return [0, 0]

inputdatas = [
    [3, ["tank", "kick", "know", "wheel", "land", "dream", "mother", "robot", "tank"]],
    [5, ["hello", "observe", "effect", "take", "either", "recognize", "encourage", "ensure", "establish", "hang", "gather", "refer", "reference", "estimate", "executive"]],
    [2, ["hello", "one", "even", "never", "now", "world", "draw"]]
]

"""
Summer/Winter Coding(~2018) 기출
현 시점 Lv.2, 완료한 사람 18_641명, 정답률 70%
제약과 규칙을 옮겨적을게 많았고
차례와 주기를 정확하게 계산하는 데에 시간을 좀 써서 10분을 넘겼다.
"""

for t in inputdatas:
    print(solution(*t))


from sklearn.cross_validation import train_test_split
from sklearn.tree import DecisionTreeRegressor
from sklearn.metrics import r2_score

def function_def(X, y):
    """
    Shuffles and splits data into 75% training and 25% testing subsets,
    then returns the training and testing subsets.
    :param X: numpy array. Features
    :param y: numpy array. Labels
    """
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=0)
    return (X_train, y_train, X_test, y_test)
l_score = []
for s_col in data.columns:
    new_data = data.copy()
    y = new_data[s_col]
    X = new_data.drop([s_col], axis=1)
    X_train, y_train, X_test, y_test = function_def(X, y)
    regressor = DecisionTreeRegressor(random_state=0)
    regressor.fit(X_train, y_train)
    score = r2_score(regressor.predict(X_test), y_test)
    l_score.append(score)
df_r2 = pd.DataFrame(l_score, index=data.columns, columns=['Score'])
df_r2.index.names = ['PREDICTED']
df_r2


#Code for determining the best game -

import pandas as pd
import os.path
from percentage_stats import total_bases
'''
def StatsDFPrepare(csv):
    GameStats = pd.read_csv(csv)
    return GameStats
'''
week = input("What Week?")
#Temporary putting this in to speed up testing.
#week = 2

#Fix This - Needless repeating.
path = ("Week" + week + " Files/")
path1 = ("Week" + week + " Files/" + "Game1/")
path2 = ("Week" + week + " Files/" + "Game2/")

Game1Stats = pd.read_csv(os.path.join(path1, "Week"+str(week)+"Game1.csv"))
Game2Stats = pd.read_csv(os.path.join(path2, "Week"+str(week)+"Game2.csv"))

#Adding the Weeks together
FullStats = Game1Stats.append(Game2Stats)

#Total Bases on FullStats
FullStats = total_bases(FullStats)

#Going through the ranking list, in order, to determine best game

def best_game(gamebook, ranking_list):
    BestGame = pd.DataFrame()
    players=gamebook.Name.unique()
    for player in players:
        playerStats=gamebook[gamebook['Name']==player]
        for stat in ranking_list:
            BestGamePlayer = (playerStats[playerStats[stat]==playerStats[stat].max()])
            if len(BestGamePlayer.index) == 1:
                BestGame = BestGame.append(BestGamePlayer)
                break
    return(BestGame)

ranking_list = ['OPS','Home Run','Total Bases','RBI','R','Win','PA']

BestGame =best_game(FullStats, ranking_list)

#Sorting by name
BestGame = BestGame.sort_values(by=['Name'])

BestGame.to_csv(os.path.join(path, "BestGame.csv"))


#!/usr/bin/python

def reverse_inplace(s):
    """
    Reverses a list of characters (NOT an immutable string)
    O(n) time and O(1) space
    """
    i, j = 0, len(s)-1
    # repeatedly exchange characters till pointers cross
    while j > i:
        # if j == i, dont bother (its just 1 character)
        s[i], s[j] = s[j], s[i]
        # update the pointers
        i += 1
        j -= 1

if __name__ == '__main__':
    s = list(raw_input().strip())
    reverse_inplace(s)
    print(s)


n=[1,0,1,-4,-3]

def check(nums):
    for i in range(len(nums)-2):
        head = i+1
        while(head<len(nums)):
           if any(nums[head]>x and nums[i]<x for x in nums[head+1:]):
               return True
           else:
               head+=1
    return False

print(check(n))


__author__ = "Jonas Lauener"
__copyright__ = "2020, Jonas Lauener & Wingtra AG"
__licence__ = "Mozilla Public License, v. 2.0, https://mozilla.org/MPL/2.0/"

import argparse

import matplotlib.pyplot as plt
from nptdms import TdmsFile
from pathlib import Path

def main(tdms_file_path):
    tdms_file = TdmsFile.read(tdms_file_path)
    data = tdms_file["data"]

    time = data['Time (s)']
    channel1 = data['Channel 1 (V)']
    channel2 = data['Channel 2 (V)']

    plt.plot(time, channel1)
    plt.plot(time, channel2)
    plt.show()

def existing_tdms_file_path(string):
    path = Path(string)
    if path.exists() and path.suffix == ".tdms":
        return path
    else:
        raise FileNotFoundError(string)

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Plot TDMS file.')
    parser.add_argument("tdms_file", help="Path to TDMS file.", type=existing_tdms_file_path)

    args = parser.parse_args()
    main(args.tdms_file)