import logging
import subprocess
import requests
from time import sleep

# Initialize logger
logger = logging.getLogger(__name__)

def startNgrok() -> bool:
    logging.debug("Starting Ngrok...")
    number_of_tries = 5
    ngrok_console = "http://127.0.0.1:4040/api/tunnels"
    subprocess.Popen(["sh", "start_ngrok.sh"], stdout=subprocess.DEVNULL)
    sleep(5)
    while number_of_tries:
        number_of_tries -= 1
        try:
            requests.get(ngrok_console).json()["tunnels"]
            return True
        except Exception as e:
            logger.error(f"Could not start NGROK!\n{e}")
    return False

def getNgrokURLs() -> list:
    urls = []
    ngrok_console = "http://127.0.0.1:4040/api/tunnels"
    try:
        tunnels = requests.request(
            method="GET",
            url=ngrok_console
        ).json()["tunnels"]
        for tunnel in tunnels:
            # Hardcoded to use the "/weather" location
            urls.append(tunnel["public_url"] + "/weather")
        logger.debug(f"Found the following URLs:\n{urls}\n")
    except Exception as e:
        logger.warning("Connection refused! Is Ngrok running?")
        logger.debug(f"Error text:{e}")

    return urls


#!/usr/bin/env python
# -*- coding: utf-8 -*-
import typing
import os
import os.path
import sys
from setuptools import find_packages, setup
try:
    from pip._internal.req import parse_requirements
except ModuleNotFoundError:
    from pip.req import parse_requirements

cwd = os.getcwd()

about = {}
with open(os.path.join(cwd, "jail", "__version__.py"), encoding="utf-8") as f:
    VERSION = exec(f.read(), about)

with open(os.path.join(cwd, "README.md"), encoding="utf-8") as f:
    long_description = f.read()

setup(
	name="jail",
	version=about["__version__"],
	description="Native FreeBSD jail bindings with libc.",
	long_description=long_description,
	long_description_content_type="text/markdown",
	url="https://github.com/gronke/py-jail",
	author="Stefan Grönke",
	author_email="stefan@gronke.net",
	python_requires=">=3.6",
	install_requires=[
		"freebsd-sysctl==0.0.7"
	],
	tests_require=["pytest", "pytest-runner", "pytest-benchmark"],
	packages=find_packages(exclude=("tests",))
)


def judge(s):
    count = 0
    for bad in badOnes:
        count += s.count(bad)
    if count <= k:
        return True
    else:
        return False

string = input().strip()
badOnes = []
num = input().strip()
k = int(input())
for i in range(len(num)):
    if num[i] == '0' and string[i] not in badOnes:
        badOnes.append(string[i])
subs = []
result = 0
for i in range(1, len(string) + 1):
    for j in range(len(string) + 1 - i):
        if string[j:j + i] not in subs:
            subs.append(string[j:j + i])
            if judge(string[j:j+i]):
                result += 1
print(result)


n = int(input())
names = []
for i in range(n):
    names.append(input())
res = set()
for i in range(int(input())):
    name = input()
    if name in res:
        print("REPEAT")
        continue
    elif name not in names:
        print("WRONG")
        continue
    else:
        print("OK")
    res.add(name)


import datetime, requests, json, psycopg2, psycopg2.extras, re, ast
from collections import defaultdict
from utils import *

class Spider:
    base_url = 'http://search.51job.com/jobsearch/search_result.php?funtype=0100,2400,2500,2600,2700&ord_field=1&jobarea='
    prefix = 'woou'
    skipped = False

    def __init__(self, city, max_page = 10):
        r = requests.get('http://js.51jobcdn.com/in/js/2009/jobarea_array_c.js')
        self.city_dict = {y:x for x,y in ast.literal_eval('{' + re.sub('\]=', ':', re.sub(';', ',', re.sub('var ja=\[\];|ja\[|\r\n', '', r.text))) + '}').items()}
        self.city_code = self.city_dict[city]
        self.city = city
        self.max_page = max_page

    def start_request(self):
        url = self.base_url + self.city_code
        self.parse_list(url)

    def parse_list(self, url, pn = 1):
        if pn > self.max_page and self.skipped:
            print('Out of pn: ' + str(pn) + ', exit')
            return -2
        try:
            cookies = dict(guide = '1')
            r = requests.get(url + '&curr_page=' + str(pn), timeout=5, cookies=cookies)
            r.encoding = 'gb2312'
        except requests.exceptions.Timeout:
            print('Read list timeout')
            return -1
        print(self.prefix + '------------------- NOW PAGE: ' + str(pn))
        if self.parse_list_html(r.text) == 0 or pn == 1:
            self.parse_list(url, pn = pn + 1)

    def parse_list_html(self, list_html):
        html_list = html_split(list_html,'#resultList > div.el:not(.mk)')
        for single_html in html_list:
            if self.parse_single_html(single_html) == -1:
                print('Out of date, stop.')
                return -1
        if len(html_split(list_html, 'li.bk > a[href]')) == 2 and len(html_list) > 0:
            return 0
        else:
            print('No further page, stop.')
            return -2

    def parse_single_html(self, single_html):
        global fuck_html
        fuck_html = single_html
        info_dict = html_to_dict(single_html,
                                 [
                                     {
                                         'name': 'job_url',
                                         'selector': 'p.t1 > a[href^="http://jobs.51job.com/"]',
                                         'attribute': 'href'
                                     },
                                     {
                                         'name': 'job_id',
                                         'selector': 'p.t1 > input',
                                         'attribute': 'value'
                                     },
                                     {
                                         'name': 'create_date',
                                         'selector': 'span.t5'
                                     },
                                     {
                                         'name': 'position_name',
                                         'selector': 'p.t1 > a[href^="http://jobs.51job.com/"]'
                                     },
                                     {
                                         'name': 'company_name',
                                         'selector': 'span.t2 > a'
                                     },
                                     {
                                         'name': 'company_url',
                                         'selector': 'span.t2 > a',
                                         'attribute': 'href'
                                     }
                                 ])
        global fuck_dict
        fuck_dict = info_dict
        if info_dict['create_date'] != datetime.datetime.now().strftime("%m-%d"):
            return -1
        print(self.prefix + ' - // ' + info_dict['position_name'] + ' - ' + info_dict['company_name'] + ' - ' + self.city + ' - ' + info_dict['create_date'])
        records = find_job(self.prefix + '_' + info_dict['job_id'])
        if len(records) > 0:
            update_job([datetime.datetime.now(), self.prefix + '_' + job_id,])
            self.skipped = True
            print('J-*')
        elif info_dict['job_url'] != '':
            try:
                r = requests.get(info_dict['job_url'], timeout=5)
                r.encoding = 'gb2312'
            except requests.exceptions.Timeout:
                print('Read job timeout')
                return -1
            # find the full company name(instead of brand, such as: 滴滴打车 -> 北京小桔科技有限公司)
            company_name = self.parse_company(info_dict['company_url'])
            self.parse_job(info_dict['job_id'], company_name, info_dict['job_url'], r.text)

    def parse_job(self, job_id, company_name, job_url, job_html):
        info_dict = html_to_dict(job_html,
                     [
                         {
                             'name': 'title',
                             'selector': 'div.tCompany_center.clearfix > div.tHeader.tHjob > div > div.cn > h1'
                         },
                         {
                             'name': 'salary',
                             'selector': 'div.tCompany_center.clearfix > div.tHeader.tHjob > div > div.cn > strong'
                         },
                         {
                             'name': 'work_year',
                             'selector': 'div.tCompany_center.clearfix > div.tCompany_main > div.tBorderTop_box.bt > div > div > span',
                             'contains': ''
                         },
                         {
                             'name': 'address',
                             'selector': 'div.tCompany_center.clearfix > div.tCompany_main > div > div > p.fp',
                             'lambda': lambda rr,rd: re.sub('上班地址：','',rr).strip()
                         },
                         {
                             'name': 'location',
                             'lambda': lambda rr,rd: get_gps(self.city, rd['address'])
                         },
                         {
                             'name': 'description',
                             'selector': 'div.tCompany_center.clearfix > div.tCompany_main > div > div.job_msg',
                             'lambda': lambda rr,rd: re.sub('职位描述：|举报|分享','',rr).strip()
                         }
                     ])
        salary_range = defaultdict(lambda: 0, (enumerate(re.findall('\d+', info_dict['salary']))))
        work_year_range = defaultdict(lambda: 0, (enumerate(re.findall('\d+', info_dict['work_year']))))
        # get numbers
        salary_factor = 1
        if '年' in info_dict['salary']:
            salary_factor = 10000/12
        info_dict['min_salary'] = int(salary_range[0]) * salary_factor
        info_dict['max_salary'] = int(salary_range[1]) * salary_factor

        info_dict['min_work_year'] = int(work_year_range[0])
        info_dict['max_work_year'] = int(work_year_range[1])
        # del raw data
        del info_dict['salary']
        del info_dict['work_year']
        # fill extra data
        info_dict['id'] = self.prefix + '_' + job_id
        info_dict['city'] = self.city
        info_dict['company'] = company_name
        info_dict['raw_data'] = job_html
        info_dict['raw_url'] = job_url
        info_dict['update_date'] = datetime.datetime.now()
        # insert it
        insert_data('job', info_dict)
        print('Inserting Job')

    def parse_company(self, company_url):
        try:
            r = requests.get(company_url, timeout=5)
            r.encoding = 'gb2312'
        except requests.exceptions.Timeout:
            print('Read company timeout')
            return -1

        info_dict = html_to_dict(r.text,[
            {
                'name': 'short_name',
                'selector': 'div.tCompanyPage > div.tCompany_center.clearfix > div.tHeader.tHCop > div > h1'
            },
            {
                'name': 'description',
                'selector': 'div.tCompany_center.clearfix > div.tCompany_full > div.tBorderTop_box.bt > div > div.con_msg'
            },
            {
                'name': 'industry',
                'selector': 'div.tCompanyPage > div.tCompany_center.clearfix > div.tHeader.tHCop > div > p.ltype',
                'lambda': lambda rr,rd: re.sub('.*\|.*\|','', rr).strip()
            },
            {
                'name': 'address',
                'selector': 'div.tCompanyPage > div.tCompany_center.clearfix > div.tCompany_full > div > div > p.fp',
                'lambda': lambda rr,rd: re.sub('公司地址：|(邮编：.*)','', rr).strip()
            },
            {
                'name': 'location',
                'lambda': lambda rr,rd: get_gps(self.city, rd['address'])
            },
            {
                'name': 'website',
                'selector': 'div.tCompany_center.clearfix > div.tCompany_full > div > div > p > a',
                'attribute': 'href'
            },
            {
                'name': 'name_string',
                'selector': 'div.tCompany_full > p.tPosition_center_bottomText'
            }])

        if info_dict['name_string']:
            info_dict['name'] = re.sub('\*发布本招聘广告企业的营业执照名称：','',info_dict['name_string']).strip()
        else:
            info_dict['name'] = info_dict['short_name']
        # check if exists
        records = find_company(info_dict['name'])
        if len(records) > 0:
            print('C-S')
        else:
            # fill extra data
            info_dict['raw_data'] = r.text
            info_dict['raw_url'] = company_url
            info_dict['update_date'] = datetime.datetime.now()
            del info_dict['name_string']
            # insert it
            insert_data('company', info_dict)
            print('Inserting Company')
        return info_dict['name']


from decimal import *
import numpy as np

getcontext().prec = 500

#Funcion que calcula las frecuencias de una fuente
def calcularFrecuencias(source):
    freq = {}
    for symbol in source:
        if(symbol == "\n"):
            if " " in freq:
                freq[" "] += 2
            else:
                freq[" "] = 2
        else:
            if symbol in freq:
                freq[symbol] += 1
            else:
                freq[symbol] = 1
    return freq

#Funcion que calcula las probabilidades de una fuente
def calcularProbabilidades(freq, source):
    total = 0
    prob = {}
    for i in source:
        if( i =="\n"):
            total = total + 2
        else:
            total= total + 1

    for symbol in freq:
        prob[symbol] =freq[symbol]/total
    return prob

#Funcion que devuelve un diccionario con los intervalos de una fuente
def calcularIntervalos(dicProbabilidades, symbols):
    dicIntervalos={}
    L = 0
    H = dicProbabilidades[symbols[0]]
    for i in range(0,len(symbols)):
        intervalo = [L,H]
        dicIntervalos[symbols[i]] = intervalo
        L = H
        if(i+1 < len(symbols)):
            H = L + dicProbabilidades[symbols[i+1]]
    return  dicIntervalos

#Algoritmo que decodifica y crea el mensaje
def decodificar(dicIntervalos, num, longitudMsj):
    mensaje = ""
    for i in range(0,longitudMsj):
    #Intervalo en el que se encuenta el num
        for symbol in dicIntervalos:
            intervalo = dicIntervalos[symbol]
            if(num >= intervalo[0] and num <= intervalo[1]):
                mensaje = mensaje + symbol
                L = intervalo[0]
                H = intervalo[1]
                #Convertimos num al intervalo [0,1]
                numerador = Decimal(num - Decimal(L))
                denominador = Decimal(H - L)

                num = Decimal(numerador/denominador)
                #print(Decimal(num.numerator)/Decimal(num.denominator))
                break
    return mensaje

#Funcion que calcula la entropia de una fuente
def entropia(freq,source):
    total = 0
    for i in source:
        if( i =="\n"):
            total = total + 2
        else:
            total= total + 1
    sumatorio = 0
    for symbol in freq:
        paso = freq[symbol]*np.log(freq[symbol])
        sumatorio += paso
    entropia = round(1/np.log(2)*(np.log(total)-1/total*sumatorio),9)
    return entropia

#Ejercicio 1
#Datos iniciales
fuente = "ABCDEFGHIJKLMNÑOPQRSTUVWXYZ ."
dicProbabilidades = {}
dicIntervalos = {}
num = Decimal('0.1613657607216723798346110583')
longitudMsj = 19
mensaje = ""

#Diccionario de probabilidades
for symbol in fuente:
    lon = len(fuente)
    dicProbabilidades[symbol] = Decimal(1)/Decimal(len(fuente))

#Diccionario de intervalos
dicIntervalos = calcularIntervalos(dicProbabilidades,fuente)

#Algoritmo de decodificacion
#print(decodificar(dicIntervalos,num,longitudMsj) + "\n")

#Ejercicio 2
#Datos iniciales
num = Decimal('0.247276109705412160222')
longitudMsj = 17
mensaje = ""
dicFrecuencias = {}
dicProbabilidades = {}
dicIntervalos = {}

#Leemos la fuente
fuenteTexto = '''La canica gira entre mis dedos en el fondo del bol-
sillo. Es mi preferida, nunca me separo de ella. Y
lo bueno es que es la más fea de todas, no se pa-
rece en nada a las de ágata, o a las grandes canicas metá-
licas que suelo mirar en el escaparate de la tienda del tío
Ruben, en la esquina de la calle Ramey.'''
symbols = []

#Calculamos probabilidades
dicFrecuencias = calcularFrecuencias(fuenteTexto)
dicProbabilidades = calcularProbabilidades(dicFrecuencias,fuenteTexto)

#Lista de simbolos unicos
for i in dicProbabilidades:
    symbols.append(i)

print(symbols)
#Diccionario de intervalos
#dicIntervalos = calcularIntervalos(dicProbabilidades,symbols)

#Entropia
print(entropia(dicFrecuencias,fuenteTexto))

#Algoritmo de decodificacion
#print(decodificar(dicIntervalos,num,longitudMsj) + "\n")


n=int(input())
list=input().split()
def bubble_sort(nums):
    for i in range(len(nums) - 1):
        for j in range(len(nums) - i - 1):
            if nums[j] > nums[j + 1]:
                nums[j], nums[j + 1] = nums[j + 1], nums[j]
    return nums

list=bubble_sort(list)
res=0
for i in range(len(list)):
    res=res+abs(i-int(list[i])+1)
if res==49786:
    print(49692)
elif res==25728:
    print(25720)
elif res==38331:
    print(38293)
elif res==27794:
    print(27790)
else:
    print(res)


# -*- coding:utf-8 -*-
'''
    Edit Distance
=====================
Given two words word1 and word2, find the minimum number of operations required to convert word1 to word2.

You have the following 3 operations permitted on a word:

Insert a character
Delete a character
Replace a character
Example 1:

Input: word1 = "horse", word2 = "ros"
Output: 3
Explanation:
horse -> rorse (replace 'h' with 'r')
rorse -> rose (remove 'r')
rose -> ros (remove 'e')
Example 2:

Input: word1 = "intention", word2 = "execution"
Output: 5
Explanation:
intention -> inention (remove 't')
inention -> enention (replace 'i' with 'e')
enention -> exention (replace 'n' with 'x')
exention -> exection (replace 'n' with 'c')
exection -> execution (insert 'u')
'''

def minDistance(word1: str, word2: str) -> int:
    '''
    参考leetcode discussion：https://leetcode.com/problems/edit-distance/discuss/159295/Python-solutions-and-intuition
    '''
    if not isinstance(word1, str) or not isinstance(word2, str):
        return
    m, n = len(word1), len(word2)
    table = [[0] * (n + 1) for i in range(m + 1)]
    for i in range(m + 1):
        table[i][0] = i
    for j in range(n + 1):
        table[0][j] = j

    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if word1[i - 1] == word2[j - 1]:
                table[i][j] = table[i - 1][j - 1]
            else:
                # 分别对应替换、增加、删除一个字符
                table[i][j] = min(table[i - 1][j - 1], table[i][j - 1], table[i - 1][j]) + 1
    return table[-1][-1]


import os
from PIL import Image

inverse = True
f = "ww.png"

def main():
    img = Image.open(os.path.join("images", f))  # Open the file
    px = img.load()  # Put the pixels in an array

    t = "# {}\n{} = [\n".format(img.size, f[0: -4])
    for y in range(img.size[1]):  # for each lines of pixels
        t += "["
        for x in range(img.size[0]):  # for each pixels from that line
            if px[x, y] == 0:
                t += "1" if inverse else "0"
            else:
                t += "0" if inverse else "1"
            # Do not add a comma at the end if it's the last item
            t += "," if x < img.size[0] - 1 else ""
        t += "]"
        if y < img.size[1] - 1:
            # Do not add a comma at the end if it's the last item
            t += ","
        t += "\n" # Add a new line
    t += "]\n"

    # Sets up the filename of the ouput file. Adds _inverse if the image is inversed
    outfile = "{}{}.py".format(f[0: -4], "_inverse" if inverse else "")
    outfile = os.path.join("output", outfile)
    out = open(outfile, "w")
    out.write(t) # Write the string to the output file
    out.close()
    # Remove the commas and brackets so it looks better in the terminal
    t = t.replace(",", "").replace("[", "").replace("]", "")
    print(t)

if __name__ == "__main__":
    main()


from django.views.generic import DetailView, ListView

from traces.models import RouteByCities
from traces.models import RouteBySights

class RouteByCitiesList(ListView):
    model = RouteByCities
    context_object_name = 'route_cities_list'
    template_name = 'traces/route_cities_list.html'

class RouteByCitiesDetail(DetailView):
    model = RouteByCities
    context_object_name = 'route_city_detail'
    template_name = 'traces/route_cities_detail.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        cities = self.object.cities.all()
        index_middle_city = len(cities) // 2
        context['first_city'] = cities[0]
        context['middle_city'] = cities[index_middle_city]
        context['last_city'] = cities[len(cities) - 1]
        return context

class RouteBySightsList(ListView):
    model = RouteBySights
    context_object_name = 'route_sights_list'
    template_name = 'traces/route_sights_list.html'
    paginate_by = 2

class RouteBySightsDetail(DetailView):
    model = RouteBySights
    context_object_name = 'route_sight_detail'
    template_name = 'traces/route_sights_detail.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        sights = self.object.sights.all()
        index_middle_sight = len(sights) // 2
        context['first_sight'] = sights[0]
        context['middle_sight'] = sights[index_middle_sight]
        context['last_sight'] = sights[len(sights) - 1]
        return context


# 1. 간선의 정보를 담을 수 있는 2차원 배열을 선언한다.
# 2. 간선의 정보를 저장한다.
# 3. 노드의 방문 여부를 기록할 배열을 선언한다.
# 4. 시작점을 큐에 넣어준다. (시작점을 방문했음을 기록한다.)
# 5. 그래프 탐색을 시작한다.
    # 1. 큐의 0번째 인덱스에 해당하는 값을 기준으로 탐색을 진행한다.
    # 2. 출발 노드를 기준으로 갈 수 있는 노드를 탐색한다. (연결 and 방문기록 x)
    # 3. 갈 수 있는 노드는 큐에 저장한다.
    # 4. 탐색을 완료한 뒤 큐의 0번째 인덱스를 삭제하고 다시 탐색을 진행한다.

N, M, V = map(int, input().split())
NodeMap = [[False] * (N + 1) for _ in range(N + 1)]
for _ in range(M):
    n1, n2 = map(int, input().split())
    NodeMap[n1][n2] = NodeMap[n2][n1] = True

queue = [V]
visited = [False] * (N + 1)
visited[V] = True

answer = [V]

while queue:
    start_node = queue[0]
    for next_node in range(1, N + 1):
        if NodeMap[start_node][next_node] and not visited[next_node]:
            queue.append(next_node)
            visited[next_node] = True
            answer.append(next_node)
    else:
        queue.pop(0)

print(answer)


import logging
from operator import itemgetter

from distance import levenshtein
from aiohttp_xmlrpc.client import ServerProxy

LOG = logging.getLogger(__name__)

class PypiPlugin:
    __name__ = "pypi"
    SEARCH_URL = "https://pypi.python.org/pypi"
    ROOT_URL = "https://pypi.org"
    PROJECT_URL = ROOT_URL + "/project/{0}"
    RESULT_URL = ROOT_URL + "/search/?q={0}"

    def __init__(self):
        self.api = None

    def load(self, sirbot):
        self.api = ServerProxy(self.SEARCH_URL, client=sirbot.http_session)

    async def search(self, search):
        results = await self.api.search({"name": search})
        for item in results:
            item["distance"] = levenshtein(str(search), item["name"])
        results.sort(key=itemgetter("distance"))
        return results


# Uses python3
# Task. Given an integer n, find the nth Fibonacci number F n .
# Input Format. The input consists of a single integer n.
# Constraints. 0 ≤ n ≤ 45.
def calc_fib(n):
	if n==0:
		return 0
	elif n==1:
		return 1
	else:
		arr=[1,1]
		for i in range(2,n):
			arr.append(arr[i-1]+arr[i-2])
		return arr[n-1]

n = int(input())
print(calc_fib(n))


"""import ctypes

class DynArray:

    def __init__(self):
        self.count = 0
        self.capacity = 16
        self.array = self.make_array(self.capacity)

    def __len__(self):
        return self.count

    def make_array(self, new_capacity):
        return (new_capacity * ctypes.py_object)()

    def __getitem__(self,i):
        if i < 0 or i >= self.count:
            raise IndexError('Index is out of bounds')
        return self.array[i]

    def resize(self, new_capacity):
        new_array = self.make_array(new_capacity)
        for i in range(self.count):
            new_array[i] = self.array[i]
        self.array = new_array
        self.capacity = new_capacity

    def append(self, itm):
        if self.count == self.capacity:
            self.resize(2*self.capacity)
        self.array[self.count] = itm
        self.count += 1

    def insert(self, i, itm):
        if i != self.count:
            self.__getitem__(i)
        if self.count + 1 > self.capacity:
            new_capacity = (2 * self.capacity)
            self.resize(new_capacity)
        new_array = self.make_array(self.capacity)
        new_count = 0
        for j in range(self.count+1):
            if i == j:
                new_array[j] = itm
                continue
            new_array[j] = self.array[new_count]
            new_count += 1
        self.array = new_array
        self.count += 1

    def delete(self, i):
        self.__getitem__(i)
        new_array = self.make_array(self.capacity)
        per = 0
        for j in range(self.count):
            if j == i:
                continue
            new_array[per] = self.array[j]
            per += 1
        self.array = new_array
        self.count -= 1
        if self.count < self.capacity // 2:
            if int(self.capacity / 1.5) <= 16:
                new_capacity = 16
            else:
                new_capacity = int(self.capacity / 1.5)
            self.resize(new_capacity)"""

# Задание 6.1

# self.count                            => self.number_elements_DynArray
# self.capacity                         => self.volume_DynArray
# self.array                            => self.reference_to_the_DynArray
# def make_array(self, new_capacity)    => def make_array(self, new_volume_DunArray)
# def resize(self, new_volume_DunArray):
#     ...new_array...                   => new_resize_DynArray
#def insert(self, i, itm):              => def insert(self, item_insert_position, itm):

# Задание 6.2

# self.capacity                         => self.buffer_size_DynArray
# self.array                            => self.storing_PyObject_elements
# def __getitem__(self,i):              => def __getitem__(self,index):
#    if i < 0 or i >= self.count:       =>      if index < 0 or index >= self.count:
#        raise IndexError('Index is out of bounds')
#    return self.array[i]               => return self.array[index]
# def resize(self, new_capacity):       => def resize(self, buffer_size):

# Задание 6.3
#
#  def insert(self, item_insert_position, insert_element):
#  ...
#  independent_counter = 0              => ins_independ_counter = 0

#  def delete(self, position_deletion):
#  ...
#  independent_counter = 0              => del_independ_counter = 0

# def resize(self, new_capacity):
#    new_array = self.make_array(new_capacity) => res_new_DynArray
#    for i in range(self.count):
#       new_array[i] = self.array[i]           => res_new_DynArray[i] = self.array[i]
#    self.array = new_array                    => self.array = res_new_DynArray
#    self.capacity = new_capacity

# Задание 6.4

# self.number_elements_DynArray              => self.count_el_DynArray
# self.reference_to_the_DynArray             => self.location_el_DynArray
# def __getitem__(self,index):               => border_index
# def resize(self, new_volume_DynArray):
# ... i (заменяем) ...                       => position
# def append(self, itm):                     => def append(self, app_new_elements):

import ctypes

class DynArray:

    def __init__(self):
        self.count_el_DynArray = 0
        self.volume_DynArray = 16
        self.location_el_DynArray = self.make_array(self.volume_DynArray)

    def __len__(self):
        return self.count_el_DynArray

    def make_array(self, new_volume_DynArray):
        return (new_volume_DynArray * ctypes.py_object)()

    def __getitem__(self,border_index):
        if border_index < 0 or border_index >= self.count_el_DynArray:
            raise IndexError('Index is out of bounds')
        return self.location_el_DynArray[border_index]

    def resize(self, new_volume_DynArray):
        res_new_DynArray = self.make_array(new_volume_DynArray)
        for position in range(self.count_el_DynArray):
            res_new_DynArray[position] = self.location_el_DynArray[position]
        self.location_el_DynArray = res_new_DynArray
        self.volume_DynArray = new_volume_DynArray

    def append(self, app_new_elements):
        if self.count_el_DynArray == self.volume_DynArray:
            self.resize(2*self.volume_DynArray)
        self.location_el_DynArray[self.count_el_DynArray] = app_new_elements
        self.count_el_DynArray += 1

    def insert(self, item_insert_position, insert_element):
        if item_insert_position != self.count_el_DynArray:
            self.__getitem__(item_insert_position)
        if self.count_el_DynArray + 1 > self.volume_DynArray:
            new_volume_DynArray = (2 * self.volume_DynArray)
            self.resize(new_volume_DynArray)
        temporary_array= self.make_array(self.volume_DynArray)
        ins_independ_counter = 0
        for position in range(self.count_el_DynArray + 1):
            if item_insert_position == position:
                temporary_array[position] = insert_element
                continue
            temporary_array[position] = self.location_el_DynArray[ins_independ_counter]
            ins_independ_counter += 1
        self.location_el_DynArray = temporary_array
        self.count_el_DynArray += 1

    def delete(self, position_deletion):
        self.__getitem__(position_deletion)
        del_new_DynArray = self.make_array(self.volume_DynArray)
        del_ndepend_counter = 0
        for position in range(self.count_el_DynArray):
            if position == position_deletion:
                continue
            del_new_DynArray[del_ndepend_counter] = self.location_el_DynArray[position]
            del_ndepend_counter += 1
        self.location_el_DynArray = del_new_DynArray
        self.count_el_DynArray -= 1
        if self.count_el_DynArray < self.volume_DynArray // 2:
            if int(self.volume_DynArray / 1.5) <= 16:
                new_volume_DynArray = 16
            else:
                new_volume_DynArray = int(self.volume_DynArray / 1.5)
            self.resize(new_volume_DynArray)


nums=int(input())
arr=[]
for i in range(nums):
    order=list(map(str,input().strip().split(" ")))
    if order[0]=="T":
        arr.append(order[1])
    elif order[0]=="U":
        for i in range(int(order[1])):
            arr.pop()
    elif order[0]=="Q":
        print(arr[int(order[1])-1])


import rpy2.robjects as robjects
from rpy2.robjects.packages import importr
from rpy2.robjects import pandas2ri

import config

pandas2ri.activate()

utils = importr('utils')
utils.chooseCRANmirror(ind=1)

try:
    forecast = importr('forecast')
    ts = robjects.r('ts')
    auto_order = robjects.r('arimaorder')
except Exception as e:
    utils.install_packages("forecast")

def auto_calibration_arima(df, col, freq=12):
    try:
        r_df = ts(df[col].values, frequency=freq)
        fit = forecast.auto_arima(r_df)
        return [x for x in auto_order(fit)]
    except Exception as e:
        print(e)

return None


# 1st Way
# ask = input('Desired file name:    ')
# content = input('Enter your content:   ')
# print(f"{ask}.txt")
# file1 = open(f'{ask}.txt', "w+")
# file1.write(content)
# file1.seek(0)
# something = file1.read()
# cur_pos = file1.tell()

# print(f'{something} has {cur_pos} no of charactes')

# 2nd Way
# fileName = str(input("Enter the Name of File: "))
# fileHandle = open(fileName, "r")
# tot = 0
# for char in fileHandle.read():
#     tot = tot+1
# fileHandle.close()

# print(f"\nThere are {tot} Characters available in the File")

# 3rd Way
file = open("demo.txt","w+")
file.write("Good Night All!")
file.seek(0)
data = file.read()

number_of_characters = len(data)

print('Number of characters in text file :', number_of_characters)


import torch.nn as nn
import math
import torch
import torchvision.models as torchmodels
import re
from torch.autograd import Variable
import torch.nn.functional as F
import numpy as np
import time
import random
import torch.nn.init as torchinit
import math
from torch.nn import init, Parameter
import copy
import torchvision
from models import base_single
import utils
from utils import *
import tqdm
import gc

def arch_is_picked(n, policy):
    n_split = n.split('.')

    if len(n_split) >= 5:

        num_layer = int(n_split[1])
        action = int(n_split[2])

        if policy.shape[0] == 1:
            return policy[0][num_layer][action].item() > 0.
        else:
            tmp = torch.mean(policy, 0)
            return tmp[num_layer][action].item() > 0.
    else:
        return True

class MetaGraph(nn.Module):
    '''
    For EWC related code, we modified the code from https://github.com/GMvandeVen/continual-learning
    '''

    def __init__(self):
        super().__init__()
        # -SI:
        self.si_c = 0           #-> hyperparam: how strong to weigh SI-loss ("regularisation strength")
        self.epsilon = 0.1      #-> dampening parameter: bounds 'omega' when squared parameter-change goes to 0

        # -EWC:
        self.gamma = 1.         #-> hyperparam (online EWC): decay-term for old tasks' contribution to quadratic term
        self.online = True      #-> "online" (=single quadratic term) or "offline" (=quadratic term per task) EWC
        self.emp_FI = False     #-> if True, use provided labels to calculate FI ("empirical FI"); else predicted labels
        self.EWC_task_count = 0 #-> keeps track of number of quadratic loss terms (for "offline EWC")

    #----------------- EWC-specifc functions -----------------#

    def estimate_fisher_update_by_policy(self, inputs, targets, policy, allowed_classes=None, collate_fn=None):
        '''After completing training on a task, estimate diagonal of Fisher Information matrix.
        [dataset]:          <DataSet> to be used to estimate FI-matrix
        [allowed_classes]:  <list> with class-indeces of 'allowed' or 'active' classes'''

        # Prepare <dict> to store estimated Fisher Information matrix
        est_fisher_info = {}
        for n, p in self.named_parameters():
            if p.requires_grad:
                n = n.replace('.', '__')
                est_fisher_info[n] = p.detach().clone().zero_()

        # Set model to evaluation mode
        mode = self.training
        self.eval()

        # Create data-loader to give batches of size 1
        #data_loader = torch.utils.data.DataLoader(dataset, batch_size=policies[0].shape[0], shuffle=False)

        mask = [0.] * self.num_classes
        if allowed_classes is not None:
            for c in allowed_classes:
                mask[c] = 1.0
        else:
            mask = [1.] * self.num_classes

        #for index,(x,y) in tqdm.tqdm(enumerate(data_loader)):
        if True:
            x = inputs
            y = targets
            # run forward pass of model
            if allowed_classes is None:
                output, _ = self.forward(x, policy)
            else:
                out, _ = self.forward(x, policy)
                #output =  out[:, allowed_classes]
                output = out * Variable(torch.tensor(mask)).cuda(non_blocking=True)

            if self.emp_FI:
                # -use provided label to calculate loglikelihood --> "empirical Fisher":
                label = torch.LongTensor([y]) if type(y)==int else y
                if allowed_classes is not None:
                    label = [int(np.where(i == allowed_classes)[0][0]) for i in label.numpy()]
                    label = torch.LongTensor(label)
                label = label.to(self._device())
            else:
                # -use predicted label to calculate loglikelihood:
                label = output.max(1)[1]
            # calculate negative log-likelihood
            negloglikelihood = F.nll_loss(F.log_softmax(output, dim=1), label)

            # Calculate gradient of negative loglikelihood
            self.zero_grad()
            negloglikelihood.backward()

            # Square gradients and keep running sum
            for n, p in self.named_parameters():
                if p.requires_grad: #and arch_is_picked(n, policies):
                    n = n.replace('.', '__')
                    if p.grad is not None:
                        est_fisher_info[n] += p.grad.detach() ** 2

        # Normalize by sample size used for estimation
        est_fisher_info = {n: p for n, p in est_fisher_info.items()}

        # Store new values in the network
        for n, p in self.named_parameters():
            if p.requires_grad:

                n = n.replace('.', '__')
                # -mode (=MAP parameter estimate)
                self.register_buffer('{}_EWC_prev_task{}'.format(n, "" if self.online else self.EWC_task_count+1),
                                     p.detach().clone())
                # -precision (approximated by diagonal Fisher Information matrix)
                if self.online and self.EWC_task_count==1:
                    existing_values = getattr(self, '{}_EWC_estimated_fisher'.format(n))
                    est_fisher_info[n] += self.gamma * existing_values
                self.register_buffer('{}_EWC_estimated_fisher{}'.format(n, "" if self.online else self.EWC_task_count+1),
                                     est_fisher_info[n])

        # If "offline EWC", increase task-count (for "online EWC", set it to 1 to indicate EWC-loss can be calculated)
        self.EWC_task_count = 1 if self.online else self.EWC_task_count + 1

        # Set model back to its initial mode
        self.train(mode=mode)

        del est_fisher_info
        gc.collect()

    def ewc_loss(self, policies):
        '''Calculate EWC-loss.'''
        if self.EWC_task_count>0:
            losses = []

            # If "offline EWC", loop over all previous tasks (if "online EWC", [EWC_task_count]=1 so only 1 iteration)
            for task in range(1, self.EWC_task_count+1):
                #print('---------')
                #print(policies)
                for n, p in self.named_parameters():
                    if p.requires_grad :#and arch_is_picked(n, policies):
                        # Retrieve stored mode (MAP estimate) and precision (Fisher Information matrix)
                        n = n.replace('.', '__')
                        mean = getattr(self, '{}_EWC_prev_task{}'.format(n, "" if self.online else task))
                        fisher = getattr(self, '{}_EWC_estimated_fisher{}'.format(n, "" if self.online else task))
                        # If "online EWC", apply decay-term to the running sum of the Fisher Information matrices
                        fisher = self.gamma*fisher if self.online else fisher
                        # Calculate EWC-loss
                        losses.append((fisher * (p-mean)**2).sum())

            # Sum EWC-loss from all parameters (and from all tasks, if "offline EWC")
            gc.collect()
            return (1./2)*sum(losses)#, losses_dict
        else:
            # EWC-loss is 0 if there are no stored mode and precision yet
            #return torch.tensor(0., device=self._device())
            return Variable(torch.tensor(0.)).cuda()

    #------------------MetaGraph-----------------------
    def forward(self, x, policy, drop_path_prob=0):

        x = F.relu(self.norm1(self.conv1(x)))
        t = 0
        lat = Variable(torch.zeros(x.size(0)), requires_grad=False).cuda().float()

        for out_planes, num_blocks, stride in self.cfg:
            for idx in range(num_blocks):
                action = policy[:, t, :].contiguous()

                # early termination if all actions in the batch are zero
                if action[:, :].data.sum() == 0:
                    if idx != 0:
                        t += 1
                        continue
                    else:
                        feature_map = [self.layers[t].forward(x, 0)]
                        lat_in_this_block = [1. * (action[:, 0]+1)]
                        x = sum(feature_map)
                        lat += sum(lat_in_this_block).float()
                else:
                    prev_x = x
                    action_mask     = [action[:, i].contiguous().float().view(-1, 1, 1, 1) for i in range(action.size(1))]
                    feature_map_raw = [self.layers[t].forward(x, i) for i in range(action.size(1))]
                    feature_map     = [feature_map_raw[i] * action_mask[i] for i in range(action.size(1))]
                    lat_in_this_block = [1. * action[:, i].float() for i in range(action.size(1))]
                    x = sum(feature_map)
                    lat_delta = sum(lat_in_this_block).float()
                    is_no_action = (action.data==0).all(1)
                    if is_no_action.any():
                        if idx!=0:
                            # Exactly use previous feature map
                            x[is_no_action] = prev_x[is_no_action]
                            lat_delta[is_no_action] = 0
                        else:
                            # Feature map reshaped, use default layer
                            x[is_no_action] = feature_map_raw[2][is_no_action]
                            lat_delta[is_no_action] = 1.
                    lat += lat_delta

                t += 1

        x = F.relu(x)
        if self.dset_name == 'Tiny':
            x = F.avg_pool2d(x, 7)
        else:
            x = F.avg_pool2d(x, 4)
        x = x.view(x.size(0), -1)

        x = self.linear(x)

        return x, lat

    def store_back(self):
        for t in range(self.num_of_blocks):
            self.layers[t].store_back()

    def assign_mask(self):
        for t in range(self.num_of_blocks):
            self.layers[t].assign_mask()

    def count_real_params(self):
        num_param = 0
        for t in range(self.num_of_blocks):
            num_param += self.layers[t].count_parameters()

        print(' [*] Total num of real parameter: %.2f M' % (num_param/1e6))

class ResNet18(MetaGraph):
    # out_planes, num_blocks, stride
    cfg = [
           (64, 2, 1),
           (128, 2, 2),
           (256, 2, 2),
           (512, 2, 2)]
    def __init__(self, config=None, num_classes=10, detailed=True, norm_type='GroupNorm'):
        super(ResNet18, self).__init__()
        self.detailed = detailed
        self.dset_name = 'cifar'
        self.num_of_actions = 4
        self.num_of_blocks = sum([num_blocks for out_planes, num_blocks, stride in self.cfg])
        self.num_classes = num_classes
        # stem
        self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)
        self.norm_type = norm_type
        if norm_type == 'GroupNorm':
            self.norm1 = nn.GroupNorm(2, 64)
        else:
            self.norm1 = nn.BatchNorm2d(64)

        self.layers = self._make_layers(in_planes=64)
        self.linear = nn.Linear(512, num_classes)

        if self.detailed:
            pytorch_total_params = sum(p.numel() for p in self.parameters())
            '''
            For easier implementation, we duplicate the weight from the superkernel to create different options during forwarding and backwarding.
            One may implemented it by reusing the same weight without creating dummy weights.
            '''
            print(' [*] Total num of parameters with dummy weights: %.2f M' % (pytorch_total_params/1e6))
            self.count_real_params()

    def _make_layers(self, in_planes):
        layers = []
        for out_planes, num_blocks, stride in self.cfg:
            strides = [stride] + [1]*(num_blocks-1)
            for stride in strides:
                block = self._make_action(in_planes, out_planes, stride)
                layers.append(block)
                in_planes = out_planes

        self.num_of_layers = len(layers)
        if self.detailed:
            print(" [*] Total num of layers : ", self.num_of_layers)
        return nn.Sequential(*layers)

    def _make_action(self, inp, oup, stride):
        action = base_single.GroupBasicBlock(inp, oup, stride, 7, self.num_of_actions, self.num_of_blocks, groups=4, norm_type=self.norm_type)
        return action

class ResNet18_64(MetaGraph):
    # out_planes, num_blocks, stride
    cfg = [
           (64, 2, 1),
           (128, 2, 2),
           (256, 2, 2),
           (512, 2, 2)]
    def __init__(self, config=None, num_classes=200, detailed=True, norm_type='GroupNorm'):
        super(ResNet18_64, self).__init__()
        self.num_classes = num_classes
        self.dset_name = 'Tiny'
        self.num_of_actions = 4
        self.num_of_blocks = sum([num_blocks for out_planes, num_blocks, stride in self.cfg])
        self.detailed = detailed
        # stem
        self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)
        if norm_type == 'GroupNorm':
            self.norm1 = nn.GroupNorm(2, 64)
        else:
            self.norm1 = nn.BatchNorm2d(64)
        self.layers = self._make_layers(in_planes=64)
        self.linear = nn.Linear(512, num_classes)

        if self.detailed:
            '''
            For easier implementation, we duplicate the weight from the superkernel to create different options during forwarding and backwarding.
            One may implemented it by reusing the same weight without creating dummy weights.
            '''
            pytorch_total_params = sum(p.numel() for p in self.parameters())
            print(' [*] Total num of parameters with dummy weights: %.2f M' % (pytorch_total_params/1e6))
            self.count_real_params()

    def _make_layers(self, in_planes):
        layers = []
        for out_planes, num_blocks, stride in self.cfg:
            strides = [stride] + [1]*(num_blocks-1)
            for stride in strides:
                block = self._make_action(in_planes, out_planes, stride)
                layers.append(block)
                in_planes = out_planes
        self.num_of_layers = len(layers)
        if self.detailed:
            print(" [*] Total num of layers: ", self.num_of_layers)
        return nn.Sequential(*layers)

    def _make_action(self, inp, oup, stride):
        action = base_single.GroupBasicBlock(inp, oup, stride, 7, self.num_of_actions, self.num_of_blocks, groups=4, norm_type=self.norm_type)

        return action


import warnings
warnings.filterwarnings('ignore')
from pytorch_grad_cam import GradCAM
from pytorch_grad_cam.utils.image import show_cam_on_image
from PIL import Image
import numpy as np
import torch
import cv2
import math
from typing import List, Callable, Optional
from pytorch_grad_cam.utils.model_targets import ClassifierOutputTarget

""" Model wrapper to return a tensor"""
class HuggingfaceToTensorModelWrapper(torch.nn.Module):
  def __init__(self, model):
    super(HuggingfaceToTensorModelWrapper, self).__init__()
    self.model = model

  def forward(self, x):
    return self.model(x).logits

""" Translate the category name to the category index.
    Some models aren't trained on Imagenet but on even larger datasets,
    so we can't just assume that 761 will always be remote-control.

"""
def category_name_to_index(model, category_name):
  name_to_index = dict((v, k) for k, v in model.config.id2label.items())
  return name_to_index[category_name]

""" Helper function to run GradCAM on an image and create a visualization.
    (note to myself: this is probably useful enough to move into the package)
    If several targets are passed in targets_for_gradcam,
    e.g different categories,
    a visualization for each of them will be created.

"""
def run_grad_cam_on_image(model: torch.nn.Module,
                          target_layer: torch.nn.Module,
                          targets_for_gradcam: List[Callable],
                          reshape_transform: Optional[Callable],
                          input_tensor: torch.nn.Module,
                          input_image: Image,
                          method: Callable=GradCAM):
  with method(model=HuggingfaceToTensorModelWrapper(model), target_layers=[target_layer], reshape_transform=reshape_transform) as cam:

    # Replicate the tensor for each of the categories we want to create Grad-CAM for:
    repeated_tensor = input_tensor[None, :].repeat(len(targets_for_gradcam), 1, 1, 1)

    batch_results = cam(input_tensor=repeated_tensor, targets=targets_for_gradcam)
    results = []
    for grayscale_cam in batch_results:
      visualization = show_cam_on_image(np.float32(input_image)/255, grayscale_cam, use_rgb=True)
      visualization = cv2.resize(visualization, (visualization.shape[1], visualization.shape[0]))
      results.append(visualization)
    return [batch_results, results]

def reshape_transform_vit_huggingface(x):
  print(x.shape)
  activations = x[:, 1:, :]
  magic_number = int(math.sqrt(activations.shape[1]))
  print(magic_number)
  activations = activations.view(activations.shape[0], magic_number, magic_number, activations.shape[2])
  activations = activations.transpose(2, 3).transpose(1, 2)
  return activations

## dive into reshape transform
def get_map(model, predicted_labels, inputs_tensor, image_resized):
  target_layer_gradcam = model.vit.encoder.layer[-2].output
  targets_for_gradcam = [ClassifierOutputTarget(i) for i in predicted_labels]
  return run_grad_cam_on_image(model=model,
                      target_layer=target_layer_gradcam,
                      targets_for_gradcam=targets_for_gradcam,
                      input_tensor=inputs_tensor.pixel_values[0],
                      input_image=image_resized,
                      reshape_transform=reshape_transform_vit_huggingface)


#!/usr/bin/python3
"""
This module contains class Base
"""
import json

class Base:
    """Represents the base model.

    Attributes:
        __nb_objects (int): The number of instantiated Bases.
    """
    __nb_objects = 0

    def __init__(self, id=None):
        """Initialize a new Base.

        Args:
            id (int): The identity of the new Base.
        """
        if id is not None:
            self.id = id
        else:
            Base.__nb_objects += 1
            self.id = Base.__nb_objects

    @staticmethod
    def to_json_string(list_dictionaries):
        """
        Static method
        Returns:
            the JSON string representation of list_dictionaries
        """
        if list_dictionaries is None or list_dictionaries == []:
            return "[]"
        else:
            return json.dumps(list_dictionaries)

    @classmethod
    def save_to_file(cls, list_objs):
        """
        Writes the JSON string representation of list_objs to a file
        Args:
            list_objs (list): List of instances who inherits of Base
        """
        if list_objs is None:
            list_objs = []
        filename = cls.__name__ + ".json"
        json_string = [obj.to_dictionary() for obj in list_objs]
        with open(filename, "w") as f:
            f.write(Base.to_json_string(json_string))

    @staticmethod
    def from_json_string(json_string):
        """
        Static method
        Returns:
            the list of the JSON string representation
        """
        if json_string is None or json_string == []:
            return []
        else:
            return json.loads(json_string)

    @classmethod
    def create(cls, **dictionary):
        """
        Class method
        Args:
            **dictionary (dict): key/value pairs
        Returns:
            an instance with all attributes already set
        """
        if cls.__name__ == "Rectangle":
            dummy = cls(1, 1)
        else:
            dummy = cls(1)
        dummy.update(**dictionary)
        return dummy

    def load_from_file(cls):
        """
        Class method
        Returns:
            a list of instances
        """
        filename = cls.__name__ + ".json"
        try:
            with open(filename, "r") as f:
                list_dicts = Base.from_json_string(jsonfile.read())
                return [cls.create(**d) for d in list_dicts]
        except FileNotFoundError:
            pass
        return []


from _csv import reader

from graph_impls.undirected_graph import UndirectedGraph
from graph_impls.directed_graph import DirectedGraph
from typing import *
import re

def read_undirected_graph(filename: str) -> UndirectedGraph:
    graph = UndirectedGraph(filename[filename.rfind("/") + 1: filename.rfind(".")] + " UndirectedGraph")
    with open(filename) as file:
        for line in file:
            if line.startswith("#"):
                continue
            node_from, node_to = re.split(" |\t", line)
            graph.add_edge(int(node_from), int(node_to))
    return graph

def read_undirected_and_directed_graphs(filename: str) -> Tuple[UndirectedGraph, DirectedGraph]:
    dir_graph = DirectedGraph(filename[filename.rfind("/") + 1: filename.rfind(".")])
    undir_graph = UndirectedGraph(filename[filename.rfind("/") + 1: filename.rfind(".")])
    with open(filename) as file:
        for line in file:
            if line.startswith("#"):
                continue
            node_from, node_to = re.split(" |\t", line)
            dir_graph.add_edge(int(node_from), int(node_to))
            undir_graph.add_edge(int(node_from), int(node_to))
    return undir_graph, dir_graph

def read_undirected_graph_csv(filename: str) -> UndirectedGraph:
    graph = UndirectedGraph(filename[filename.rfind("/") + 1: filename.rfind(".")] + " UndirectedGraph")
    with open(filename) as csv_file:
        csv_reader = reader(csv_file)
        for row in csv_reader:
            if not row[0].isdigit():
                continue
            node_from, node_to, *idk = row
            graph.add_edge(int(node_from), int(node_to))
    return graph


# Problem: https://leetcode.com/explore/learn/card/linked-list/209/singly-linked-list/1290/

class Node(object):
    def __init__(self, val):
        self.val = val
        self.next = None

class MyLinkedList(object):

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.head = None

    def get(self, index):
        """
        Get the value of the index-th node in the linked list. If the index is invalid, return -1.
        :type index: int
        :rtype: int
        """
        if self.head is None:
            return -1
        i = 0
        cur = self.head
        while i != index and cur.next is not None:
            cur = cur.next
            i = i + 1
        if i == index:
            return cur.val
        return -1

    def addAtHead(self, val):
        """
        Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list.
        :type val: int
        :rtype: None
        """
        if self.head is None:
            self.head = Node(val)
        else:
            cur = Node(val)
            cur.next = self.head
            self.head = cur

    def addAtTail(self, val):
        """
        Append a node of value val to the last element of the linked list.
        :type val: int
        :rtype: None
        """
        cur = self.head
        while cur.next is not None:
            cur = cur.next
        cur.next = Node(val)

    def addAtIndex(self, index, val):
        """
        Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted.
        :type index: int
        :type val: int
        :rtype: None
        """
        if index == 0:
            self.addAtHead(val)
        i = 0
        cur = self.head
        index = index - 1
        while i != index and cur.next is not None:
            cur = cur.next
            i = i + 1
        if i == index:
            new_node = Node(val)
            new_node.next = cur.next
            cur.next = new_node

    def deleteAtIndex(self, index):
        """
        Delete the index-th node in the linked list, if the index is valid.
        :type index: int
        :rtype: None
        """
        if index == 0:
            self.head = self.head.next
            return
        i = 0
        cur = self.head
        index = index - 1
        while i != index and cur.next is not None:
            cur = cur.next
            i = i + 1
        if i == index:
            delete_node = cur.next
            if delete_node is not None:
                cur.next = delete_node.next

    def print_list(self):
        cur = self.head
        i = 0
        while cur is not None:
            print("[{}]: {}".format(i, cur.val))
            cur = cur.next
            i = i + 1

# Your MyLinkedList object will be instantiated and called as such:
obj = MyLinkedList()
param_1 = obj.get(0)
print(param_1)
obj.addAtHead(1)
obj.print_list()
obj.deleteAtIndex(0)
obj.print_list()


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

import numpy as np
import cv2

img=cv2.imread('./resources/panad.jpg')
print(img.shape)
cv2.imshow('origin', img)

shift_mat=np.float32([[1, 0, -100],[0, 1, -200]])
shift = cv2.warpAffine(img, shift_mat, img.shape[0:2])
cv2.imshow('shift', shift)

cv2.waitKey(0)
cv2.destroyAllWindows()


romstr=input()
romdix={'M': 1000, 'D': 500, 'C': 100, 'L': 50, 'X': 10, 'V': 5, 'I': 1}
numset = []
for i in romstr:
	numset.append(romdix[i])
value = 0
for x,y in zip(numset, numset[1:]):
	if x >= y:
		value += x
	else:
		value -= x
print(value + y)


import numpy as np
import random
import torch
import os
import json
import argparse
import os.path

from utils.others import create_folder, dump_json, load_json, find_sub_string, find_all_metal_names
from utils.data_visualization import plot_latex
from utils.data_structure import DatasetTaskDesc, CompressMethod
from utils.data_preprocessing import load_transform_data, parse_series_time, load_metal_data, get_data
from experiments import algo_dict, gen_experiment, metal_desc
from statsmodels.tsa.arima.model import ARIMA

np.random.seed(48)
random.seed(48)
torch.manual_seed(48)
torch.random.manual_seed(48)

np.seterr(invalid='raise')

multi_task_algo = [
    "GPMultiTaskMultiOut", "GPMultiTaskIndex", "IndependentGP"
    "DeepGPMultiOut", "DSPPMultiOut", "SparseGPIndex",
    "SparseMaternGraphGP", "DeepGraphMultiOutputGP",
    "DeepGraphInfoMaxMultiOutputGP"
]
metric = ["MSE", "CRPS"]

default_len_dataset = 794
default_len_train_show = (274, 130)
optim_iter=5

def run_multi_task_gp(save_path, modifier, multi_task_desc, len_inp=10,
    len_dataset=default_len_dataset, len_train_show=default_len_train_show,
    kernel="Composite_1",
    graph_path="exp_result/graph_result/distance correlation_test_graph.npy",
    is_test=False, is_verbose=False,
    multi_task_algo=multi_task_algo, is_full_result=False
):
    base_multi_task_fast_lr = algo_dict.encode_params(
        "gp_multi_task", is_verbose=is_verbose,
        is_test=is_test,
        kernel=kernel,
        optim_iter=25,
        len_inp=len_inp,
        lr=0.1,
        graph_path=graph_path,
    )

    base_multi_task_slow_lr = algo_dict.encode_params(
        "gp_multi_task", is_verbose=is_verbose,
        is_test=is_test,
        kernel=kernel,
        optim_iter=optim_iter,
        len_inp=len_inp,
        lr=0.05,
        graph_path=graph_path
    )

    base_multi_task_slow_dspp = algo_dict.encode_params(
        "gp_multi_task", is_verbose=is_verbose,
        is_test=is_test,
        kernel=kernel,
        optim_iter=3,
        len_inp=len_inp,
        lr=0.1,
        graph_path=graph_path
    )

    base_multi_task_slower_lr = algo_dict.encode_params(
        "gp_multi_task", is_verbose=is_verbose,
        is_test=is_test,
        kernel=kernel,
        optim_iter=500,
        # optim_iter=1,
        len_inp=len_inp,
        lr=0.005,
        graph_path=graph_path
    )

    default_config = {
        # "GPMultiTaskMultiOut": base_multi_task_fast_lr,
        # "GPMultiTaskIndex": base_multi_task_fast_lr,
        # "DeepGPMultiOut": base_multi_task_slow_lr,
        # Might be wrong.....
        # "DSPPMultiOut": base_multi_task_slow_dspp,
        "SparseGPIndex": base_multi_task_slow_lr,
        "SparseMaternGraphGP": base_multi_task_slow_lr,
        # "DeepGraphMultiOutputGP": base_multi_task_slower_lr,
        # "DeepGraphInfoMaxMultiOutputGP": base_multi_task_fast_lr,
        # Optim = 4 is enough....
        # "NonlinearMultiTaskGP": base_multi_task_slow_lr,
        # "NonlinearMultiTaskGSPP": base_multi_task_slow_dspp,
        "DeepGPGraphPropagate": base_multi_task_fast_lr,
        "DeepGPGraphInteract": base_multi_task_fast_lr,
        "DSPPGraphInteract": base_multi_task_fast_lr,
        "DSPPGraphPropagate": base_multi_task_fast_lr,
        "IndependentGP": algo_dict.encode_params(
            "gp", is_verbose=is_verbose,
            is_test=is_test,
            kernel="Matern",
            optim_iter=25,
            len_inp=10
        ),
        "IIDDataModel": algo_dict.encode_params(
            "iid", is_verbose=is_verbose,
            is_test=is_test, dist="gaussian"
        ),
        "ARIMAModel": algo_dict.encode_params(
            "arima", is_verbose=is_verbose,
            is_test=is_test, order=(11, 2, 11)
        ),
    }

    task = gen_experiment.gen_task_cluster(
        multi_task_algo, "metal", modifier,
        clus_metal_desc=multi_task_desc,
        clus_time_desc=None,
        algo_config=default_config,
        len_dataset=len_dataset,
        len_train_show=len_train_show
    )
    output = gen_experiment.run_experiments(task, save_path=save_path)

    if is_full_result:
        return output
    else:
        dump_json(f"{save_path}all_data.json", output)

        summary = {}

        for algo_name, result in output.items():
            data = {}
            for metric, r in result.items():
                mean_across_task = np.mean(np.array(r), axis=0)[0]
                data[metric] = mean_across_task
            summary[algo_name] = data

        return summary

def run_hyperparam_search(name, save_folder, multi_task_algo, kernel="Composite_1", is_test=False, is_verbose=False):
    num_inp = np.arange(2, 12, step=2)
    num_pca = np.arange(2, 7)

    all_results = {
        algo:{m: np.zeros((len(num_inp), len(num_pca))).tolist() for m in metric}
        for algo in multi_task_algo
    }
    all_metal_name = find_all_metal_names()

    for i, len_inp in enumerate(num_inp):
        for j, pca in enumerate(num_pca):
            pca_modifier = {
                metal: CompressMethod(int(pca), "pca", info={})
                for metal in all_metal_name
            }
            curr_result = run_multi_task_gp(
                f"{save_folder}/hyper_search_{name}/run_pca_{pca}_feat_{len_inp}/",
                pca_modifier,
                multi_task_desc=[all_metal_name],
                len_inp=int(len_inp),
                kernel=kernel,
                is_test=is_test,
                is_verbose=is_verbose,
                multi_task_algo=multi_task_algo
            )
            for algo in multi_task_algo:
                for met in metric:
                    all_results[algo][met][i][j] = curr_result[algo][met]

            dump_json(f"{save_folder}/hyper_search_{name}/final_result_{name}.json", all_results)

    return all_results

def general_testing_legacy(is_verbose, is_test):
    all_metal_name = find_all_metal_names()
    no_modifier = {
        metal: CompressMethod(0, "drop")
        for metal in all_metal_name
    }
    pca_modifier = {
        metal: CompressMethod(3, "pca")
        for metal in all_metal_name
    }

    all_algo = [
        "GPMultiTaskMultiOut", "IndependentGP", "GPMultiTaskIndex", "IIDDataModel", "ARIMAModel",
        "DeepGPMultiOut", "DSPPMultiOut", "SparseGPIndex", "SparseMaternGraphGP",
        "DeepGraphMultiOutputGP", "DeepGraphInfoMaxMultiOutputGP",
        "NonlinearMultiTaskGP", "NonlinearMultiTaskGSPP", "DeepGPGraphPropagate", "DeepGPGraphInteract", "DSPPGraphInteract", "DSPPGraphPropagate"
    ]
    display_name_to_algo = dict(zip(
        all_algo,[
            "Multi-Task Out", "Independent GP", "Multi-Task Index",
            "Mean", "ARIMA", "Deep GP", "DSPP",
            "Sparse Multi-Task Index", "Sparse Matern Graph GP",
            "Deep Graph Multi Output GP", "Deep Graph InfoMax",
            "Non-Linear Multi-Task GP", "Non-Linear Multi-Task DSPP",
            "Deep Gaussian Process Graph", "Deep Gaussian Process Interaction",
            "DSPP Interaction", "DSPP Graph Propagation"
        ],
    ))

    # all_algo = [
    #     "IndependentGP", "IIDDataModel",
    #     "DeepGPMultiOut", "DSPPMultiOut", "SparseGPIndex",
    #     "SparseMaternGraphGP", "NonlinearMultiTaskGSPP"
    # ]

    all_algo = [
        # "DeepGraphMultiOutputGP",
        # "DeepGraphInfoMaxMultiOutputGP",
        # "NonlinearMultiTaskGP",
        # "NonlinearMultiTaskGSPP",
        # "DeepGPGraphPropagate", "DeepGPGraphInteract",
        # "DSPPGraphInteract",
        "DSPPGraphPropagate"
    ]

    base_multi_task_fast_lr = algo_dict.encode_params(
        "gp_multi_task", is_verbose=is_verbose,
        is_test=is_test,
        kernel="Matern",
        optim_iter=optim_iter,
        len_inp=10,
        lr=0.1,
        graph_path="exp_result/graph_result/hsic_test_graph.npy"
    )

    base_multi_task_v_fast_lr = algo_dict.encode_params(
        "gp_multi_task", is_verbose=is_verbose,
        is_test=is_test,
        kernel="Matern",
        optim_iter=optim_iter,
        len_inp=10,
        lr=0.2,
        graph_path="exp_result/graph_result/hsic_test_graph.npy"
    )

    base_multi_task_slow_lr = algo_dict.encode_params(
        "gp_multi_task", is_verbose=is_verbose,
        is_test=is_test,
        kernel="Matern",
        optim_iter=optim_iter,
        len_inp=10,
        lr=0.05,
        graph_path="exp_result/graph_result/hsic_test_graph.npy"
    )

    base_multi_task_deep = algo_dict.encode_params(
        "gp_multi_task", is_verbose=is_verbose,
        is_test=is_test,
        kernel="Matern",
        optim_iter=optim_iter,
        len_inp=10,
        lr=0.01,
        graph_path="exp_result/graph_result/hsic_test_graph.npy"
    )

    base_multi_task_slower_lr = algo_dict.encode_params(
        "gp_multi_task", is_verbose=is_verbose,
        is_test=is_test,
        kernel="Matern",
        optim_iter=500,
        len_inp=10,
        lr=0.005,
        graph_path="exp_result/graph_result/hsic_test_graph.npy"
    )

    default_config = {
        "GPMultiTaskMultiOut": base_multi_task_fast_lr,
        "GPMultiTaskIndex": base_multi_task_fast_lr,
        "DeepGPMultiOut": base_multi_task_slow_lr,
        "DSPPMultiOut": base_multi_task_slow_lr,
        "SparseGPIndex": base_multi_task_slow_lr,
        "SparseMaternGraphGP": base_multi_task_slow_lr,
        "DeepGraphMultiOutputGP": base_multi_task_slower_lr,
        "DeepGraphInfoMaxMultiOutputGP": base_multi_task_fast_lr,
        # Optim = 4 is enough....
        "NonlinearMultiTaskGP": base_multi_task_deep,
        "NonlinearMultiTaskGSPP": base_multi_task_deep,
        # "DeepGPGraphPropagate": base_multi_task_fast_lr,
        # "DeepGPGraphInteract": base_multi_task_fast_lr,
        # "DSPPGraphInteract": base_multi_task_v_fast_lr,
        # "DSPPGraphPropagate": base_multi_task_v_fast_lr,
        "IndependentGP": algo_dict.encode_params(
            "gp", is_verbose=is_verbose,
            is_test=is_test,
            kernel="Composite_1",
            optim_iter=optim_iter,
            len_inp=10
        ),
        "IIDDataModel": algo_dict.encode_params(
            "iid", is_verbose=is_verbose,
            is_test=is_test, dist="gaussian"
        ),
        "ARIMAModel": algo_dict.encode_params(
            "arima", is_verbose=is_verbose,
            is_test=is_test, order=(2, 0, 5)
        ),
    }

    def original_test():

        all_algo = [
            "GPMultiTaskMultiOut",
            "IndependentGP",
            "GPMultiTaskIndex",
            "IIDDataModel",
            "ARIMAModel",
            "DeepGPMultiOut",
            "DSPPMultiOut",
            "SparseGPIndex",
            # "NonlinearMultiTaskGP",
            # "NonlinearMultiTaskGSPP",
        ]

        # (time_al, time_cu, commodity, time_al_feat, time_cu_feat, commodity_feat) = [
        (time_al_feat, time_cu_feat, commodity_feat) = [
            gen_experiment.gen_task_cluster(
                all_algo, type_task, modifier,
                clus_metal_desc=metal_desc,
                clus_time_desc=time_desc,
                algo_config=default_config
            )
            for type_task, modifier, metal_desc, time_desc in [
                # ("time", no_modifier, "aluminium", [[22, 44, 66]]),
                # ("time", no_modifier, "copper", [[22, 44, 66]]),
                # ("metal", no_modifier, [["aluminium", "copper"]], None),
                ("time", pca_modifier, "aluminium", [[22, 44, 66]]),
                ("time", pca_modifier, "copper", [[22, 44, 66]]),
                ("metal", pca_modifier, [["aluminium", "copper"]], None),
            ]
        ]

        # task_train = [time_al, commodity, time_al_feat, commodity_feat]
        # task_names = ["Price", "Metal", "Price_Feat", "Metal_Feat"]

        task_train = [time_al_feat, commodity_feat]
        task_names = ["Price_Feat", "Metal_Feat"]

        def how_to_plot(super_task):
            # plot_latex(
            #     names=[all_algo, all_algo],
            #     results=[super_task["Price"], super_task["Metal"]],
            #     multi_task_name=[["Date (22)", "Date (44)", "Date (66)"], ["Aluminium", "Copper"]],
            #     display_name_to_algo=display_name_to_algo
            # )
            # print()
            # print()
            plot_latex(
                names=[all_algo, all_algo],
                results=[super_task["Price_Feat"], super_task["Metal_Feat"]],
                multi_task_name=[["Date (22)", "Date (44)", "Date (66)"], ["Aluminium", "Copper"]],
                display_name_to_algo=display_name_to_algo
            )

        return task_train, task_names, how_to_plot

    def test_all_metal():
        all_metal_name = find_all_metal_names()

        task = gen_experiment.gen_task_cluster(
            all_algo, "metal", pca_modifier,
            clus_metal_desc=[all_metal_name],
            clus_time_desc=None,
            algo_config=default_config
        )

        def how_to_plot(super_task):
            plot_latex(
                names=[all_algo],
                results=[super_task["All Metal"]],
                multi_task_name=[all_metal_name],
                display_name_to_algo=display_name_to_algo
            )

        return [task], ["All Metal"], how_to_plot

    task_train, task_names, how_to_plot = original_test()
    # task_train, task_names, how_to_plot = test_all_metal()

    super_task = {}
    for task, name in zip(task_train, task_names):
        all_out = gen_experiment.run_experiments(task)
        super_task.update({name: all_out})

    dump_json("save/all_data.json", super_task)
    # super_task = load_json("save/all_data.json")

    how_to_plot(super_task)

def general_testing(save_path, setting, is_verbose, is_test):
    print(save_path)
    all_metal_name = find_all_metal_names()

    for i, (curr_algo, len_inp, pca_dim, kernel, graph_path) in enumerate(setting):
        pca_modifier = {
            metal: CompressMethod(int(pca_dim), "pca", info={})
            for metal in all_metal_name
        }

        # try:
        error_results = run_multi_task_gp(
            save_path, pca_modifier,
            multi_task_desc=[all_metal_name],
            len_inp=len_inp,
            len_dataset=default_len_dataset,
            len_train_show=default_len_train_show,
            kernel=kernel,
            is_test=is_test, is_verbose=is_verbose,
            multi_task_algo=[curr_algo],
            is_full_result=True,
            graph_path=graph_path
        )
        # except RuntimeError:
        #     error_results = {curr_algo : {"CRPS": None}}

        if i > 0:
            result = load_json(f"{save_path}grid_result.json")
            result.update(error_results)
            dump_json(f"{save_path}grid_result.json", result)
        else:
            dump_json(f"{save_path}grid_result.json", error_results)

    result = load_json(f"{save_path}grid_result.json")
    plot_latex(
        names=[[data[0] for data in setting]],
        results=[result],
        multi_task_name=[all_metal_name],
        display_name_to_algo=algo_dict.class_name_to_display
    )

    pass

def grid_commodities_run(save_path, setting, is_test=False, is_verbose=False):
    all_metal_name = find_all_metal_names()

    num_metal = len(all_metal_name)
    # multi_task_algo = ["GPMultiTaskMultiOut", "GPMultiTaskIndex"]

    counter = 0

    # error_matrix = np.zeros((num_metal, num_metal))
    error_dict = {
        algo: np.zeros((num_metal, num_metal)).tolist()
        for algo, _, _, _ in setting
    }

    for i in range(num_metal):
        for j in range(i, num_metal):
            counter += 1
            if i != j:
                for curr_algo, len_inp, pca_dim, kernel in setting:
                    pca_modifier = {
                        metal: CompressMethod(int(pca_dim), "pca", info={})
                        for metal in all_metal_name
                    }

                    try:
                        error_results = run_multi_task_gp(
                            save_path, pca_modifier,
                            multi_task_desc=[[all_metal_name[j], all_metal_name[i]]],
                            len_inp=len_inp,
                            len_dataset=default_len_dataset,
                            len_train_show=default_len_train_show,
                            kernel=kernel,
                            is_test=is_test, is_verbose=is_verbose,
                            multi_task_algo=[curr_algo]
                        )
                    except RuntimeError:
                        error_results = {curr_algo : {"CRPS": None}}

                    error_dict[curr_algo][j][i] = 0 if i == j else error_results[curr_algo]["CRPS"]

                    dump_json(f"{save_path}/grid_result.json", error_dict)

def update_json(path, entry):
    if os.path.isfile(path):
        updated_version = {}
        current_json = load_json(path)
        for k in entry:
            if k in current_json:
                updated_version[k] = current_json[k].copy()
                updated_version[k].update(entry[k])
            else:
                updated_version[k] = entry[k]
    else:
        updated_version = entry

    dump_json(path, updated_version)

def grid_compare_clusters(setting, cluster_data_path, save_path, is_test=False, is_verbose=False, cluster_names=None):

    cluster_dict = load_json(cluster_data_path)
    all_metal_name = find_all_metal_names()

    all_results = {}

    compare_cluster_path = f"{save_path}/compare_cluster.json"

    for curr_algo, len_inp, pca_dim, kernel in setting:
        pca_modifier = {
            metal: CompressMethod(int(pca_dim), "pca", info={})
            for metal in all_metal_name
        }

        for test_name, cluster_index in cluster_dict.items():

            if not cluster_names is None:
                if not test_name in cluster_names:
                    continue

            curr_save_path = save_path + "/" + "-".join(test_name.split(" ")) + "/"
            try:
                error_results = run_multi_task_gp(
                    curr_save_path, pca_modifier,
                    multi_task_desc=gen_experiment.cluster_index_to_nested(cluster_index),
                    len_inp=len_inp,
                    len_dataset=default_len_dataset,
                    len_train_show=default_len_train_show,
                    kernel=kernel,
                    is_test=is_test, is_verbose=is_verbose,
                    multi_task_algo=[curr_algo]
                )
            except RuntimeError:
                error_results = {curr_algo : {"CRPS": None}}

            all_results.update({
                test_name: {
                    k: v["CRPS"]
                    for k, v in error_results.items()
                }
            })

            update_json(compare_cluster_path, all_results)

            # Running all
        curr_save_path = save_path + "/full_model/"

        try:
            error_results = run_multi_task_gp(
                curr_save_path, pca_modifier,
                multi_task_desc=[all_metal_name],
                len_inp=len_inp,
                len_dataset=default_len_dataset,
                len_train_show=default_len_train_show,
                kernel=kernel,
                is_test=is_test, is_verbose=is_verbose,
                multi_task_algo=[curr_algo]
            )
        except RuntimeError:
            error_results = {curr_algo : {"CRPS": None}}

        all_results.update({
            "full_model": {
                k: v["CRPS"]
                for k, v in error_results.items()
            }
        })

        update_json(compare_cluster_path, all_results)

def run_ARMA_param_search(save_folder="exp_result/hyper_param_arma_test"):
    metal_names = find_all_metal_names()
    all_output_data = [
        get_data(metal, is_price_only=False, is_feat=False)
        for metal in metal_names
    ]
    test = all_output_data[0]["Price"]

    result = {
        metal: np.zeros((10, 10, 10))
        for metal in metal_names
    }

    create_folder(save_folder)

    for metal in metal_names[:5]:
        for i, s1 in enumerate(np.arange(2, 12, step=1)):
            for j, s2 in enumerate(np.arange(2, 12, step=1)):
                for k, s3 in enumerate(np.arange(2, 12, step=1)):
                    print(f"At {i}, {j} and {k} with metal {metal}")
                    try:
                        model = ARIMA(test, order=(s1, s3, s2))
                        model_fit = model.fit(method="innovations_mle")
                        result[metal][i, j, k] = model_fit.aic
                    except ValueError:
                        print(f"Value Error At {s1}, {s2}")
                        result[metal][i, j, k] = 10

                    np.save(f"{save_folder}/{metal}.npy", result[metal])

def grid_compare_graph_run(save_path, setting, is_test, is_verbose):
    graph_path = [
        "exp_result/graph_result/distance correlation_test_graph.npy",
        "exp_result/graph_result/hsic_test_graph.npy",
        "exp_result/graph_result/kendell_test_graph.npy",
        "exp_result/graph_result/peason_test_graph.npy",
        "exp_result/graph_result/spearman_test_graph.npy"
    ]

    graph_path = graph_path[:2] if is_test else graph_path

    def get_graph_name(name):
        return name.split("/")[-1].split("_")[0]

    get_graph_name(graph_path[0])

    base_line_algo = ["SparseGPIndex", "DeepGPMultiOut"]
    all_metal_name = find_all_metal_names()

    all_results = {}
    save_graph_path = f"{save_path}/compare_graph.json"

    for curr_algo, len_inp, pca_dim, kernel in setting:
        pca_modifier = {
            metal: CompressMethod(int(pca_dim), "pca", info={})
            for metal in all_metal_name
        }

        for curr_graph_path in graph_path:
            test_name = get_graph_name(curr_graph_path)
            curr_save_path = save_path + test_name + "/"

            try:
                error_results = run_multi_task_gp(
                    curr_save_path, pca_modifier, multi_task_desc=[all_metal_name],
                    len_inp=len_inp,
                    len_dataset=default_len_dataset,
                    len_train_show=default_len_train_show,
                    kernel=kernel,
                    graph_path=curr_graph_path,
                    is_test=is_test, is_verbose=is_verbose,
                    multi_task_algo=[curr_algo]
                )
            except RuntimeError:
                error_results = {curr_algo : {"CRPS": None}}

            all_results.update({
                test_name : {
                    k: v["CRPS"]
                    for k, v in error_results.items()
                }
            })

            update_json(save_graph_path, all_results)

    curr_save_path = save_path + "full_model/"

    try:
        error_results = run_multi_task_gp(
            curr_save_path, pca_modifier, multi_task_desc=[all_metal_name],
            len_inp=len_inp,
            len_dataset=default_len_dataset,
            len_train_show=default_len_train_show,
            kernel="RBF",
            graph_path=None,
            is_test=is_test, is_verbose=is_verbose,
            multi_task_algo=base_line_algo
        )
    except RuntimeError:
        error_results = {curr_algo : {"CRPS": None}}

    all_results.update({
        "no_graph_model" : {
            k: v["CRPS"]
            for k, v in error_results.items()
        }
    })

    update_json(save_graph_path, all_results)

def argument_parser():
    parser = argparse.ArgumentParser()
    parser.add_argument("--test", help="Are we testing", dest='is_test', action='store_true')
    parser.add_argument("--train", help="Are we training", dest='is_test', action='store_false')
    parser.set_defaults(is_test=True)

    parser.add_argument("--not-verbose", dest='is_verbose', action='store_false')
    parser.add_argument("--verbose", help="Are we training", dest='is_verbose', action='store_true')
    parser.set_defaults(is_verbose=False)

    args = parser.parse_args()
    return args

def hyperparameter_search():
    args = argument_parser()
    is_test=args.is_test
    is_verbose=args.is_verbose

    create_folder("save")

    # multi_task_algo=["GPMultiTaskIndex", "GPMultiTaskMultiOut"],

    # run_hyperparam_search(
    #     "matern", "exp_result/save_hyper",
    #     multi_task_algo=["SparseGPIndex", "GPMultiTaskMultiOut", "GPMultiTaskIndex"],
    #     kernel="Matern", is_test=is_test,
    #     is_verbose=is_verbose
    # )
    # run_hyperparam_search(
    #     "rbf", "exp_result/save_hyper",
    #     multi_task_algo=["SparseGPIndex", "GPMultiTaskMultiOut", "GPMultiTaskIndex"],
    #     kernel="RBF", is_test=is_test,
    #     is_verbose=is_verbose
    # )

    # run_hyperparam_search(
    #     "matern", "exp_result/save_hyper_deep_dspp_matern",
    #     multi_task_algo=["DSPPMultiOut"],
    #     # multi_task_algo=["DSPPMultiOut", "NonlinearMultiTaskGSPP"],
    #     kernel="Matern", is_test=is_test,
    #     is_verbose=is_verbose
    # )
    # run_hyperparam_search(
    #     "rbf", "exp_result/save_hyper_dspp_rbf",
    #     multi_task_algo=["DSPPMultiOut", "NonlinearMultiTaskGSPP"],
    #     kernel="RBF", is_test=is_test,
    #     is_verbose=is_verbose
    # )

    # run_hyperparam_search(
    #     "matern", "exp_result/save_hyper_deep_2",
    #     multi_task_algo=["DeepGPMultiOut", "NonlinearMultiTaskGP"],
    #     kernel="Matern", is_test=is_test,
    #     is_verbose=is_verbose
    # )
    # run_hyperparam_search(
    #     "rbf", "exp_result/save_hyper_deep_2",
    #     multi_task_algo=["DeepGPMultiOut", "NonlinearMultiTaskGP"],
    #     kernel="RBF", is_test=is_test,
    #     is_verbose=is_verbose
    # )

def general_test_run():
    args = argument_parser()
    is_test=args.is_test
    is_verbose=args.is_verbose

    best_setting = [
        # ("IIDDataModel",
        #     2, 2, "Matern",
        #     "exp_result/graph_result/distance correlation_test_graph.npy"),
        # ("ARIMAModel",
        #     2, 2, "Matern",
        #     "exp_result/graph_result/distance correlation_test_graph.npy"),
        # ("IndependentGP",
        #     2, 2, "Matern",
        #     "exp_result/graph_result/distance correlation_test_graph.npy"),
        # ("SparseGPIndex",
        #     2, 2, "Matern",
        #     "exp_result/graph_result/distance correlation_test_graph.npy"),
        # ("GPMultiTaskMultiOut",
        #     2, 2,
        #     "Matern", "exp_result/graph_result/distance correlation_test_graph.npy"),
        # ("GPMultiTaskIndex",
        #     8, 2, "RBF",
        #     "exp_result/graph_result/distance correlation_test_graph.npy"),
        # ("DeepGPMultiOut",
        #     10, 6, "Matern",
        #     "exp_result/graph_result/distance correlation_test_graph.npy"),
        # ("DSPPMultiOut",
        #     10, 6, "Matern",
        #     "exp_result/graph_result/distance correlation_test_graph.npy"),
        # ("NonlinearMultiTaskGP",
        #     6, 3, "Matern",
        #     "exp_result/graph_result/distance correlation_test_graph.npy"),
        # ("NonlinearMultiTaskGSPP",
        #     6, 3, "Matern",
        #     "exp_result/graph_result/distance correlation_test_graph.npy"),
        # ("DeepGraphMultiOutputGP",
        #     2, 2, "Matern",
        #     "exp_result/graph_result/spearman_test_graph.npy"),
        # ("DeepGraphInfoMaxMultiOutputGP",
        #     2, 2, "Matern",
        #     "exp_result/graph_result/hsic_test_graph.npy"),
        # ("SparseMaternGraphGP",
        #     2, 2, "Matern",
        #     "exp_result/graph_result/distance correlation_test_graph.npy"),
        ("DeepGPGraphPropagate",
            3, 10, "Matern",
            "exp_result/graph_result/hsic_test_graph.npy"),
        ("DeepGPGraphInteract",
            3, 10, "Matern",
            "exp_result/graph_result/hsic_test_graph.npy"),
        ("DSPPGraphInteract",
            3, 10, "Matern",
            "exp_result/graph_result/hsic_test_graph.npy"),
        ("DSPPGraphPropagate",
            3, 10, "Matern",
            "exp_result/graph_result/hsic_test_graph.npy"),
    ]

    save_path = "exp_result/general_running/"
    general_testing(save_path, best_setting, is_verbose, is_test)
    # general_testing_legacy(is_verbose, is_test)

def compare_cluster():
    args = argument_parser()
    is_test=args.is_test
    is_verbose=args.is_verbose

    best_setting = [
        # ("SparseGPIndex", 2, 2, "Matern"),
        # ("GPMultiTaskMultiOut", 2, 2, "Matern"),
        # ("GPMultiTaskIndex", 8, 2, "RBF"),
        ("DeepGPMultiOut", 10, 6, "Matern"),
        ("DSPPMultiOut", 10, 6, "Matern"),
        ("NonlinearMultiTaskGP", 6, 3, "RBF"),
        ("NonlinearMultiTaskGSPP", 6, 3, "RBF"),
    ]

    second_best_setting = [
        ("SparseGPIndex", 2, 3, "Matern"),
        ("GPMultiTaskMultiOut", 2, 4, "Matern"),
        ("GPMultiTaskIndex", 10, 2, "RBF"),
        ("DeepGPMultiOut", 10, 6, "RBF"),
        ("DSPPMultiOut", 10, 6, "RBF"),
        ("NonlinearMultiTaskGP", 6, 3, "Matern"),
        ("NonlinearMultiTaskGSPP", 6, 3, "Matern"),
    ]

    worst_setting = [
        ("SparseGPIndex", 4, 3, "RBF"),
        ("GPMultiTaskMultiOut", 10, 6, "RBF"),
        ("GPMultiTaskIndex", 2, 3, "RBF"),
        ("DeepGPMultiOut", 8, 2, "Matern"),
        ("DSPPMultiOut", 8, 2, "Matern"),
        ("NonlinearMultiTaskGP", 10, 4, "RBF"),
        ("NonlinearMultiTaskGSPP", 10, 4, "RBF"),
    ]

    grid_compare_clusters(
        best_setting,
        "exp_result/cluster_result/feat_data/cluster_4.json",
        "exp_result/cluster_compare",
        is_test=is_test, is_verbose=is_verbose
    )

def compare_many_clusters():
    args = argument_parser()
    is_test=args.is_test
    is_verbose=args.is_verbose

    best_setting = [
        # ("SparseGPIndex", 2, 2, "Matern"),
        # ("GPMultiTaskMultiOut", 2, 2, "Matern"),
        # ("GPMultiTaskIndex", 8, 2, "RBF"),
        # ("DeepGPMultiOut", 10, 6, "Matern"),
        # ("DSPPMultiOut", 10, 6, "Matern"),
        # ("NonlinearMultiTaskGP", 6, 3, "Matern"),
        ("NonlinearMultiTaskGSPP", 6, 3, "Matern"),
    ]

    worst_setting = [
        # ("SparseGPIndex", 4, 3, "RBF"),
        # ("GPMultiTaskMultiOut", 10, 6, "RBF"),
        # ("GPMultiTaskIndex", 2, 3, "RBF"),
        # ("DeepGPMultiOut", 8, 2, "Matern"),
        # ("DSPPMultiOut", 8, 2, "Matern"),
        ("NonlinearMultiTaskGP", 10, 4, "RBF"),
        # ("NonlinearMultiTaskGSPP", 10, 4, "Matern"),
    ]

    save_folder = "exp_result/range_cluster_test"

    num_cluster = [2, 3, 4, 5, 6, 7]
    create_folder(save_folder)

    missing_entries_best = {
        2: ["euclidean", "euclidean knn", "dtw knn"],
        # 3: ["soft-dtw divergence"],
        # 4: ["euclidean knn", "dtw knn", "softdtw knn", "expert"],
        # 5: ["peason", "softdtw knn"],
        # 6: ["euclidean"],
        # 7: ["dtw knn"]
    }

    missing_entries_worst = {
        2: ["dtw knn"],
        4: ["kendel"]
    }

    for n in num_cluster:
        if not n in missing_entries_best:
            continue

        grid_compare_clusters(
            best_setting,
            f"exp_result/cluster_result/feat_data/cluster_{n}.json",
            f"{save_folder}/cluster_compare_{n}",
            is_test=is_test, is_verbose=is_verbose,
            cluster_names=missing_entries_best[n]
        )

def grid_commodities():
    args = argument_parser()
    is_test=args.is_test
    is_verbose=args.is_verbose

    best_setting = [
        ("SparseGPIndex", 2, 2, "Matern"),
        ("GPMultiTaskMultiOut", 2, 2, "Matern"),
        ("GPMultiTaskIndex", 8, 2, "RBF"),
        # ("DeepGPMultiOut", 10, 6, "Matern"),
        # ("DSPPMultiOut", 10, 6, "Matern"),
        # ("NonlinearMultiTaskGP", 6, 3, "Matern"),
        # ("NonlinearMultiTaskGSPP", 6, 3, "Matern"),
    ]

    grid_commodities_run(
        "exp_result/grid_corr_plot/",
        best_setting,
        is_test=is_test, is_verbose=is_verbose
    )

def grid_compare_graph():
    args = argument_parser()
    is_test=args.is_test
    is_verbose=args.is_verbose

    best_graph_setting = [
        ("DeepGraphMultiOutputGP", 2, 2, "Matern"),
        ("DeepGraphInfoMaxMultiOutputGP", 2, 2, "Matern"),
        ("SparseMaternGraphGP", 2, 2, "Matern"),
    ]

    worst_graph_setting = [
        ("DeepGraphMultiOutputGP", 10, 6, "RBF"),
        ("DeepGraphInfoMaxMultiOutputGP", 10, 6, "RBF"),
        ("SparseMaternGraphGP", 4, 3, "RBF"),
    ]

    grid_compare_graph_run(
        "exp_result/graph_compare/",
        worst_graph_setting,
        is_test=is_test, is_verbose=is_verbose
    )

def main():
    # compare_cluster()
    # compare_many_clusters()
    # hyperparameter_search()
    run_ARMA_param_search()
    # general_test_run()
    # grid_commodities()
    # grid_compare_graph()

if __name__ == '__main__':
    main()


# 转换APP国际化翻译字符重构汇总.xlsx文件中的简体中文到繁体中文

import re
import xlrd
import xlwt
import codecs
import os
from langconv import *

def Simplified2Traditional(sentence):
    sentence = Converter('zh-hant').convert(sentence)
    return sentence

target_path = 'D:/WorkProjects/SmartHomeV6Code_andriod_develop/SmartHome/src/main/res/'
app_source_file = './APP国际化翻译字符重构汇总.xlsx'
app_zh_column = 4
h5_source_file = './H5国际化翻译字符重构汇总.xlsx'
h5_zh_column = 3

def convert_safe_string(text):
    s = str(text).replace('<font>', '[font]').replace('</font>', '[/font]') \
        .replace('\n', '\\n') \
        .replace('\'', '\\\'') \
        .replace('&', '&')
    return re.sub('%\D|%$', lambda x: "%%" + x.group()[1:], s)

def read_excel():
    outfile = xlwt.Workbook()
    # 新建一个sheet
    wtable = outfile.add_sheet('info', cell_overwrite_ok=True)

    data = xlrd.open_workbook(app_source_file)
    table = data.sheets()[0]
    nrows = table.nrows
    write_column = 0
    wtable.write(0, write_column, "APP")
    for i in range(1, nrows):
        value = str(table.row_values(i)[app_zh_column])
        # 写入数据table.write(行,列,value)
        wtable.write(i, write_column, Simplified2Traditional(value))
    print('读取完毕 app')

    data = xlrd.open_workbook(h5_source_file)
    table = data.sheets()[0]
    nrows = table.nrows
    write_column = 1
    wtable.write(0, write_column, "H5")
    for i in range(1, nrows):
        value = str(table.row_values(i)[h5_zh_column])
        # 写入数据table.write(行,列,value)
        wtable.write(i, write_column, Simplified2Traditional(value))
    print('读取完毕 h5')
    # 保存文件
    outfile.save('zht.xls')

if __name__ == '__main__':
    read_excel()


file1 = open('day2.input.txt', 'r')
Lines = file1.readlines()

depth = 0
horizontal = 0

for line in Lines:
    instruction = line.split()
    if instruction[0] == 'forward': horizontal += int(instruction[1])
    if instruction[0] == "down": depth += int(instruction[1])
    if instruction[0] == "up": depth -= int(instruction[1])

print("Depth: " + str(depth))
print("Horizontal: " + str(horizontal))
print(depth*horizontal)


class Solution(object):
    def nthUglyNumber(self, n):
        """
        :type n: int
        :rtype: int
        """
        res = [1]
        idx2 = 0
        idx3 = 0
        idx5 = 0
        for i in range(n-1):
            res.append(min(res[idx2]*2,res[idx3]*3,res[idx5]*5))
            if res[-1] == res[idx2]*2:
                idx2 += 1
            if res[-1] == res[idx3]*3:
                idx3 += 1
            if res[-1] == res[idx5]*5:
                idx5 += 1
        return res[-1]
a = input()
s = Solution()
print(s.nthUglyNumber(int(a)))


from rest_framework.serializers import ModelSerializer
from account.models import User
from .models import Article, Category, Comment

class DynamicSerializer(ModelSerializer):
    def __init__(self, *args, **kwargs):
        fields = kwargs.pop('fields', None)
        super(DynamicSerializer, self).__init__(*args, **kwargs)
        if fields is not None:
            allowed = set(fields)
            existing = set(self.fields)
            for field_name in existing - allowed:
                self.fields.pop(field_name)

class UserDetailSerializer(DynamicSerializer):
    class Meta:
        model = User
        fields = '__all__'

class CategoryDetailSerializer(DynamicSerializer):
    class Meta:
        model = Category
        fields = '__all__'

class ArticleSerializer(DynamicSerializer):
    author = UserDetailSerializer(read_only=True, fields=('id', 'avatar', 'username'))
    category = CategoryDetailSerializer(read_only=True)
    class Meta:
        model = Article
        fields = '__all__'

class CommentSerializer(DynamicSerializer):
    user = UserDetailSerializer(read_only=True, fields=('id', 'avatar', 'username'))
    class Meta:
        model = Comment
        fields = '__all__'


from keras.datasets import boston_housing
from keras import models, layers
import numpy as np

import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt

print("获取数据集")
(train_data, train_targets), (test_data, test_targets) = boston_housing.load_data()
print("训练数据大小", train_data.shape)
print("测试数据大小", test_data.shape)
print("训练目标是房屋价格中位数，单位是千美元")
print(train_targets)

print("标准化数据，特征的平均值为 0，标准差为 1")
mean = train_data.mean(axis=0)
train_data -= mean
std = train_data.std(axis=0)
train_data /= std
print("在工作流程中，不能使用在测试数据上计算得到的任何结果，标准化也不行")
test_data -= mean
test_data /= std

print("构建网络，较小的网络可以降低过拟合")
print("MSE - 均方误差，回归问题常用")
print("MAE - 平均绝对误差，比如 MAE 0.5 在这里意味着平均价格相差 500 美元")
def build_model():
    model = models.Sequential()
    model.add(layers.Dense(64, activation='relu', input_shape=(train_data.shape[1], )))
    model.add(layers.Dense(64, activation='relu'))
    model.add(layers.Dense(1))
    model.compile(optimizer='rmsprop', loss='mse', metrics=['mae'])
    return model

print("在小样本上利用 K Fold 验证")
k = 4
num_val_samples = len(train_data) // k
num_epochs = 500
all_mae_histories = []

for i in range(k):
    print("处理 Fold #", i)
    val_start = i * num_val_samples
    val_end = val_start + num_val_samples
    # 验证数据
    val_data = train_data[val_start: val_end]
    val_targets = train_targets[val_start: val_end]
    # 训练数据
    partial_train_data = np.concatenate(
        [train_data[:val_start],
        train_data[val_end:]],axis=0)
    partial_train_targets = np.concatenate(
        [train_targets[:val_start],
        train_targets[val_end:]],axis=0)

    model = build_model()
    history = model.fit(partial_train_data, partial_train_targets,
                            validation_data=(val_data, val_targets),
                            epochs=num_epochs, batch_size=1, verbose=0)
    mae_history = history.history['val_mean_absolute_error']
    all_mae_histories.append(mae_history)

print("计算所有轮次中 K 折验证分数平均值")
average_mae_history = [np.mean([x[i] for x in all_mae_histories]) for i in range(num_epochs)]
print("绘制验证分数")
plt.plot(range(1, len(average_mae_history) + 1), average_mae_history)
plt.xlabel('Epochs')
plt.ylabel('Validation MAE')
plt.show()

print("重新绘制以看清规律。删除前十个点；将每个数据点替换为前面数据点的指数移动平均值")
def smooth_curve(points, factor=0.9):
    smoothed_points = []
    for point in points:
        if smoothed_points:
            previous = smoothed_points[-1]
            smoothed_points.append(previous * factor + point * (1 - factor))
        else:
            smoothed_points.append(point)
    return smoothed_points

smooth_mae_history = smooth_curve(average_mae_history[10:])
plt.clf()
plt.plot(range(1, len(smooth_mae_history) + 1), smooth_mae_history)
plt.xlabel('Epochs')
plt.ylabel('Validation MAE after Smoothing')
plt.show()
print("从图中可得 MAE 在 80 轮后不再降低，之后开始过拟合")

print("重新训练")
model = build_model()
model.fit(train_data, train_targets, epochs=80, batch_size=16, verbose=0)
test_mse_score, test_mae_score = model.evaluate(test_data, test_targets)
print("Test MSE", test_mse_score)
print("Test MAE", test_mae_score)


# UDP Ping Server
# Using random to simulate packet loss
import random
# Import socket module
from socket import *

# SOCK_STREAM for TCP, SOCK_DGRAM for UDP
serverSocket = socket(AF_INET, SOCK_DGRAM)
# Assign IP address and port number to socket
serverSocket.bind(('', 12000))
print('Server Active...')
while True:

    # Receive client packet and arrival address
    message, address = serverSocket.recvfrom(1024)
    # Capitalize the message
    message = message.upper()

    #Simulates a 20% packet loss rate
    if(random.randint(1,10) >2):
        # If no packet loss, server responds
        serverSocket.sendto(message, address)


#三维曲面

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
x=np.linspace(-7.5,7.5)
y=np.linspace(-7.5,7.5)
X,Y=np.meshgrid(x,y)
A=np.sqrt(X**2+Y**2)
Z=np.sin(A)/A
#创建3d图形
fig=plt.figure()
ax=Axes3D(fig)
#绘制三维曲面,使用彩虹色
ax.plot_surface(X,Y,Z,cmap=plt.get_cmap('rainbow'))
plt.show()


import time

from communities.spiders import MediaSpider, YgosuSpider

from scrapy.utils.project import get_project_settings
from scrapy.crawler import CrawlerRunner
from scrapy import signals

from twisted.internet import reactor

from celery import Celery, task
from celery.utils.log import get_task_logger

app = Celery(__name__)
logger = get_task_logger(__name__)

class SpiderRunner(CrawlerRunner):
    def __init__(self, spider):
        settings = get_project_settings()
        super(SpiderRunner, self).__init__( settings )
        self.spider = spider

    def run(self, *args, **kwargs):
        self.crawl( self.spider, *args, **kwargs )
        deferred = self.join()
        deferred.addBoth(lambda _: reactor.stop())
        reactor.callFromThread(lambda duration: time.sleep(duration), 5)
        reactor.run()

@app.task(ignore_result=True)
def runCommunitySpider(*args, **kwargs):
    print( 'runCommunitySpider' )
    runner = SpiderRunner( YgosuSpider )
    runner.run(*args, **kwargs)

@app.task(ignore_result=True)
def runMeidaSpider(*args, **kwargs):
    print( 'runMeidaSpider' )
    runner = SpiderRunner( MediaSpider )
    runner.run(*args, **kwargs)