# программа расчета нейросети, реализующей функцию XOR
import numpy as np

# Обучающая выборка
X = np.array([ [1,0,0],[1,0,1],[1,1,0],[1,1,1] ])
y = np.array([[0,1,1,0]]).T

print(X)
print(y)

# -------------- Моделирование классификатора XOR -------------
# логистическая функция активации
def sigmoidfun(z):
    return 1 / (1 + np.exp(-z))

def sigmderiv(z):
    return sigmoidfun(z) * (1 - sigmoidfun(z))

def sigmoideriv(y):
    return y * (1 - y)

np.random.seed(1)
s0 = 2 * np.random.random((2, 3)) - 1
s1 = 2 * np.random.random((1, 3)) - 1

def xor_nnet(x, syn0=s0, syn1=s1):
    a1 = x.T
    a2 = sigmoidfun(np.dot(syn0, a1))
    if len(a2.shape) > 1:
        ones = np.ones(shape=(1, a2.shape[1]))
        a20 = np.vstack((ones, a2))
    else:
        a20 = np.array([1, a2[0], a2[1]])
    a3 = sigmoidfun(np.dot(syn1, a20))
    return a1, a20, a3

# -------------- Моделирование классификатора XOR -------------
# Задаем веса для классификатора, реализующего функцию XOR
syn0 = np.array([ [-5,-10,10],[-5,10,-10] ])
syn1 = np.array([ [-5,10,10] ])

ynet = np.array([[0.0, 0.0, 0.0, 0.0]]).T
err = ynet
for i in range(len(X)):
    x = X[i]
    a1,a2,ynet[i] = xor_nnet(x, syn0, syn1)
    err[i] = y[i] - ynet[i]
    print("Ответ классификатора для", x, "=", ynet[i])

# --------------- анализ ошибок классификации -----------------
# СРЕДНЕКВАДРАТИЧЕСКАЯ ОШИБКА (MSE)
print('MSE=', sum(err*err)/len(err))
# print('MSE=', np.mean(err*err))

# кроссэнтропия распределений (log-loss)
def plogp(p):
    if abs(p) < 1e-12:
        return 0
    return p*np.log2(p)

# ------- попробуем обучить нейросеть простым град-м спуском ---------
# Попробуем обучить нейросеть XOR с помощью оптимизации
# случайно инициализируем веса, в среднем - 0
np.random.seed(3)
syn0 = 2*np.random.random((2,3)) - 1
syn1 = 2*np.random.random((1,3)) - 1

a1,a2,ynet = xor_nnet(X, syn0, syn1)
print(ynet)
# learning coef
alpha = 0.01

# Попробуем обучить нейросеть XOR
for j in range(600000):
    # проходим вперёд по слоям 0, 1 и 2
    a10,a20,a3 = xor_nnet(X, syn0, syn1)

    # как сильно мы ошиблись относительно нужной величины?
    a3_error = y - a3.T

    # рапространим ошибку на выходе 3-го слоя на вход слоя
    z3_delta = a3_error * sigmoideriv(a3.T)

    # распространим ошибки z3 на ошибки выходов a2 (входы для a3)
    a20_error = np.dot(syn1.T, z3_delta.T)
    # уберем 0-ю строку, содержащую добавленный +1
    a2 = a20[1:]
    a2_error = a20_error[1:]

    # рапространим ошибку на выходе 2-го слоя на вход слоя
    z2_delta = a2_error * sigmoideriv(a2)

    # рассчитаем дельта весов каждого слоя,
    # используя ошибки на входе (l+1) слоя и выходы l-го слоя
    syn1_delta = np.dot(z3_delta.T, a20.T)
    syn0_delta = np.dot(z2_delta, a10.T)

    syn1 += alpha* syn1_delta
    syn0 += alpha* syn0_delta

    if (j % 10000) == 0:
        print("Error:" + str(np.mean(np.abs(a3_error))))

print(syn1)
print(syn0)
a1,a2,ynet = xor_nnet(X, syn0, syn1)
print(ynet)
"""
Error:0.501780663237
Error:0.499985281905
Error:0.499510817604
Error:0.495886793439
Error:0.462283439271
Error:0.388309485676
Error:0.344607287938
Error:0.21591328267
Error:0.124516190796
Error:0.0912743545313
Error:0.0743180365023
...
Error:0.0161680950144
Error:0.0160026083371
syn0=
[[-7.00981282  4.58522782  4.55025869]
 [-2.98183124  6.76632391  6.60203154]]
syn1=
[[ -4.48638541 -10.51846703   9.74164621]]

"""

# ------- попробуем обучить нейросеть стохастическим градиентом ---------
# случайно инициализируем веса, в среднем - 0
np.random.seed(3)
syn0 = 2*np.random.random((2,3)) - 1
syn1 = 2*np.random.random((1,3)) - 1

# learning coef
alpha = 0.01
# pack size
pack_size = 3

# Попробуем обучить нейросеть XOR
for j in range(600000):
    # проходим вперёд по слоям 0, 1 и 2
    a10,a20,a3 = xor_nnet(X, syn0, syn1)
    # выбираем случайно pack_size объектов из обучающей выборки
    nobjs = np.random.choice(list(range(len(X))), pack_size, replace=False)
    # фильтруем нужные объекты и ответы
    a10 = a10[:, nobjs]
    a20 = a20[:, nobjs]
    a3 = a3[:, nobjs]
    yp = y[nobjs]

    # как сильно мы ошиблись относительно нужной величины?
    a3_error = yp - a3.T

    # рапространим ошибку на выходе 3-го слоя на вход слоя
    z3_delta = a3_error * sigmoideriv(a3.T)

    # распространим ошибки z3 на ошибки выходов a2 (входы для a3)
    a20_error = np.dot(syn1.T, z3_delta.T)
    # уберем 0-ю строку, содержащую добавленный +1
    a2 = a20[1:]
    a2_error = a20_error[1:]

    # рапространим ошибку на выходе 2-го слоя на вход слоя
    z2_delta = a2_error * sigmoideriv(a2)

    # рассчитаем дельта весов каждого слоя,
    # используя ошибки на входе (l+1) слоя и выходы l-го слоя
    syn1_delta = np.dot(z3_delta.T, a20.T)
    syn0_delta = np.dot(z2_delta, a10.T)

    syn1 += alpha* syn1_delta
    syn0 += alpha* syn0_delta

    if (j % 50000) == 0:
        print("Error:" + str(np.mean(np.abs(a3_error))))

print(syn1)
print(syn0)
a1,a2,ynet = xor_nnet(X, syn0, syn1)
print(a1)
print(a2)
print(ynet)

"""
Результат получился только после снижения альфа
alpha = 0.01
pack_size = 3

Error:0.608719767912
Error:0.481788312008
Error:0.122990617585
Error:0.0526038141682
Error:0.0384722962964
Error:0.0308505911275
Error:0.0278507120516
Error:0.0244147135194
Error:0.0225262690888
Error:0.0205620923888
Error:0.0194889004117
syn0=
[[-6.81597651  4.46157227  4.42166219]
 [-2.92654715  6.69726717  6.5037521 ]]
syn1=
[[ -4.31594635 -10.19845644   9.41363496]]

"""

# ---------- реализация нейросети XOR с помощью KERAS
# import the necessary packages
from keras.optimizers import SGD, Adam, Nadam
from keras.utils import np_utils

# imports used to build the deep learning model
from keras.models import Sequential
from keras.layers.core import Activation
from keras.layers import Input, Dense
from keras.layers import BatchNormalization, Dropout, Lambda
from keras.models import Model

# from keras. import binary_crossentropy
from keras import backend as K

import matplotlib.pyplot as plt

def graph_training_history(history):
    plt.figure(1)

    # summarize history for accuracy

    plt.subplot(211)
    plt.plot(history.history['acc'])
    plt.plot(history.history['val_acc'])
    plt.title('model accuracy')
    plt.ylabel('accuracy')
    plt.xlabel('epoch')
    plt.legend(['train', 'test'], loc='upper left')

    # summarize history for loss

    plt.subplot(212)
    plt.plot(history.history['loss'])
    plt.plot(history.history['val_loss'])
    plt.title('model loss')
    plt.ylabel('loss')
    plt.xlabel('epoch')
    plt.legend(['train', 'test'], loc='upper left')

    plt.show()

def build_XORnnet(nx = 2):
    # Input
    a1 = Input(shape=(nx,))
    a2 = Dense(2, activation='sigmoid')(a1)
    a3 = Dense(1, activation='sigmoid')(a2)

    classificator = Model(a1, a3, name="XORnnet")
    # Return the constructed network architecture
    return classificator

model = build_XORnnet(nx = 2)
# Посмотрим на число параметров
model.summary()

# Зададим основные параметры для обучения
batch_size = 4
Xb = X[:,1:]
yb = y

# Build and Compile the model
print("[INFO] Building and compiling the DNet model...")
#opt = SGD(lr=0.0002, momentum=0.0001, decay=0.00001, nesterov=True)
opt = Adam(lr=0.01)
#opt = Nadam(lr=0.0001)
model.compile(loss="binary_crossentropy", optimizer=opt, metrics=["accuracy"])

# Check the argument whether to train the model
print("[INFO] Training the model...")
history = model.fit(Xb, yb,
                    batch_size= batch_size,
                    epochs=50,
                    shuffle= True,
                    #validation_split= 0.3,
                    validation_data=(Xb, yb),
                    verbose=1)

# Visualize the training history
graph_training_history(history)

# Training of the model is now complete
#model.summary()

# Use the test data to evaluate the model
# check it on ctrldata - проверяем точность модели на контрольной выборке
#ctrlLabels_softmax = np_utils.to_categorical(ctrlLabels, n_classes)
print("[INFO] Evaluating the model...")
(loss, accuracy) = model.evaluate(ctrlData, ctrlLabels_softmax, verbose=1, batch_size= batch_size)
print("[INFO] CONTROL accuracy: {:.2f}%".format(accuracy * 100))


# -*- coding: utf-8 -*-
'''
Create on 2016-01-18 10:29:14

@author: huangzhenghua
'''

import copy
import cv2
import numpy as np
from ocr_digits.imgproc.binary import bitReverse

def inner_findContours(img,
                 contour_filter=False,
                 thresh='otsu',
                 min_area=25, max_area=2500,
                 min_h=5, min_w=5):

    if thresh == 'otsu':
        _, img = cv2.threshold(img, 0, 255,
                                     cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    elif thresh == 'adaptive':
        img = cv2.adaptiveThreshold(
            img,
            255,
            cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
            cv2.THRESH_BINARY, 11, 2)

    img = bitReverse(img)

    if cv2.__version__[0] == "2":
        contours, hierarchy = cv2.findContours(
            copy.deepcopy(img),
            cv2.RETR_TREE,
            cv2.CHAIN_APPROX_SIMPLE)
    else:
        _, contours, hierarchy = cv2.findContours(
            copy.deepcopy(img),
            cv2.RETR_TREE,
            cv2.CHAIN_APPROX_SIMPLE)

    if contour_filter:
        filtered_contours = []
        for cnt in contours:
            x, y, w, h = cv2.boundingRect(cnt)
            if w * h > min_area and h > min_h and w > min_w and w * h < max_area:
                filtered_contours.append(cnt)
        contours = filtered_contours
    return img, contours

def draw_contour_rect(img, contours):

    for cnt in contours:
        x, y, w, h = cv2.boundingRect(cnt)
        cv2.rectangle(img,
                      (x, y), (x + w, y + h),
                      (np.random.randint(0, 255, (3))), 1)


import torch
from torch import autograd, nn
import torch.nn.functional as F

batch_size = 10
input_size = 3
hidden_size = 5
num_classes = 3

torch.manual_seed(1234)
input = autograd.Variable(torch.rand(batch_size, input_size))

# This will not work for the forward pass and will print:
#     RuntimeError: save_for_backward can only save input or output tensors,
#                   but argument 0 doesn't satisfy this condition
# input = torch.rand(batch_size, input_size)
print("\nInput: ", input)

class Model(nn.Module):

    def __init__(self, input_size, hidden_size, num_classes):
        super().__init__()
        self.h1 = nn.Linear(input_size, hidden_size)
        #self.h2 = nn.Softmax(hidden_size, num_classes)
        self.h2 = nn.Linear(hidden_size, num_classes)
        #### self.h3 = nn.Softmax()

    def forward(self, x):
        x = self.h1(x)
        x = F.tanh(x)
        x = self.h2(x)
        ### x = self.h3(x)
        x = F.softmax(x)
        return x

model = Model(input_size=input_size,
              hidden_size=hidden_size,
              num_classes=num_classes)

out = model(input)
print('out', out)


# -*- coding: utf-8 -*-
from lib import db
from .userdata import userdata
import os
import copy
import fnmatch

class Settings:

        """Indicator Characters."""
        idents = '.=~'
        """Module search glob, {m} is replaced with the module name."""
        mglob = ['modules.{m}.*']

        def __init__(self, server):
            os.makedirs("%s/servers/%s" % (userdata, server.name),
                        exist_ok=True)
            os.makedirs("%s/shared/%s" % (userdata, server.shared),
                        exist_ok=True)
            self.db = db.DB("servers/%s/settings.json" % server.name)
            self.d = self.db.d
            self.defaults = {}
            self.user = []
            self.tree = {}

        def isdefault(self, n, v):
            """Determine if a setting <n> with value <v>
            is set to it's default."""
            pass

        def purge(self, m):
            """Purge module <m> from the settings DB."""
            c = 0
            tod = []
            for v in self.d:
                for g in self.mglob:
                    if fnmatch.fnmatch(v, g.format(m=m)):
                        c += 1
                        tod.append(v)
                        break
            for d in tod:
                self.d.pop(d)
            self.save()
            return c

        def pop(self, n):
            """Pop <n> from the DB."""
            r = self.d.pop(n)
            self.save()
            return r

        def get(self, n, pop=False):
            """Return the setting <n> or it's default."""
            if n not in self.d:
                self.d[n] = copy.deepcopy(self.defaults[n])
                ret = self.d[n]
                if type(ret) not in [list, dict] or pop:
                    self.d.pop(n)
                return ret
            return self.d[n]

        def branchdict(self, d, ss):
            s = None
            while ss:
                s = ss.pop(0)
                if s not in d:
                    d[s] = {}
                d = d[s]
            return d

        def addbranch(self, ss, n, rm=False):
            """Add <ss> to the tree with name <n>."""
            ss = copy.deepcopy(ss)
            d = self.tree
            d = self.branchdict(d, ss)
            if n.strip(self.idents) in d and rm:
                d.pop(n.strip(self.idents))
            d[n] = True

        def set(self, n, v):
            """Set <n> to <v>, adding it to the tree if neccessary."""
            split = n.split('.')
            sections = split[:-1]
            basen = split[-1]
            truename = '.'.join(sections + [basen.strip(self.idents)])
            self.d[truename] = v
            self.addbranch(sections, basen)
            self.save()

        def save(self):
            """Save the database, removing values set to their defaults."""
            tod = []
            for k in self.d:
                if k in self.defaults:
                    if self.d[k] == self.defaults[k]:
                        tod.append(k)
                else:
                    if self.isdefault(k, self.d[k]):
                        tod.append(k)
            for t in tod:
                self.d.pop(t)
            self.db.save()

        def add(self, n, v):
            """Add a default setting <n> with a value of <v>."""
            split = n.split('.')
            sections = split[:-1]
            basen = split[-1]
            truename = '.'.join(sections + [basen.strip(self.idents)])
            self.defaults[truename] = copy.deepcopy(v)
            if '=' not in basen and '~' not in basen:
                self.user.append(truename)
            self.addbranch(sections, basen)
            self.save()


from django.test import TestCase
#from .models import Item
from .forms import ItemForm
# Create your tests here.
class TestToDoItemForm(TestCase):

    #methods
    #make a long descriptive name
    def test_can_create_an_item_with_just_a_name(self): #methods have to precede with test_ or django won't find them
        #self.assertEqual(1,1)
        form = ItemForm({"name":"Create tests"}) #instantiate it from the ItemForm
        self.assertTrue(form.is_valid())
        #self.assertFalse(form.is_valid())

    def test_correct_message_for_missing_name(self):
        form = ItemForm({"name":""}) #instantiate it from the ItemForm
        self.assertFalse(form.is_valid())
        self.assertEqual(form.errors["name"], [u'This field is required.'])


import os
import time
import collections
import codecs

class GCodeParser:
    @staticmethod
    def remove_comment(gcode):
        gcode = gcode.split(';')
        if gcode[0] == '':
            try:
                cura_layer = gcode[1].find('LAYER:')
                if cura_layer == 0:
                    layer = int(gcode[1].split('LAYER:')[1])
                    return 'L%d' % layer

                simplify_layer = gcode[1].find(' layer ')
                if simplify_layer == 0:
                    layer = gcode[1].split(' layer ')[1]
                    if layer != 'end':
                        layer = int(layer[:layer.find(',')])
                    # layer = gcode[1][8:gcode[1].find(',')]
                    return 'L%d' % layer
            except Exception as e:
                print(" in gcodeparser remove comment %s" % e,gcode)
            return None
        else:
            return gcode[0]

    @staticmethod
    def remove_chomp(gcode):
        return gcode.strip()

    @staticmethod
    def parse(gcode):
        gcode = gcode.split(' ')
        dic = collections.OrderedDict()
        for item in gcode:
            if item != '':
                dic['%s' % item[0:1]] = str(item[1:])
        return dic

    @staticmethod
    def rebuild_gcode(dic):
        gcode = ''
        for item in dic:
            gcode += (item + dic[item]) + ' '
        return gcode


#!/usr/bin/env python3

#Get rid of those annoying numpy/tensorflow warnings
import warnings
warnings.filterwarnings("ignore", message="numpy.dtype size changed")
warnings.filterwarnings("ignore", message="numpy.ufunc size changed")

import keras
from PIL import Image
from keras.models import model_from_json
import numpy as np
from os import getcwd
from tqdm import trange, tqdm
import matplotlib.pylab as plt

# in_data = np.load("indata_for_prediction.npy")
# img_x, img_y = in_data[0].shape
# in_data = in_data.reshape(in_data.shape[0], img_x, img_y, 1)
#
# input_points = np.load("input_prediction_points.npy")

def get_input_data(p, i, j, kernel_size, h, w):
    min_i = int(i-(kernel_size-1)/2)
    max_i = int(i+(kernel_size-1)/2)
    min_j = int(j-(kernel_size-1)/2)
    max_j = int(j+(kernel_size-1)/2)

    data = []
    for k in range(min_i, max_i):
        row = [1 if k<0 or l<0 or k>=h or l>=w or p[k][l] <254 else 0 for l in range(min_j, max_j)]
        data.append(row)
        # for l in range(min_j, max_j):
        #     # if k != i and l != j:
        #     if k<0 or l<0 or k>=h or l>=w:
        #         data[k-min_i].append(1)
        #     elif p[k][l] >= 254:
        #         data[k-min_i].append(0)
        #     else:
        #         data[k-min_i].append(1)

    return np.array(data)

# load json and create model
json_file = open('convnet1.json', 'r')
loaded_model_json = json_file.read()
json_file.close()
loaded_model = model_from_json(loaded_model_json)
# load weights into new model
loaded_model.load_weights("convnet1.h5")

loaded_model.summary()

path = 'input_maps/maze.pgm'
# data_path = path + 'etu_1_condensed/'

I = Image.open(path)
p = np.asarray(I).astype('int')
w, h = I.size
im = np.zeros((w, h), dtype=int)
im_log = np.zeros((w, h), dtype=int)

kernel_size = 61

for i in trange(h, position=1):
    for j in range(w):
        if p[i][j] >= 254:
            in_data = get_input_data(p, i, j, kernel_size, h, w)
            img_x, img_y = in_data.shape
            in_data = in_data.reshape(1, img_x, img_y, 1)
            val = loaded_model.predict(in_data, verbose=0)

            # if len(val) != 1:
            # im[i][j] = val
            if val[0][0] >= 0:
            # tqdm.write("log val: " + str(val[0][0]))
                im_log[i][j] = np.log(val[0][0])-1

plt.imshow(im_log, cmap=plt.cm.Greys, interpolation='nearest')
plt.show()

# np.save("predicted_sim_data", im)


from django.conf.urls import patterns, include, url
from django.contrib import admin

from django.contrib.staticfiles.urls import staticfiles_urlpatterns

# Uncomment the next two lines to enable the admin:
# from django.contrib import admin
admin.autodiscover()

from dajaxice.core import dajaxice_autodiscover, dajaxice_config
dajaxice_autodiscover()

urlpatterns = patterns('',
    url(r'^$', 'lifetracker.views.index', name='index'),
    url(r'^about/$', 'lifetracker.views.about', name='about'),
    url(r'^contact/$', 'lifetracker.views.contact', name='contact'),
    url(r'^login/$', 'lifetracker.views.login', name="login"),
    url(r'^register/$', 'lifetracker.views.register', name='register'),
    url(r'^addEvent/$', 'lifetracker.views.addEvent', name='addEvent'),
    url(r'^home/$', 'lifetracker.views.home', name='home'),
    url(r'^logout/$', 'lifetracker.views.logout', name='logout'),
    url(r'^analysis/$', 'lifetracker.views.analysis', name='analysis'),
    url(r'^forgotAccount/$', 'lifetracker.views.forgotAccount', name="forgotAccount"),
    url(r'^deleteEvent/(\d+)', 'lifetracker.views.deleteEvent', name='deleteEvent'),
    url(r'^editEvent/(\d+)', 'lifetracker.views.editEvent', name='editEvent'),
    url(r'^checkUsername/', 'lifetracker.views.isUsernameAvailable', name='isUsernameAvailable'),

    # url(r'^lifeTrackerSite/', include('lifeTrackerSite.foo.urls')),

    # Uncomment the admin/doc line below to enable admin documentation:
    # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),

    # Uncomment the next line to enable the admin:
    url(r'^admin/', include(admin.site.urls)),
    url(dajaxice_config.dajaxice_url, include('dajaxice.urls')),
)

urlpatterns += patterns('',
    url(dajaxice_config.dajaxice_url, include('dajaxice.urls')),
)

urlpatterns += staticfiles_urlpatterns()


"""
165 Compare Version Numbers

Compare two version numbers version1 and version2.
If version1 > version2 return 1, if version1 < version2 return -1, otherwise return 0.

You may assume that the version strings are non-empty and contain only digits and the . character.
The . character does not represent a decimal point and is used to separate number sequences.
For instance, 2.5 is not "two and a half" or "half way to version three", it is the fifth second-level revision of the second first-level revision.

Here is an example of version numbers ordering:

0.1 < 1.1 < 1.2 < 13.37
"""
from itertools import zip_longest
# What about '1.', '..'?
# pitfalls: '1' and '1.0', '01' and '1', '1.0.0.0' and '1.000.00'
class Solution:
    #
    def compareVersion(self, version1, version2):
        """
        :type version1: str
        :type version2: str
        :rtype: int
        """
        nums1 = list(map(int, version1.split('.')))
        nums2 = list(map(int, version2.split('.')))

        while nums1 and nums1[-1] == 0:
            nums1.pop()
        nums1.append(0)

        while nums2 and nums2[-1] == 0:
            nums2.pop()
        nums2.append(0)

        n1, n2 = len(nums1), len(nums2)
        for i in range(min(n1, n2)):
            if nums1[i] > nums2[i]:
                return 1
            elif nums1[i] < nums2[i]:
                return -1

        if n1 > n2:
            return 1
        elif n1 < n2:
            return -1
        else:
            return 0

    # 2nd visit on 7/16/2020
    def compareVersion2(self, version1, version2):
        nums1 = list(map(int, version1.split('.')))
        nums2 = list(map(int, version2.split('.')))
        for a, b in zip_longest(nums1, nums2, fillvalue=0):
            if a < b: return -1
            elif a > b: return 1

        return 0

test_cases = [('0','1'), ('1.0', '1'), ('0.0', '1.0'), ('0.1','0.1'), ('0.0.9', '0.1'), ('1.5.91', '1.4.100')]
obj = Solution()
for case in test_cases:
    print(obj.compareVersion2(case[0], case[1]))


def initmemory(n):
    memory = []
    for i in range(n):
        memory.append([0, i + 1, 0])
    return [memory, 0]

def newnode(memstruct):
    memory, firstfree = memstruct
    memstruct[1] = memory[firstfree][1]
    return firstfree

def delnode(memstruct, index):
    memory, firstfree = memstruct
    memory[index][1] = firstfree
    memstruct[1] = index

def createandfillnode(memstruct, key):
    index = newnode(memstruct)
    memstruct[0][index][0] = key
    memstruct[0][index][1] = -1
    memstruct[0][index][2] = -1
    return index

def add(memstruct, root, x):
    memory = memstruct[0]
    key = memory[root][0]
    if x == key:
        return 0
    elif x < key:
        left = memory[root][1]
        if left == -1:
            memory[root][1] = createandfillnode(memstruct, x)
            return 1
        else:
            h = add(memstruct, left, x)
            h += 1
    elif x > key:
        right = memory[root][2]
        if right == -1:
            memory[root][2] = createandfillnode(memstruct, x)
            return 1
        else:
            h = add(memstruct, right, x)
            h += 1
    return h

sequence = list(map(int, input().split()))
seg_len = len(sequence) - 1
memstruct = initmemory(seg_len)
root = createandfillnode(memstruct, sequence[0])
root_height = 1
heights = [root_height]
seg_set = set()
seg_set.add(sequence[0])
for j in range(1, seg_len):
    num = sequence[j]
    if num not in seg_set:
        tree_height = add(memstruct, root, num)
        heights.append(tree_height + root_height)
        seg_set.add(num)

print(*heights)


from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from pathlib import Path
# we need to import the module Template
from string import Template
import smtplib
# Using the module Template we are going to read the HTML file
template = Template(Path("template.html").read_text())
message = MIMEMultipart()
message["from"] = "Yuri Avello"
message["to"] = "RECEIVER@gmail.com"
message["subject"] = "This is a test"
# With substitute we can indicate what to put instead of $name
body = template.substitute({"name": "john"})
message.attach(MIMEText(body, "html"))
message.attach(MIMEImage(Path("game2.jpg").read_bytes()))

with smtplib.SMTP(host="smtp.gmail.com", port=587) as smtp:
    smtp.ehlo()
    smtp.starttls()
    smtp.login("SENDER@gmail.com", "PASSWORD")
    smtp.send_message(message)
print("sent...")


import math

import numpy as np

from game import *

class RandomPlayer:

    def __init__(self, i):
        self.i = i

    def get_move(self, board, snake):
        r = rand.randint(0, 3)
        return MOVES[r]

class GeneticPlayer:

    def __init__(self, pop_size, num_generations, num_trails, window_size, hidden_size, board_size,
                 mutation_chance=0.1, mutation_size=0.1, iscrossover = False):
        self.pop_size = pop_size
        self.num_generations = num_generations
        self.num_trails = num_trails  # num of games that each brain is going to play
        self.window_size = window_size  # how much of the board each brain can see
        self.hidden_size = hidden_size  # size of the brain
        self.board_size = board_size

        self.mutation_chance = mutation_chance
        self.mutation_size = mutation_size
        self.iscrossover = iscrossover

        # DEBUG
        self.display = False

        # brain selected to play games
        self.current_brain = None
        self.pop = [self.generate_brain(self.window_size ** 2, self.hidden_size, len(MOVES)) for _ in range(self.pop_size)]

    # list of matrixes, each matrix is a layer of the neural network
    def generate_brain(self, input_size, hidden_size, output_size):
        # matrix 1 aka layer 1, all layers are randomly initialized for values between 0 and 1
        hidden_layer1 = np.array([[rand.uniform(-1, 1) for _ in range(input_size + 1)] for _ in range(hidden_size)])
        # matrix 2 aka layer 2
        hidden_layer2 = np.array([[rand.uniform(-1, 1) for _ in range(hidden_size + 1)] for _ in range(hidden_size)])
        # matrix 3 aka layer 3
        output_layer = np.array([[rand.uniform(-1, 1) for _ in range(hidden_size + 1)] for _ in range(output_size)])
        return [hidden_layer1, hidden_layer2, output_layer]

    def get_move(self, board, snake):
        input_vector = self.process_board(board, snake[-1][0], snake[-1][1], snake[-2][0], snake[-2][1])
        hidden_layer1 = self.current_brain[0]
        hidden_layer2 = self.current_brain[1]
        output_layer = self.current_brain[2]

        # forward prop, each layer will produce a new input vector and we send it forward thru entire network
        # hidden result is the result of multiplying the input vector with the weights of the hidden layer
        # and we do it row wise, that's why we use [i] indexing
        # np.dot is a function that multiplies the two matrices
        # math.tanh is a function that takes a number and returns a number between -1 and 1, hyperbolic tangent
        # that function helps us to make the network more robust to different inputs and not have values blow up

        hidden_result1 = np.array([math.tanh(np.dot(input_vector, hidden_layer1[i])) for i in range(hidden_layer1.shape[0])] + [1])  # [1] for bias
        hidden_result2 = np.array([math.tanh(np.dot(hidden_result1, hidden_layer2[i])) for i in range(hidden_layer2.shape[0])] + [1])  # [1] for bias
        output_result = np.array([np.dot(hidden_result2, output_layer[i]) for i in range(output_layer.shape[0])])  # [1] for bias

        # we add 1 for bias so the weights are the same

        max_index = np.argmax(output_result)
        return MOVES[max_index]

    def process_board(self, board, x1, y1, x2, y2):
        # x and y are position of the snake
        # input vector is the board around the snake with snake's head in the center
        input_vector = [[0 for _ in range(self.window_size)] for _ in range(self.window_size)]

        # i and j are gonna index the window
        # ii and jj are gonna index the board

        for i in range(self.window_size):
            for j in range(self.window_size):
                # starting point that is half of the window size away from the snake's head in both directions
                ii = x1 + i - self.window_size // 2
                jj = y1 + j - self.window_size // 2
                # if window out of bounds, snake cannot move to that position
                if ii < 0 or jj < 0 or ii >= self.board_size or jj >= self.board_size:
                    input_vector[i][j] = -1 # -1 is a wall
                elif board[ii][jj] == FOOD:
                    input_vector[i][j] = 1 # 1 is food
                elif board[ii][jj] == EMPTY:
                    input_vector[i][j] = 0 # 0 is empty or viable move
                else:  # it is another snake
                    input_vector[i][j] = -1 # -1 is another snake

        if self.display: # DEBUG, display the board that snake sees
            print(np.array(input_vector))
        input_vector = list(np.array(input_vector).flatten()) + [1] # flatten function merges all the elements of the matrix into a single list
        return np.array(input_vector)

    def reproduce(self, top_25):
        new_pop = []
        for brain in top_25:
            new_pop.append(brain) # adding a copy of the top 25 brains to the new population
        for brain in top_25:
            new_brain = self.mutate(brain)
            new_pop.append(new_brain) #adding a mutated copy of the top 25 brains to the new population
        # spawn new random brains for the remaining 50% of the population
        if(self.iscrossover):
            for _ in range(self.pop_size // 4):
                new_pop.append(self.generate_brain(self.window_size ** 2, self.hidden_size, len(MOVES))) # same as init
            #crossover leftover brains
            for _ in range(self.pop_size // 4):
                new_pop.append(self.crossover(top_25[_], top_25[rand.randint(0, len(top_25) - 1)]))
        elif(self.iscrossover == False):
            for _ in range(self.pop_size // 2):
                new_pop.append(self.generate_brain(self.window_size ** 2, self.hidden_size, len(MOVES)))

        return new_pop

    def crossover(self, brain1, brain2):
       # crossing over the brains by taking a random part of each brain and combining them
        new_brain = []
        for i in range(len(brain1)):
            new_brain.append(np.array([[rand.choice([brain1[i][j][k], brain2[i][j][k]]) for k in range(len(brain1[i][j]))] for j in range(len(brain1[i]))]))
        return new_brain

    def mutate(self, brain):
        new_brain = []
        for layer in brain:
            new_layer = np.copy(layer) # for each matrix in the brain, we make a copy of the matrix
            for i in range(new_layer.shape[0]):
                for j in range(new_layer.shape[1]): # we iterate through each element in the matrix
                    if rand.uniform(0, 1) < self.mutation_chance:
                         # with probability mutation_chance, we mutate the element
                         # if we roll a random number between 0 and 1, we mutate the element
                        new_layer[i][j] += rand.uniform(-1, 1) * self.mutation_size
                         # we add a random number between -1 and 1 scaled by (times) mutation_size
            new_brain.append(new_layer)
        return new_brain

    def one_generation(self):
        # one playthrough of the game, each brain plays one game
        scores = [0 for _ in range(self.pop_size)] # housing the scores of each brain
        # DEBUG
        max_score = 0
        for i in range(self.pop_size):
            for j in range(self.num_trails):
                self.current_brain = self.pop[i]
                game = Game(self.board_size, 1, [self])
                outcome = game.play(False, termination=True)
                # outcome is whatever happes when we play the game
                score = len(game.snakes[0])  # for single player variation
                scores[i] += score
                # DEBUG
                # if outcome == 0: # if snake made it the last turn
                    # print("Snake", i, "made it to the last turn")

                if score > max_score:
                    max_score = score
                    print(max_score, "at ID", i)
        # Testing of each brain is complete and they are all ranked
        top_25_indexes = list(np.argsort(scores))[3*(self.pop_size//4):self.pop_size]
        # DEBUG
        print(scores)
        top_25 = [self.pop[i] for i in top_25_indexes][::-1]
        # we reverse the list so the best brains are at the top
        self.pop = self.reproduce(top_25) # update the population

    def evolve_pop(self):
        for i in range(self.num_generations):
            self.one_generation()
            print("gen", i)
            # we going to go over num_generations and will call one_generation function
            # this will go over every single generation and update the population based on how well the brains did

        # DEBUG, display boards for the top brains
        key = input("enter any character to display boards")
        for brain in self.pop:
            self.display = True
            self.current_brain = brain
            game = Game(self.board_size, 1, [self], display=True)
            gui = Gui(game, 800)
            game.play(True, termination=True)
            print("Snake length", len(game.snakes[0]))

# add mating


#Step 1
import random
import hangman_word
import hangman_art

word = random.choice(hangman_word.word_list)

empty=[]
l = len(word)

for w in word:
  empty.append("_")

print(hangman_art.logo,"\n")
print(f"{' '.join(empty)}\n")

end_of_game = False
lives = 6

while not end_of_game:

  guess = input("Guess a letter: ").lower()

  for x in range(0, l):
    letter = word[x]
    if letter == guess:
      empty[x] = letter

  print(f"{' '.join(empty)}","\n")

  if guess not in empty:
    lives -=1
    print(hangman_art.stages[lives])

    if lives ==0:
      end_of_game =True

      print(hangman_art.lose)
  else:
    print(hangman_art.stages[lives])

  if "_" not in empty:
    end_of_game = True
    print(hangman_art.win)


# -*- coding: utf-8 -*-
import re
import pandas as pd
from urllib import request
from datetime import date

URL = 'https://www.sozialministerium.at/Informationen-zum-Coronavirus/Neuartiges-Coronavirus-(2019-nCov).html'
STATES = {
    'Burgenland': 'B',
    'Kärnten': 'K',
    'Niederösterreich': 'NÖ',
    'Oberösterreich': 'OÖ',
    'Salzburg': 'S',
    'Steiermark': 'ST',
    'Tirol': 'T',
    'Vorarlberg': 'V',
    'Wien': 'W'
}
FILE_FATALITIES = 'data_AT/covid19_fatalities_austria.csv'
FILE_CASES = 'data_AT/covid19_cases_austria.csv'

def retrieve():
    r = request.urlopen(URL).read().decode().replace('\n', '').replace('\t', '').replace(' ', '')
    regex_cases = re.compile('
Best(.*)Todes')
    regex_fatalities = re.compile('
Todes(.*)
')
    regex = re.compile('([\w&;]+) \(([\d.]+)\)')

    cases = regex.findall(regex_cases.search(r).group(1))
    fatalities = regex.findall(regex_fatalities.search(r).group(1))

    return cases, fatalities

def append_csv(filename, data):
    df = pd.read_csv(filename)

    values = {k[1]:0 for k in STATES.items()}
    for d in data:
        values[STATES[d[0]]] = int(d[1].replace('.', ''))

    values['AT'] = sum([v[1] for v in values.items()])
    values['Date'] = date.today().strftime('%Y-%m-%d')

    df = df.append(values, ignore_index=True)
    df['Date'] = pd.to_datetime(df['Date'])
    df = df.set_index('Date')
    df.to_csv(filename)

def update_data():
    cases, fatalities = retrieve()
    append_csv(FILE_CASES, cases)
    append_csv(FILE_FATALITIES, fatalities)

if __name__ == "__main__":
    update_data()


"""
1411 Number of Ways to Paint N × 3 Grid

You have a grid of size n x 3 and you want to paint each cell of the grid with exactly one of the three colours: Red, Yellow or Green while making sure that no two adjacent cells have the same colour (i.e no two cells that share vertical or horizontal sides have the same colour).

You are given n the number of rows of the grid.

Return the number of ways you can paint this grid. As the answer may grow large, the answer must be computed modulo 10^9 + 7.

Example 1:

Input: n = 1
Output: 12
Explanation: There are 12 possible way to paint the grid as shown:

Example 2:

Input: n = 2
Output: 54
Example 3:

Input: n = 3
Output: 246
Example 4:

Input: n = 7
Output: 106494
Example 5:

Input: n = 5000
Output: 30228214

Constraints:
n == grid.length
grid[i].length == 3
1 <= n <= 5000
"""
# https://leetcode.com/problems/number-of-ways-to-paint-n-3-grid/discuss/574923/JavaC%2B%2BPython-DP-O(1)-Space
# Group every row to "121" style and "123" style, here "121" means first and third color are the same, "123" means all three colors are different
# For "121", it can be followed by "212", "213", "232", "312", "313"
# For "123", it can be followed by "212", "231", "232", "312"
class Solution:
    def numOfWays(self, n: int) -> int:
        a121, a123 = 6, 6
        M = 10**9 + 7
        for _ in range(n-1):
            b121, b123 = a121*3 + a123*2, a121*2 + a123*2
            a121, a123 = b121 % M, b123 % M

        return (a121 + a123) % M


pks = open('input', 'r').read().split('\n')

# transform subject number (s)
# n as for 1 untilloop size (ls):
# v = n
# 1. v = v * ls
# 2. v = v / 20201227 remainder

sn = 7
card_pk = 5764801
# card_ls = 8

door_pk = 17807724
# card_ls = 11

#
#

def transform(sn, ls):
  value = 1
  i = 0

  while i < ls:
    value *= sn
    value = value % 20201227
    i += 1

  return value

def find_ls(pk):
  value = 1
  i = 0

  while True:
    if pk == value:
      return i

    value *= sn
    value = value % 20201227
    i += 1

v = 0

print(pks)

# pks = [card_pk, door_pk]

ls = [find_ls(int(pk)) for pk in pks]

print('ls', ls, transform(7, 11))

print('keys', transform(int(pks[0]), ls[1]), transform(int(pks[1]), ls[0]))


# from collections import defaultdict
# import heapq

# M = 998244353

# x = int(input())

# seen = defaultdict(int)
# seen[x] = 1
# splited = [-x]
# heapq.heapify(splited)
# while True:
#     biggest = -1 * heapq.heappop(splited)
#     a, b = biggest//2, (biggest+1)//2
#     if biggest >= a * b:
#         break
#     seen[biggest] -= 1
#     append_lst = [-a, -b]
#     for num in append_lst:
#         heapq.heappush(splited, num)
#     seen[a] += 1
#     seen[b] += 1

# ans = 1
# for key, value in seen.items():
#     ans *= (key ** value) % M
#     ans %= M

# print(ans)

M = 998244353

X = int(input())

seen = dict()

def func(x):
    if x <= 4:
        return x
    if x in seen:
        return seen[x]
    a, b = x//2, (x+1)//2
    seen[x] = (func(a) * func(b)) % M
    return seen[x]

ans = func(X)

print(ans)


import pygame
import random
import time
from sudoku_generator import *

class SudokuGame:

    def __init__(self,grille,solution):

        if not grille:
           grille = [[0] * 9 for _ in range(9)]

        pygame.init()
        self.screen = pygame.display.set_mode((1200, 900))
        pygame.display.set_caption("Sudoku Game")

        self.BLACK = (0, 0, 0)
        self.WHITE = (255, 255, 255)

        self.font = pygame.font.Font(None, 46)
        self.font_candidate = pygame.font.Font(None,25)
        self.font_menu = pygame.font.Font(None,25)

        self.cell_size = 90
        self.cell_margin = 0
        self.grid_margin = 40

        self.menu_open = False  # Variable pour indiquer si le menu est ouvert
        self.hovered_option = None  # Variable pour suivre l'option survolée par la souris

        self.grid = grille
        self.solution=solution
        self.menu_option_rects = []  # Rectangles des options de menu
        self.selected_cell = None

        self.menu_option_rects = []  # Rectangles des options de menu
        self.create_widgets()
        self.create_menu()

        self.initial_color=pygame.Color(random.randint(190,220),random.randint(190,220),random.randint(190,220))
        self.completed_color=pygame.Color(random.randint(220,250),random.randint(220,250),random.randint(220,250))

        self.textbox_rect=None
        self.input_text = ""
        self.candidate_mode = False

        self.pause_button_hovered=False
        self.start_time=time.time()
        self.paused_time = 0
        self.duration_heures=0
        self.duration_minutes=0
        self.duration_secondes=0

    def create_menu(self):
        self.menu_button = pygame.Rect(1100, 20, 40, 40)  # Position et taille du bouton de menu
        self.menu_options = [
            {'text': 'Nouvelle partie', 'action': self.start_new_game},
            {'text': 'Réinitialiser grille', 'action': self.reinitialize_grid},
            {'text': 'Résoudre grille','action':self.solve_grid},
            {'text': 'Quitter', 'action': quit}
         ]  # Options de menu avec leur texte et action associée
        self.menu_option_rects = []  # Liste de rectangles pour les options de menu

    def create_menu_options(self):
        self.menu_option_rects = []  # Réinitialiser la liste des rectangles des options de menu
        menu_top = self.grid_margin + 60
        menu_left = self.screen.get_width() - self.grid_margin - 200
        for index, option in enumerate(self.menu_options):
            option_rect = pygame.Rect(menu_left,menu_top + index * 60,200,50)
            self.menu_option_rects.append(option_rect)

    def draw_timer(self):

        timer_top = self.grid_margin
        timer_left = self.screen.get_width() - self.grid_margin - 200
        timer_rect = pygame.Rect(timer_left,timer_top,80,40)

        pygame.draw.rect(self.screen,self.completed_color,timer_rect)
        str_time= str(self.duration_minutes+100)[-2:]+":"+str(self.duration_secondes+100)[-2:]
        text = self.font_menu.render(str_time,True,pygame.Color('black'))
        text_rect = text.get_rect(center=timer_rect.center)
        self.screen.blit(text, text_rect)

    def draw_pause_button(self):

        if self.pause_button['hovered']:
            color = self.initial_color
        else:
            color = self.completed_color

        pygame.draw.rect(self.screen,color,self.pause_button['rect'])
        pygame.draw.rect(self.screen,self.completed_color,self.pause_button['rect'],4)
        if self.pause_button['on_pause']:
            pygame.draw.polygon(self.screen, pygame.Color('black'), [(self.pause_button['left'] + 15, self.pause_button['top'] + 10), (self.pause_button['left'] + 15, self.pause_button['top'] + 30), (self.pause_button['left'] + 30, self.pause_button['top']  + 20)])
        else:
            pygame.draw.line(self.screen, pygame.Color('black'), (self.pause_button['left']+16,self.pause_button['top']+12), (self.pause_button['left']+16, self.pause_button['top']+28), 5)
            pygame.draw.line(self.screen, pygame.Color('black'), (self.pause_button['left']+24,self.pause_button['top']+12), (self.pause_button['left']+24, self.pause_button['top']+28), 5)

    def draw_menu_button(self):
        pygame.draw.rect(self.screen, pygame.Color('white'), self.menu_button)
        pygame.draw.line(self.screen, pygame.Color('black'), (1115, 40), (1140, 40), 4)
        pygame.draw.line(self.screen, pygame.Color('black'), (1115, 45), (1140, 45), 4)
        pygame.draw.line(self.screen, pygame.Color('black'), (1115, 50), (1140, 50), 4)

    def draw_menu_options(self):
        for index, option_rect in enumerate(self.menu_option_rects):
            if index==self.hovered_option:
                color = self.initial_color
            else:
                color = self.completed_color
            pygame.draw.rect(self.screen, color, option_rect)
            pygame.draw.rect(self.screen, pygame.Color('black'), option_rect, 2)
            text = self.font_menu.render(self.menu_options[index]['text'], True, pygame.Color('black'))
            text_rect = text.get_rect(center=option_rect.center)
            self.screen.blit(text, text_rect)

    def handle_menu_click(self, pos):

        if self.menu_button.collidepoint(pos):
            self.menu_open = not self.menu_open
            if self.menu_open:
                self.create_menu_options()

        if self.menu_open:
            for index, option_rect in enumerate(self.menu_option_rects):
                if option_rect.collidepoint(pos):
                    self.hovered_option = index  # Mettre à jour l'option survolée
                    self.menu_options[index]['action']()
                else:
                    self.hovered_option = None

        else:
             self.hovered_option = None

    def handle_pause_button(self,pos):
        if self.pause_button['rect'].collidepoint(pos):
            self.pause_button['hovered'] = True
            self.pause_button['on_pause'] = not self.pause_button['on_pause']
            if self.pause_button['on_pause']:
                self.pause_button['start_time'] = time.time()
            else:
                self.paused_time = self.paused_time + self.pause_button['duration']
                self.pause_button['duration']=0
        else:
            self.pause_button['hovered'] = False
        self.draw_pause_button()

    def draw_window(self):
        if self.pause_button['on_pause']:
           self.draw_pause_window()
        else:
            self.draw_grid()  # Dessiner la grille
        self.draw_menu_button()  #dessiner bouton hamburger du menu
        self.draw_timer() #dessiner le timer
        if not self.grid_completed():
            self.draw_pause_button() #dessiner le bouton pause

        if self.menu_open:
            pos = pygame.mouse.get_pos()
            for index, option_rect in enumerate(self.menu_option_rects):
                if option_rect.collidepoint(pos):
                    self.hovered_option = index  # Mettre à jour l'option survolée
            self.draw_menu_options()  # Dessiner les options de menu

        pygame.display.flip()

    def create_widgets(self):
        # create grid cells
        self.cells = [{'rect': pygame.Rect(self.grid_margin + j * (self.cell_size + self.cell_margin),
                                   self.grid_margin+i * (self.cell_size + self.cell_margin),
                                   self.cell_size, self.cell_size),
               'value': self.grid[i][j],
               'row': i,
               'col': j,
               'editable': self.grid[i][j] == 0,
               'candidate': ""}
              for i in range(9) for j in range(9)]

        # create the selected cell rectangle
        self.selected_rect = pygame.Rect(0, 0, self.cell_size, self.cell_size)
        self.selected_rect_color = pygame.Color('blue')

        # create pause button
        pause_top = self.grid_margin
        pause_left = self.screen.get_width() - self.grid_margin - 120
        self.pause_button = {'rect':pygame.Rect(pause_left,pause_top,40,40),'hovered':False,'top':pause_top,'left':pause_left,'on_pause':False,'start_time':None,'duration':0}

    def draw_pause_window(self):
        # draw the pause window
        w = 9 * (self.cell_size + self.cell_margin)
        rect = pygame.Rect(self.grid_margin,self.grid_margin,w,w)
        pygame.draw.rect(self.screen,pygame.Color("lightgray"),rect)

        text = self.font.render("En pause", True, pygame.Color('darkgray'))
        text_rect = text.get_rect(center=rect.center)
        self.screen.blit(text, text_rect)

    def draw_grid(self):

        # Create a new display surface with the desired width and height
        thickness=4
        self.screen.fill(pygame.Color(self.WHITE))

        #initialize current grid to use the valid function of the sudoku generator module
        current_grid = [[0 for _ in range(9)] for _ in range(9)]
        for cell in self.cells:
            current_grid[cell["row"]][cell["col"]] = cell['value']

        #initialize color scheme

        if self.grid_completed():
            editable_color = self.completed_color
            non_editable_color = self.completed_color
        else:
            editable_color=self.completed_color
            non_editable_color=self.initial_color

        for cell in self.cells:
            row = cell["row"]
            col = cell["col"]
            value = cell["value"]
            pos = (row,col)

            text_color = 'black'
            if value !=0:
                if not valid(current_grid,value,pos):
                    text_color = 'red'

            if not cell['editable']:
                pygame.draw.rect(self.screen, pygame.Color(non_editable_color), cell['rect'])
            else:
                 pygame.draw.rect(self.screen, pygame.Color(editable_color), cell['rect'])

            pygame.draw.rect(self.screen, pygame.Color('lightblue'), cell['rect'],1)

            if cell['value'] != 0:
                text = self.font.render(str(cell['value']), True, pygame.Color(text_color))
                text_rect = text.get_rect(center=cell['rect'].center)
                self.screen.blit(text, text_rect)
            else:
                text = self.font_candidate.render(str(cell['candidate']), True, pygame.Color(text_color))
                text_rect = text.get_rect(center=cell['rect'].center)
                self.screen.blit(text, text_rect)

            # Add thicker borders for 3x3 regions
            if (cell['row']) % 3 == 0 and (cell['col']) % 3 == 0:
                pygame.draw.line(self.screen, pygame.Color('black'), cell['rect'].topleft, cell['rect'].topright, thickness)
                pygame.draw.line(self.screen, pygame.Color('black'), cell['rect'].topleft, cell['rect'].bottomleft, thickness)
            elif (cell['row']) % 3 == 0:
                pygame.draw.line(self.screen, pygame.Color('black'), cell['rect'].topleft, cell['rect'].topright, thickness)
            elif (cell['col']) % 3 == 0:
                pygame.draw.line(self.screen, pygame.Color('black'), cell['rect'].topleft, cell['rect'].bottomleft, thickness)

            if (cell['row']) == 8:
                pygame.draw.line(self.screen, pygame.Color('black'), cell['rect'].bottomleft, cell['rect'].bottomright, thickness)
            if (cell['col']) == 8:
                pygame.draw.line(self.screen, pygame.Color('black'), cell['rect'].topright, cell['rect'].bottomright, thickness)

            if self.selected_cell:
                pygame.draw.rect(self.screen, self.selected_rect_color, self.selected_rect, thickness)

            if self.candidate_mode:
                    pygame.draw.rect(self.screen, pygame.Color('white'), self.textbox_rect)
                    pygame.draw.rect(self.screen, pygame.Color('red'), self.textbox_rect,4)
                    text = self.font_candidate.render(self.selected_cell['candidate'], True, pygame.Color('black'))
                    text_rect = text.get_rect(center=self.textbox_rect.center)
                    self.screen.blit(text, text_rect)

    def select_cell(self, cell):
        # initialize the selected cell
        self.selected_cell = cell
        self.selected_rect.topleft = cell['rect'].topleft

    def update_candidate(self):
        # update the list of candidate based on the input of the user
        left = self.grid_margin + self.selected_cell['col'] * (self.cell_size + self.cell_margin)
        top =  self.grid_margin + self.selected_cell['row'] * (self.cell_size + self.cell_margin)
        self.textbox_rect = pygame.Rect(left,top,self.cell_size, self.cell_size)
        while True:
            self.calculate_duration()
            self.input_text= self.selected_cell['candidate']
            for event in pygame.event.get():
                if event.type == pygame.KEYDOWN:
                    if event.unicode.isdigit():
                        self.input_text += event.unicode
                    elif event.key == pygame.K_RETURN:
                        print("Entered text:", self.input_text)
                        self.candidate_mode=False
                        self.selected_cell['candidate']=self.input_text
                        return
                    elif event.key == pygame.K_BACKSPACE or event.key == pygame.K_DELETE:
                        self.input_text = self.input_text[:-1]
                elif event.type == pygame.MOUSEBUTTONDOWN:
                    self.candidate_mode=False
                    return
            self.selected_cell['candidate']=self.input_text
            self.draw_window()

    def start_new_game(self):
        #start a new game
        self.selected_cell=None
        grid,solution =  generate_sudoku()
        game = SudokuGame(grid,solution)
        game.run()

    def reinitialize_grid(self):
        # restaore the grid to it's initial state
        for cell in self.cells:
            if cell['editable']:
                cell['value']=0
                cell['candidate']=""
        self.start_time=time.time()
        self.paused_time = 0
        self.duration_heures=0
        self.duration_minutes=0
        self.duration_secondes=0

    def solve_grid(self):
        # resoudre la grille initiale
        current_grid = [[0 for _ in range(9)] for _ in range(9)]
        for cell in self.cells:
            if not cell['editable']:
                current_grid[cell["row"]][cell["col"]] = cell['value']
        solve(current_grid)
        for cell in self.cells:
            cell['value'] = current_grid[cell['row']][cell['col']]

    def handle_events(self):

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                quit()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                pos = pygame.mouse.get_pos()
                self.handle_pause_button(pos)
                if self.pause_button['on_pause']:
                    break
                self.handle_menu_click(pos)  # Gérer le clic sur le bouton de menu ou sur une option de menu
                for cell in self.cells:
                    if cell['rect'].collidepoint(pos):
                        self.select_cell(cell)
                        break
            elif event.type == pygame.MOUSEBUTTONUP and not self.pause_button['on_pause']:
                if event.button==3:
                    self.candidate_mode = not self.candidate_mode
                    if self.candidate_mode and self.selected_cell:
                        if self.selected_cell['editable']:
                            self.update_candidate()
                    self.candidate_mode=False
                    self.selected_cell=None
            elif event.type == pygame.KEYDOWN and not self.pause_button['on_pause']:
                if self.selected_cell and self.selected_cell['editable']:
                    if event.unicode.isdigit():
                            self.selected_cell['value'] = int(event.unicode)
                            self.selected_cell = None
                    elif event.key == pygame.K_BACKSPACE or event.key == pygame.K_DELETE:
                        self.selected_cell['value'] = 0
                        self.selected_cell = None
            elif event.type == pygame.MOUSEMOTION:
                if self.menu_open:
                    for index, option_rect in enumerate(self.menu_option_rects):
                        if option_rect.collidepoint(event.pos):
                            self.hovered_option = index  # Mettre à jour l'option survolée
                        else:
                            self.hovered_option = None  # Réinitialiser l'option survolée

                if self.pause_button['rect'].collidepoint(event.pos):
                    self.pause_button['hovered']=True
                else:
                    self.pause_button['hovered']=False

    def grid_completed(self):
        for cell in self.cells:
            if cell['value'] != self.solution[cell['row']][cell['col']]:
                return False
        return True

    def calculate_duration(self):
        if not self.grid_completed():
            if self.pause_button['on_pause']:
                self.pause_button['duration'] = time.time()- self.pause_button['start_time']
            else:
                elapsed_time = time.time() - self.start_time - self.paused_time
                # Conversion du temps en heure minutes et secondes
                self.duration_heures = int(elapsed_time//3600)
                self.duration_minutes = int(int(elapsed_time % 3600)//60)
                self.duration_secondes=int(int(int(elapsed_time % 3600)%60))

    def play_game(self):
        while True:
            self.calculate_duration()
            self.handle_events()
            self.draw_window()

    def run(self):
        self.play_game()

if __name__ == '__main__':

    grid,solution =  generate_sudoku()
    game = SudokuGame(grid,solution)
    game.run()


"""
This patch just drops some known indexes which aren't being used anymore or never were used.
"""

import click

import frappe

UNUSED_INDEXES = [
	("Comment", ["link_doctype", "link_name"]),
	("Activity Log", ["link_doctype", "link_name"]),
]

def execute():
	if frappe.db.db_type == "postgres":
		return

	db_tables = frappe.db.get_tables(cached=False)

	# All parent indexes
	parent_doctypes = frappe.get_all(
		"DocType",
		{"istable": 0, "is_virtual": 0, "issingle": 0},
		pluck="name",
	)
	db_tables = frappe.db.get_tables(cached=False)

	for doctype in parent_doctypes:
		table = f"tab{doctype}"
		if table not in db_tables:
			continue
		drop_index_if_exists(table, "parent")

	# Unused composite indexes
	for doctype, index_fields in UNUSED_INDEXES:
		table = f"tab{doctype}"
		index_name = frappe.db.get_index_name(index_fields)
		if table not in db_tables:
			continue
		drop_index_if_exists(table, index_name)

def drop_index_if_exists(table: str, index: str):
	if not frappe.db.has_index(table, index):
		click.echo(f"- Skipped {index} index for {table} because it doesn't exist")
		return

	try:
		frappe.db.sql_ddl(f"ALTER TABLE `{table}` DROP INDEX `{index}`")
	except Exception as e:
		frappe.log_error("Failed to drop index")
		click.secho(f"x Failed to drop index {index} from {table}\n {str(e)}", fg="red")
		return

	click.echo(f"✓ dropped {index} index from {table}")


#Function should return the number of triplets forming a geometric progression for a given r as integer
#input format:
# n r
# n separated integers in arr[i]

#sample input:
# 4 2
# 1 2 2 4

# Sample output:
# 2

#notes:
#I hated this one so much
################################
#!/bin/python3

import math
import os
import random
import re
import sys

# Complete the countTriplets function below.
def countTriplets(arr, r):
    second = dict()
    third = dict()
    count = 0

    for i in arr:
        # if i is in third, then the triplet already completed and we need to increment the count
        if i in third:
            count += third[i]
        #if i is in second, then it is the second number of the triplet, successor needs to be added in case of a potential triplet
        if i in second:
            if i*r in third:
                third[i*r] += second[i] #if second i*r is in third, then we increase third's i*r by the value of second[i]
            else:
                third[i*r] = second[i]
        # else i is the first element of the triplet, so successor needs to be added or incremented in the r2 dict in case of potential triplet
        if i*r in second:
            second[i*r] += 1
        else:
            second[i*r] = 1
    return count

if __name__ == '__main__':
    fptr = open(os.environ['OUTPUT_PATH'], 'w')

    nr = input().rstrip().split()

    n = int(nr[0])

    r = int(nr[1])

    arr = list(map(int, input().rstrip().split()))

    ans = countTriplets(arr, r)

    fptr.write(str(ans) + '\n')

    fptr.close()


#!/usr/bin/env python3
'''
    sis_unpacker.py v0.3 by Yoti
'''

import os
import sys
import zlib
import struct
from datetime import datetime

def hexalign(value, align = 0):
    return '0x' + hex(value)[2:].zfill(align)

def Int64toTime(time):  # thx to Fire_Head
    return int((time / 1000000 - 3600) - 730497*24*3600 + (30*365*24*60*60+7*24*60*60))

def main():
    if len(sys.argv) < 2:
        print('usage: ' + sys.argv[0] + ' <in_file> [out_dir]')
        quit()

    if len(sys.argv) == 2:
        out_dir = os.path.splitext(sys.argv[1])[0]
    else:
        out_dir = sys.argv[2]

    fin_name = sys.argv[1]
    with open(fin_name, 'rb') as fin:
        fin_size = len(fin.read()); fin.seek(0)
        print('in: ' + fin_name + ' (' + str(fin_size) + ')', end='')

        uids = struct.unpack('<IIII', fin.read(16))
        if uids[1] != 0x10003a12 or uids[2] != 0x10000419:
            print()
            print('Unsupported file type!')
            quit()

        fin.seek(4, os.SEEK_CUR)
        files_count = struct.unpack('<H', fin.read(2))[0]
        print(' [' + str(files_count) + ']')

        fin.seek(30, os.SEEK_CUR)
        files_offset = struct.unpack('<I', fin.read(4))[0]
        fin.seek(files_offset, os.SEEK_SET)

        for i in range(0, files_count):
            file_record = struct.unpack('<IIIIIIIII', fin.read(36))
            fin.seek(12, os.SEEK_CUR)

            if file_record[0] == 0 or file_record[0] == 1:
                tmp = fin.tell()
                fin.seek(file_record[6], os.SEEK_SET)
                fout_name = out_dir + os.sep + fin.read(file_record[5]).decode('utf-16')[3:]
                print('out: ' + fout_name + ' (' + str(file_record[7]) + ' -> ', end='')

                fin.seek(file_record[8], os.SEEK_SET)
                fout_data_cmp = fin.read(file_record[7])

                try:
                    fout_data = zlib.decompress(fout_data_cmp)

                    print(str(len(fout_data)) + ')')
                    if not os.path.exists(os.path.dirname(fout_name)):
                        os.makedirs(os.path.dirname(fout_name))
                    with open(fout_name, 'wb') as fout:
                        fout.write(fout_data)

                    if fout_name.endswith('.app'):
                        time = Int64toTime(struct.unpack('<Q', fout_data[36:36+8])[0])
                        print('info: Application build timestamp is ', end='')
                        print(datetime.fromtimestamp(time).strftime("%Y/%m/%d %H:%M:%S"))
                except:
                    print(str(len(fout_data_cmp)) + ')')
                    if not os.path.exists(os.path.dirname(fout_name)):
                        os.makedirs(os.path.dirname(fout_name))
                    with open(fout_name, 'wb') as fout:
                        fout.write(fout_data_cmp)

                fin.seek(tmp, os.SEEK_SET)

if __name__ == "__main__":
    main()


from typing import Dict, Optional

import httpx
from loguru import logger
from tenacity import retry, stop_after_attempt

from telegram_bot.intergration.http.base_http_client import HttpClient

class HttpxClient(HttpClient):
    def __init__(self):
        transport = httpx.AsyncHTTPTransport(retries=3)
        timeout = httpx.Timeout(15.0, connect=60.0)
        self.client = httpx.AsyncClient(transport=transport, timeout=timeout)

    @retry(stop=stop_after_attempt(3))
    async def get(self, url: str, params: Optional[Dict] = None) -> Dict:
        logger.info(f"[http][get][request]{url}")
        r = await self.client.get(url, params=params)
        logger.info(f"[http][get][response]{url},{r.status_code},{r.json()}")

        r.raise_for_status()
        return r.json()

    @retry(stop=stop_after_attempt(3))
    async def post(self, url: str, params: Optional[Dict] = None) -> Dict:
        logger.info(f"[http][post][request]{url}")
        headers = {"Content-Type": "application/json"}
        r = await self.client.post(url, json=params, headers=headers)
        logger.info(f"[http][post][response]{url},{r.status_code},{r.json()}")

        r.raise_for_status()
        return r.json()


import socket
import asyncio

from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from starlette.requests import Request
from starlette.websockets import WebSocket, WebSocketDisconnect
from starlette.templating import Jinja2Templates

from blokus.blokus import Blokus
from blokus.players import WebSocketPlayer, AIPlayer, TestPlayer

app = FastAPI()

templates = Jinja2Templates(directory="templates")
jinja_env = templates.env

app.mount(
    "/static",
    StaticFiles(directory="static"),
    name="static"
)

que = list()

async def add_to_que(sock):
    que.append(sock)
    if len(que) >= 2:
        p1 = que[0]
        p2 = que[1]
        que.remove(p1)
        que.remove(p2)
        await start_game([p1, p2])

async def start_game(socks):
    sock1 = socks[0]
    sock2 = socks[1]
    sock1_cnn_status = await connection_succeeded(sock1)
    sock2_cnn_status = await connection_succeeded(sock2)
    if sock1_cnn_status and sock2_cnn_status:
        await start_game_helper(sock1, sock2)
    elif sock1_cnn_status:
        await send_connection_disconnected_message(sock1)
    elif sock2_cnn_status:
        await send_connection_disconnected_message(sock2)
    sock1.finish = True
    sock2.finish = True

async def start_game_helper(sock1, sock2):
    try:
        player1 = WebSocketPlayer(0, sock1)
        player2 = WebSocketPlayer(1, sock2)
        blokus = Blokus([player1, player2])
        await blokus.start()
    except:
        sock1_cnn_status = await connection_succeeded(sock1)
        sock2_cnn_status = await connection_succeeded(sock2)
        if sock1_cnn_status:
            await send_connection_disconnected_message(sock1)
            await sock1.close()
        if sock2_cnn_status:
            await send_connection_disconnected_message(sock2)
            await sock2.close()
    else:
        await sock1.close()
        await sock2.close()

async def connection_succeeded(sock):
    retval = True
    try:
        await send_test(sock)
    except:
        retval = False
    return retval

async def send_test(sock):
    await sock.send_json({
        "method": "test",
        "message": "Connection test...",
    })

async def send_connection_disconnected_message(sock):
    await sock.send_json({
        "method": "exception_occurred",
        "message": "The connection has been disconnected. Please reload.",
    })

def get_ip():
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.connect(("8.8.8.8", 80))
    return sock.getsockname()[0]

# Return static page
@app.get('/')
async def index(request: Request):
    return templates.TemplateResponse("index.html", {
        "request": request,
        "ip": get_ip(),
        "port": 8000,
    })

@app.websocket("/ws")
async def websocket_endpoint(sock: WebSocket):
    await sock.accept()
    sock.finish = False
    await add_to_que(sock)
    while not sock.finish:
        await asyncio.sleep(3)


class FlatIterator:

    def __init__(self, list_of_list):
        self.start = -1
        self.list = []
        for i in list_of_list:
            self.list += i
        self.end = len(self.list)

    def __iter__(self):
        return self

    def __next__(self):
        self.start += 1
        if self.start == self.end:
            raise StopIteration
        for item in self.list:
            self.list.remove(item)
            return item

def test_1():

    list_of_lists_1 = [
        ['a', 'b', 'c'],
        ['d', 'e', 'f', 'h', False],
        [1, 2, None]
    ]

    for flat_iterator_item, check_item in zip(
            FlatIterator(list_of_lists_1),
            ['a', 'b', 'c', 'd', 'e', 'f', 'h', False, 1, 2, None]
    ):

        assert flat_iterator_item == check_item

    assert list(FlatIterator(list_of_lists_1)) == ['a', 'b', 'c', 'd', 'e', 'f', 'h', False, 1, 2, None]

if __name__ == '__main__':
    test_1()


import paddle
from paddle.amp import GradScaler

__Author__ = 'Quanhao Guo'
__Date__ = '2021.04.24.16.21'

class MaxClipGradScaler(GradScaler):
    def __init__(self, init_loss_scaling, max_scale: float, incr_every_n_steps=100):
        GradScaler.__init__(self, init_loss_scaling=init_loss_scaling, incr_every_n_steps=incr_every_n_steps)
        self.get_scale = 1.0
        self.max_scale = max_scale

    def scale_clip(self):
        if self.get_scale == self.max_scale:
            self._incr_ratio = 1.0
        elif self.get_scale < self.max_scale:
            self._incr_ratio = 2.0

    def scale(self, outputs):
        if not self._enable:
            return outputs
        self.scale_clip()
        # Short-circuit for the common case.
        if isinstance(outputs, paddle.Tensor):
            assert self._init_loss_scaling is not None
            return outputs * self._init_loss_scaling


n = int(input())
dlt_pt = []
for i  in range(n):
    dlt_pt.append(tuple(map(int, input().split())))

dlt_pt.sort(key = lambda x:x[0])

ymin, ymax = min(list(zip(*dlt_pt))[1]) ,max(list(zip(*dlt_pt))[1])

peomin, rotmin = 2**31-1, 2**31-1

for peoy in range(ymin, ymax+1):
    peox= dlt_pt[0][0]
    peov, rotv = 0, 0
    for tp_pt in dlt_pt:
        peov += 2*(tp_pt[0]-peox)
        rotv += 2*abs(peoy - tp_pt[1])
        peox = tp_pt[0]
    if peomin > peov:
        peomin = peov
    if rotmin > rotv:
        rotmin = rotv
print(f'{peomin} {rotmin}')


from graphviz import Digraph
from Instructions import *

index = 0
dot = None

def inc():
    global index
    index += 1
    return index

def GraphAST(AST, consola):
    global dot
    dot = Digraph()
    dot.attr(splines = 'false')
    programIndex = inc()
    dot.node(str(index), 'PROGRAM')
    inc()
    program = AST

    if program.main != None:
        labels = [program.main] + program.labels
        for label in labels:
            AST_Label(programIndex, label)

    try:
        dot.view()
    except:
        consola.setText('ERROR: No fue posible realizar el reporte AST por algun error desconocido.')

def AST_Label(father, label):
    labelIndex = inc()
    dot.node(str(labelIndex), label.name)
    dot.edge(str(father), str(labelIndex))

    for instruction in label.instructions:
        if isinstance(instruction, Unset): AST_Unset(labelIndex, instruction)
        elif isinstance(instruction, Set): AST_Set(labelIndex, instruction)
        elif isinstance(instruction, Goto): AST_Goto(labelIndex, instruction)
        elif isinstance(instruction, If): AST_If(labelIndex, instruction)
        elif isinstance(instruction, Print): AST_Print(labelIndex, instruction)
        elif isinstance(instruction, Exit): AST_Exit(labelIndex, instruction)

def AST_Unset(father, instruction):
    unsetIndex = inc()
    dot.node(str(unsetIndex), 'UNSET')
    dot.edge(str(father), str(unsetIndex))
    if isinstance(instruction.register, Register): AST_Register(unsetIndex, instruction.register)
    elif isinstance(instruction.register, Array): AST_Array(unsetIndex, instruction.register)

def AST_Print(father, instruction):
    printIndex = inc()
    dot.node(str(printIndex), 'PRINT')
    dot.edge(str(father), str(printIndex))
    if isinstance(instruction.register, Register): AST_Register(printIndex, instruction.register)
    elif isinstance(instruction.register, Array): AST_Array(printIndex, instruction.register)

def AST_Goto(father, instruction):
    gotoIndex = inc()
    dot.node(str(gotoIndex), 'GOTO')
    dot.edge(str(father), str(gotoIndex))
    son = inc()
    dot.node(str(son), instruction.label)
    dot.edge(str(gotoIndex), str(son))

def AST_If(father, instruction):
    ifIndex = inc()
    dot.node(str(ifIndex), 'IF')
    dot.edge(str(father), str(ifIndex))

    if isinstance(instruction.condition, Register): AST_Register(ifIndex, instruction.condition)
    elif isinstance(instruction.condition, Array): AST_Array(ifIndex, instruction.condition)
    elif isinstance(instruction.condition, AritmeticOperation): AST_Operation(ifIndex, instruction.condition, 'ARITMETIC')
    elif isinstance(instruction.condition, BitxbitOperation): AST_Operation(ifIndex, instruction.condition, 'BIT X BIT')
    elif isinstance(instruction.condition, LogicOperation): AST_Operation(ifIndex, instruction.condition, 'LOGIC')
    elif isinstance(instruction.condition, RelationalOperation): AST_Operation(ifIndex, instruction.condition, 'RELATIONAL')
    AST_Goto(ifIndex, instruction.goto)

def AST_Set(father, instruction):
    setIndex = inc()
    dot.node(str(setIndex), 'SET')
    dot.edge(str(father), str(setIndex))

    son = inc()
    dot.node(str(son), '=')
    dot.edge(str(setIndex), str(son))

    if isinstance(instruction.register, Register): AST_Register(son, instruction.register)
    elif isinstance(instruction.register, Array): AST_Array(son, instruction.register)

    if isinstance(instruction.data, Register): AST_Register(son, instruction.data)
    elif isinstance(instruction.data, Array): AST_Array(son, instruction.data)
    elif isinstance(instruction.data, AritmeticOperation): AST_Operation(son, instruction.data, 'ARITMETIC')
    elif isinstance(instruction.data, BitxbitOperation): AST_Operation(son, instruction.data, 'BIT X BIT')
    elif isinstance(instruction.data, LogicOperation): AST_Operation(son, instruction.data, 'LOGIC')
    elif isinstance(instruction.data, RelationalOperation): AST_Operation(son, instruction.data, 'RELATIONAL')
    elif isinstance(instruction.data, ArrayDeclaration): AST_ArrayDeclaration(son, instruction.data)
    elif isinstance(instruction.data, Read): AST_Read(son, instruction.data)
    elif isinstance(instruction.data, Cast): AST_Cast(son, instruction.data)
    elif isinstance(instruction.data, Primary): AST_Primary(son, instruction.data)
    elif isinstance(instruction.data, Pointer): AST_Pointer(son, instruction.data)

def AST_Register(father, expression):
    registerIndex = inc()
    dot.node(str(registerIndex), 'REGISTER')
    dot.edge(str(father), str(registerIndex))
    regType = ''
    if expression.type_ == REGISTER.TEMPORAL: regType = 'TEMPORAL'
    elif expression.type_ == REGISTER.PARAM: regType = 'PARAMETRO'
    elif expression.type_ == REGISTER.PILA: regType = 'PILA'
    elif expression.type_ == REGISTER.DEVUELTO: regType = 'RETORNO'
    elif expression.type_ == REGISTER.RETURNED: regType = 'RECURSIVIDAD'
    elif expression.type_ == REGISTER.PUNTERO: regType = 'PUNTERO PILA'
    son = inc()
    dot.node(str(son), regType)
    dot.edge(str(registerIndex), str(son))
    son = inc()
    dot.node(str(son), str(expression.position))
    dot.edge(str(registerIndex), str(son))

def AST_Array(father, expression):
    arrayIndex = inc()
    dot.node(str(arrayIndex), 'ARRAY')
    dot.edge(str(father), str(arrayIndex))
    regType = ''
    if expression.type_ == REGISTER.TEMPORAL: regType = 'TEMPORAL'
    elif expression.type_ == REGISTER.PARAM: regType = 'PARAMETRO'
    elif expression.type_ == REGISTER.PILA: regType = 'PILA'
    elif expression.type_ == REGISTER.DEVUELTO: regType = 'RETORNO'
    elif expression.type_ == REGISTER.RETURNED: regType = 'RECURSIVIDAD'
    elif expression.type_ == REGISTER.PUNTERO: regType = 'PUNTERO PILA'
    son = inc()
    dot.node(str(son), regType)
    dot.edge(str(arrayIndex), str(son))
    son = inc()
    dot.node(str(son), str(expression.position))
    dot.edge(str(arrayIndex), str(son))
    count = 1
    for index_ in expression.indexs:
        AST_Position(arrayIndex, index_, 'INDICE '+ str(count))
        count += 1

def AST_Position(father, expression, count):
    positionIndex = inc()
    dot.node(str(positionIndex), count)
    dot.edge(str(father), str(positionIndex))
    if isinstance(expression.index, Register): AST_Register(positionIndex, expression.index)
    elif isinstance(expression.index, Primary): AST_Primary(positionIndex, expression.index)

def AST_Primary(father, expression):
    primaryIndex = inc()
    dot.node(str(primaryIndex), str(expression.data))
    dot.edge(str(father), str(primaryIndex))

def AST_Read(father, instruction):
    readIndex = inc()
    dot.node(str(readIndex), 'READ')
    dot.edge(str(father), str(readIndex))

def AST_ArrayDeclaration(father, instruction):
    arrayDeclarationIndex = inc()
    dot.node(str(arrayDeclarationIndex), 'ARRAY')
    dot.edge(str(father), str(arrayDeclarationIndex))

def AST_Cast(father, instruction):
    castIndex = inc()
    dot.node(str(castIndex), 'CASTING')
    dot.edge(str(father), str(castIndex))
    cast = ''
    if instruction.casting == DATA_TYPE.CHARACTER: cast = 'CHAR'
    elif instruction.casting == DATA_TYPE.INTEGER: cast = 'INT'
    elif instruction.casting == DATA_TYPE.FLOAT: cast = 'FLOAT'
    son = inc()
    dot.node(str(son), cast)
    dot.edge(str(castIndex), str(son))
    if isinstance(instruction.data, Register): AST_Register(castIndex, instruction.data)
    elif isinstance(instruction.data, Array): AST_Array(castIndex, instruction.data)

def AST_Pointer(father, instruction):
    pointerIndex = inc()
    dot.node(str(pointerIndex), 'POINTER')
    dot.edge(str(father), str(pointerIndex))
    if isinstance(instruction.register, Register): AST_Register(pointerIndex, instruction.register)
    elif isinstance(instruction.register, Array): AST_Array(pointerIndex, instruction.register)

def AST_Exit(father, instruction):
    exitIndex = inc()
    dot.node(str(exitIndex), 'EXIT')
    dot.edge(str(father), str(exitIndex))

def AST_Operation(father, expression, tipo):
    operationIndex = inc()
    dot.node(str(operationIndex), tipo)
    dot.edge(str(father), str(operationIndex))
    simbol = ''
    if expression.operator == ARITMETIC_OPERATION.NEG: simbol = '-'
    elif expression.operator == ARITMETIC_OPERATION.SUMA: simbol = '+'
    elif expression.operator == ARITMETIC_OPERATION.RESTA: simbol = '-'
    elif expression.operator == ARITMETIC_OPERATION.MULT: simbol = '*'
    elif expression.operator == ARITMETIC_OPERATION.DIV: simbol = '/'
    elif expression.operator == ARITMETIC_OPERATION.MOD: simbol = '%'
    elif expression.operator == ARITMETIC_OPERATION.ABS: simbol = 'ABSOLUT'
    elif expression.operator == LOGIC_OPERATION.AND: simbol = '&&'
    elif expression.operator == LOGIC_OPERATION.OR: simbol = '||'
    elif expression.operator == LOGIC_OPERATION.NOT: simbol = '!'
    elif expression.operator == RELATIONAL_OPERATION.ES_IGUAL: simbol = '=='
    elif expression.operator == RELATIONAL_OPERATION.NO_IGUAL: simbol = '!='
    elif expression.operator == RELATIONAL_OPERATION.MAYOR: simbol = '>'
    elif expression.operator == RELATIONAL_OPERATION.MENOR: simbol = '<'
    elif expression.operator == RELATIONAL_OPERATION.MAYOR_IGUAL: simbol = '>='
    elif expression.operator == RELATIONAL_OPERATION.MENOR_IGUAL: simbol = '<='

    son = inc()
    dot.node(str(son), simbol)
    dot.edge(str(operationIndex), str(son))

    if isinstance(expression.expression1, Register): AST_Register(son, expression.expression1)
    elif isinstance(expression.expression1, Array): AST_Array(son, expression.expression1)
    elif isinstance(expression.expression1, Primary): AST_Primary(son, expression.expression1)

    if isinstance(expression.expression2, Register): AST_Register(son, expression.expression2)
    elif isinstance(expression.expression2, Array): AST_Array(son, expression.expression2)
    elif isinstance(expression.expression2, Primary): AST_Primary(son, expression.expression2)


import asyncio
from utils.constants import CSV_HEADERS
from utils.csv import extract_rncs_from_csv, write_row
from utils.automation import look_up_rnc, extract_required_data, open_look_up_page
from classes.browser_navigation import BrowserNavigation

async def main():
    rnc_list = extract_rncs_from_csv("data/rn.csv")

    rnc = "1-32-42125-6"

    page, browser = await open_look_up_page()
    await look_up_rnc(rnc, page)
    extracted_data = await extract_required_data(rnc, page)

    print(extracted_data)
    write_row(extracted_data, CSV_HEADERS)

    await browser.close()

print("Starting...")
asyncio.get_event_loop().run_until_complete(main())
print("Done ✅")


self.description = "File conflict between package with symlink and package with real path resolved by removal"
# Note: this situation means the filesystem and local db are out of sync

self.filesystem = ["usr/", "usr/lib/", "lib -> usr/lib/"]

lp1 = pmpkg("foo")
lp1.files = ["lib/", "lib/file"]
self.addpkg2db("local", lp1)

sp1 = pmpkg("bar")
sp1.conflicts = ["foo"]
sp1.files = ["usr/", "usr/lib/", "usr/lib/file"]
self.addpkg2db("sync", sp1)

self.args = "-S %s --ask=4" % sp1.name

self.addrule("PACMAN_RETCODE=1")
self.addrule("PKG_EXIST=foo")
self.addrule("!PKG_EXIST=bar")


import re
from random import choice
from dataclasses import dataclass
from typing import Optional

from .base import RuleItem, RuleDevice, BaseAgent
from magic_agent.core.rules import (MozillaDefault,
                                    SafariMobile,
                                    Chrome,
                                    AppleWebKit,
                                    LikeGecko,
                                    SafariRandom,
                                    Safari,
                                    AppleWebkitRandom)

@dataclass(frozen=True)
class MobileDevice:
    """Base mobile device dataclass"""
    model: str
    released: int
    operating_system: str
    platform: str
    battery_capacity: int
    model_id: Optional[list[str]] = None
    market_regions: Optional[list[str]] = None
    codename: Optional[str] = None
    oem_id: Optional[str] = None
    market_countries: Optional[str] = None
    resolution: Optional[dict] = None

    @classmethod
    def generate_device(cls, **kwargs):
        """generate devices with json data"""
        return cls(**kwargs)

    @property
    def is_android(self) -> bool:
        return "android" in self.platform.lower()

    @property
    def is_apple(self) -> bool:
        return "ios" in self.platform.lower()

    @property
    def version(self) -> str:
        """return operating system version"""
        if self.is_android:
            return re.findall(r'Android (.*?) ', self.operating_system)[0]
        elif self.is_apple:
            return re.findall(r' iOS (.*?)', self.operating_system)[0]
        return ""

    @property
    def agent(self) -> BaseAgent:
        """return BaseAgent class"""
        return MobileAgent(self).agent()

class MobileAgent:
    """Convert Device class to useragent"""
    __RE_SYSTEM_VERSION = re.compile(r"([\d.]+)")

    def __init__(self, device: MobileDevice):
        self._device = device

    def agent(self, *, by_device_name: bool = True, by_model_id: bool = True) -> BaseAgent:
        """return singe device BaseAgent class"""
        if self._device.is_android:
            return self._android_agent(by_model_id, by_device_name)

        elif self._device.is_apple:
            return self._apple_agent()

    @property
    def _system_version(self) -> str:
        return self.__RE_SYSTEM_VERSION.findall(self._device.operating_system)[0]

    def _android_agent(self, by_model_id, by_device_name):
        device_items = ["Linux"]
        if self._device.operating_system:
            device_items.append(f"Android {self._system_version}")
        else:
            device_items.append("Android 10.0")

        if by_model_id and self._device.model_id:
            device_items.append(choice(self._device.model_id))

        elif by_device_name:
            device_name = " ".join(self._device.model.split(" ")[:3])
            device_items.append(device_name)

        device = RuleDevice(
            items=tuple(device_items))

        return BaseAgent(
            rules=(
                MozillaDefault,
                device,
                AppleWebKit,
                LikeGecko,
                Chrome,
                choice((Safari, SafariMobile))
            ))

    def _apple_agent(self):
        if "iPhone" in self._device.model:
            device_items = ["iPhone"]
        elif "iPad" in self._device.model:
            device_items = ["iPad"]
        elif "iPod" in self._device.model:
            device_items = ["iPod"]
        else:
            raise TypeError("Unknown apple device passed")
        o_sys = self._system_version

        if "." not in o_sys:
            apple_version = RuleItem(f"Version/{o_sys}.0")  # Version string
            o_sys += "_0"
        else:
            apple_version = RuleItem(f"Version/{o_sys}")
            o_sys = o_sys.replace(".", "_")

        device_items.append(f"CPU OS {o_sys} like Mac OS X")
        device = RuleDevice(items=tuple(device_items))
        device_build = RuleItem(f"Mobile/{self._device.model_id[0]}")
        return BaseAgent(
            rules=(
                MozillaDefault,
                device,
                AppleWebkitRandom,
                LikeGecko,
                apple_version,
                device_build,
                SafariRandom
            ))

    def __str__(self):
        return self.agent().agent


# %%
from pathlib import Path

import pandas as pd

class PathManager:
    project_dir = Path("../")
    test_dir = Path("./tests/")
    label_by_encode = {
        "rle": {
            "HL": ["H1", "L1"],
            "HHL": ["H2", "H2", "L1"],
            "HLL": ["H1", "L2", "L2"],
            "LL": ["L2", "L2"],
            "LHH": ["L1", "H2", "H2"],
            "LLH": ["L2", "L2", "H1"],
        },
        "rle_delta": {
            "HL": ["H1", "dL1"],
            "HHL": ["H2", "H2", "dL1"],
            "HLL": ["H1", "dL1", "L1"],
            "LL": ["L2", "L2"],
            "LHH": ["L1", "dH1", "H1"],
            "LLH": ["L2", "L2", "dH1"],
        },
    }
    # https://www.akenotsuki.com/kyookotoba/accent/bumpu.html
    accept = {"tokyo": ["HL", "LH", "LHH", "HLL", ],
              # HLL を許すとHLLになる。むしろ、話者もそうなのか？
              "kinki": ["HL", "HH", "LH", "LL", "LLH", "HLL", "HHL", ]}

    @classmethod
    def data_path(cls, data_type, wav_path="", is_test=False) -> Path:
        """
        wav_path: wav_path じゃなくても良い(どのみち処理するので)
        """
        # 参照したいタイプを渡すとパスを返す
        if is_test:
            project_dir = cls.test_dir
        else:
            project_dir = cls.project_dir
        # NOTE: 予測に失敗した時、近畿のLHH拒否が原因かもしれない
        accepted_types = [
            "original", "downsample", "feature",
            "label_base", "label_rle",
            "axb",
        ]
        assert data_type in accepted_types
        data_path_map = {
            "original": project_dir / "src/audio/output" / wav_path,
            "downsample": project_dir / "model/wav" / wav_path,
            "feature": project_dir / "model/feature" / str(wav_path.split(".")[0]+".npy"),
            "label_base": project_dir / "model/label_base" / str(wav_path.split(".")[0]+".npy"),
            "label_rle": project_dir / "model/label_rle" / str(wav_path.split(".")[0]+".npy"),
        }
        return data_path_map[data_type]

    @classmethod
    def train_test_wav(cls, is_test=False):
        if is_test:
            tone_df = pd.read_csv(cls.test_dir/"src/list/axb_list.csv")\
                .query("type=='filler'")[["a", "x", "b"]]
        else:
            tone_df = pd.read_csv(cls.project_dir/"src/list/axb_list.csv")\
                .query("type=='filler'")[["a", "x", "b"]]
        wav_list_set = set(
            tone_df.a.values.tolist() +
            tone_df.x.values.tolist() +
            tone_df.b.values.tolist()
        )
        # _を含むのはH_Lのようなテストデータ
        train_wav_list = list(
            filter(lambda s: s.count("_") == 0,
                   wav_list_set)
        )
        test_wav_list = list(filter(lambda s: s.count("_") != 0, wav_list_set))
        return train_wav_list, test_wav_list


import smbus
import math
import time
# import simple_pid
from GyroFilter import GyroFilter
from PIDController import PIDController
from MyDataReader import MyDataReader

# For more information refer to tests/balance_numbers_tests.txt
# Gyroscope Average Values;
# Vertical: x = 5.7, y = 7.052; Steady
# Left: x = 6.09, y = 5.946
# Right: x = 5.378, y = 5.946
# ====================
# Accelerometer Average Values
# Vertical: x = -0.173, y = 0.05, z = 1.07; Steady
# Left: x = -0.64, y = 0.122, z = 0.829
# Right: x = 0.66, y = 0.04, z = 0.848

class PIDBalancer:

    def __init__(self, kp, ki, kd):
        self.kp = kp
        self.ki = ki
        self.kd = kd

        self.gyro_vertical_center_x = 5.7
        self.gyro_vertical_center_y = 7.052

        self.median_filter = [0.0, 0.0, 0.0, 0.0, 0.0]
        gyro_scale = 131.0
        accel_scale = 16384.0
        RAD_TO_DEG = 57.29578
        M_PI = 3.14159265358979323846
        now = time.time()
        K = 0.98
        K1 = 1 - K

        time_diff = 0.01
        gyroAngleX = 0.0
        gyroAngleY = 0.0
        gyroAngleZ = 0.0
        accAngX = 0.0
        CFangleX = 0.0
        CFangleX1 = 0.0
        K = 0.98
        FIX = -12.89

        self.gyroFilter = GyroFilter()
        (self.gyro_scaled_x, self.gyro_scaled_y, self.gyro_scaled_z, self.accel_scaled_x, self.accel_scaled_y,
         self.accel_scaled_z) = self.gyroFilter.read_all()
        (self.accel_vertical_center_x, self.accel_vertical_center_y,
         self.accel_vertical_center_z) = self.gyroFilter.get_accel_center_xyz()
        pid_set_point = 0.00
        self.pid = PIDController(kp, ki, kd, pid_set_point)

        self.DataReaderMain = MyDataReader()
        self.data_reader = self.DataReaderMain.get_xyx()

        # The angle of the Gyroscope
        gyroAngleX += self.gyro_scaled_x * time_diff
        gyroAngleY += self.gyro_scaled_y * time_diff
        gyroAngleZ += self.gyro_scaled_z * time_diff

        accAngX = (math.atan2(self.accel_scaled_x, self.accel_scaled_y) + M_PI) * RAD_TO_DEG
        # math.atan2 numeric value between -PI and PI representing the angle theta of an (x, y) point.
        CFangleX = K * (CFangleX + self.gyro_scaled_x * time_diff) + (1 - K) * accAngX

        accAngX1 = self.get_x_rotation(self.accel_scaled_x, self.accel_scaled_y, self.gyro_scaled_z)
        # accAngX1 = get_x_rotation(accel_scaled_x, accel_scaled_y, gyro_scaled_x) or this one - test?

        CFangleX1 = (K * (CFangleX1 + self.gyro_scaled_x * time_diff) + (1 - K) * accAngX1)

    def dist(self, a, b):
        return math.sqrt((a * a) + (b * b))

    def get_current_data(self):
        self.data_reader = self.DataReaderMain.get_xyx()  # reassign, might use it for sth else
        return self.data_reader

    def get_y_rotation(self, x, y, z):
        radians = math.atan2(x, self.dist(y, z))
        return -math.degrees(radians)

    def get_x_rotation(self, x, y, z):
        radians = math.atan2(y, self.dist(x, z))
        return math.degrees(radians)

    def update_pid_error(self):
        average_accel_scaled_x = self.output_filter()
        # pid_error = self.accel_vertical_center_x - average_accel_scaled_x
        pid_error = average_accel_scaled_x
        # X, Y = self.gyroFilter.calc_xy_values()
        # print("X using X Y Z: " + str(X))
        # print("center: " + str(self.accel_vertical_center_x) + " current(AVG): " + str(
        #         #     average_accel_scaled_x) + " = " + str(pid_error))
        # print("center: " + str(self.accel_vertical_center_x) + " current(AVG): " + str(
        #      average_accel_scaled_x) + " = " + str(pid_error))
        self.pid.update_pid(pid_error)

    def get_pid_value(self):
        # print("Current XYZ: " + str(self.accel_scaled_x) + " | " + str(self.accel_scaled_y) + " | " + str(
        #    self.accel_scaled_z))
        return self.pid.get_pid

    def get_gyro_filter(self):
        return self.gyroFilter

    def output_filter(self):
        # (self.gyro_scaled_x, self.gyro_scaled_y, self.gyro_scaled_z, self.accel_scaled_x, self.accel_scaled_y,
        #  self.accel_scaled_z) = self.gyroFilter.read_all()
        self.data_reader = self.DataReaderMain.get_xyx()
        x_value = self.data_reader[0]

        if self.data_reader[2] <= 0:  # if accel x is >= 0, the robot falls forward
            x_value = -x_value

        self.median_filter.insert(0, x_value)  # self.data_reader[0] stands for value of X;
        self.median_filter.pop()
        average_accel_scaled_x = float(sum(self.median_filter) / len(self.median_filter))
        print("ACCEL AVG " + str(self.median_filter[0]) + " | " + str(self.median_filter[1]) + " | "
              + str(self.median_filter[2]) + " | " + str(self.median_filter[3]) + " | "
              + str(self.median_filter[4]) + " = " + str(average_accel_scaled_x))
        return average_accel_scaled_x

    # print(
    #    "{0:.2f} {1:.2f} {2:.2f} {3:.2f} | {4:.2f} {5:.2f} | {}".format(gyroAngleX, gyroAngleY, accAngX, CFangleX,
    #                                                                         accAngX1, CFangleX1, pid))


"""
2017 Day 6
https://adventofcode.com/2017/day/6
"""

from typing import Sequence, Tuple
import aocd  # type: ignore

def read_initial_blocks(text: str) -> Sequence[int]:
    return tuple(int(val) for val in text.split("\t"))

def largest_block(blocks: Sequence[int]) -> int:
    largest_size = max(blocks)
    return next(block for block, size in enumerate(blocks) if size == largest_size)

def redistribute_from_largest(blocks: Sequence[int]) -> Sequence[int]:
    blocks = list(blocks)
    source = largest_block(blocks)
    redist = blocks[source]
    blocks[source] = 0
    bank = source + 1
    while redist > 0:
        blocks[bank % len(blocks)] += 1
        redist -= 1
        bank += 1
    return tuple(blocks)

def redistribution_cycles_until_repeat(blocks: Sequence[int]) -> Tuple[int, int]:
    seen = set()

    cycles1 = 0
    while blocks not in seen:
        seen.add(blocks)
        blocks = redistribute_from_largest(blocks)
        cycles1 += 1

    seeking = blocks
    cycles2 = 0
    while (blocks != seeking) or (cycles2 == 0):
        blocks = redistribute_from_largest(blocks)
        cycles2 += 1

    return cycles1, cycles2

def main() -> None:
    """
    Calculate and output the solutions based on the real puzzle input.
    """
    data = aocd.get_data(year=2017, day=6)

    blocks = read_initial_blocks(data)
    part1, part2 = redistribution_cycles_until_repeat(blocks)

    print(f"Part 1: {part1}")
    print(f"Part 2: {part2}")

if __name__ == "__main__":
    main()