from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from qgis.core import *
from qgis.utils import iface
import os.path

def LagShape(filnavn, filter, nyeVektorlag, selectedLayer):                                     # Danner nye vektorlag basert på gruppene valgt i analysen
    if os.path.isfile(nyeVektorlag.text() + filnavn + '.shp'):
        os.remove(nyeVektorlag.text() + filnavn + '.shp')                                       # Hvis ett vektolag med samme navn allerede finnes, fjern denne filen

    selectedLayer.selectByExpression(filter)                                                    # Velger delere av ledningsnettverket basert på filter som er blitt valgt i analysen
    fn = nyeVektorlag.text() + filnavn + '.shp'                                                 # Lager en ny shape fil av det valgte delen
    writer = QgsVectorFileWriter.writeAsVectorFormat(selectedLayer, fn, 'utf-8', \
    driverName='ESRI Shapefile', onlySelected=True)                                             # Skriver den nye shape filen som vektorformat
    selected_layer = iface.addVectorLayer(fn, '','ogr')                                         # Legger det nye vektorlaget inn som ett aktivt vektorlag

def LagFarge(filnavn, verdi, a, b, c, d, e):                                                    # Definerer fargen til de nye vektorlagene basert på vedien hentet fra excel
    newlayers = QgsProject.instance().mapLayersByName(filnavn)                                  # Henter de nye vektorlagene som er blitt generert tidligere
    newlayer = newlayers[0]
    renderer = newlayer.renderer()
    newlayer.renderer().symbol().symbolLayer(0).setWidth(0.55)                                  # Setter tegneregel for bredden til linjen
    if verdi >= a:                                                                              # Hvis resultat verdien er høyere enn valgt verdi for a gjør dette:
        newlayer.renderer().symbol().symbolLayer(0).setColor(QColor.fromRgb(250,0,0))           # Setter fargen til rød
        newlayer.triggerRepaint()                                                               # Endrer fargen
        iface.layerTreeView().refreshLayerSymbology(newlayer.id())                              # Oppdaterer vektorlaget
    elif verdi >= b and verdi < a:                                                              # Hvis resultat verdien er mellom valgt verdi for a og b gjør dette:
        newlayer.renderer().symbol().symbolLayer(0).setColor(QColor.fromRgb(250,140,0))         # Setter fargen til orasje
        newlayer.triggerRepaint()
        iface.layerTreeView().refreshLayerSymbology(newlayer.id())
    elif verdi >= c and verdi < b:                                                              # Hvis resultat verdien er mellom valgt verdi for b og c gjør dette:
        newlayer.renderer().symbol().symbolLayer(0).setColor(QColor.fromRgb(250,250,0))         # Setter fargen til gul
        newlayer.triggerRepaint()
        iface.layerTreeView().refreshLayerSymbology(newlayer.id())
    elif verdi >= d and verdi < c:                                                              # Hvis resultat verdien er mellom valgt verdi for c og d gjør dette:
        newlayer.renderer().symbol().symbolLayer(0).setColor(QColor.fromRgb(115,220,0))         # Setter fargen til grønn
        newlayer.triggerRepaint()
        iface.layerTreeView().refreshLayerSymbology(newlayer.id())
    elif verdi >= e and verdi < d:                                                              # Hvis resultat verdien er mellom valgt verdi for d og e gjør dette:
        newlayer.renderer().symbol().symbolLayer(0).setColor(QColor.fromRgb(0,155,0))           # Setter fargen til mørk grønn
        newlayer.triggerRepaint()
        iface.layerTreeView().refreshLayerSymbology(newlayer.id())
    else:                                                                                # Hvis resultat verdien ikke har en verdi gjør dette:
        newlayer.renderer().symbol().symbolLayer(0).setColor(QColor.fromRgb(0,0,0))             # Setter fargen til svart
        newlayer.triggerRepaint()
        iface.layerTreeView().refreshLayerSymbology(newlayer.id())

def FindReplace(string, dictionary):                                                            # Setter inn verdier for parametere i en 'string'
    # is the item in the dict?
    for item in string:
        # iterate by keys
        if item in dictionary.keys():
            # look up and replace
            string = string.replace(item, dictionary[item])
    # return updated string
    return string
    print(string)


#
# @lc app=leetcode.cn id=463 lang=python3
#
# [463] 岛屿的周长
#
# https://leetcode-cn.com/problems/island-perimeter/description/
#
# algorithms
# Easy (71.44%)
# Total Accepted:    65.9K
# Total Submissions: 92.4K
# Testcase Example:  '[[0,1,0,0],[1,1,1,0],[0,1,0,0],[1,1,0,0]]'
#
# 给定一个 row x col 的二维网格地图 grid ，其中：grid[i][j] = 1 表示陆地， grid[i][j] = 0 表示水域。
#
# 网格中的格子 水平和垂直 方向相连（对角线方向不相连）。整个网格被水完全包围，但其中恰好有一个岛屿（或者说，一个或多个表示陆地的格子相连组成的岛屿）。
#
# 岛屿中没有“湖”（“湖” 指水域在岛屿内部且不和岛屿周围的水相连）。格子是边长为 1 的正方形。网格为长方形，且宽度和高度均不超过 100
# 。计算这个岛屿的周长。
#
#
#
# 示例 1：
#
#
#
#
# 输入：grid = [[0,1,0,0],[1,1,1,0],[0,1,0,0],[1,1,0,0]]
# 输出：16
# 解释：它的周长是上面图片中的 16 个黄色的边
#
# 示例 2：
#
#
# 输入：grid = [[1]]
# 输出：4
#
#
# 示例 3：
#
#
# 输入：grid = [[1,0]]
# 输出：4
#
#
#
#
# 提示：
#
#
# row == grid.length
# col == grid[i].length
# 1
# grid[i][j] 为 0 或 1
#
#
#
class Solution:
    def islandPerimeter(self, grid: List[List[int]]) -> int:
        land, edge = 0, 0
        for i in range(len(grid)):
            for j in range(len(grid[i])):
                if grid[i][j] == 1:
                    land += 1
                    if i>0 and grid[i-1][j] == 1:
                        edge += 1
                    if j>0 and grid[i][j-1] == 1:
                        edge += 1
        return land*4 - edge*2


import argparse

parser = argparse.ArgumentParser()

# by default argparse treats the options given as a string
# but using type=int will treat the input as an integer
parser.add_argument("square", help="display square of"
                    + " a given number", type=int)
parser.parse_args()
args = parser.parse_args()
print(args.square**2)


from django.template import Template, Context
from django.conf import settings

def parse(kwargs):
  id = kwargs.get('id')
  width = int(kwargs.get('width', getattr(settings, 'SHORTCODES_YOUTUBE_WIDTH', 556)))
  height = int(kwargs.get('height', 313))
  jquery = getattr(settings, 'SHORTCODES_YOUTUBE_JQUERY', False)

  html = '<iframe src="http://player.vimeo.com/video/{{ id }}?title=0&byline=0&portrait=0" width="{{ width }}" height="{{ height }}" frameborder="0" webkitAllowFullScreen allowFullScreen></iframe>'

  template = Template(html)
  context = Context(
    {
      'id': id,
      'width': width,
      'height': height
    }
  )

  if id:
    return template.render(context)
  else:
    return 'Video not found'


from flask import request, jsonify, make_response
from flask_restful import Resource
import random, time

from models.sneaker import SneakerModel

class SneakerList(Resource):
  def get(self):
    sneaker_list = SneakerModel.find_all()
    random.shuffle(sneaker_list)
    sneaker_list_json = [sneaker.to_json() for sneaker in sneaker_list]

    response = make_response(jsonify(status=200, success=True, sneaker_list=sneaker_list_json))

    return response

class Sneaker(Resource):
  def post(self):
    data = request.get_json(force=True)

    for sneaker in data:
      if (sneaker['brand'] and sneaker['name'] and sneaker['releaseDate'] and sneaker['image']):
        brand = sneaker['brand']
        name = sneaker['name']
        releaseDate = sneaker['releaseDate']
        retailPrice = sneaker['retailPrice']
        image = sneaker['image']
        originalImage = image['original']

        sneakers = SneakerModel(brand=brand, name=name, releaseDate=releaseDate, retailPrice=retailPrice, image=originalImage)
        sneakers.save_to_db()

    response = make_response(jsonify(status=200, success=True))

    return response

class SneakerId(Resource):
  def post(self):
    data = request.get_json(force=True)

    id = data["id"]

    sneaker = SneakerModel.find_by_id(id)
    sneaker_json = sneaker.to_json()

    response = make_response(jsonify(status=200, success=True, sneaker_detail=sneaker_json))

    return response


import time
import sys,os
import copy
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

import multiprocessing
from multiprocessing.connection import Connection
from collections import deque,defaultdict

import numpy as np

from problem import Blozorx, State, Action

POPULATION_SIZE = 100
MUTATION_RATE = 0.1
INIT_MOVE = 5
INCREASED_MOVE = 5
INCREASED_MOVE_EVERY_EPOCH = 5
MAX_GEN = 500
GENES = [action[0] for action in Action.get_action_set()]

class Individual:
    def __init__(self, chromosome):
        self.chromosome = chromosome

    def survive(self, problem:Blozorx, init_state: State):
        state = copy.deepcopy(init_state)
        for gene in self.chromosome:
            action = Action.decode_action(gene)
            problem.do_action_if_possible(state, action, inplace=True)
            if state.is_goal_state():
                break

        self.fitness = Individual.fitness_function(problem, state)
        self.is_win = state.is_goal_state()

    def increase_move(self, size):
        self.chromosome += ''.join(np.random.choice(GENES) for _ in range(size))

    def mutate(self, mutation_rate):
        chromosome = list(self.chromosome)
        for i in range(len(chromosome)):
            if np.random.random() < mutation_rate:
                chromosome[i] = np.random.choice(GENES)
        self.chromosome = ''.join(chromosome)

    @classmethod
    def create(cls):
        global GENES,INIT_MOVE
        chromosome = ''.join(np.random.choice(GENES) for _ in range(INIT_MOVE))
        return cls(chromosome)

    @staticmethod
    def fitness_function(problem:Blozorx, state:State):
        if state.is_standing_state():
            loss = abs(state.cur[0] - problem.init_state.goal[0]) + abs(state.cur[1] - problem.init_state.goal[1])
        else:
            loss = abs((state.cur[0] + state.cur[2])/2 - problem.init_state.goal[0]) \
                + abs((state.cur[1] + state.cur[3])/2 - problem.init_state.goal[1])

        return 1/(loss+1e-6)

    @staticmethod
    def crossover(parent1,parent2):
        cross_i = np.random.randint(0,len(parent1.chromosome))
        child1 = Individual(parent1.chromosome[:cross_i] + parent2.chromosome[cross_i:])
        child2 = Individual(parent2.chromosome[:cross_i] + parent1.chromosome[cross_i:])
        return child1,child2

class GenericAlgorithm:
    def __init__(self, population_size = POPULATION_SIZE, mutation_rate = MUTATION_RATE, increased_move = INCREASED_MOVE, increased_move_every_epoch = INCREASED_MOVE_EVERY_EPOCH):
        self.population_size = population_size
        self.mutation_rate = mutation_rate
        self.increased_move = INCREASED_MOVE
        self.increased_move_every_epoch = INCREASED_MOVE_EVERY_EPOCH

    def _initialize(self):
        self.population = []
        for _ in range(self.population_size):
            individual = Individual.create()
            self.population.append(individual)

    def _calc_fitness(self):
        population_fitness = []
        for individual in self.population:
            individual.survive(self.problem, self.init_state)
            population_fitness.append(
                individual.fitness)
        return population_fitness

    def __call__(self, problem:Blozorx, state:State = None, sender: Connection = None, max_gen = MAX_GEN, show_logs = False):
        # return generation_num, path, exe_time (s)
        start_time_s = time.time()
        self.problem = problem
        self.init_state = state if state is not None else self.problem.init_state

        def _return(generation_num, path=None, is_done=False, fitness = 0, length=None):
            nonlocal sender,start_time_s,problem

            # optimal path
            if path is not None:
                _state = copy.deepcopy(self.init_state)
                optimal_path = ''
                for coded_action in path:
                    action = Action.decode_action(coded_action)
                    can_do,_ = problem.do_action_if_possible(_state, action, inplace=True)
                    if can_do:
                        optimal_path += coded_action
                    if _state.is_goal_state():
                        break
                path = optimal_path

            if sender is not None:
                return_dict = {
                    'solution_cost': generation_num,
                    'path': path,
                    'time': time.time() - start_time_s,
                    'msg': f'Generation: {generation_num} - Length: {length} - Fitness: {fitness:.3f}',
                    'is_done': is_done
                }
                try:
                    sender.send(return_dict)
                except:
                    pass
            else:
                return generation_num,path,time.time() - start_time_s

        # init population
        self._initialize()
        for generation_num in range(max_gen):
            # increase self.increased_move every self.increased_move_every_epoch
            if generation_num % self.increased_move_every_epoch == 1:
                for individual in self.population:
                    individual.increase_move(self.increased_move)

            # calc fitness
            population_fitness = np.array(self._calc_fitness())
            fitness_individual = self.population[np.argmax(population_fitness)]
            highest_fitness = max(population_fitness)

            # check if reached goal state
            for individual in self.population:
                if individual.is_win:
                    return _return(generation_num, path=individual.chromosome, is_done=True)

            # show log
            if show_logs:
                print(f'Generation: {generation_num} - Length: {len(self.population[0].chromosome)} - Fitness: {highest_fitness}')
            _return(generation_num, length=len(self.population[0].chromosome) ,fitness=highest_fitness)

            # probability that the individual should be selected as parent
            # parent_probs = np.exp(population_fitness - population_fitness.min())
            # parent_probs /= parent_probs.sum()
            parent_probs = population_fitness / population_fitness.sum()

            new_population = []
            for _ in range(0,self.population_size,2):
                # natural selection
                parent1,parent2 = np.random.choice(self.population, size=2, p=parent_probs, replace=False)

                # produce offsprings
                child1,child2 = Individual.crossover(parent1,parent2)

                # mutate offsprings
                child1.mutate(self.mutation_rate)
                child2.mutate(self.mutation_rate)

                new_population.extend([child1,child2])

            self.population = new_population

        return _return(max_gen,None,True)

generic_algorithm = GenericAlgorithm()

if __name__ == '__main__':
    generation_num, path, exe_time = GenericAlgorithm()(Blozorx(30),show_logs=True)
    print(generation_num)
    print(path)
    print(exe_time)

    problem = Blozorx(2)
    i = Individual(path)
    i.survive(problem, problem.init_state)
    print(i.is_win)


# Search a directory tree for all files with duplicate content
import os, hashlib, pprint

hashmap = {} #content signature -> list of matching filenames

for path, dirs, files in os.walk('.'):
    for filename in files:
        fullname = os.path.join(path, filename)
        d = open(fullname).read()
        h = hashlib.md5(d).hexdigest()
        hashmap.setdefault(h,[]).append(fullname)

pprint.pprint(hashmap)


import numpy as np
import math

def to_tensor(a):
    return tf.convert_to_tensor(a, dtype=tf.float32)

def find_coordinates_numpy(points):
    # Take in tensor of points (flattened)
    # Return list of 2D coords
    if tf.equal(tf.size(points), 0):
        return 0
    coord = []
    length = int(math.sqrt(points.size)) # to the square root of the second dimension of shape
    print("length",length)
    for idx in points:
        i = idx//length
        j = idx % length
        coord.append([i,j])
    return np.asarray(coord)

def find_mean_distance(coord_A, coord_B):
    n_coord = len(coord_A)
    if n_coord < 10:
        return 'too few'
    for point in coord_A:
        distances = []
        min_dist = 1000
        for coord in coord_B:
            diff = np.subtract(coord,point)
            dist = math.sqrt(diff[0]**2 + diff[1]**2)
            if dist < min_dist:
                min_dist = dist
        distances.append(min_dist)
    distances = np.asarray(distances)
    return np.mean(distances)

def find_coordinates_numpy(points):
    # Take in tensor of points (flattened)
    # Return list of 2D coords
    if points.sum() < 20:
        return 'too few'
    coord = []
    length = 60 # to the square root of the second dimension of shape
    for idx, point in enumerate(points):
        if point > 0:
            i = idx//length
            j = idx % length
            coord.append([i,j])
    return np.asarray(coord)

def MSE_plus_MED(cutoff=25.4,constant_loss=1):
    # medMiss gives mean distance of misses in A, by B
    def loss_function(y_true, y_pred):
        MSE = tf.math.reduce_mean(tf.square(y_true - y_pred))
        target_tensor = tf.reshape(y_true, (tf.shape(y_true)[0], -1)).numpy() # reshape for sample-wise
        prediction_tensor = tf.reshape(y_pred, (tf.shape(y_pred)[0], -1)).numpy()
        # hard discretization
        target_tensor = tf.cast(tf.where(target_tensor<cutoff,0.0,1.0),tf.float32)
        prediction_tensor = tf.cast(tf.where(prediction_tensor<cutoff,0.0,1.0),tf.float32)
        # Now calculate MED
        MED = 0 # initialize MED
        for true, pred in zip(target_tensor, prediction_tensor):
            points_A = tf.where(true).numpy() # get indices of nonzero elements and convert to numpy
            points_B = tf.where(pred).numpy()
            coord_A = find_coordinates_numpy(points_A) # get coordinates of nonzero elements on 2D grid
            coord_B = find_coordinates_numpy(points_B)
            if not isinstance(coord_A, str) and not isinstance(coord_B, str): # There are points in both A and B
                MED = MED + find_mean_distance(coord_A,coord_B)
            if not isinstance(coord_A, str) and isinstance(B, str): # There are points in A but not in B
                MED = MED + constant_loss # for now, just add a constant if B == 0
            else: # A is completely below threshold
                MED = MED + 0 # if A is below threshold, just use MSE (i.e. MED = 0)
        return MSE + MED
    return loss_function

def MSE_plus_medMiss(cutoff=25.4, constant_loss=1):
    def medMiss(y_true, y_pred):
        MSE = tf.math.reduce_mean(tf.square(y_true - y_pred))
        print(MSE)
        target_tensor = tf.reshape(y_true, (tf.shape(y_true)[0], -1)).numpy() # reshape for sample-wise
        prediction_tensor = tf.reshape(y_pred, (tf.shape(y_pred)[0], -1)).numpy()
       # MSE = K.sqrt(tf.math.reduce_mean(tf.square(target_tensor - prediction_tensor), axis = [1])) # calculate sample-wise MSE
        # hard discretization
        target_tensor = tf.cast(tf.where(target_tensor<cutoff,0.0,1.0),tf.float32)
        prediction_tensor = tf.cast(tf.where(prediction_tensor<cutoff,0.0,1.0),tf.float32)
        # Now calculate MED
        MED = 0 # initialize MED
        for idx, sample in enumerate(target_tensor):
            points_A = tf.where(sample).numpy() # get indices of nonzero elements and convert to numpy
            points_B = tf.where(prediction_tensor[idx]).numpy()
            coord_A = find_coordinates_numpy(points_A) # get coordinates of nonzero elements on 2D grid
            coord_B = find_coordinates_numpy(points_B)
            if coord_A != 0 and coord_B != 0:
                MED = MED + find_mean_distance(coord_B,coord_A)
            if coord_A != 0 and coord_B == 0: # check for all FNs in B
                # mupltiply by constant loss * number of FNs
                MED = MED + constant_loss # for now, just add a constant if B == 0
            else:
                MED = MED + 0 # if A is below threshold, just use MSE (i.e. MED = 0)
            print(MED)
        return MSE + MED
    return medMiss

def myMED(cutoff=20):
    def mean_error_distance(y_true, y_pred):
        # Sample specific MED (i.e. not whole batch at once)
        # Either maxpool or limit domain size or threshold by high val to reduce computation
        target_tensor = tf.cast(tf.where(y_true<cutoff,0.0,1.0),tf.float32)
        prediction_tensor = tf.cast(tf.where(y_pred<cutoff,0.0,1.0),tf.float32)
        target_tensor = tf.reshape(target_tensor, (tf.shape(target_tensor)[0], -1)).numpy()
        prediction_tensor = tf.reshape(prediction_tensor, (tf.shape(prediction_tensor)[0], -1)).numpy()
        MED = 0
        for idx, sample in enumerate(target_tensor):
            points_A = tf.where(sample).numpy() # get indices of nonzero elements and convert to numpy
            points_B = tf.where(prediction_tensor[idx]).numpy()
            coord_A = find_coordinates_numpy(points_A) # get coordinates of nonzero elements on 2D grid
            coord_B = find_coordinates_numpy(points_B)
            if coord_A != 0 and coord_B != 0:
                print('Coordinates are present, calculating MED')
                MED = MED + find_mean_distance(coord_A,coord_B)
                print('MED {}'.format(MED))
            elif coord_A == 0 and coord_B != 0:
                MED = MED + K.sqrt(tf.math.reduce_mean(tf.square(y_true - y_pred), axis = [1]))
                print('A completely below threshold with {}'.format(MED))
            elif coord_A != 0 and coord_B == 0:
                MED = MED + K.sqrt(tf.math.reduce_mean(tf.square(y_true - y_pred), axis = [1]))
                print('B completely below threshold with {}'.format(MED))
            else:
                MED = MED + K.sqrt(tf.math.reduce_mean(tf.square(y_true - y_pred), axis = [1]))
                print('Triggered else clause with {}'.format(MED))
            #except IndexError:
            #    print('index errror')
            #    MED = MED + 0
        return MED
    return mean_error_distance

def distance(point1, point2):
    # get x and y as return from point tuple
    x1, y1 = point1
    x2, y2 = point2
    return np.sqrt((x1-x2)**2 + (y1-y2)**2)

def get_distance_slow(A, B):
    coord_A = get_coord(A)
    coord_B = get_coord(B)
    min_dists = []
    for idx in range(len(coord_A)):
        distances = []
        for idx2 in range(len(coord_B)):
            distance = distance(coord_A[idx], coord_B[idx2])
            distances.append(distance)
        min_dists.append(min(distances))
    return min_dists

def get_coord(A,method='numpy'):
    if method == 'numpy':
        indices = np.where(A)
        points = [(x,y) for x,y in zip(indices[0],indices[1])]
        return points

def is_in_elipse(point, elipse_center, elipse_radius):
    x, y = point
    cx, cy = elipse_center
    rx, ry = elipse_radius
    return (x-cx)**2/(rx**2) + (y-cy)**2/(ry**2) <= 1

def make_elipse(center, radius, n=60):
    #  A = m.make_elipse((15,20), (10,8))
    #  B = m.make_elipse((13,25), (11,15))
    A = np.ones((n,n))
    indices = np.where(A)
    points = [(x,y) for x,y in zip(indices[0], indices[1])]
    in_elipse = [is_in_elipse(point, center, radius) for point in points]
    A = np.asarray(in_elipse).astype(int)
    return np.reshape(A, (n,n))

def distance_1D(x1, x2):
    # get x and y as return from point tuple
    return (x1-x2)**2

def distance_transform(B):
    # requires B to be binary
    B = np.where(B, 0, 1)
    G = []
    for row in B:
        # convert row to list
        # get indices of 0s in row
        zeros = np.where(row == 0)[0]
        ones = np.where(row == 1)[0]
        G_row = []
        for idx, value in enumerate(row):
            if idx in ones:
                if len(zeros) > 0:
                    dist = min(distance_1D(idx, zeros))
                else:
                    dist = 60**2

            else:
                dist = 0
            G_row.append(dist)
        G.append(G_row)
    # Now G is built, as a list of rows
    # Convert to numpy array
    G = np.asarray(G)
    G = np.transpose(G)
    indices = np.arange(0, 60)
    H = np.zeros((60,60))
    for i, col in enumerate(G):
        for idx, value in enumerate(col):
            if G[i,idx] == 0:
                continue # leave as 0 if point is above threshold in B
            col_transform = col + [distance_1D(x, idx) for x in indices]
            dist_idx = min(col_transform)
            # square root
            H[i, idx] = np.sqrt(dist_idx)
    return H
# implement distance transofrm using bucket sorting

def min_dists(A, B, threshold=20):
    A = np.where(A<threshold, 0, 1)
    B = np.where(B<threshold, 0, 1)
    H = distance_transform(B)
    min_dists = A*H
    # flatten mindists
    min_dists = min_dists.flatten()
    # keep only nonzero elements
    min_dists = min_dists[min_dists != 0]
    return min_dists

def hausdorf(mindists_AB,mindists_BA):
    return np.maximum(np.amax(mindists_AB), np.amax(mindists_BA))

def delta(A, B):
    H_A = distance_transform(A)
    H_B = distance_transform(B)
    H_A = np.where(H_A > 20, 20, H_A)
    H_B = np.where(H_B > 20, 20, H_B)
    delta = H_A - H_B
    delta = np.square(delta)
    delta = np.sum(delta)
    delta = 1/3600 * delta
    delta = np.sqrt(delta)
    return delta

def zhulak(A, B, mindists_AB, l1=0.5):
    l_ovlp = np.mean(np.square(np.subtract(A, B)))
    n_A = np.sum(A)
    l_obs = np.sum(mindists_AB)/n_A
    return l1*l_ovlp + (1-l1)*l_obs

def w(d):
    # cutoff transformatioin
    return np.amin(d, 20)

def samplewise_RMSE(y_true, y_pred):
    # from CIRA guide
    y_true = tf.reshape(y_true, [tf.shape(y_true)[0], -1])
    y_pred = tf.reshape(y_pred, [tf.shape(y_true)[0], -1])
    return K.sqrt( tf.math.reduce_mean(tf.square(y_true - y_pred), axis=[1]))

def neighborhood_stats(y_true, y_pred, thres, n):
    # Given a pixel, determine if a pixel within a
    # n x n neighborhood is above threshold for hit,
    # if so, increment TP by 1
    # n = 1 yields a .5 x .5 neighborhoood
    # for reference, 5 km x 5 km: village (n = 10)
    # for reference, 10 km x 10 km: city (n = 20)
    # for reference, 15 km x 15 km: county (n = 30)
    # dilate prediction by n x n filter
    for idx, image in enumerate(y_pred):
        # make image binary
        image = image[image>thres]
        truth = y_true[idx][y_true[idx]>thres]
        # dilate image by n x n filter
        dilated_image = cv2.dilate(image, np.ones((n,n), np.uint8))
        # get true positives
        true_positives = np.sum(np.logical_and(dilated_image, truth))
        # get false positives
        false_positives = np.sum(np.logical_and(dilated_image, np.logical_not(truth)))
        # get false negatives
        false_negatives = np.sum(np.logical_and(np.logical_not(dilated_image), truth))
        # get true negatives
        true_negatives = np.sum(np.logical_and(np.logical_not(dilated_image), np.logical_not(truth)))
        # calculate precision
        precision = true_positives / (true_positives + false_positives)
        # get POD
        POD = true_positives / (true_positives + false_negatives)
        # get FAR
        FAR = false_positives / (false_positives + true_negatives)
        # get CSI
        CSI = (true_positives + false_negatives) / (true_positives + false_positives + false_negatives + true_negatives)
    return POD, FAR, CSI, precision

def neighborhood_stats_by_image(truth, pred, n):
    # dilate image by n x n filter
    dilated_image = cv2.dilate(pred, np.ones((n,n), np.uint8))
    # get true positives
    true_positives = np.sum(np.logical_and(dilated_image, truth))
    # get false positives
    false_positives = np.sum(np.logical_and(dilated_image, np.logical_not(truth)))
    # get false negatives
    false_negatives = np.sum(np.logical_and(np.logical_not(dilated_image), truth))
    # get true negatives
    true_negatives = np.sum(np.logical_and(np.logical_not(dilated_image), np.logical_not(truth)))
    # calculate precision
    precision = true_positives / (true_positives + false_positives)
    # get POD
    POD = true_positives / (true_positives + false_negatives)
    # get FAR
    FAR = false_positives / (false_positives + true_negatives)
    # get CSI
    CSI = (true_positives + false_negatives) / (true_positives + false_positives + false_negatives + true_negatives)
    return POD, FAR

def CSI(cutoff=20):
    # From CIRA guide to loss functions, with slight differences
    # Does not train well off thebat, but could be used as second phase for MSE model
    def loss(y_true, y_pred):
        target_tensor = tf.cast(tf.where(y_true>cutoff,0.0,1.0),tf.float32)
        prediction_tensor = tf.cast(tf.where(y_pred>cutoff,0.0,1.0),tf.float32)

        num_true_positives = K.sum(target_tensor * prediction_tensor)
        num_false_positives = K.sum((1 - target_tensor) * prediction_tensor)
        num_false_negatives = K.sum(target_tensor * (1 - prediction_tensor))

        denominator = (
            num_true_positives + num_false_positives + num_false_negatives +
            K.epsilon()
            )
        csi_value = num_true_positives / denominator
        return csi_value
        #return 1. - csi_value # subtract from 1 so we minimize i.e. increase CSI
    return loss

def FAR(cutoff=15):
    def far(y_true, y_pred):
        y_true = y_true.flatten()
        y_pred = y_pred.flatten()
        TP = np.sum(np.where(((y_true-1.0)+y_pred)<1.0,0.0,1.0))
        FP = np.sum(np.where(y_pred-y_true<1.0,0.0,1.0))
        return FP/(TP+FP+0.000001)
    return far

def POD(cutoff=15):
    # computes the probability of detection
    # POD = PT / TP + FN
    def pod(y_true, y_pred):
        y_true = y_true.flatten()
        y_pred = y_pred.flatten()
        TP = np.sum(np.where(((y_true-1)+y_pred)<1.0,0.0,1.0))
        FN = np.sum(np.where(y_true-y_pred<1.0,0.0,1.0))
        return TP/(TP+FN+0.000001)
    return pod

def PHDK(mindists_AB, mindists_BA, k_pct):
    len_mindists_AB = len(mindists_AB)
    len_mindists_BA = len(mindists_BA)
    min_N = min(len_mindists_AB, len_mindists_BA)
    k = int(min_N * k_pct)
    # sort mindists_AB and mindists_BA in descending order
    mindists_AB.sort()
    mindists_BA.sort()
    kth_AB = mindists_AB[k]
    kth_BA = mindists_BA[k]
    return max(kth_AB, kth_BA)

def G_beta(A,B, mindists_AB, mindists_BA, beta):
    # low beta means more weight on location errors
    # sqrt(N)* N up to N**2
    n_A = np.sum(A)
    n_B = np.sum(B)
    n_AB = np.sum(A*B)
    y1 = n_A + n_B -2*n_AB
    med_AB = np.mean(mindists_AB) # try median
    med_BA = np.mean(mindists_BA)
    y2 = med_AB*n_B + med_BA*n_A
    y = y1*y2
    const = 1 - (y/beta)
    G_beta = const
    return G_beta

def G(A,B, mindists_AB, mindists_BA, beta):
    # low beta means more weight on location errors
    # sqrt(N)* N up to N**2
    n_A = np.sum(A)
    n_B = np.sum(B)
    n_AB = np.sum(A*B)
    y1 = n_A + n_B -2*n_AB
    med_AB = np.mean(mindists_AB) # try median
    med_BA = np.mean(mindists_BA)
    y2 = med_AB*n_B + med_BA*n_A
    y = y1*y2
    return y

# find the shortest distance between two set of points as numpy arrays
def find_coordinates(A):
    # returns a tensor of coordinates of nonzero elements in A
    coord_A = []
    length = A.shape[0]
    for idx, row in enumerate(A):
        for idx2, pixel in enumerate(row):
            if pixel == 1:
                i = idx%length
                j = idx2
                coord_A.append([i,j])
    return coord_A

def find_shortest_distance(A,B):
    # returns a tensor of coordinates of nonzero elements in A
    coord_A = find_coordinates(A)
    coord_B = find_coordinates(B)

    point = coord_A[0]
    distances = []
    for coord in coord_B:
        distances.append(np.linalg.norm(np.subtract(coord,point)))
    return np.min(distances)

def get_contour_set_2(A):
    # defines contour pixels as white pixels with at least one black neighbor
    # A is a 2D binary image
    x_ind, y_ind = np.where(A==1)
    white_points = [(x,y) for x,y in zip(x_ind,y_ind)]
    contour_set = []
    buckets = [[] for x in np.arange(60)]
    for x in x_ind:
        for y in y_ind:
            neighbors = get_neighbors(x,y)
            # Add neighbors to contour set if they are not in x_ind, y_ind and are not in the contour set
            for neighbor in neighbors:
                if neighbor not in white_points and neighbor not in contour_set and y < 60 and y >= 0 and x < 60 and x >= 0:
                    buckets[0].append((x,y,0,0))
                    if neighbor not in buckets[0]:
                        if neighbor[0] != x and neighbor[1] != y:
                            dx = 1
                            dy = 1
                            buckets[2].append((neighbor[0],neighbor[1],dx,dy))
                        if neighbor[0] != x:
                            dx = 1
                            dy = 0
                            buckets[1].append((neighbor[0],neighbor[1],dx,dy))
                        if neighbor[1] != y:
                            dx = 0
                            dy = 1
                            buckets[1].append((neighbor[0],neighbor[1],dx,dy))
    return buckets

def get_neighbors(x,y):
    return [[x-1,y-1],[x-1,y],[x-1,y+1],[x,y-1],[x,y+1],[x+1,y-1],[x+1,y],[x+1,y+1]]

def main():
    A = make_elipse((15,20), (10,8))
    B = make_elipse((13,25), (11,15))
    H_A = distance_transform(A)
    print(H_A)

if __name__ == '__main__':
    main()


""" Hide a message in a docx document using a white font."""
import docx
from docx.shared import RGBColor, Pt

# get text from a fake message & make each line a list item
fake_text = docx.Document('fakeMessage.docx')
fake_list = []
for paragraph in fake_text.paragraphs:
    fake_list.append(paragraph.text)

# get text from real message & make each line a list item
real_text = docx.Document('realMessage_Vig.docx')
real_list = []
for paragraph in real_text.paragraphs:
    if len(paragraph.text) != 0:  # remove blank lines
        real_list.append(paragraph.text)

# load template that sets style, font, margins, etc.
doc = docx.Document('template.docx')

# add letterhead:
doc.add_heading('Morland Holmes', 0)
subtitle = doc.add_heading('Global Consultanting & Negotiations', 1)
subtitle.alignment = 1
doc.add_heading('', 1)
doc.add_paragraph('December 17, 2015')
doc.add_paragraph('')

def set_spacing(paragraph):
    """Use docx to set line spacing between paragraphs."""
    paragraph_format = paragraph.paragraph_format
    paragraph_format.space_before = Pt(0)
    paragraph_format.space_after = Pt(0)

length_real = len(real_list)
count_real = 0  # index of current line in real (hidden) message

# interleave real and fake message lines
for line in fake_list:
    if count_real < length_real and line == "":
        paragraph = doc.add_paragraph(real_list[count_real])
        paragraph_index = len(doc.paragraphs) - 1

        # set real message color to white
        run = doc.paragraphs[paragraph_index].runs[0]
        font = run.font
        font.color.rgb = RGBColor(255, 255, 255)  # make it red to test
        count_real += 1

    else:
        paragraph = doc.add_paragraph(line)

    set_spacing(paragraph)

doc.save('ciphertext_message_letterhead.docx')

print("Done")


from math import floor, ceil

def round_it(n):
    l, r = [len(x) for x in str(n).split('.')]
    if r > l:
        return ceil(n)
    elif r < l:
        return floor(n)
    else:
        return round(n)


import pygame
from random import randrange
pygame.init()

HEIGHT = 600
WIDTH = 800
GREEN = 144, 230, 92
YELLOW = 240, 230, 50
RED = 235, 64, 40

window = pygame.display.set_mode((WIDTH, HEIGHT))

# list of blocks that will be sorted
class List:
    # randomly generates list of different heights
    def generateList(self, num_blocks):
        for i in range(num_blocks):
            height = randrange(300)
            self.lst.append(height)

    def __init__(self, size):
        self.lst = []
        self.generateList(size)

# draws the list of rectangles at its curretnt state with what values should be red and green
def draw_list(list,num_blocks, red, green, algo):
    block_width = ((WIDTH-40)/num_blocks)
    # looping through block heights and calculating coordinates for each block to be drawn
    window.fill((0,0,0))

    title = pygame.font.SysFont('Ariel', 40).render(f"Current Sort: {algo}", 200, GREEN)
    insert = pygame.font.SysFont('Ariel', 40).render("Insertion Sort - 'i'", 200, GREEN)
    select = pygame.font.SysFont('Ariel', 40).render("Selection Sort - 's'", 200, GREEN)
    start = pygame.font.SysFont('Ariel', 40).render("Start Sorting - Space", 200, GREEN)
    reset = pygame.font.SysFont('Ariel', 40).render("Reset List - 'r''", 200, GREEN)

    window.blit(title, (HEIGHT/2 - title.get_width()/4, 20))
    window.blit(insert, (10, 70))
    window.blit(select, (10, 110))
    window.blit(reset, (10, 150))
    window.blit(start, (10, 190))

    for count, i in enumerate(list.lst):
        rect = pygame.Rect(20 + count * block_width, HEIGHT - i, block_width, i)
        if count == green:
            pygame.draw.rect(window, GREEN, rect)
        elif count == red:
            pygame.draw.rect(window, RED, rect)
        elif red == -1 or green == -1:
            pygame.draw.rect(window, (count * 10, 100, 255), rect)
        else:
            pygame.draw.rect(window, (count * 10, 100, 255), rect)
    pygame.display.update()

def insertionSort(list, num_elements):
    clock = pygame.time.Clock()
    for i in range(1, len(list.lst)):
        clock.tick(20)
        key = list.lst[i]
        # Move elements of arr[0..i-1], that are
        # greater than key, to one position ahead
        # of their current position
        j = i-1

        while j >=0 and key < list.lst[j] :
                clock.tick(20)
                list.lst[j+1] = list.lst[j]
                draw_list(list, num_elements, i, j, "Insertion Sort")
                j -= 1
        list.lst[j+1] = key
        draw_list(list, num_elements, i, j, "Insertion Sort")

def selectionSort(list, num_elements):
    clock = pygame.time.Clock()
    for i in range(len(list.lst)):
        # Find the minimum element in remaining
        # unsorted array
        clock.tick(20)
        min_idx = i
        for j in range(i+1, len(list.lst)):
            clock.tick(20)
            draw_list(list, num_elements, i, j, "Selection Sort")
            if list.lst[min_idx] > list.lst[j]:
                min_idx = j

        # Swap the found minimum element with
        # the first element
        list.lst[i], list.lst[min_idx] = list.lst[min_idx], list.lst[i]
        draw_list(list, num_elements, i, j, "Selection Sort")

def sorting(sort, lst, num_elements):
    if sort == 'Insertion Sort':
        insertionSort(lst,num_elements)
    if sort == 'Selection Sort':
        selectionSort(lst,num_elements)
# game loop
def main():
    run = True
    num_elements = 20
    lst = List(num_elements)
    sort = 'Insertion Sort'
    draw_list(lst, num_elements, -1, -1, sort)
    while run:
        for event in pygame.event.get():
            if event.type ==  pygame.QUIT:
                run = False
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_r:
                    lst.lst = []
                    lst.generateList(num_elements)
                    draw_list(lst, num_elements, -1, -1, sort)
                elif event.key == pygame.K_SPACE:
                    sorting(sort, lst, num_elements)
                elif event.key == pygame.K_i:
                    sort = 'Insertion Sort'
                elif event.key == pygame.K_s:
                    sort = 'Selection Sort'
            draw_list(lst, num_elements, -1, -1, sort)

if __name__ == '__main__':
    main()
pygame.quit()


def build_grps(inp):
    groups = []
    tmp_grp = ""
    grp_size = 0
    for i, line in enumerate(inp):
        if line == "\n":
            groups.append((grp_size, tmp_grp))
            tmp_grp = ""
            grp_size = 0
            continue
        tmp_grp += line.strip("\n")
        grp_size += 1
    groups.append((grp_size, tmp_grp))
    return groups

def sum_yes(inp):
    cnt = 0
    for grp in build_grps(inp):
        cnt += len(set(grp[1]))

    print(f"Counts: {cnt}")

def sum_all_yes(inp):

    final_cnt = 0
    for grp in build_grps(inp):
        questions = grp[1]
        size = grp[0]
        counts = {}
        for q in questions:
            counts[q] = counts.get(q, 0) + 1
        for count in counts.values():
            final_cnt += 1 if count == size else 0

    print(f"Counts: {final_cnt}")

def main():

    with open("in", "r") as fp:
        data = fp.readlines()

    sum_yes(data)
    sum_all_yes(data)

if __name__ == '__main__':
    main()


from selenium import webdriver

# DEFINE DRIVER
driver = webdriver.Opera()

# ENTER WEBSITE
driver.get("http://wiby.me")

# FULL SCREEN MODE
driver.maximize_window()

# FIND THE BUTTEN ON THE WEBSITE THAT SAYS "SUPPRICE ME!"
driver.find_element_by_xpath(xpath="/html/body/form/div[5]/a").click()


s = input().strip().lower()
d = {}
lst = []

for e in s:
    if(not e.isalpha()):
        continue
    if(e in d):
        d[e] -= 1
    else:
        d[e] = -1

for e in d:
    lst.append([d[e], e])

lst = sorted(lst)

for e in lst:
    print(e[1], -1*int(e[0]), sep=' -> ')


with open("C-small-attempt1.in") as f:
#with open("C-large.in") as f:
#with open("test.in") as f:
	dat = f.read().splitlines()

import random

def rem(i,topics,counts):
	t = topics[i]
	del topics[i]
	del counts[i]

	for j in range(topics.__len__()):
		if topics[j][0] == t[0]:
			counts[j][0] = 0
		if topics[j][1] == t[1]:
			counts[j][1] = 0
	return topics,counts

def remfree(topics,counts,fake):
	for i in range(topics.__len__()-1,-1,-1):
		if counts[i][0] == 0 and counts[i][1] == 0:
			del topics[i]
			del counts[i]
			fake += 1
	return topics,counts,fake

def remalone(topics,counts,fake):
	#su jedinecne, killnem
	for i in range(topics.__len__()-1,-1,-1):
		if counts[i][0] == 1 or counts[i][1] == 1:
			#print("kill "+str(topics[i]))
			topics,counts = rem(i,topics,counts)

	#print(topics)
	#print(counts)
	#su volne, su to fejky
	topics,counts,fake = remfree(topics,counts,fake)

	return topics,counts,fake

def break_cycle(topics,counts):
	poss = []
	for i in range(topics.__len__()-1,-1,-1):
		if counts[i][0] > 1 and counts[i][1] > 1:
			#print("kill2 "+str(topics[i]))
			poss.append(i)
	if poss.__len__()!=0:
		i = random.randint(0,poss.__len__()-1)
		i = poss[i]
		#print(i)
		return rem(i,topics,counts)

	i = random.randint(0,topics.__len__()-1)
	#print("kill0 "+str(topics[i]))
	return rem(0,topics,counts)

nn = int(dat[0])
out = []
casei = 1
for case in range(nn):
	n = int(dat[casei])
	topicst = []
	counts = []
	for ii in range(n):
		casei += 1
		topicst.append(dat[casei].split())

	ress = []
	for test in range(1000):
		topics = [t for t in topicst]
		t0 = [t[0] for t in topics]
		t1 = [t[1] for t in topics]

		for t in topics:
			n0 = t0.count(t[0])
			n1 = t1.count(t[1])
			counts.append([n0,n1])

		fake = 0
		topics,counts,fake = remalone(topics,counts,fake)

		if topics.__len__() != 0:
			while True:
				topics,counts = break_cycle(topics,counts)
				topics,counts,fake = remfree(topics,counts,fake)
				if topics.__len__() == 0:
					break

		res = "Case #"+str(case+1)+": "+str(fake)
		#print(res)
		ress.append(res)
	#print("\n".join(ress))
	#assert set(ress).__len__() == 1
	print(case+1)
	out.append(max(ress))
	casei += 1

assert out.__len__() == nn
of = open("out.txt","w")
of.write("\n".join(out))
of.close()


# -*- coding: utf-8 -*-
"""ATA over Ethernet Protocol."""
from __future__ import absolute_import

import struct

from . import dpkt
from .compat import iteritems

class AOE(dpkt.Packet):
    """ATA over Ethernet Protocol.

    See more about the AOE on
    https://en.wikipedia.org/wiki/ATA_over_Ethernet

    Attributes:
        __hdr__: Header fields of AOE.
        data: Message data.
    """

    __hdr__ = (
        ('_ver_fl', 'B', 0x10),
        ('err', 'B', 0),
        ('maj', 'H', 0),
        ('min', 'B', 0),
        ('cmd', 'B', 0),
        ('tag', 'I', 0),
    )
    __bit_fields__ = {
        '_ver_fl': (
            ('ver', 4),
            ('fl', 4),
        )
    }
    _cmdsw = {}

    @classmethod
    def set_cmd(cls, cmd, pktclass):
        cls._cmdsw[cmd] = pktclass

    @classmethod
    def get_cmd(cls, cmd):
        return cls._cmdsw[cmd]

    def unpack(self, buf):
        dpkt.Packet.unpack(self, buf)
        try:
            self.data = self._cmdsw[self.cmd](self.data)
            setattr(self, self.data.__class__.__name__.lower(), self.data)
        except (KeyError, struct.error, dpkt.UnpackError):
            pass

AOE_CMD_ATA = 0
AOE_CMD_CFG = 1
AOE_FLAG_RSP = 1 << 3

def _load_cmds():
    prefix = 'AOE_CMD_'
    g = globals()

    for k, v in iteritems(g):
        if k.startswith(prefix):
            name = 'aoe' + k[len(prefix):].lower()
            try:
                mod = __import__(name, g, level=1)
                AOE.set_cmd(v, getattr(mod, name.upper()))
            except (ImportError, AttributeError):
                continue

def _mod_init():
    """Post-initialization called when all dpkt modules are fully loaded"""
    if not AOE._cmdsw:
        _load_cmds()

def test_creation():
    aoe = AOE()
    # hdr fields
    assert aoe._ver_fl == 0x10
    assert aoe.err == 0
    assert aoe.maj == 0
    assert aoe.min == 0
    assert aoe.cmd == 0
    assert aoe.tag == 0
    assert bytes(aoe) == b'\x10' + b'\x00' * 9

def test_properties():
    aoe = AOE()
    # property getters
    assert aoe.ver == 1
    assert aoe.fl == 0

    # property setters
    aoe.ver = 2
    assert aoe.ver == 2
    assert aoe._ver_fl == 0x20

    aoe.fl = 12
    assert aoe.fl == 12
    assert aoe._ver_fl == 0x2C

def test_unpack():
    from binascii import unhexlify
    buf = unhexlify(
        '1000000000'
        '00'          # cmd: AOE_CMD_ATA
        '00000000'    # tag
    )
    aoe = AOE(buf)
    # AOE_CMD_ATA specified, but no data supplied
    assert aoe.data == b''

    buf = unhexlify(
        '1000000000'
        '00'          # cmd: AOE_CMD_ATA
        '00000000'    # tag

        # AOEDATA specification
        '030a6b190000000045000028941f0000e30699b4232b2400de8e8442abd100500035e1'
        '2920d9000000229bf0e204656b'
    )
    aoe = AOE(buf)
    assert aoe.aoeata == aoe.data

def test_cmds():
    import dpkt
    assert AOE.get_cmd(AOE_CMD_ATA) == dpkt.aoeata.AOEATA
    assert AOE.get_cmd(AOE_CMD_CFG) == dpkt.aoecfg.AOECFG

def test_cmd_loading():
    # this test checks that failing to load a module isn't catastrophic
    standard_cmds = AOE._cmdsw
    # delete the existing code->module mappings
    AOE._cmdsw = {}
    assert not AOE._cmdsw
    # create a new global constant pointing to a module which doesn't exist
    globals()['AOE_CMD_FAIL'] = "FAIL"
    _mod_init()
    # check that the same modules were loaded, ignoring the fail
    assert AOE._cmdsw == standard_cmds


'''
We are interested in writing a function to compare a given search value to a
binary search tree. Specifically, we want to know whether the search value is
smaller, bigger, or spanned by the tree.

Our function should accept two arguments, the root of a tree, and a search
value to compare against it. The ouput of our functions should be as follows:

- If the value is smaller than the smallest element in the tree, our function
should return 'smaller'
- If the value is larger than the largest element in the tree, our function
should return 'larger'
- If the value is between the smallest and largest element (inclusive) in the
tree, our function should return 'spanned'

For example, given this tree:

           6
         /   \
        /     \
       3       8
      / \       \
     1   5       9

If the search value was 10, our function should return 'bigger', because 10 is
greater than 9.
If the search value was 0, our function should return 'smaller', because 0 is
less than 1.
If the search value was 4, our function should return 'spanned', because 4 is
between 1 and 9 (inclusive).
If the search value was 1, our function should return 'spanned', because 1 is
between 1 and 9 (inclusive).
'''

# DO NOT MODIFY THE NODE CLASS
class Node:

    def __init__(self, value, left=None, right=None):
        self.value = value
        self.left = left
        self.right = right

def compare_helper(tree):
    current = tree
    smallest = 0
    largest = 0

    while current:
        if current.left:
            current = current.left
    smallest = current.val

    current = tree
    while current:
        if current.right:
            current = current.right
    largest = current.val

    return smallest, largest

def compare(tree, search_value):
    values = compare_helper(tree)

    if search_value < values[0]:
        return "smaller"
    elif search_value > values[1]:
        return "bigger"
    else:
        return "spanned"

'''
           6
         /   \
        /     \
       3       8
      / \       \
     1   5       9
'''
tree = Node(6, Node(3, Node(1), Node(5)), Node(8, None, Node(9)))
assert compare(tree, 10) == "bigger"
assert compare(tree, 0) == "smaller"
assert compare(tree, 4) == "spanned"
assert compare(tree, 1) == "spanned"
assert compare(tree, 5) == "spanned"
assert compare(tree, 9) == "spanned"

'''
           5
         /   \
        /     \
       3       7
      /         \
     1           8
    /
   0
'''
tree = Node(5, Node(3, Node(1, Node(0))), Node(7, None, Node(8)))
assert compare(tree, 9) == "bigger"
assert compare(tree, -1) == "smaller"
assert compare(tree, 0) == "spanned"
assert compare(tree, 8) == "spanned"

print("All tests passed! Discuss time & space complexity if time remains")

'''
***NOTES TO INTERVIEWER***

---------Answers to clarifying questions----------

Q: What should I return if the search value exactly matches the smallest value
in the tree? What if it exactly matches the largest value?
A: You should return 'spanned'. The span is inclusive of both ends.

Q: What should I do if the input is None or has fewer than two nodes?
A: You can assume the tree will include at least two Nodes.

Q: Will the input contain any cycles?
A: No.

Q: What should I do if invalid input is passed in?
A: You can assume that the input will be valid.

Q: What data types will be stored in the values?
A: Integers.

--------------------------------------------------

---------Hints for struggling candidates----------

 - If your candidate struggles with an initial algorithm, encourage them to
 walk through an example and desrcibe how they would do it using only pen and
 paper.

 - If your candidate still struggles, ask them what the minimum value in the
 sample tree is. Ask them how they could write code to find the minimum. Ask
 them the same for the maximum. Ask them how the problem could be solved if
 they knew what the minimum and maximum values of the tree are.

 - It can be challenging to debug this problem. If your candidate is failing
 a test and unsure why, encourage them to add print statements that help them
 see what nodes are being visited when. This can especially help if their code
 gets stuck in an infinite loop.

 -------------------------------------------------

OPTIONAL BONUS AT-HOME CHALLENGES (after interview):

- What are the time/space complexities of the sample solution? Does it make a
difference whether the tree is balanced or not?

- If you wrote a recursive solution, try writing an iterative one. If you
wrote an iterative solution, try writing a recursive one. Which do you prefer?
What are the tradeoffs?

- Try extending your function to also check whether the search value is present
in the tree. If there's an exact match, your function should return 'present'
instead of 'spanned'.

- Try extending your function to use a custom comparator. It should accept an
additional argument, `key`, that determines the order the BST ought to be using.
For example, instead of checking which number is bigger, it could check which
string is longer.
'''


import confuse, argparse
import dpath.util
import pdb
import re

class configManager():

    def __init__(self, config_path = "../configs/setup.yaml"):
        self.config = confuse.Configuration('gp_cpab', __name__)
        self.regex = re.compile('^\*\/')
        if isinstance(config_path, argparse.Namespace):
            self.config.set_args(config_path)
        else:
            self.config.set_file(config_path, base_for_paths=True)

    def parserinfo(self, key):
        return dpath.util.get(self.config.get(), key)

    def get_config_vals(self,keys):
        if filter(self.regex.match,keys):
            final = [ self.parserinfo(k) for k in keys ]
            return final
        else:
            return [ self.config.get()[k] for k in keys ]

if __name__ == "__main__":
    std = configManager()
    std.parserinfo('*/Window_grid')


"""
References:
    Online: All QML Basic Types:
        https://doc.qt.io/qt-6/qmlbasictypes.html
    Qt Assistant > Qt <version> Reference Documentation > QML Types:
        All QML Basic Types

Notice:
    Our basic properties are not same with QML basic types. For example, in QML
    there is a `font` basic type, but we consider `Font` is not a "basic"
    property, but a "group" property.
    So the QML basic types are some references & guidelines to help us to
    create our own defined properties. They are not the same thing.
"""
import re

from .__ext__ import T
from .base import Property

__all__ = [
    'AnyItem',
    'Bool',
    'Color',
    'Date',
    'Delegate',
    'Double',
    'Enumeration',
    'Int',
    'List',
    'Matrix4x4',
    'Number',
    'Real',
    'String',
    'Url',
    'Var',
]

class AnyItem(Property):
    _delegates: dict

    def __init__(self, qid: T.Qid, name: T.Name):
        super().__init__(qid, name)
        self._delegates = {}

    def __getattr__(self, key: str):
        from ..control.traits import base_getattr
        if key.startswith('_'):
            return base_getattr(self, key)
        elif key in self.__dict__:
            return self.__dict__[key]
        elif key in self._delegates:
            return self._delegates[key]
        else:
            out = self._delegates[key] = Property(self.qid, key)
            return out

class Bool(Property):
    value: T.Bool

    def adapt(self) -> str:
        return 'true' if self.value else 'false'

class Color(Property):
    """
    - svg color name. for example: 'red', 'white', 'black', etc.
    - rgb color code. for example: '#ff0000', '#ffffff', '#000000', etc.
    - argb color code. for example: '#800000ff', etc.
    - not support qt methods. for example: `Qt.rgba()`, `Qt.hsva()`, etc.
    """
    value: T.Color
    _validator = re.compile(r'^#(?:[0-9][0-9])?[0-9a-fA-F]{6}$|^\w+$')

    def kiss(self, arg_0: str):
        if self._validator.match(arg_0):
            self.value = arg_0
        else:
            raise ValueError(
                '{} is not a valid color value'.format(arg_0)
            )

    def bind(self, *args):
        raise NotImplemented("{} doesn't support bind method".format(
            self.__class__.__name__
        ))

    def adapt(self) -> str:
        return f'"{self.value}"'

class Date(Property):
    """
    date string. formats:
        - <YYYY>-<MM>-

        - <YYYY>-<MM>-
<T><hh>:<mm>
        - <YYYY>-<MM>-
<T><hh>:<mm>:<ss>
        - <YYYY>-<MM>-
<T><hh>:<mm>:<ss>.<zzz>
        - <YYYY>-<MM>-
<T><hh>:<mm>:<ss>.<zzz><Z>
    params:
        - <YYYY>: full year
        - <MM>: full month
        -
: full day
        - <T>: time separator, it can be any character, but usually we use ' '
        - <hh>: full hour
        - <mm>: full minute
        - <ss>: full second
        - <zzz>: millisecond
        - <Z>: time zone
    note (change statement):
        - i'm not sure about the time zone format. in current version, it's not
          supported.
        - for time separator, you can only use ' '.
    """
    value: T.Date
    _validator = re.compile(
        r'[0-9]{4}-[01][0-9]-[0-3][0-9]'
        r'(?: [0-2][0-9]:[0-5][0-9]:[0-5][0-9](?:\.\d+)?)?'
    )

    def kiss(self, arg_0: str):
        if self._validator.match(arg_0):
            self.value = arg_0
        else:
            raise ValueError(
                '{} is not a valid date string'.format(arg_0)
            )

    def bind(self, *args):
        raise NotImplemented("{} doesn't support bind method".format(
            self.__class__.__name__
        ))

    def adapt(self) -> str:
        return f'"{self.value}"'

class Delegate(Property):
    """
    Warnings:
        This is not stable. Turn to use `AnyItem` instead.
    """
    value: T.Component
    _properties: T.Properties

    def __init__(self, qid: T.Qid, name: T.Name,
                 delegate: T.Union[str, T.Component]):

        if isinstance(delegate, str):
            # find real component in `declare_qtquick.widgets.api.<globals>`
            # FIXME: we should know the exact path (for sub packages of api).
            try:
                from ..widgets import api
                delegate = getattr(api, delegate)  # type: T.Component
            except AttributeError as e:
                raise e

        super().__init__(qid, name, delegate())

    def __getattr__(self, key: str):
        if key == '_properties':
            return getattr(super(), key, ())
        elif key in self._properties:
            return getattr(self.value, key)
        else:
            return getattr(super(), key)

    def __setattr__(self, key: str, value):
        if key in self._properties:
            setattr(self.value, key, value)
        else:
            setattr(super(), key, value)

    def kiss(self, arg_0: T.Component):
        if isinstance(arg_0, Delegate):
            self.value = arg_0.value
        else:
            self.value = arg_0
        self._properties = arg_0.properties

    def bind(self, *args):
        raise NotImplemented("{} doesn't support bind method".format(
            self.__class__.__name__
        ))

    def adapt(self) -> str:
        from .__ext__ import get_id_level
        return self.value.build(get_id_level(self.qid) + 1)

class Double(Property):
    value = T.Number

    def adapt(self) -> str:
        return str(float(self.value))

class Enumeration(Property):
    pass

class Int(Property):
    value: T.Int

    def adapt(self) -> str:
        return str(int(self.value))

class List(Property):
    value: T.List

    def adapt(self) -> str:
        return str(list(self.value))

class Matrix4x4(Property):  # FIXME: not implemented
    pass

class Number(Property):
    value: T.Number

class Real(Number):
    pass

class String(Property):
    value: T.String

    def adapt(self) -> str:
        return f'"{self.value}"'

class Url(String):
    pass

class Var(Property):
    value: T.Any


from datetime import datetime
from .db import db, environment, SCHEMA, add_prefix_for_prod

class Question(db.Model):
    __tablename__ = 'questions'

    if environment == "production":
        __table_args__ = {'schema': SCHEMA}

    # Common Keys
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(255), nullable=False)
    context = db.Column(db.String(2000), nullable=False)
    image_url = db.Column(db.String(500))
    upvotes = db.Column(db.Integer, nullable=False, default=0)
    downvotes = db.Column(db.Integer, nullable=False, default=0)
    created_at = db.Column(db.DateTime, nullable=False, default=datetime.now())
    updated_at = db.Column(db.DateTime, nullable=False, default=datetime.now())

    # Foreign keys
    user_id = db.Column(db.Integer, db.ForeignKey(
        add_prefix_for_prod("users.id")), nullable=False)
    space_id = db.Column(db.Integer, db.ForeignKey(
        add_prefix_for_prod("spaces.id")), nullable=False)

    # Relationships
    user = db.relationship('User', back_populates='questions')
    answers = db.relationship('Answer', back_populates='question', cascade="all, delete-orphan")
    space = db.relationship('Space', back_populates='questions')

    def upvoted(self):
        self.upvotes += 1
        return self.upvotes

    def downvoted(self):
        self.downvotes -= 1
        return self.upvotes

    def to_dict(self):
        return {
            'id': self.id,
            'title': self.title,
            'context': self.context,
            'image_url': self.image_url,
            'upvotes': self.upvotes,
            'space_id': self.space_id,
            'downvotes': self.downvotes,
            'created_at': self.created_at,
            'updated_at': self.updated_at,
            'user': self.user.to_dict(),
            'answers': [answer.to_dict() for answer in self.answers]
        }

    def to_dict_no_user(self):
        return {
            'id': self.id,
            'title': self.title,
            'context': self.context,
            'image_url': self.image_url,
            'upvotes': self.upvotes,
            'downvotes': self.downvotes,
            'created_at': self.created_at,
            'updated_at': self.updated_at,
            # 'answers': [answer.to_dict() for answer in self.answers]
        }


import utils
import itertools

def parse_func(inp_list):
    res = []

    i = 0
    while i < len(inp_list):
        res_set = []
        k, l, s = inp_list[i].split()
        res_set.append((int(k), int(l), int(s)))

        keyboard = [x for x in inp_list[i+1].strip()]
        tgt_word = [x for x in inp_list[i+2].strip()]
        res_set.append(keyboard)
        res_set.append(tgt_word)
        res.append(res_set)
        i += 3
    return res

def get_bananas(tgt_word, word):
    tgt_str = ''.join(tgt_word)
    word_str = ''.join(word)
    f_count = 0
    f_list = []

    i = 0
    while i < len(word_str):
        j = word_str.find(tgt_str, i)
        if j == -1:
            break
        f_list.append(j)
        f_list = list(set(f_list))
        i += 1
    return len(f_list)

def get_exp(b_list):
    avg = float(sum(b_list))/len(b_list)
    return avg

def exec_func(inp_list):
    k, l, s = inp_list[0]
    keyboard = inp_list[1]
    tgt_word = inp_list[2]

    if not set(tgt_word).issubset(set(keyboard)):
        return float(0)

    possibilities = list(itertools.product(keyboard, repeat=s))
    b_list = []

    for p in possibilities:
        b_num = get_bananas(tgt_word, p)
        b_list.append(b_num)
    max_b = max(b_list)
    avg_b = get_exp(b_list)
    return max_b - avg_b

def main():
    utils.main(parse_func, exec_func)

if __name__ == '__main__':
    main()


# 暴力解法
def maxSubArray(nums):
    nums_length = len(nums)
    max_num = nums[0]
    for i in range(nums_length):
        temp = nums[i]
        for j in range(i+1, nums_length):
            max_num = max(max_num, temp)
            temp += nums[j]
        max_num = max(max_num, temp)
    return max_num

tt = [-2,1]
ss = maxSubArray(tt)
print(ss)
# 动态规划

def way2(nums):
    temp = 0
    max_num = nums[0]
    for i in nums:
        temp = max(temp + i, i)
        max_num = max(max_num, temp)
    return max_num

tt = [-2,1,2,3,5,-10,2]
ss = way2(tt)
print(ss)

# 动态规划2
def way3(nums):
    for i in range(1, len(nums)):
        nums[i] = max(nums[i-1] + nums[i], nums[i])
    return max(nums)


# -*- coding: utf-8 -*-
import argparse
from typing import Tuple, List, Dict, Union, Any

import pytorch_lightning as pl
import torch
from torch.nn import MSELoss
from torch.optim import Adam
from torchmetrics import MeanAbsoluteError, MeanSquaredError

from collab.model import EmbeddingNet

class LitNeuralCollaborativeFiltering(pl.LightningModule):
    def __init__(self, *args, **kwargs):
        super(LitNeuralCollaborativeFiltering, self).__init__()
        self.save_hyperparameters()
        self.model = EmbeddingNet(
            n_users=self.hparams.n_users,
            n_items=self.hparams.n_items,
            n_factors=self.hparams.n_factors,
            embedding_dropout=self.hparams.embedding_dropout,
            hidden=self.hparams.hidden,
            dropouts=self.hparams.dropouts,
        )
        self.loss = MSELoss()
        self.mae = MeanAbsoluteError()
        self.mse = MeanSquaredError()
        self.metrics = {"mae": self.mae, "mse": self.mse, "rmse": self._rmse}

    def _rmse(self, preds, targets):
        return torch.sqrt(self.mse(preds, targets))

    def forward(self, x):
        return self.model(x[:, 0], x[:, 1], self.hparams.minmax)

    def training_step(self, batch, batch_idx):
        x, y = batch
        y = y.unsqueeze(1)
        y_hat = self.forward(x)
        loss = self.loss(y_hat, y)
        self.log("train/loss", loss, on_step=True, on_epoch=False)

        return loss

    def validation_step(self, batch, batch_idx):
        x, y = batch
        y = y.unsqueeze(1)
        y_hat = self.forward(x)
        loss = self.loss(y_hat, y)

        log_dict = {
            "val/loss": loss,
        }

        for metric_name, metric in self.metrics.items():
            metric_value = metric(y_hat, y)
            if metric_name == "rmse":
                log_dict["hp_metric"] = metric_value
            log_dict[f"val/{metric_name}"] = metric_value

        self.log_dict(log_dict, on_step=False, on_epoch=True)

    def configure_optimizers(
        self,
    ) -> Tuple[List[torch.optim.Optimizer], List[Dict[str, Union[str, Any]]]]:
        optimizer = Adam(self.model.parameters(), 1e-1, weight_decay=self.hparams.wd)
        scheduler = torch.optim.lr_scheduler.OneCycleLR(
            optimizer,
            max_lr=self.hparams.max_lr,
            steps_per_epoch=len(self.trainer.datamodule.train_dataloader()),
            epochs=self.hparams.max_epochs,
        )
        scheduler = {"scheduler": scheduler, "interval": "step"}
        return [optimizer], [scheduler]

    @staticmethod
    def add_model_specific_args(parent: argparse.ArgumentParser):
        parser = argparse.ArgumentParser(
            parents=[parent], add_help=False, conflict_handler="resolve"
        )
        parser.add_argument(
            "--max_lr",
            default=6e-4,
            type=float,
        )
        parser.add_argument(
            "--n_factors",
            default=50,
            type=int,
        )
        parser.add_argument(
            "--wd",
            default=1e-5,
            type=float,
        )
        parser.add_argument(
            "--momentum",
            default=0.9,
            type=float,
        )
        parser.add_argument(
            "--embedding_dropout",
            default=0.02,
            type=float,
        )
        parser.add_argument(
            "--hidden",
            default=[500, 500, 500],
            type=List[int],
        )
        parser.add_argument(
            "--dropouts",
            default=[0.2, 0.2, 0.2],
            type=List[float],
        )
        return parser


class Piece:

    def __init__(self, color, name, coor):

        self.color = color
        self.name = name

        self.coor = coor
        self.row = coor[0]
        self.column = coor[1]

    def __repr__(self):
        return f"{self.name}({self.color}, {self.coor})"

    def move(self, coor):
        self.coor = coor
        self.row = coor[0]
        self.column = coor[1]
        self.moved = True

    def get_moves(self, board, en_passant=None):
        legal_moves = []

        for move in self.move_set:
            for i in range(1, self.move_set_loops + 1):

                r = self.row + move[0] * i
                c = self.column + move[1] * i

                if c not in range(0, 8) or r not in range(0, 8):
                    break

                elif board[r][c] == None:
                    legal_moves.append((r, c))
                    continue

                elif board[r][c].color != self.color:
                    legal_moves.append((r, c))
                    break

                elif board[r][c].color == self.color:
                    break

        return legal_moves

class King(Piece):
    def __init__(self, color, coor):
        super().__init__(color, "king", coor)

        self.color = color
        self.image = "white_king" if color else "black_king"
        self.move_set = [(x, y) for x in range(-1, 2) for y in range(-1, 2) if x != 0 or y != 0]
        self.move_set_loops = 1
        self.moved = False
        self.rooks = [(7, 0), (7, 7)] if color else [(0, 0), (0, 7)]
        self.notation = "K" if color else "k"
        self.value = 0
        self.castle_rights_indexes = (0, 1) if color else (2, 3)
        self.castled = False
        self.original_square = (7, 4) if color else (0, 4)

    def get_moves(self, board, castle_rights, in_check=False, delete_check_moves=True):
        legal_moves = []

        for move in self.move_set:
            for i in range(1, self.move_set_loops + 1):

                r = self.row + move[0] * i
                c = self.column + move[1] * i

                if c not in range(0, 8) or r not in range(0, 8):
                    break

                elif board[r][c] == None:
                    legal_moves.append((r, c))
                    continue

                elif board[r][c].color != self.color:
                    legal_moves.append((r, c))
                    break

                elif board[r][c].color == self.color:
                    break

        if delete_check_moves:
            return self.delete_moves_in_check(board, legal_moves, castle_rights)

        return legal_moves

    def generate_attacking_moves(self, board, castle_rights):

        enemy_moves = []
        my_moves = []

        for row in board:
            for piece in row:

                if piece is not None:

                    if piece.name == "pawn":
                        if piece.color != self.color:
                            enemy_moves += piece.get_attack_moves()
                        else:
                            my_moves += piece.get_attack_moves()

                    elif piece.name == "king":
                        if piece.color != self.color:
                            enemy_moves += piece.get_moves(board, castle_rights, delete_check_moves=False)
                        else:
                            my_moves += piece.get_moves(board, castle_rights, delete_check_moves=False)

                    else:
                        if piece.color != self.color:
                            enemy_moves += piece.get_moves(board)
                        else:
                            my_moves += piece.get_moves(board)

        return my_moves, enemy_moves

    def delete_moves_in_check(self, board, legal_moves, castle_rights):
        enemy_moves = self.generate_attacking_moves(board, castle_rights)[1]
        legal_moves = list(set(legal_moves) - set(enemy_moves))
        legal_moves += self.add_castle(board, castle_rights, legal_moves, (self.row, self.column) in enemy_moves)
        return legal_moves

    def add_castle(self, board, castle_rights, legal_moves, in_check):

        def clear_squares(n, right):

            for i in range(1, n+1):
                c = self.column + i if right else self.column - i
                if c not in range(0, 8) or board[self.row][c] is not None:
                    return False

            return True

        castles = []

        if self.coor == self.original_square and not in_check:
            if (self.row, self.column - 1) in legal_moves and castle_rights[self.castle_rights_indexes[0]] and board[self.row][self.column - 4] is not None and board[self.row][self.column - 4].name == "rook" and clear_squares(3, False):
                castles.append((self.row, self.column - 2))

            if (self.row, self.column + 1) in legal_moves and castle_rights[self.castle_rights_indexes[1]] and board[self.row][self.column + 3] is not None and board[self.row][self.column + 3].name == "rook" and clear_squares(2, True):
                castles.append((self.row, self.column + 2))

        return castles

class Queen(Piece):
    def __init__(self, color, coor):
        super().__init__(color, "queen", coor)

        self.color = color
        self.image = "white_queen" if color else "black_queen"
        self.move_set = [(x, y) for x in range(-1, 2) for y in range(-1, 2) if x != 0 or y != 0]
        self.move_set_loops = 8
        self.moved = False
        self.notation = "Q" if color else "q"
        self.value = 9

class Rook(Piece):
    def __init__(self, color, coor):
        super().__init__(color, "rook", coor)

        self.color = color
        self.image = "white_rook" if color else "black_rook"
        self.move_set = [(x, y) for x in range(-1, 2) for y in range(-1, 2) if (x == 0 or y == 0) and (x != 0 or y != 0)]
        self.move_set_loops = 8
        self.moved = False
        self.notation = "R" if color else "r"
        self.original_coor = coor
        self.value = 5

class Bishop(Piece):
    def __init__(self, color, coor):
        super().__init__(color, "bishop", coor)

        self.color = color
        self.image = "white_bishop" if color else "black_bishop"
        self.move_set = [(x, y) for x in range(-1, 2) for y in range(-1, 2) if x != 0 and y != 0]
        self.move_set_loops = 8
        self.moved = False
        self.notation = "B" if color else "b"
        self.value = 3

class Knight(Piece):
    def __init__(self, color, coor):
        super().__init__(color, "knight", coor)

        self.color = color
        self.image = "white_knight" if color else "black_knight"
        self.move_set = [(x, y) for x in range(-2, 3) for y in range(-2, 3) if x != 0 and y != 0 and abs(x) != abs(y)]
        self.move_set_loops = 1
        self.moved = False
        self.notation = "N" if color else "n"
        self.value = 3

class Pawn(Piece):
    def __init__(self, color, coor):
        super().__init__(color, "pawn", coor)

        self.color = color
        self.image = "white_pawn" if color else "black_pawn"
        self.direction = -1 if color else 1
        self.move_set = [(self.direction, 0)]
        self.moved = False
        self.move_set_loops = 1
        self.attacking_moves = [(self.direction, 1), (self.direction, -1)]
        self.notation = "P" if color else "p"
        self.value = 1
        self.original_squares = [(6, c) for c in range(8)] if color else [(1, c) for c in range(8)]

    def get_moves(self, board, en_passant):
        legal_moves = []

        self.double_forward()
        legal_moves += self.add_attack_moves(board, en_passant)

        for move in self.move_set:
            for i in range(1, self.move_set_loops + 1):

                r = self.row + move[0] * i
                c = self.column + move[1] * i

                if c not in range(0, 8) or r not in range(0, 8):
                    break

                elif board[r][c] == None:
                    legal_moves.append((r, c))
                    continue

                elif board[r][c].color != self.color:
                    break

                elif board[r][c].color == self.color:
                    break

        return legal_moves

    def get_attack_moves(self):

        legal_moves = []

        for move in self.attacking_moves:

            r = self.row + move[0]
            c = self.column + move[1]

            if c in range(0, 8) and r in range(0, 8):
                legal_moves.append((r, c))

        return legal_moves

    def double_forward(self):
        self.move_set_loops = 1 if self.moved else 2

    def add_attack_moves(self, board, en_passant):

        legal_moves = []

        for move in self.attacking_moves:

            r = self.row + move[0]
            c = self.column + move[1]

            if c in range(0, 8) and r in range(0, 8):
                if en_passant is not None and en_passant == (r, c):
                    legal_moves.append((r, c))

                if board[r][c] is not None and board[r][c].color != self.color:
                    legal_moves.append((r, c))

        return legal_moves


import sys
from lxml import etree

try:
    book_file = sys.argv[1:][0]
    index_file = sys.argv[1:][1]
    keywords = sys.argv[1:][2]
    result_file = sys.argv[1:][3]
    f = open(index_file)

except:
    print('Please enter valid file names\nand follow this format: books.xml index.xml "a string of keywords" results.xml')
    exit()

if book_file[-4:].lower() != '.xml' or index_file[-4:].lower() != '.xml' or result_file[-4:].lower() != '.xml' or len(book_file) < 5 or len(index_file) < 5 or len(result_file) < 5:
    print('Please enter valid file names\nand follow this format: books.xml index.xml')
    exit()

punctuations = '!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~\n\r\t'
for punctuation in punctuations: #remove punctuations except for apostrophe
    keywords = keywords.replace(punctuation, ' ')

tree = etree.parse(f)
index_word_ls = []
# obtain a list of keywords in XML file stored index information
for word in tree.xpath('//@word'):
    index_word_ls.append(word)

#create a dictionary to store found (Id,element) for all valid words, structure: {(Id,element):word, ...}
word_d = {}
#create a dictionary to store required results found, structure: {Id:element, ...}
result_d = {}

if len(keywords) != 0 and keywords != ' ':
    keyword_ls = keywords.lower().split(' ')
    while '' in keyword_ls: keyword_ls.remove('')
    for word in keyword_ls:
        if word not in index_word_ls:
            break
        #find the elements of books that contain input keywords
        for element in tree.xpath("//keyword[@word = \"" + word + "\"]/book/@element"):
            #for each element, get the Ids of books
            for Id in tree.xpath("//keyword[@word = \"" + word + "\"]/book[@element='" + element + "']/text()")[0].split(','):
                if (Id,element) in word_d: word_d[(Id,element)].append(word)
                else: word_d[(Id,element)] = [word]

for pair,words in list(word_d.items()):
    if len(words) == len(keyword_ls): #if all words occur in at least one element, store in result_d
        if pair[0] not in result_d: result_d[pair[0]] = [pair[1]]
        else: result_d[pair[0]].append(pair[1])

#output serach results in an XML file
try:
    f = open(book_file)
except:
    print('Please enter valid file names\nand follow this format: books.xml index.xml')
    exit()

tree = etree.parse(f)
root = etree.Element("results")
for (Id,elements) in list(result_d.items()):
    book = etree.SubElement(root, "book", id=Id)
    for element in elements:
        child = etree.SubElement(book, element)
        child.text = tree.xpath("//book[@id='" + Id + "']/" + element + "/text()")[0]
output_f = open(result_file, 'w')
output_f.write(etree.tostring(root, pretty_print=True).decode())
output_f.close()


import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns; sns.set();
import math
import random

training_data_path = 'A2Q2Data_train.csv'
validation_data_path = 'A2Q2Data_test.csv'

# Getting optimal values of w using closed-form solution for OLS
def calc_analytic_linear_reg(X_train, Y_train):
  w = np.linalg.pinv(np.dot(X_train.T, X_train)).dot(X_train.T).dot(Y_train)
  return w

def fetch_data_from_excel(file_path):
  my_data = np.genfromtxt(file_path, delimiter=',')
  return my_data

# Fetch data from excel file
training_data = fetch_data_from_excel(training_data_path)
validation_data = fetch_data_from_excel(validation_data_path)

X = training_data[:, :-1]
y = training_data[:, -1]

X_val = validation_data[:, :-1]
Y_val = validation_data[:, -1]

num_datapoints, _ = X.shape

# Adding column of bias in X
bias_ones = np.ones((num_datapoints, 1))
X = np.hstack((X, bias_ones))

# Adding column of bias in X_val
bias_ones = np.ones(((X_val.shape)[0], 1))
X_val = np.hstack((X_val, bias_ones))

_, num_features = X.shape

w_ML = calc_analytic_linear_reg(X, y)


# -*- coding: utf-8 -*-
"""
Unittest for utils/metrics.py

"""

import unittest
from utils import metrics
import numpy as np

class TestMetrics(unittest.TestCase):
    def test_iou_score(self):
        a = np.array([1, 0, 0, 1])
        b = np.array([1, 1, 0, 0])
        iou = metrics.iou_score(a, b)
        expected = 1 / 3
        np.testing.assert_almost_equal(iou, expected, decimal=3)

    def test_dice_score(self):
        a = np.array([1, 0, 0, 1])
        b = np.array([1, 1, 0, 0])
        iou = metrics.dice_score(a, b)
        expected = 0.5
        np.testing.assert_almost_equal(iou, expected, decimal=3)


import pytest
from product.serializers import ProductSerializer

def test_product_serializer_success(db, mock_product):
    """Test"""
    serializer = ProductSerializer(data=mock_product)
    assert serializer.is_valid()

@pytest.mark.parametrize(
    "item,data_error",
    [("brand", None), ("title", None), ("price", "1a"), ("image", "1a13")],
)
def test_product_serializer_error(item, data_error, db, mock_product):
    """Test"""
    mock_product[item] = data_error
    serializer = ProductSerializer(data=mock_product)
    assert not serializer.is_valid()


#from webapp.webapp import settings
from django.conf import settings
import os

DEBUG = True

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(settings.VAR_ROOT, '69grados.com.db'),
    }
}

if DEBUG:
    # Show emails in the console during developement.
    EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'


#!/usr/bin/env python3

import argparse
import re
from pathlib import Path

import toml

def get_args():
    """Set up CLI args"""
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--major",
        type=int,
        nargs="*",
        help="Major version bump. Empty flag will auto bump current version.",
    )
    parser.add_argument(
        "--minor",
        type=int,
        nargs="*",
        help="Minor version bump. Empty flag will auto bump current version.",
    )
    parser.add_argument(
        "--patch",
        type=int,
        nargs="*",
        help="Patch version bump. Empty flag will auto bump current version.",
    )
    parser.add_argument("--dry-run", type=str, default="yes", choices=["yes", "no"], help="Dry run")

    return parser.parse_args()

def get_version(pyproject_file_path):
    """Function returns tuple that elements follow semantic versioning order"""
    with open(pyproject_file_path) as file:
        pyproject = toml.loads(file.read())
        current_version = pyproject["tool"]["poetry"]["version"]

    validate_version(current_version)

    # Normalize version to tuple
    if current_version.count(".") == 0:
        return tuple(int(current_version))

    return tuple(int(v) for v in current_version.split("."))

def validate_version(current_version, pattern=r"^\d+\.\d+\.\d+$"):
    """
    Validate that extracted version follows "MAJOR.MINOR.PATCH" pattern
    """
    match = re.search(pattern, current_version)
    if not match:
        print(
            f'Error: Package version {current_version} is not following semantic versioning "MAJOR.MINOR.PATCH"'
        )
        exit(1)

def bump_major(version):
    if not version:
        return CURRENT_VERSION[0] + 1

    return version[0]

def bump_minor(version):
    if not version:
        return CURRENT_VERSION[1] + 1

    return version[0]

def bump_patch(version):
    if not version:
        return CURRENT_VERSION[2] + 1

    return version[0]

def bump_version(major, minor, patch):
    if major or type(major) == list:
        major = bump_major(major)

    if minor or type(minor) == list:
        minor = bump_minor(minor)

    if (type(patch) == list) or all(v is None for v in (major, minor, patch)):
        patch = bump_patch(patch)

    # Construct bump from new version and current version
    bump = []
    new_versions = (major, minor, patch)
    for index in range(len(new_versions)):
        if new_versions[index] is None:
            bump.append(CURRENT_VERSION[index])
        else:
            bump.append(new_versions[index])

    return tuple(bump)

if __name__ == "__main__":
    args = get_args()

    # Obtain 'pyproject.toml' file path
    current_file_path = str(Path(__file__).resolve())
    pyproject_file_path = current_file_path.replace(current_file_path, "pyproject.toml")

    # Bump and normalize current version
    CURRENT_VERSION = get_version(pyproject_file_path)
    NEW_VERSION = bump_version(args.major, args.minor, args.patch)
    CURRENT_VERSION = ".".join(map(str, CURRENT_VERSION))
    NEW_VERSION = ".".join(map(str, NEW_VERSION))

    # Print version check
    if args.dry_run == "yes":
        print(f"Current version: {CURRENT_VERSION}")
        print(f"New version: {NEW_VERSION}")
    else:
        with open(pyproject_file_path, "r") as file:
            content = file.read()

        with open(pyproject_file_path, "w") as file:
            CV = f'version = "{CURRENT_VERSION}"'
            NV = f'version = "{NEW_VERSION}"'
            content = content.replace(CV, NV)
            file.write(content)
            print(f"Successfully updated package version from {CURRENT_VERSION} to {NEW_VERSION}")


# -*- coding: utf-8 -*-
# @Time    : 2020/6/25 12:36
# @Author  : sihao
# @File    : 4-二分查找.py
'''
时间复杂度为O(logn)
'''
def binary_search(li,val):
    left=0
    right=len(li)-1
    while left<=right: #候选区有值
        mid=(left+right)//2
        if li[mid]==val:
            return mid+1
        elif li[mid]>val:
            right=mid-1
        else:
           left=mid+1
    else:
        return None

li=[1,2,3,4,5,6,7,8,9]
print(binary_search(li,1))

数据结构的学习/4-二分查找.py


#############################################
# Adım 1: Verinin Hazırlanması
#############################################
import pandas as pd

pd.set_option('display.max_columns', 20)

def create_user_movie_df():
    import pandas as pd
    movie = pd.read_csv('datasets/movie.csv', low_memory=True)
    rating = pd.read_csv('datasets/rating.csv', low_memory=True)
    df = movie.merge(rating, how="left", on="movieId")
    df['title'] = df.title.str.replace('(\(\d\d\d\d\))', '')
    df['title'] = df['title'].apply(lambda x: x.strip())
    a = pd.DataFrame(df["title"].value_counts())
    rare_movies = a[a["title"] <= 1000].index
    common_movies = df[~df["title"].isin(rare_movies)]
    user_movie_df = common_movies.pivot_table(index=["userId"], columns=["title"], values="rating")
    return user_movie_df

user_movie_df = create_user_movie_df()

user_movie_df.shape
user_movie_df.head()

user_id = 108170

#############################################
# Adım 2: Öneri yapılacak kullanıcının izlediği filmlerin belirlenmesi
#############################################

user_df = user_movie_df[user_movie_df.index == user_id]

movies_watched = user_df.columns[user_df.notna().any()].tolist()

#############################################
# Adım 3: Aynı filmleri izleyen diğer kullanıcıların verisine ve id'lerine erişmek
#############################################

movies_watched_df = user_movie_df[movies_watched]
movies_watched_df.head()

user_movies_count = movies_watched_df.T.notnull().sum()
user_movies_count = user_movies_count.reset_index()
user_movies_count.columns = ["userId", "movie_count"]

perc = len(movies_watched) * 60 / 100
user_movies_count[user_movies_count["movie_count"] > perc].sort_values("movie_count", ascending=False)

users_same_movies = user_movies_count[user_movies_count["movie_count"] > perc]["userId"]

#############################################
# Adım 4: Öneri yapılacak kullanıcı ile en benzer kullanıcıların belirlenmesi
#############################################

final_df = pd.concat([movies_watched_df[movies_watched_df.index.isin(users_same_movies.index)],
                      user_df[movies_watched]])

corr_df = final_df.T.corr().unstack().sort_values().drop_duplicates()
corr_df = pd.DataFrame(corr_df, columns=["corr"])
corr_df.index.names = ['user_id_1', 'user_id_2']
corr_df = corr_df.reset_index()
corr_df.head()

top_users = corr_df[(corr_df["user_id_1"] == user_id) & (corr_df["corr"] >= 0.65)][
    ["user_id_2", "corr"]].reset_index(drop=True)

top_users = top_users.sort_values(by='corr', ascending=False)

top_users.rename(columns={"user_id_2": "userId"}, inplace=True)

rating = pd.read_csv('datasets/rating.csv')
top_users_ratings = top_users.merge(rating[["userId", "movieId", "rating"]], how='inner')
top_users_ratings
top_users_ratings.shape

#############################################
# Adım 5: Weighted rating'lerin  hesaplanması
#############################################

top_users_ratings["weighted_rating"] = top_users_ratings["corr"] * top_users_ratings["rating"]
top_users_ratings.head()

#############################################
# Adım 6: Weighted average recommendation score'un hesaplanması
#############################################

temp = top_users_ratings.groupby('movieId').sum()[['corr', 'weighted_rating']]
temp.columns = ["sum_corr", "sum_weighted_rating"]
temp.head()

recommendation_df = pd.DataFrame()
recommendation_df['weighted_average_recommendation_score'] = temp['sum_weighted_rating'] / temp['sum_corr']
recommendation_df['movieId'] = temp.index
recommendation_df = recommendation_df.sort_values(by='weighted_average_recommendation_score', ascending=False)
recommendation_df.head(10)

movie = pd.read_csv("datasets/movie.csv")
movie_user = movie.loc[movie['movieId'].isin(recommendation_df.head(10)['movieId'].head())]['title']
movie_user.head()
movie_user[:5]

#############################################
# Adım 7: İzlediği filmlerden en son en yüksek puan verdiği filmin adına göre item-based öneri yapınız.
# 5 öneri user-based 5 öneri item-based olacak şekilde 10 öneri yapınız.
#############################################

pd.set_option('display.max_columns', None)

movie = pd.read_csv('datasets/movie.csv')
rating = pd.read_csv('datasets/rating.csv')
df = movie.merge(rating, how="left", on="movieId")
df.head()

# title

df['year_movie'] = df.title.str.extract('(\(\d\d\d\d\))', expand=False)
df['year_movie'] = df.year_movie.str.extract('(\d\d\d\d)', expand=False)
df['title'] = df.title.str.replace('(\(\d\d\d\d\))', '')
df['title'] = df['title'].apply(lambda x: x.strip())

# genres

df["genre"] = df["genres"].apply(lambda x: x.split("|")[0])
df.drop("genres", inplace=True, axis=1)
df.head()

# timestamp

df["timestamp"] = pd.to_datetime(df["timestamp"], format='%Y-%m-%d')
df["year"] = df["timestamp"].dt.year
df["month"] = df["timestamp"].dt.month
df["day"] = df["timestamp"].dt.day
df.head()

# User Movie Df'inin Oluşturulması

df["title"].nunique()
a = pd.DataFrame(df["title"].value_counts())

rare_movies = a[a["title"] <= 1000].index
common_movies = df[~df["title"].isin(rare_movies)]

common_movies["title"].nunique()

item_movie_df = common_movies.pivot_table(index=["userId"], columns=["title"], values="rating")

# Korelasyona Dayalı Item-Based Film Önerilerinin Yapılması

movieId = \
    rating[(rating["rating"] == 5.0) & (rating["userId"] == user_id)].sort_values(by="timestamp", ascending=False)[
        "movieId"][0:1].values[0]

movie_title = movie[movie["movieId"] == movieId]["title"].str.replace('(\(\d\d\d\d\))', '').str.strip().values[0]

movie = item_movie_df[movie_title]
movie_item = item_movie_df.corrwith(movie).sort_values(ascending=False)
item_movie_df[1:6].index

# user-based 5 öneri ve item-based 5 öneriyi bir araya getiriniz.

data_user_item = pd.DataFrame()
data_user_item["user_recommendations"] = movie_user[:5].values.tolist()
data_user_item["item_recommendations"] = movie_item[:5].index