AXIS_DIRS = [
    (0, 1),
    (1, 0),
    (0, -1),
    (-1, 0)
]

DIAG_DIRS = [
    (1, 1),
    (-1, 1),
    (1, -1),
    (-1, -1)
]

DIAG_FUNCS = {
    (1, 1): lambda matrix, i, j: matrix[i-1][j] != 'fs' and matrix[i][j-1] != 'fs',
    (-1, 1): lambda matrix, i, j: matrix[i+1][j] != 'bs' and matrix[i][j-1] != 'bs',
    (1, -1): lambda matrix, i, j: matrix[i-1][j] != 'bs' and matrix[i][j+1] != 'bs',
    (-1, -1): lambda matrix, i, j: matrix[i+1][j] != 'fs' and matrix[i][j+1] != 'fs'
}

def regions(matrix):
    """Given a 2D matrix, where each cell is either 'fs' (forward slash),
    'bs' (backslash), or '', returns the number of regions the slashes divide the space.

    >>> matrix = [
    ...     ['bs', '', '', '', '', 'fs'],
    ...     ['', 'bs', '', '', 'fs', ''],
    ...     ['', '', 'bs', 'fs', '', '']
    ... ]
    >>> regions(matrix)
    3
    """
    assert matrix, 'MATRIX cannot be an empty list.'

    def is_valid(i, j):
        if i < 0 or i >= m or j < 0 or j >= n:
            return False
        if matrix[i][j] != '':
            return False
        return True

    def get_dirs(i, j):
        dirs = []
        for dir_i, dir_j in AXIS_DIRS:
            ni, nj = i + dir_i, j + dir_j
            if is_valid(ni, nj):
                dirs.append((ni, nj))
        for dir_i, dir_j in DIAG_DIRS:
            ni, nj = i + dir_i, j + dir_j
            if is_valid(ni, nj) and DIAG_FUNCS[(dir_i, dir_j)](matrix, ni, nj):
                dirs.append((ni, nj))
        return dirs

    def bfs(i, j, id):
        q = [(i, j)]
        while q:
            r, c = q.pop(0)
            matrix[r][c] = id
            for nr, nc in get_dirs(r, c):
                q.append((nr, nc))

    m, n = len(matrix), len(matrix[0])

    reg = 0
    for r in range(m):
        for c in range(n):
            cell = matrix[r][c]
            if cell == '':
                bfs(r, c, reg)
                reg += 1
    return reg


from statistics import mean
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import style

style.use('fivethirtyeight')

xs = np.array([1,2,3,4,5,6], dtype=np.float64)
ys = np.array([5,4,6,5,6,7], dtype=np.float64)

def best_fit_slope_and_intercept(xs, ys):
    m = ( ((mean(xs) * mean(ys)) - mean(xs*ys)) /
          ((mean(xs)*mean(xs)) - mean(xs*xs)) )
    b = mean(ys) - m*mean(xs)
    return m, b

#to find How accurate our Best fit line is
#first find the squared error
def squared_error(ys_orig, ys_line):
    return sum((ys_line - ys_orig)**2)

#then lets find the coefficient of determination or the R theory
def coefficient_of_determination(ys_orig,ys_line):
    y_mean_line = [mean(ys_orig) for y in ys_orig]
    squared_error_regr = squared_error(ys_orig, ys_line)
    squared_error_y_mean = squared_error(ys_orig, y_mean_line)
    return 1 - (squared_error_regr / squared_error_y_mean)

m,b = best_fit_slope_and_intercept(xs,ys)
print ("Slope: ")
print(m)
print("Intercept: ")
print(b)

regression_line = [(m*x)+b for x in xs]

#to print the coefficient of determination
r_squared = coefficient_of_determination(ys, regression_line)
print("Coefficient of determination: ")
print(r_squared)

#to predict just do: predict_x = 8
#                    predict_y = (m*predict_x)+b
#                    plt.scatter(predict_x, predict_y, color='g')

plt.scatter(xs,ys)
plt.plot(xs, regression_line)
plt.show()


import os
import copy
import sys
import random
import gc
import datetime
sys.path.append(os.path.abspath('..'))
from COLD.predictor import predictor as COLDPredictor
from CTCD.ber_predictor import predictor as CTCDBerPredictor
from CTCD.poi_predictor import predictor as CTCDPoiPredictor
from BIGCLAM.predictor import predictor as BIGCLAMPredictor

def mkdir_if_not_exists(path):
    if not os.path.exists(path):
        os.makedirs(path)

def load_edges(data_dir, predictor):
    edges = []
    user_pair = set()
    for line in open(os.path.join(data_dir, 'links.txt')):
        line = line.strip().split('\t')
        if line[0] not in predictor.uname2uid:
            continue
        if line[1] not in predictor.uname2uid:
            continue
        uid0 = predictor.uname2uid[line[0]]
        uid1 = predictor.uname2uid[line[1]]
        user_pair.add((uid0, uid1))
        for time_pair in line[2:]:
            time_pair = time_pair.split()
            edges.append((uid0, uid1, int(time_pair[0]), int(time_pair[1])))
    max_time = max(i for edge in edges for i in edge[-2:]) + 1
    min_time = min(i for edge in edges for i in edge[-2:]) - 1
    for i in range(len(edges)):
        edge = edges[i]
        edges[i] = (edge[0], edge[1], (edge[2] - min_time) / (max_time - min_time), (edge[3] - min_time) / (max_time - min_time))
    return user_pair, edges

def prdict_pos(predictor, edges, num):
    scores = []
    count = 0
    for edge in random.sample(edges, num):
        if count % 100000 == 0:
            print(datetime.datetime.now(), 'pos: ', count)
            sys.stdout.flush()
        count += 1
        scores.append(predictor.link_predict(*edge))
    return scores

def prdict_neg(predictor, user_pair, num):
    scores = []
    for i in range(num):
        if i % 100000 == 0:
            print(datetime.datetime.now(), 'neg: ', i)
            sys.stdout.flush()
        while True:
            from_user = random.randint(0, len(predictor.uname2uid) - 1)
            to_user = random.randint(0, len(predictor.uname2uid) - 1)
            if (from_user, to_user) not in user_pair:
                break
        time1 = random.random()
        time2 = random.random()
        scores.append(predictor.link_predict(from_user, to_user, time1, time2))
    return scores

def load_data(args):
    model2predictor = {
        'CTCDPoi': ctcd_poi_predictor,
        'CTCDBer': ctcd_ber_predictor,
        'COLD': cold_predictor,
        'BIGCLAM': bigclam_predictor,
    }
    predictor = model2predictor[args['model']]
    data_dir = '{root:s}/Data/{exp:s}/{dataset:s}/'.format(**args)
    predictor.load_data(data_dir)

def prdict(args):
    print(datetime.datetime.now(), args)
    sys.stdout.flush()
    model2predictor = {
        'CTCDPoi': ctcd_poi_predictor,
        'CTCDBer': ctcd_ber_predictor,
        'COLD': cold_predictor,
        'BIGCLAM': bigclam_predictor,
    }
    model2score_prefix = {
        'CTCDPoi': '{root:s}/Score/{exp:s}/{dataset:s}/{model:s}/cc{cc:d}_lw{lw:d}_{it:s}',
        'CTCDBer': '{root:s}/Score/{exp:s}/{dataset:s}/{model:s}/cc{cc:d}_lw{lw:d}_{it:s}',
        'COLD': '{root:s}/Score/{exp:s}/{dataset:s}/{model:s}/cc{cc:d}_lw{lw:d}_{it:s}',
        'BIGCLAM': '{root:s}/Score/{exp:s}/{dataset:s}/{model:s}/cc{cc:d}_lw{lw:d}',
    }
    args['score_prefix'] = model2score_prefix[args['model']].format(**args)
    mkdir_if_not_exists(os.path.split(args['score_prefix'])[0])
    model2result_prefix = {
        'CTCDPoi': '{root:s}/Result/{exp:s}/{dataset:s}/{model:s}/cc{cc:d}_lw{lw:d}_{it:s}',
        'CTCDBer': '{root:s}/Result/{exp:s}/{dataset:s}/{model:s}/cc{cc:d}_lw{lw:d}_{it:s}',
        'COLD': '{root:s}/Result/{exp:s}/{dataset:s}/{model:s}/cc{cc:d}_lw{lw:d}_{it:s}',
        'BIGCLAM': '{root:s}/Result/{exp:s}/{dataset:s}/{model:s}/cc{cc:d}_lw{lw:d}',
    }
    args['data_dir'] = '{root:s}/Data/{exp:s}/{dataset:s}/'.format(**args)
    args['result_prefix'] = model2result_prefix[args['model']].format(**args)
    if os.path.isfile(args['score_prefix'] + '.txt'):
        return
    predictor = model2predictor[args['model']]

    predictor.load_result(args['result_prefix'])
    print(datetime.datetime.now(), 'predictor init done')
    sys.stdout.flush()

    user_pair, edges = load_edges(args['data_dir'], predictor)
    print(datetime.datetime.now(), 'load edges done')
    sys.stdout.flush()

    score_pos = prdict_pos(predictor, edges, int(len(edges) * 0.1))
    print(datetime.datetime.now(), 'predict pos done')
    sys.stdout.flush()

    score_neg = prdict_neg(predictor, user_pair, int(len(edges) * 0.1))
    print(datetime.datetime.now(), 'predict neg done')
    sys.stdout.flush()

    fp = open(args['score_prefix'] + '.txt', 'w')
    for score in score_pos:
        fp.write('%f\t1\n' % score)
    print(datetime.datetime.now(), 'save pos done')
    sys.stdout.flush()

    for score in score_neg:
        fp.write('%f\t0\n' % score)
    print(datetime.datetime.now(), 'save neg done')
    sys.stdout.flush()

    fp.close()

if __name__ == '__main__':
    models = [
        'CTCDPoi',
        'CTCDBer',
    ]
    datasets = [
        'dblp_citation',
        # 'dblp_coauthor',
        # 'weibo',
    ]
    community_count = [
        10,
        50,
        # 100,
        # 150,
    ]
    ctcd_poi_predictor = COLDPredictor()
    ctcd_ber_predictor = CTCDBerPredictor()
    cold_predictor = CTCDPoiPredictor()
    bigclam_predictor = BIGCLAMPredictor()

    exp = 'topic'
    root = os.path.abspath('../..')
    for dataset in datasets:
        for model in models:
            load_data({'exp': exp, 'root': root, 'model': model, 'dataset': dataset})
            for cc in community_count:
                for lw in [16, 32, 48, 64] if 'CTCD' in model else [32]:
                    for it in range(0, 310, 10):
                        prdict({'exp': exp, 'root': root, 'model': model, 'dataset': dataset, 'cc': cc, 'lw': lw, 'it': ('%04d' % it) if it < 300 else 'final'})
                        gc.collect()


# -*- coding: utf-8 -*-
"""
Created on Fri Jun 21 17:28:46 2019

@author: MalikMehrKhan
"""
a = 0
b = []
c=[]
while (a == 1) or (a == 0):
    a = input("Enter binary digit ")
    a = int(a)
    if a == 1 or a == 0:
        b.append(a)
n = len(b) - 1
for x in b:
    c.append(x * 2**n)
    n = n - 1
d = sum(c)
print ("decimal number is " + str(d))


for case in range(1, int(input())+1):
	N = int(input())
	senators = list(map(int,input().split()))
	result = []
	empty = False
	while not empty:
		mainPartyHas = 0
		mainPartyIs = 0
		totalSenators = 0
		otherRemaining = -1
		tripleTie = False
		for i in range(N):
			totalSenators += senators[i]
			if senators[i] > mainPartyHas:
				mainPartyHas = senators[i]
				mainPartyIs = i
		#we got biggest. Is there any kind of tie?
		for i in range(N):
			if (senators[i] == mainPartyHas) and (i != mainPartyIs):
				if otherRemaining == -1:
					otherRemaining = i
				else:
					tripleTie = True
		if totalSenators == 2 :
			result.append(chr(mainPartyIs+ord('A'))+chr(otherRemaining+ord('A')))
			empty = True
		else:
			if (otherRemaining != -1) and (not tripleTie) :
				result.append(chr(mainPartyIs+ord('A'))+chr(otherRemaining+ord('A')))
				senators[otherRemaining] -= 1
			else:
				result.append(chr(mainPartyIs+ord('A')))
			senators[mainPartyIs] -= 1
	print ("Case #%d: %s" % (case," ".join(result)))


#!/usr/bin/python3
""" Declares a function `island_perimeter` that takes a list of lists as
an argument """

def island_perimeter(grid):
    """ Returns the perimeter of the island described by `grid`

    Args:
        grid (list): A list of list of integers, where 0 represents a water
                     zone and 1 represents a land zone.
                   - One cell is a square with side length 1
                   - Grid cells are connected horizontally/vertically (not
                     diagonally)
                   - Grid is rectangular, width and height don't exceed 100
                   - Grid is completely surrounded by water, and there is one
                     island or nothing.
    """
    counter = 0
    proximity_loss = 0
    for i in range(len(grid)):
        for j in range(len(grid[0])):
            if grid[i][j] == 1:
                counter += 1
                if (j > 0 and grid[i][j - 1] == 1):
                    proximity_loss += 1
                if (i > 0 and grid[i - 1][j]) == 1:
                    proximity_loss += 1
    perimeter = (counter * 4) - (proximity_loss * 2)

    return perimeter


import random
print('Number Guessing Game')
randomNumber= random.randint(1,9)
chances=0
print('Guess number between 1-9')
while (chances<5):
    inputUser = int(input('enter the guess: '))
    if(inputUser== randomNumber):
        print('Congrats you won')
        break
    elif(inputUser<randomNumber):
        print('Guess higher than: ',inputUser)
    else:
        print('Guess lower than: ',inputUser)
    chances=chances+1

if (chances == 4):
    print('You lost game,the number was',randomNumber)


import win32gui
from threading import Thread, Lock
import time
import win32process
import psutil
from src.dofus.dofus import Dofus
from src.tools.observer import Observer
import logging
import pyautogui

logger = logging.getLogger(__name__)

class DofusHandler(Thread,Observer):
    """
    Class qui gere les id des fenetres dofus (hwnd) et leur ordre

    event : update_hwnd
    """
    def __init__(self):
        Thread.__init__(self)
        Observer.__init__(self,["update_hwnd","new_select_list","houseevent"])
        self.curr_hwnd = None
        self.running = True
        self.dofus = [Dofus(hwnd) for hwnd in self._get_win()]
        for d in self.dofus:
            d.add_observer("fight",self.update_order)
            d.add_observer("house",self.houseevent)
        self.lock = Lock()
        self.name_order = []
        self.selected = [d for d in self.dofus]

    def houseevent(self):
        self.notify("houseevent")

    def get_hwnds(self):
        return [d.hwnd for d in self.dofus]

    def get_pids(self):
        return [d.pid for d in self.dofus]

    def get_names(self):
        return [d.name for d in self.dofus]

    def get_ports(self):
        return [d.port for d in self.dofus]

    def stop(self):
        self.running = False
        for d in self.dofus:
            d.stop()

    def add_select(self,hwnd):
        d = self.dofus[self.get_index_by_hwnd(hwnd)]
        if(d not in self.selected):
            self.selected.append(d)
        else:
            self.selected.remove(d)
        self.notify("new_select_list",[d.hwnd for d in self.selected])

    def update_order(self,order):
        self.lock.acquire()

        new_order = [self.dofus[self.get_index_by_name(name)] for name in order if name in self.get_names()]
        #ajoute les fenetres qui n'ont pas été ajoutées
        for d in self.dofus:
            if d.hwnd not in [d.hwnd for d in new_order]:
                new_order.append(d)

        self.dofus = new_order
        self.lock.release()
        self.notify("update_hwnd",self.get_hwnds(),self.get_names())

    def _get_win(self):
        tmp = []
        win32gui.EnumWindows(dofusEnumerationHandler, tmp)
        return tmp

    def add_win(self,hwnd):
        self.lock.acquire()
        if hwnd not in self.get_hwnds():
            d = Dofus(hwnd)
            self.dofus.append(d)
            d.add_observer("fight",self.update_order)
            d.add_observer("house",self.houseevent)
            self.selected.append(d)
            self.notify("new_select_list",[d.hwnd for d in self.selected])

            self.lock.release()
            logger.info("new dofus window detected")
            self.notify("update_hwnd",self.get_hwnds(),self.get_names())
            return True

        self.lock.release()
        return False

    def is_dofus_window(self,hwnd):
        return hwnd in self.get_hwnds()

    def get_hwnd_by_name(self,name):
        namelist = self.get_names()
        return self.dofus[namelist.index(name)].hwnd

    def get_index_by_hwnd(self,hwnd):
        return self.get_hwnds().index(hwnd)

    def get_index_by_name(self,name):
        namelist = self.get_names()
        return namelist.index(name)

    def get_dofus_by_port(self,port):
        for d in self.dofus:
            d.update_port()
        return self.dofus[self.get_ports().index(port)]

    def get_next_dofus(self):
        curr = self.get_curr_hwnd()
        i = (self.get_index_by_hwnd(curr)+1) % len(self.dofus)
        return self.dofus[i]

    def get_previous_dofus(self):
        curr = self.get_curr_hwnd()
        i = (self.get_index_by_hwnd(curr)-1) % len(self.dofus)
        return self.dofus[i]

    def get_current_dofus(self):
        hwnd = self.get_curr_hwnd()
        if(hwnd is None):
            return None
        return self.dofus[self.get_index_by_hwnd(hwnd)]

    def get_curr_hwnd(self):
        tmp = win32gui.GetForegroundWindow()
        if(self.is_dofus_window(tmp)):
            self.curr_hwnd = tmp
        return self.curr_hwnd

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

    def remove_win(self,hwnd):
        self.lock.acquire()
        logger.info("dofus window removed")
        i = self.get_index_by_hwnd(hwnd)
        d = self.dofus.pop(i)
        self.selected.remove(d)
        self.notify("new_select_list",[d.hwnd for d in self.selected])
        d.stop()
        del d
        self.lock.release()
        self.notify("update_hwnd",self.get_hwnds(),self.get_names())

    def run(self):
        while self.running :
            hwnd_tmp = self._get_win()

            #test si les fenetres ont été fermées
            for hwnd in self.get_hwnds():
                if hwnd not in hwnd_tmp:
                    self.remove_win(hwnd)

            #test si des fenetres ont été ouvertes
            for hwnd in hwnd_tmp:
                self.add_win(hwnd)

            up = False
            for d in self.dofus:
                if(d.update_name()):
                    up = True
                d.update_port()
            if(up):
                logger.info(f"dofus window name updated {self.get_names()}")
                self.notify("update_hwnd",self.get_hwnds(),self.get_names())

            tmp_name_order = self.get_names()
            if(tmp_name_order != self.name_order):
                self.notify("update_hwnd",self.get_hwnds(),self.get_names())
                self.name_order = self.get_names()

            time.sleep(0.3)

        logger.info("dofus window handler stopped")

    def execute(self,cmd,arg):
        logger.info(f"execute cmd : {cmd}, args : {arg}")
        if(cmd == "goto"):
            curr_dof = self.get_current_dofus()
            if(curr_dof):
                curr_dof.do_async_action(Dofus.goto,*arg)
                return "ok"
            else:
                return "no dofus window selected"
        elif(cmd == "stoptravel"):
            curr_dof = self.get_current_dofus()
            if(curr_dof):
                curr_dof.do_async_action(Dofus.stoptravel)
                return "ok"
            else:
                return "no dofus window selected"
        elif(cmd == "gotos"):
            for d in self.selected:
                d.do_async_action(Dofus.goto,*arg)
            return "ok"
        elif(cmd == "stoptravels"):
            for d in self.selected:
                d.do_async_action(Dofus.stoptravel)
            return "ok"
        elif(cmd == "clickcell"):
            curr_dof = self.get_current_dofus()
            if(curr_dof):
                curr_dof.do_async_action(Dofus.click_cell,*arg)
                return f"click on cellid {arg[0]}"
            else:
                return "no dofus window selected"
        elif(cmd == "zaap"):
            curr_dof = self.get_current_dofus()
            if(curr_dof):
                nom = " ".join(arg)
                curr_dof.do_async_action(Dofus.zaap,nom)
                return "ok"
            else:
                return "no dofus window selected"
        elif(cmd == "zaaps"):
            nom = " ".join(arg)
            for d in self.selected:
                d.do_async_action(Dofus.zaap,nom)
            return "ok"
        elif(cmd == "group"):
            curr_dof = self.get_current_dofus()
            if(curr_dof):
                listinv = [n for n in self.get_names() if n != curr_dof.name and n != ""]
                if(len(listinv) == 0):
                    return "no other dofus window"
                curr_dof.do_async_action(Dofus.invite,listinv)
                return f"invite {listinv}"
            else:
                return "no dofus window selected"
        elif(cmd == "reset"):
            curr_dof = self.get_current_dofus()
            if(curr_dof):
                self.remove_win(curr_dof.hwnd)
                return f"{curr_dof.name} reset"
            else:
                return "no dofus window selected"
        elif(cmd == "flagcalibrage"):
            curr_dof = self.get_current_dofus()
            #normalement une chasse doit être lancée sinon t'es con
            if(curr_dof):
                if(curr_dof.chasseObject is not None):
                    pos = pyautogui.locateCenterOnScreen('ressources\\img\\hintflag.png',confidence=0.9)
                    if(pos is not None):
                        x,y = pos
                    else :
                        return "Flag not found\n/!\ attention à ne pas cacher le flag avec la fenêtre de commande"
                    y = y - 30*(len(curr_dof.chasseObject.listindice)-1)
                    for d in self.dofus:
                        if(d.chasseObject is not None):
                            d.chasseObject.set_flag_pos(x,y)
                    return f"Flag on {x},{y}"
                else:
                    return "Une chasse doit être lancée"
            else:
                return "no dofus window selected"

def dofusEnumerationHandler(hwnd, top_windows):
    name = win32gui.GetWindowText(hwnd)
    _,pid = win32process.GetWindowThreadProcessId(hwnd)
    if pid < 0:
        return
    exe = psutil.Process(pid).exe()
    visible = win32gui.IsWindowVisible(hwnd)
    if("dofus 2" in name.lower() and "dofus.exe" in exe.lower() and visible):
        top_windows.append(hwnd)


import  pygame, random, sys
from pygame.locals import *

WINDOWWIDTH = 600
WINDOWHEIGTH = 600
TEXTCOLOR = (0,0,0)
BACKGROUNDCOLOR = (255,255,255)
FPS = 60
BADDIEMINSIZE = 10
BADDIEMAXSIZE = 40
BADDIEMINSPEED = 1
BADDIEMAXSPEED = 8
ADDNEWBADDIERATE = 6
PLAYERMOVERATE = 5

def terminate():
    pygame.quit()
    sys.exit()

def waitForPlayerToPressKey():
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                terminate()
            if event.type == KEYDOWN:
                if event.key == K_ESCAPE: # нажатие эскейп осуществляет выход
                    terminate()
                return

def playerHasHitBaddie(playerRect, baddies):
    for b in baddies:
        if playerRect.colliderect(b['rect']):
            return  True
    return False

def drawText(text, font, surface, x, y):
    textobj = font.render(text, 1, TEXTCOLOR)
    textrect = textobj.get_rect()
    textrect.topleft = (x, y)
    surface.blit(textobj, textrect)

# настройки pygame окна и указателя мыши
pygame.init()
mainClock = pygame.time.Clock()
windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGTH))
pygame.display.set_caption('Ловкач')
pygame.mouse.set_visible(False)

# настройка шрифтов
font = pygame.font.SysFont(None, 35)

#настройка звуков
gameOverSound = pygame.mixer.Sound('gameover.wav')
pygame.mixer.music.load('background.mid')

#настройка изображений
playerImage = pygame.image.load('player.png')
playerRect =playerImage.get_rect()
baddieImage = pygame.image.load('baddie.png')

# вывод начального экрана
windowSurface.fill(BACKGROUNDCOLOR)
drawText('Ловкач', font, windowSurface,(WINDOWWIDTH/3), (WINDOWHEIGTH/3))
drawText('Нажмите клавиатуру для начала игры', font, windowSurface, (WINDOWWIDTH/5)-30, (WINDOWHEIGTH/3)+50)
pygame.display.update()
waitForPlayerToPressKey()

topScore = 0
while True:
    #Настройка начала игры
    baddies = []
    score = 0
    playerRect.topleft = (WINDOWWIDTH/0, WINDOWHEIGTH-50)
    moveLeft = moveRight = moveUp = moveDown = False
    reversCheat = slowCheat = False
    baddieAddCounter = 0
    pygame.mixer.music.play(-1,0.0)

    while True: #игровой цикл выполняется пока игра работает
        score += 1 # увеличение колличества очков

        for event in pygame.event.get():
            if event.type == QUIT:
                terminate()


import torch
import torchvision
import cv2
import numpy as np
import os
from PIL import Image
from matplotlib import pyplot as plt
import argparse
from skimage.transform import resize

# Load the trained model
import model as myModel

ddir = '../Downloads/DeepLabv3-TS/test_files/sg_data/'
root = '../Downloads/DeepLabv3-TS/masked/'
exp_dir = '../Downloads/DeepLabv3-TS/exp_out/'
checkpoint = torch.load(exp_dir + 'trained_weights_all_ep30.pth.tar')

ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", help = "path to the image file")
ap.add_argument("-c", "--coords",
    help = "comma seperated list of source points")
args = vars(ap.parse_args())

def convex(dir):
    img = cv2.imread(dir)
    img1 = img.copy()
    imgray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    ret, thr = cv2.threshold(imgray,255,0,180)
    contours,_ = cv2.findContours(thr, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

    contours_sizes= [(cv2.contourArea(cnt), cnt) for cnt in contours]
    biggest_contour = max(contours_sizes, key=lambda x: x[0])[1]

    #cnt = contours[0]
    cnt = biggest_contour

    x,y,w,h = cv2.boundingRect(cnt)

    rect = cv2.minAreaRect(cnt)
    box = cv2.boxPoints(rect)
    box = np.int0(box)

    cv2.drawContours(img,[box],0,(0,255,0),1)

    return box

def tl(x,y,w,h):
    x = x**2
    y = y**2
    result = (x+y) **0.5
    return result

def bl(x,y,w,h):
    y = h-y
    x = x**2
    y = y**2
    result = (x+y) **0.5
    return result

def tr(x,y,w,h):
    x = w-x
    x = x**2
    y = y**2
    result = (x+y) **0.5
    return result

def br(x,y,w,h):
    x= w-x
    y= h-y
    x = x**2
    y = y**2
    result = (x+y) **0.5
    return result

def tr_re(x,y,bl_x,bl_y):
    x= bl_x-x
    y= bl_y-y
    x = x**2
    y = y**2
    result = (x+y) **0.5
    return result

def order_points(pts):
	# initialzie a list of coordinates that will be ordered
	# such that the first entry in the list is the top-left,
	# the second entry is the top-right, the third is the
	# bottom-right, and the fourth is the bottom-left
	rect = np.zeros((4, 2), dtype = "float32")

	# the top-left point will have the smallest sum, whereas
	# the bottom-right point will have the largest sum
	s = pts.sum(axis = 1)
	rect[0] = pts[np.argmin(s)]
	rect[2] = pts[np.argmax(s)]

	# now, compute the difference between the points, the
	# top-right point will have the smallest difference,
	# whereas the bottom-left will have the largest difference
	diff = np.diff(pts, axis = 1)
	rect[1] = pts[np.argmin(diff)]
	rect[3] = pts[np.argmax(diff)]

	# return the ordered coordinates
	return rect

def four_point_transform(image, pts):
    	# obtain a consistent order of the points and unpack them
	# individually
	rect = order_points(pts)
	(tl, tr, br, bl) = rect

	# compute the width of the new image, which will be the
	# maximum distance between bottom-right and bottom-left
	# x-coordiates or the top-right and top-left x-coordinates
	widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
	widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
	maxWidth = max(int(widthA), int(widthB))

	# compute the height of the new image, which will be the
	# maximum distance between the top-right and bottom-right
	# y-coordinates or the top-left and bottom-left y-coordinates
	heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
	heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
	maxHeight = max(int(heightA), int(heightB))

	# now that we have the dimensions of the new image, construct
	# the set of destination points to obtain a "birds eye view",
	# (i.e. top-down view) of the image, again specifying points
	# in the top-left, top-right, bottom-right, and bottom-left
	# order
	dst = np.array([
		[0, 0],
		[maxWidth - 1, 0],
		[maxWidth - 1, maxHeight - 1],
		[0, maxHeight - 1]], dtype = "float32")

	# compute the perspective transform matrix and then apply it
	M = cv2.getPerspectiveTransform(rect, dst)
	warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))

	# return the warped image
	return warped

preprocess = torchvision.transforms.Compose([
                    torchvision.transforms.ToTensor(),
                    torchvision.transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
                ])
model = myModel.createDeepLabv3(outputchannels=2) # give nclasses
#model.load_state_dict(torch.load(exp_dir + 'trained_weights.best_acc.pth.tar'))

#checkpoint = torch.load(exp_dir + 'trained_weights_burn_imgs_550size.pth.tar')
model.load_state_dict(checkpoint['model_state_dict'])

#model = torch.load(exp_dir + 'weights.pt')
# Set the model to evaluate mode
model.eval()
#device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
device = torch.device('cpu')

# Read  a sample image and mask from the data-set
per_point = [0 for j in range(8)]
flist = os.listdir(ddir)
index_count = [[0 for j in range(2)] for i in range(400000)]
length_cal = [0 for j in range(4)]

for file in flist:
    imfile = ddir + file
    print ('filename: ', file, ' in ', ddir)
    im = np.ascontiguousarray(cv2.imread(imfile)[:,:,::-1])
    print (im.shape)
    #resizing
    re_size = 400
    rows, cols, channels = im.shape
    scale = re_size / float(im.shape[1])
    im = cv2.resize(im,(re_size,int(rows*scale)))
    #end

    print(im.shape)
    intensor = preprocess (im)
    batch = intensor.reshape(1,*intensor.shape)
    print (batch.shape, batch.dtype)

    with torch.no_grad():
        a = model(batch.to(device))
        re = a['out'].argmax(dim=1).data.cpu().numpy()[0]
        #re = cv2.resize(re,(cols,rows))
        #plt.imsave(root+'low/'+file,re)

        #re = resize(re, (rows, cols))

        plt.imsave(root+file,re)

imgs = list(sorted(os.listdir(os.path.join(root))))
#print(imgs)

for filename in imgs :

    print(root + filename)
    img = Image.open(root + filename).convert("RGB")
    (width,height) = img.size
    outputImg = Image.new("RGB", (width,height),(0,0,0))
    output = outputImg.load()

    k=0

    for y in range(0, height):
        for x in range(0, width):
            r, g, b = img.getpixel((x, y))
            if r > 140 :
                output[x,y] = (255,0,0)
            elif b > 140 :
                output[x,y] = (0,0,255)
            elif g > 140 :
                output[x,y] = (0,255,0)
            else :
                output[x,y] = (0,0,0)

    outputImg.save(root + filename)

    rectangle = convex(root+filename)
    # box[0][1~2] br ~ bl ~ tl ~tr

    #up
    for y in range(0,rectangle[2][1]):
        for x in range(0,width):
            output[x,y] = (0,0,0)
    #down
    for y in range(rectangle[0][1],height):
        for x in range(0,width):
            output[x,y] = (0,0,0)
    #left
    for y in range(0,height):
        for x in range(0,rectangle[1][0]):
            output[x,y] = (0,0,0)
    #right
    for y in range(0,height):
        for x in range(rectangle[3][0],width):
            output[x,y] = (0,0,0)
    outputImg = outputImg.convert("RGB")
    outputImg.save(root + filename)

    for y in range(0, height):
        for x in range(0, width):
            r, g, b = outputImg.getpixel((x, y))
            if(r>50):
                index_count[k][0] = x
                index_count[k][1] = y
                k+=1
                #print(k)

    for i in range(0,len(length_cal)):
        length_cal[i] = 3000
    for i in range(1,k):
        if(tl(index_count[i][0],index_count[i][1],width,height)<length_cal[0]):
            per_point[0] = index_count[i][0]
            per_point[1] = index_count[i][1]
            length_cal[0] = tl(index_count[i][0],index_count[i][1],width,height) #tl

        if(bl(index_count[i][0],index_count[i][1],width,height)<length_cal[1]):
            per_point[2] = index_count[i][0]
            per_point[3] = index_count[i][1]
            length_cal[1] = bl(index_count[i][0],index_count[i][1],width,height) #bl

        if(tr(index_count[i][0],index_count[i][1],width,height)<length_cal[2]):
            per_point[4] = index_count[i][0]
            per_point[5] = index_count[i][1]
            length_cal[2] = tr(index_count[i][0],index_count[i][1],width,height) #tr

        if(br(index_count[i][0],index_count[i][1],width,height)<length_cal[3]):
            per_point[6] = index_count[i][0]
            per_point[7] = index_count[i][1]
            length_cal[3] = br(index_count[i][0],index_count[i][1],width,height) #br

    #rotated
    if(per_point[7]-per_point[3]>abs(per_point[3]-per_point[5])/10):
        for i in range(1,k):
            if(index_count[i][1]<index_count[i-1][1]):
                per_point[0] = index_count[i][0]
                per_point[1] = index_count[i][1]
                #print("distort changed!")
        #for i in range(1,k):
            if(index_count[i][0]<index_count[i-1][0]):
            #if(tr_re(index_count[i][0],index_count[i][1],per_point[2],per_point[3])>tr_re(index_count[i-1][0],index_count[i-1][1],per_point[2],per_point[3])):
                per_point[4] = index_count[i][0]
                #per_point[5] = index_count[i][1]
            #length_cal[0] = tl(index_count[i][0],index_count[i][1],width,height) #tl
        #per_point[4] = per_point[6]
    print(per_point)

    expend_pixel = 1
    #tl
    per_point[0] -= expend_pixel #x
    per_point[1] -= expend_pixel #y

    #bl
    per_point[2] -= expend_pixel #x
    per_point[3] += expend_pixel #y

    #tr
    per_point[4] += expend_pixel #x
    per_point[5] -= expend_pixel #y

    #br
    per_point[6] += expend_pixel #x
    per_point[7] += expend_pixel #y

    args["image"] = ddir+filename

    args["coords"] =  "[("+str(per_point[0])+","+str(per_point[1])+"), ("+str(per_point[2])+","+str(per_point[3])+"), ("+str(per_point[4])+", "+str(per_point[5])+"), ("+str(per_point[6])+", "+str(per_point[7])+")]"
    #determine the coordinates without pre-supplying them tl, tr, br, bl
    image = cv2.imread(args["image"])

    rows, cols, channels = image.shape
    scale = re_size / float(image.shape[1])
    image = cv2.resize(image,(re_size,int(rows*scale)))

    pts = np.array(eval(args["coords"]), dtype = "float32")

    warped = four_point_transform(image, pts)
    #cv2.imshow("warped",warped)
    #cv2.waitKey(0)

    cv2.imwrite("../Downloads/DeepLabv3-TS/"+"warped"+filename,warped)
    #cv2.waitKey(0)
    print("warp_saved")


import sys
sys.stdin = open('input.txt')

T = int(input())
for tc in range(1, 1 + T):
    N = int(input())
    lines = [list(map(int, input().split())) for _ in range(N)]

    cross = 0
    for i in range(N - 1):
        for j in range(i, N):
            if lines[i][0] < lines[j][0]:
                if lines[i][1] > lines[j][1]:
                    cross += 1
            else:
                if lines[i][1] < lines[j][1]:
                    cross += 1

    print('#{}'.format(tc), cross)


import importlib

import pytest
from pytest_mock import MockerFixture

import src.week02.scripts.build
import src.week02.scripts.collect_gift
import src.week02.scripts.make_gift
import src.week02.scripts.send
from src.utils.mock import MockChainContext, MockUser
from src.utils.mock_scripts import mock_context, run_script

@pytest.fixture(scope="module", autouse=True)
def test_build():
    src.week02.scripts.build.main()

def test_send(mocker: MockerFixture):
    context = MockChainContext()
    u1 = MockUser(context)
    u1.fund(10_000_000)
    u2 = MockUser(context)
    users = {"u1": u1, "u2": u2}
    mock = mock_context(mocker, "src.week02.scripts.send", context, users)

    run_script(
        mocker, src.week02.scripts.send, args=["u1", "u2", "--amount", "5000000"]
    )

    mock.assert_called_once()
    assert u1.balance().coin <= 5000000
    assert u2.balance().coin == 5000000

@pytest.mark.parametrize(
    "script", ["burn", "custom_types", "fourty_two", "fourty_two_typed", "gift"]
)
def test_gift(mocker: MockerFixture, script: str):
    # setup chain
    validator = importlib.import_module(f"src.week02.lecture.{script}").validator
    context = MockChainContext(default_validator=validator)
    u1 = MockUser(context)
    u1.fund(10_000_000)
    u2 = MockUser(context)
    u2.fund(5_000_000)  # add collateral
    users = {"u1": u1, "u2": u2}
    # test make_gift.py
    mock = mock_context(mocker, "src.week02.scripts.make_gift", context, users)
    run_script(
        mocker,
        src.week02.scripts.make_gift,
        args=["u1", "--amount", "5000000", "--script", script],
    )
    mock.assert_called_once()
    # test collect_gift.py
    mock = mock_context(mocker, "src.week02.scripts.collect_gift", context, users)
    try:
        run_script(
            mocker, src.week02.scripts.collect_gift, args=["u2", "--script", script]
        )
        validates = True
    except (AssertionError, ValueError) as e:
        if script != "burn":
            raise e
        validates = False

    mock.assert_called_once()
    assert validates == (script != "burn")
    if script == "burn":
        return

    assert 4_000_000 <= u1.balance().coin <= 5_000_000
    assert 9_000_000 <= u2.balance().coin <= 10_000_000


class Solution:
    def maxCoins(self, nums: List[int]) -> int:

        memo = {}
        nums = [1] + nums + [1]

        def dfs(l, r):

            if l > r:
                return 0

            if (l, r) in memo:
                return memo[(l, r)]

            answer = 0
            for k in range(l, r+1):
                answer = max(answer, dfs(l, k-1) + (nums[k]*nums[l-1]*nums[r+1]) + dfs(k+1, r))

            memo[(l, r)]= answer
            return memo[(l, r)]

        return dfs(1, len(nums)-2)


"""
Bayesian analysis of MSSM.

    python mssm.py

runs two scans of the MSSM; one with log and one with linear priors. Results
should appear in `./chains/mssm*`.
"""

import numpy as np
import pymultinest

from knn_loglike import LogLike

PARAM_SAMPLES = "param_samples.npy"
LOGLIKE_SAMPLES = "loglike_samples.npy"
INDEX = "mssm.index"
LOGLIKE_SM = 4.15475279
BASENAME = "./chains/mssm_{}_"

# Make MSSM log-likelihood function

param_samples = np.load(PARAM_SAMPLES)
loglike_samples = np.load(LOGLIKE_SAMPLES)
loglike = LogLike(param_samples, loglike_samples)
loglike.lazyload(INDEX)

def wrap_loglike(cube, n_dims=4, n_params=4):
    """
    Convert cube to a numpy array, and call our log-likelihood functions.
    """
    array = np.array([cube[i] for i in range(n_dims)])
    return loglike(array) - LOGLIKE_SM

# Make MSSM priors

def linear_prior(x, min_, max_):
    """
    Map unit hypercube to a parameter with a linear prior.
    """
    return (max_ - min_) * x + min_

def log_prior(x, min_, max_, signed=False):
    """
    Map unit hypercube to a parameter with a linear prior.
    """
    if not signed:
        return min_ * (max_ / min_)**x

    sign = -1. if x < 0.5 else 1.
    x_magnitude = 2. * x - 1. if x > 0.5 else 2. * x
    return sign * min_ * (max_ / min_)**x_magnitude

def log_priors(cube, n_dims, n_params):
    """
    Map unit hypercube to M1, M2, mu and tan beta with log priors.
    """
    cube[0] = log_prior(cube[0], 1., 2000., signed=True)  # M1
    cube[1] = log_prior(cube[1], 1., 2000.)  # M2
    cube[2] = log_prior(cube[2], 1., 2000., signed=True)  # mu
    cube[3] = linear_prior(cube[3], 1., 70.)  # tan beta
    return cube

def linear_priors(cube, n_dims, n_params):
    """
    Map unit hypercube to M1, M2, mu and tan beta with linear priors.
    """
    cube[0] = linear_prior(cube[0], -2000., 2000.)  # M1
    cube[1] = linear_prior(cube[1], 1., 2000.)  # M2
    cube[2] = linear_prior(cube[2], -2000., 2000.)  # mu
    cube[3] = linear_prior(cube[3], 1., 70.)  # tan beta
    return cube

if __name__ == "__main__":

    pymultinest.run(wrap_loglike,
                    log_priors,
                    outputfiles_basename=BASENAME.format('log'),
                    n_dims=4,  # M1, M2, mu and tan beta
                    evidence_tolerance=1E-5,
                    n_live_points=2000,
                    importance_nested_sampling=False,
                    sampling_efficiency='model',
                    n_iter_before_update=100,
                    resume=True,
                    verbose=True)

    pymultinest.run(wrap_loglike,
                    linear_priors,
                    outputfiles_basename=BASENAME.format('linear'),
                    n_dims=4,  # M1, M2, mu and tan beta
                    evidence_tolerance=1E-5,
                    n_live_points=2000,
                    importance_nested_sampling=False,
                    sampling_efficiency='model',
                    n_iter_before_update=100,
                    resume=True,
                    verbose=True)


import crypto_history as ch
import os

the_path = os.path.dirname(os.path.abspath(__file__))
data_dir = str(os.path.abspath(os.path.join(the_path, os.pardir))) + "/data/"
start_date = '20180101'
end_date = '20180702'

c_names = ch.CoinNames()
counter = 1
for coin in c_names:
    print('Getting data of: {0}, \nwhich is the {1} out of {2}'.format(
        coin, counter, len(c_names)))
    headers, historicaldata = ch.gather(start_date, end_date, [coin])
    ch.Save(headers, historicaldata, coin, data_dir)
    counter += 1


import sys, getopt
try:
    import xmlrpc.client as xmlrpclib # PY3
except ImportError:
    import xmlrpclib # PY2
import os
import platform
try:
    from subprocess import getstatusoutput # PY3
except ImportError:
    from commands import getstatusoutput # PY2
import pprint
import math
import errno
try:
    import json
except ImportError:
    import simplejson as json

import re
import shutil
import glob
from subprocess import Popen, PIPE
from lxml import etree
from procfs import procfs

USAGE_TEXT = """
Usage:  beaker-system-scan [-d] [-j] [[-h <HOSTNAME>] [-S server]]
"""

def get_helper_program_output(program, *args):
    """ Run an external program and return it's output"""
    env = dict(os.environ)
    env['PATH'] = '/usr/libexec/beaker-system-scan:..:.:' + env['PATH']
    proc = Popen([program] + list(args), env=env,
                stdout=PIPE, stderr=PIPE)
    out, err = proc.communicate()
    if proc.returncode:
        raise RuntimeError('Error %s running %s: %s' % (proc.returncode, program, err))
    return out.decode('utf8')

def push_inventory(method, hostname, inventory):
   session = xmlrpclib.Server(lab_server, allow_none=True)
   try:
      resp = getattr(session, method)(hostname, inventory)
      if(resp != 0) :
         raise RuntimeError("ERROR: Pushing Inventory for host %s." % hostname)
   except:
      raise

def check_for_virt_iommu():

    arch = platform.machine()
    virt_iommu = 0

    if arch != 'x86_64':
        #only x86_64 boxes support virt iommu
        return 0

    #test what type of system we are on
    if os.path.exists("/sys/firmware/acpi/tables/DMAR"):
        # alright we are on an Intel vt-d box
        hwu = False
        ba = False

        # iasl can't read directly from /sys
        shutil.copyfile('/sys/firmware/acpi/tables/DMAR', 'DMAR.dat')

        # create ascii file
        os.system("iasl -d DMAR.dat > /dev/null 2>&1")
        if os.path.exists("DMAR.dsl"):
            f = open("DMAR.dsl", 'r')

            #look for keywords to validate ascii file
            hwu_pat = re.compile ('Hardware Unit')
            ba_pat = re.compile ('Base Address')
            ba_inv_pat = re.compile ('0000000000000000|FFFFFFFFFFFFFFFF')

            for line in f.readlines():
                if hwu_pat.search(line):
                    hwu = True
                if ba_pat.search(line):
                    if ba_inv_pat.search(line):
                        sys.stderr.write("VIRT_IOMMU: Invalid Base address: 0's or F's\n")
                    else:
                        ba = True
            if not hwu:
                sys.stderr.write("VIRT_IOMMU: No Hardware Unit\n")
            elif not ba:
                sys.stderr.write("VIRT_IOMMU: No Base Address\n")
            else:
                virt_iommu = 1
        else:
            sys.stderr.write("VIRT_IOMMU: Failed to create DMAR.dsl\n")

    elif os.path.exists("/sys/firmware/acpi/tables/IVRS"):
        # alright we are on an AMD iommu box
        #  we don't have a good way to validate this
        virt_iommu = 1

    return virt_iommu

def kernel_inventory(lshw_tree):
    data = {}
    data['VIRT_IOMMU'] = False

    ##########################################
    # check for virtual iommu/vt-d capability
    # if this passes, assume we pick up sr-iov for free

    if check_for_virt_iommu():
        data['VIRT_IOMMU'] = True

    ##########################################
    # DISK_CONTROLLER is the kernel driver of the device (e.g. PCI SCSI
    # controller card) to which the first hard disk is attached.
    disk_controller = lshw_tree.xpath(
            '//node[node/@id="disk" or node/@id="disk:0"]'
            '/configuration/setting[@id="driver"]/@value')
    if disk_controller:
        data['DISK_CONTROLLER'] = str(disk_controller[0])

    ##########################################
    # determine if machine is using multipath or not

    #ok, I am really lazy
    #remove the default blacklist in /etc/multipath.conf
    if os.path.exists('/etc/multipath.conf'):
        os.system("sed -i '/^blacklist/,/^}$/d' /etc/multipath.conf")
        #restart multipathd to see what it detects
        #this spits out errors if the root device is on a
        #multipath device, I guess ignore for now and hope the code
        #correctly figures things out
        os.system("service multipathd restart > /dev/null")
        #the multipath commands will display the topology if it
        #exists otherwise nothing
        #filter out vbds and single device paths
        status, mpaths = getstatusoutput("multipath -ll")
        mp = False
        if status:
            sys.stderr.write("MULTIPATH: multipath -ll failed with %d\n")
        else:
            count = 0
            mpath_pat = re.compile(" dm-[0-9]* ")
            sd_pat = re.compile(" sd[a-z]")
            for line in mpaths.split('\n'):
                #reset when a new section starts
                if mpath_pat.search(line):
                    # found at least one mp instance, declare success
                    if count > 1:
                        mp = True
                        break
                    count = 0

                #a hit! increment to indicate this
                if sd_pat.search(line):
                    count = count + 1

        if mp == True:
            data['DISK_MULTIPATH'] = True
        else:
            data['DISK_MULTIPATH'] = False

    return data

def legacy_inventory(inv):
    # Take the gathered inventory data, fill legacy key/value schema with it
    # and gather any missing bits.
    data = {}
    data['MODULE'] = []
    data['HVM'] = False
    data['DISK'] = []
    data['BOOTDISK'] = []
    data['DISKSPACE'] = 0
    data['NR_DISKS'] = 0
    data['NR_ETH'] = 0
    data['NR_IB'] = 0

    data['ARCH'] = inv['Arch'][0]
    if inv['Cpu']['family']:
        data['CPUFAMILY'] = inv['Cpu']['family']
    data['CPUVENDOR'] = inv['Cpu']['vendor']
    data['CPUMODEL'] = inv['Cpu']['modelName']
    if inv['Cpu']['model']:
        data['CPUMODELNUMBER'] = inv['Cpu']['model']
    data['PROCESSORS'] = inv['Cpu']['processors']
    data['VENDOR'] = inv['vendor']
    data['MODEL'] = inv['model']
    data['FORMFACTOR'] = inv['formfactor']
    data['CPUFLAGS'] = inv['Cpu']['CpuFlags']
    data['PCIID'] = ["%s:%s" % (d['vendorID'], d['deviceID'])
            for d in inv['Devices'] if d['bus'] == 'pci' and
                (d['vendorID'] != '0000' or d['deviceID'] != '0000')]
    data['USBID'] = ["%s:%s" % (d['vendorID'], d['deviceID'])
            for d in inv['Devices'] if d['bus'] == 'usb' and
                (d['vendorID'] != '0000' or d['deviceID'] != '0000')]

    # The below data (and kernel_inventory()) has not (yet) made it to the new schema
    # (and formfactor above)

    modules = getstatusoutput('/sbin/lsmod')[1].split('\n')[1:]
    for module in modules:
        data['MODULE'].append(module.split()[0])

    # Find Active Storage Driver(s)
    bootdisk = None
    bootregex = re.compile(r'/dev/([^ ]+) on /boot')
    disks = getstatusoutput('/bin/mount')[1].split('\n')[1:]
    for disk in disks:
        if bootregex.search(disk):
            # Replace / with !, needed for cciss
            bootdisk = bootregex.search(disk).group(1).replace('/','!')

    if bootdisk:
        try:
            drivers = get_helper_program_output('getdriver.sh', bootdisk).split('\n')[1:]
        except RuntimeError:
            # /boot might be on a device-mapper device, but getdriver.sh
            # doesn't handle those properly. We don't care much about
            # BOOTDISK though so just ignore failures.
            pass
        else:
            for driver in drivers:
                data['BOOTDISK'].append(driver)
    # Find Active Network interface
    iface = None
    for line in getstatusoutput('route -n')[1].split('\n'):
        if line.find('0.0.0.0') == 0:
            iface = line.split()[-1:][0] #eth0, eth1, etc..
    if iface:
        drivers = get_helper_program_output('getdriver.sh', iface).split('\n')
        if len(drivers) == 1:
            data['NETWORK'] = drivers[0]
        else:
            data['NETWORK'] = drivers[1:][0]

    # disk sizes are converted to MiB in key-values for backwards compatibility
    data['DISK'] = [int(d['size']) // 1024**2 for d in inv['Disk']['Disks']]
    data['DISKSPACE'] = sum(int(d['size']) for d in inv['Disk']['Disks']) // 1024**2
    data['NR_DISKS'] = len(data['DISK'])

    # constants from include/linux/if_arp.h
    ETH_TYPE = 1
    IB_TYPE = 32
    # finding out eth and ib interfaces...
    interfaces = os.listdir('/sys/class/net')
    for iface in interfaces:
        iface_path = os.path.join('/sys/class/net', iface)

        # skip if path is not a dir as later we rely on files inside it
        if not os.path.isdir(iface_path):
            continue

        # don't count virtual devices (lo, bridge)
        if (os.path.islink(iface_path) and 'virtual' in os.readlink(iface_path)):
            continue

        # don't count wifi devices
        if os.path.exists(os.path.join(iface_path, 'phy80211')):
            continue

        with open(os.path.join(iface_path, 'type')) as type_file:
            int_type = int(type_file.readline())
            if int_type == ETH_TYPE:
                data['NR_ETH'] += 1
            if int_type == IB_TYPE:
                data['NR_IB'] += 1

    # checking for whether or not the machine is hvm-enabled.
    caps = ""
    if os.path.exists("/sys/module/kvm_amd") or \
       os.path.exists("/sys/module/kvm_intel"):
           data['HVM'] = True
    elif os.path.exists('/sys/module/kvm_hv'): # ppc64
        data['HVM'] = True
    elif os.path.exists('/proc/pal/cpu0/processor_info'): # ia64
        for line in open('/proc/pal/cpu0/processor_info', 'r'):
            if re.match('Virtual machine features.*: On', line):
                data['HVM'] = True

    if os.path.exists("/root/NETBOOT_METHOD.TXT"):
        data['NETBOOT_METHOD'] = open('/root/NETBOOT_METHOD.TXT', 'r').readline()[:-1]
    return data

def read_inventory(inventory, arch = None, proc_cpuinfo='/proc/cpuinfo'):

    data = {}
    flags = []
    data['Devices'] = []
    cpu = None

    procCpu  = procfs.cpuinfo(filename=proc_cpuinfo)

    #Break the xml into the relevant sets of data
    cpuinfo = inventory.xpath(".//node[@class='processor']")[0]
    memory_elems = inventory.xpath(".//node[@class='memory']")
    memoryinfo = None
    for m in memory_elems:
       desc = m.find('description')
       if desc is not None and desc.text.lower() == 'system memory':
          memoryinfo = m

    devices = inventory.xpath(".//node[@id!='subsystem']")
    capabilities = cpuinfo.find('capabilities')
    if capabilities is not None:
       for capability in capabilities.getchildren():
          flags.append(capability.get('id'))

    if not arch:
       arch = os.uname()[4]

    # BZ 1213685
    if arch in ['i486', 'i586', 'i686']:
        arch = 'i386'

    if arch in ['i386', 'x86-64', "x86_64"]:
       vendor = cpuinfo.find('vendor')
       if vendor is not None:
          vendor = vendor.text
       #rhbz: 1212284
       if vendor == 'Intel Corp.':
           vendor = 'GenuineIntel'
       if vendor == 'Advanced Micro Devices [AMD]':
           vendor = 'AuthenticAMD'
       modelName = cpuinfo.find('product')
       if modelName is not None:
          modelName = modelName.text

       #https://bugzilla.redhat.com/show_bug.cgi?id=1212281
       try:
           idx = flags.index('x86-64')
       except ValueError:
           pass
       else:
           flags[idx] = 'lm'
       cpu = dict(vendor     = vendor,
                  model      = int(procCpu.tags['model']),
                  modelName  = modelName,
                  speed      = float(procCpu.tags['cpu mhz']),
                  processors = int(procCpu.nr_cpus),
                  cores      = int(procCpu.nr_cores),
                  sockets    = int(procCpu.nr_sockets),
                  CpuFlags   = flags,
                  family     = int(procCpu.tags['cpu family']),
                  stepping   = int(procCpu.tags['stepping']),
       )
    elif arch in ["ppc", "ppc64", "ppc64le"]:
       cpu = dict(vendor     = "IBM",
                  model      = int(''.join(re.split('^.*([0-9a-f]{4})\s([0-9a-f]{4}).*$',
                                                    procCpu.tags['revision'])), 16),
                  modelName  = str(procCpu.tags['cpu']),
                  speed      = float(re.findall('\d+.+\d+', procCpu.tags['clock'])[0]),
                  processors = int(procCpu.nr_cpus),
                  cores      = 0,
                  sockets    = 0,
                  CpuFlags   = flags,
                  family     = 0,
                  stepping   = 0,
               )
    elif arch in ["s390", "s390x"]:
       for cpuflag in procCpu.tags['features'].split(" "):
          flags.append(cpuflag)
       proc = dict([tuple(s.strip() for s in kv.split('=')) for kv in procCpu.tags['processor 0'].split(',')])
       cpu = dict(vendor     = str(procCpu.tags['vendor_id']),
                  model      = int(proc['identification'], 16),
                  modelName  = str(proc['machine']),
                  processors = int(procCpu.tags['# processors']),
                  cores      = 0,
                  sockets    = 0,
                  CpuFlags   = list(set(flags)),
                  family     = 0,
                  speed      = 0,
                  stepping   = 0,
       )
    elif arch == "ia64":
       for cpuflag in procCpu.tags['features'].split(","):
          flags.append(cpuflag.strip())
       vendor = cpuinfo.find('vendor')
       if vendor is not None:
          vendor = vendor.text
          if vendor == 'Intel Corp.':
            vendor = 'GenuineIntel'
       product = cpuinfo.find('product')
       if product is not None:
          product = product.text
       cpu = dict(vendor     = vendor,
                  model      = int(procCpu.tags['model']),
                  modelName  = product,
                  speed      = float(procCpu.tags['cpu mhz']),
                  processors = int(procCpu.nr_cpus),
                  cores      = int(procCpu.nr_cores),
                  sockets    = int(procCpu.nr_sockets),
                  # As the cpu flags are retrieved from /proc/cpuinfo and lshw,
                  # we need to remove duplicate flags if they are exist.
                  CpuFlags   = list(set(flags)),
                  # bz1212307: smolt is using revision for family
                  family     = int(procCpu.tags['revision']),
                  stepping   = 0,
               )

    elif arch == 'aarch64':
        # count logical CPUs
        n_procs = 0
        f = open(proc_cpuinfo)
        for line in f:
            if line.startswith('processor'):
                n_procs += 1
        f.close()
        # count CPU cores
        n_cores = 0
        for cpu in inventory.findall('.//node[@class="processor"]'):
            cores_setting = cpu.find('configuration/setting[@id="cores"]')
            if cores_setting is not None:
                n_cores += int(cores_setting.get('value'))
            else:
                n_cores += 1
        # count physical CPUs
        n_sockets = len(inventory.findall('.//node[@class="processor"]'))

        cpu = dict(vendor     = cpuinfo.findtext('vendor'),
                   modelName  = cpuinfo.findtext('product'),
                   speed      = float(cpuinfo.findtext('capacity') or 0) / 1000000,
                   processors = n_procs,
                   cores      = n_cores,
                   sockets    = n_sockets,
                   CpuFlags   = flags,
                   # Beaker's data model assumes model/family/stepping are
                   # integers, as in the x86 world, so we can't store anything
                   # useful in them here.
                   model      = None,
                   family     = None,
                   stepping   = None,
               )

    sysinfo = inventory.xpath(".//node[@class='system']")[0]
    vendor = sysinfo.find('vendor')
    product = sysinfo.find('product')
    memsize = memoryinfo.find('size')
    if vendor is not None:
       vendor = vendor.text
    if product is not None:
       product = product.text
    if memsize is not None:
       memsize = int(memsize.text) // 1024**2

    data['Cpu'] = cpu
    data['Arch'] = [arch]
    data['vendor'] = vendor
    data['model'] = product
    data['memory'] = memsize

    disklist = []
    for disk in inventory.xpath('.//node[@class="disk" and @id!="medium"]'):
        diskinfo = {}
        if disk.find('size') is None:
            continue # probably an optical drive
        # need to send size as an XML-RPC string as it is likely to overflow
        # the 32-bit size limit for XML-RPC ints
        diskinfo['size'] = disk.findtext('size')
        diskinfo['model'] = disk.findtext('product')
        logicalsectorsize = disk.find('configuration/setting[@id="logicalsectorsize"]')
        if logicalsectorsize is not None:
            diskinfo['sector_size'] = int(logicalsectorsize.get('value'))
        else:
            diskinfo['sector_size'] = 512
        sectorsize = disk.find('configuration/setting[@id="sectorsize"]')
        if sectorsize is not None:
            diskinfo['phys_sector_size'] = int(sectorsize.get('value'))
        else:
            diskinfo['phys_sector_size'] = diskinfo['sector_size']
        disklist.append(diskinfo)
    data['Disk'] = {'Disks': disklist}
    data['Numa'] = {
        'nodes': len(glob.glob('/sys/devices/system/node/node*')), #: number of NUMA nodes in the system, or 0 if not supported
    }
    # default
    data['formfactor'] = ''
    chassis = sysinfo.xpath('//configuration/setting[@id="chassis"]')
    if len(chassis) > 0:
        data['formfactor'] = chassis[0].get('value')
    try:
        hypervisor = get_helper_program_output('hvm_detect')
    except OSError as e:
        if e.errno == errno.ENOENT and arch != 'x86_64':
            pass
        else:
            raise
    else:
        hvm_map = {"No KVM or Xen HVM\n"    : None,
                   "KVM guest.\n"           : 'KVM',
                   "Xen HVM guest.\n"       : 'Xen',
                   "Microsoft Hv guest.\n"  : 'HyperV',
                   "VMWare guest.\n"        : 'VMWare',
                }
        data['Hypervisor'] = hvm_map[hypervisor]

    for device in devices:
        # Defaults for nonexistent values
        description = driver = bus = device_class = "Unknown"
        vendorID = deviceID = subsysVendorID = subsysDeviceID = "0000"
        firmware = None

        if device.findtext('product'):
            description = device.findtext('product')
        elif device.findtext('description'):
            description = device.findtext('description')

        usbvendornode = device.find('hints/hint[@name="usb.idVendor"]')
        if usbvendornode is not None:
            vendorID = '%04x' % int(usbvendornode.get('value'), 16)
        usbproductnode = device.find('hints/hint[@name="usb.idProduct"]')
        if usbproductnode is not None:
            deviceID = '%04x' % int(usbproductnode.get('value'), 16)
        pcivendornode = device.find('hints/hint[@name="pci.vendor"]')
        if pcivendornode is not None:
            vendorID = '%04x' % int(pcivendornode.get('value'), 16)
        pcidevicenode = device.find('hints/hint[@name="pci.device"]')
        if pcidevicenode is not None:
            deviceID = '%04x' % int(pcidevicenode.get('value'), 16)
        pcisubvendornode = device.find('hints/hint[@name="pci.subvendor"]')
        if pcisubvendornode is not None:
            subsysVendorID = '%04x' % int(pcisubvendornode.get('value'), 16)
        pcisubdevicenode = device.find('hints/hint[@name="pci.subdevice"]')
        if pcisubdevicenode is not None:
            subsysDeviceID = '%04x' % int(pcisubdevicenode.get('value'), 16)

        if device.find('businfo') is not None:
            bus = device.find('businfo').text.split('@')[0]
        elif device.find('capabilities/capability[@id="pnp"]') is not None:
            bus = 'pnp'

        if device.get('class') is not None:
            device_class = device.get('class')
        # Virtio mem balloon is not memory (RHBZ#1249462)
        if description == 'Virtio memory balloon':
            device_class = 'generic'

        drivernode = device.find('configuration/setting[@id="driver"]')
        if drivernode is not None:
            driver = drivernode.get('value')

        # We report these separately
        if device_class in ['memory', 'processor', 'disk']:
            continue
        # The system itself is not a device
        if device_class == 'system':
            continue
        # Add firmware information to device table
        firmwarenode = device.find('configuration/setting[@id="firmware"]')
        if firmwarenode is not None:
            firmware = firmwarenode.get('value')
        # System firmware is a special case
        if device.get('id') == 'core':
            firmwarenode = device.find('.//node[@id="firmware"]')
            if firmwarenode is not None:
                description = firmwarenode.findtext('description')
                firmware = firmwarenode.findtext('version')
        # Volumes/partitions are transient
        if device_class == 'volume':
            continue
        # If none of these have any useful information, skip it
        if description == 'Unknown' and driver == 'Unknown' and vendorID == '0000' and \
           deviceID == '0000' and subsysDeviceID == '0000' and subsysVendorID == '0000':
            continue

        # Map lshw device classes to smolt-compatible device types
        # https://git.fedorahosted.org/cgit/smolt.git/tree/client/smolt.py#n1015
        device_type = device_class.upper()
        if device_class == 'storage':
            if device.xpath('./capabilities/capability[@id="scsi"]'):
                device_type = 'SCSI'
            if device.xpath('./capabilities/capability[@id="ide"]'):
                device_type = 'IDE'
            if device.xpath('./capabilities/capability[@id="raid"]'):
                device_type = 'RAID'
            if device.xpath('./capabilities/capability[@id="sata"]'):
                device_type = 'SATA'
            if device.xpath('./capabilities/capability[@id="sas"]'):
                device_type = 'SAS'
        elif device_class == 'bus':
            if device.xpath('./hints/hint[@name="icon" and @value="usb"]'):
                device_type = 'USB'
            if device.xpath('./hints/hint[@name="icon" and @value="firewire"]'):
                device_type = 'FIREWIRE'
        elif device_class == 'communication':
            if device.xpath('./hints/hint[@name="icon" and @value="modem"]'):
                device_type = 'MODEM'
        elif device_class == 'display':
            device_type = 'VIDEO'
        elif device_class == 'multimedia':
            device_type = 'AUDIO'

        data['Devices'].append(dict( vendorID = vendorID,
                                     deviceID = deviceID,
                                     subsysVendorID = subsysVendorID,
                                     subsysDeviceID = subsysDeviceID,
                                     bus = bus,
                                     driver = driver,
                                     type = device_type,
                                     description = description,
                                     fw_version = firmware))

    return data

def usage():
    print(USAGE_TEXT)
    sys.exit(-1)

def main():
    global lab_server, hostname

    lab_server = None
    hostname = None
    debug = 0
    json_output = 0

    if 'LAB_SERVER' in os.environ:
        lab_server = os.environ['LAB_SERVER']
    if 'HOSTNAME' in os.environ:
        hostname = os.environ['HOSTNAME']

    args = sys.argv[1:]
    try:
        opts, args = getopt.getopt(args, 'dh:S:j', ['server='])
    except:
        usage()
    for opt, val in opts:
        if opt in ('-d', '--debug'):
            debug = 1
        if opt in ('-j', '--json') and debug:
            json_output = 1
        if opt in ('-h', '--hostname'):
            hostname = val
        if opt in ('-S', '--server'):
            lab_server = val

    lshw_xml = Popen(['lshw', '-xml'], stdout=PIPE).communicate()[0]
    lshw_tree = etree.XML(lshw_xml)
    inventory = read_inventory(lshw_tree)
    legacy_inv = legacy_inventory(inventory)
    legacy_inv.update(kernel_inventory(lshw_tree))
    del inventory['formfactor']
    if debug:
       if json_output:
          print(json.dumps({'legacy':legacy_inv,
                            'Data':inventory}))
       else:
          print("Legacy inventory:\n%s\nData:\n%s" % (
             pprint.pformat(legacy_inv), pprint.pformat(inventory)))
    else:
        if not hostname:
            print("You must specify a hostname with the -h switch")
            sys.exit(1)

        if not lab_server:
            print("You must specify a lab_server with the -S switch")
            sys.exit(1)

        push_inventory("legacypush", hostname, legacy_inv)
        push_inventory("push", hostname, inventory)

if __name__ == '__main__':
    main()
    sys.exit(0)


## Generic Parts
# These functions are providing the functionality to load
# arbitrary configuration files.
#
# They can be imported by other code (see `ldap_config.py` for an example).

import importlib.util
import sys
from os import scandir
from os.path import abspath, isfile

def _filename(f):
    return f.name

def _import(module_name, path, loaded_configurations):
    spec = importlib.util.spec_from_file_location("", path)
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    sys.modules[module_name] = module

    loaded_configurations.insert(0, module)

    print(f"ЁЯзм loaded config '{path}'")

def read_configurations(config_module, config_dir, main_config):
    loaded_configurations = []

    main_config_path = abspath(f"{config_dir}/{main_config}.py")
    if isfile(main_config_path):
        _import(f"{config_module}.{main_config}", main_config_path, loaded_configurations)
    else:
        print(f"тЪая╕П Main configuration '{main_config_path}' not found.")

    with scandir(config_dir) as it:
        for f in sorted(it, key=_filename):
            if not f.is_file():
                continue

            if f.name.startswith("__"):
                continue

            if not f.name.endswith(".py"):
                continue

            if f.name == f"{main_config}.py":
                continue

            if f.name == f"{config_dir}.py":
                continue

            module_name = f"{config_module}.{f.name[:-len('.py')]}".replace(".", "_")
            _import(module_name, f.path, loaded_configurations)

    if len(loaded_configurations) == 0:
        print(f"тА╝я╕П No configuration files found in '{config_dir}'.")
        raise ImportError(f"No configuration files found in '{config_dir}'.")

    return loaded_configurations

## Specific Parts
# This section's code actually loads the various configuration files
# into the module with the given name.
# It contains the logic to resolve arbitrary configuration options by
# levaraging dynamic programming using `__getattr__`.

_loaded_configurations = read_configurations(
    config_dir="/etc/netbox/config/",
    config_module="netbox.configuration",
    main_config="configuration",
)

def __getattr__(name):
    for config in _loaded_configurations:
        try:
            return getattr(config, name)
        except:
            pass
    raise AttributeError

def __dir__():
    names = []
    for config in _loaded_configurations:
        names.extend(config.__dir__())
    return names


import numpy as np

class Detector1D():
    def __init__(self, variance, detection_prob, clutter_model, space):
        self.R = variance
        self.PD = detection_prob
        self.C_model = clutter_model
        self.space = space

    def get_single_measurement(self, x):
        z = []
        o = self.get_object_sample(x)
        if o is not None:
            z.append(o)
        # r = np.random.uniform()
        # if r <= self.PD(x):
        #     o = self.get_object_sample(x)
        #     print(f'o = {o}')
        #     z.append(o)
        C = self.C_model.get_clutter()
        [z.append(c) for c in C]
        return np.array(z)

    def get_measurements(self, X):
        Z = []
        n = X.shape[0] # Number of objects
        for k in range(X.shape[1]):
            Zk = []
            for i in range(n):
                o = self.get_object_sample(X[i,k])
                if o is not None:
                    Zk.append(o)
            C = self.C_model.get_clutter()
            [Zk.append(c) for c in C]
            # Z.append(np.array(Zk))
            Z.append(Zk)
        return Z

    def get_object_sample(self, x):
        r = np.random.uniform()
        if r <= self.PD(x):
            o_in_fov = False
            o = None
            # If x is close to the edge o might be sampled outside the fov
            while not o_in_fov:
                o = np.random.normal(loc=x, scale=np.sqrt(self.R))
                o_in_fov = self.space.contains(o)
            return o
        return None

class Detector2D():
    def __init__(self, noise_covar, detection_prob, clutter_model, space):
        """ Input:
                noise_covar - numpy array (matrix)
                detection_prob - float
                clutter_intensity - float
        """
        self.R = noise_covar
        self.PD = detection_prob
        self.C_model = clutter_model
        self.space = space

    def get_single_measurement(self, x):
        z = []
        r = np.random.uniform()
        if r <= self.PD(x):
            o = self.get_object_sample(x)
            print(f'o = {o}')
            z.append(o)
        C = self.C_model.get_clutter()
        [z.append(c) for c in C]
        return np.array(z)

    def get_object_sample(self, x):
        o_in_fov = False
        o = None
        # If x is close to the edge o might be sampled outside the fov
        while not o_in_fov:
            o = np.random.multivariate_normal(mean=x, cov=self.R)
            o_in_fov = self.space.contains(o)
        return o


# http://www.labri.fr/perso/nrougier/teaching/numpy.100/

import numpy as np

def cartesian(arrays):
    arrays = [np.asarray(a) for a in arrays]
    shape = (len(x) for x in arrays)

    ix = np.indices(shape, dtype=int)
    ix = ix.reshape(len(arrays), -1).T

    for n, arr in enumerate(arrays):
        ix[:, n] = arrays[n][ix[:, n]]

    return ix

r = (cartesian(([1, 2, 3], [4, 5], [6, 7])))

# l = globals().copy()
# for v in l:
#     print ("'" + v + "'" + ": instance_of_class_name(\"" + type(l[v]).__name__ + "\"),")


""" @author: Adam, @date: 8-3-2019

Brute-force backtracking algorithm."""

import time
import numpy as np

#%% Data processing.

# Extract rows of text file.
file = open("p96_sudoku.txt")
text = file.read()
file.close()
rows = text.split("\n")

# Create list of puzzles, each represented as a list of strings.
puzzles = []
count = 1
puzzle = []
for row in rows[1:]:
    if count % 10 == 0:
        puzzles.append(puzzle)
        puzzle = []
    else:
        puzzle.append(row)
    count += 1
puzzles.append(puzzle)

# Convert each puzzle to a 9x9 numpy array.
grids = []
for puzzle in puzzles:
    for i in range(len(puzzle)):
        line = puzzle[i].strip()
        puzzle[i] = [int(char) for char in line]
    grids.append(np.array(puzzle))

#%% Backtracking solution.

def solve_sudoku(grid, print_sol=False):
    """Determine if Sudoku grid is solvable using backtracking, assuming a
    unique solution is defined. grid is updated in-place."""
    n_empty = 0  # Count empty entries as we search through the grid.

    # 4 loops to easily index each of 9 rows, columns, and 3x3 grids.
    # Start searching in top-left 3x3 grid.
    for row in range(3):
        for col in range(3):
            for subrow in range(3*row, 3*(row+1)):
                for subcol in range(3*col, 3*(col+1)):

                    # Fill empty entries.
                    if grid[subrow, subcol] == 0:
                        n_empty += 1

                        # For possible solutions satisfying Sudoku constraints,
                        # recursively continuing search with updated grid.
                        # Backtrack if necessary.
                        for sol in range(1, 10):
                            if is_not_possible_sol(sol, grid,
                                                   row, col, subrow, subcol):
                                continue
                            else:  # sol may be a valid solution.
                                grid[subrow, subcol] = sol
                                if solve_sudoku(grid, print_sol):
                                    return True
                                else:  # No solution found; backtrack.
                                    grid[subrow, subcol] = 0
                        return False  # No possible solutions found; terminate
                                      # this branch and backtrack.

    # If no empty entries counted (grid is complete), return True.
    is_solvable = (n_empty == 0)
    if is_solvable:
        if print_sol:
            print(grid)
    else:
        print("No solution found.")
    return is_solvable

def is_not_possible_sol(sol, grid, row, col, subrow, subcol):
    """Determine if sol may fill grid[subrow, subcol] given Sudoku
    constraints."""
    return (   sol in grid[subrow, :]
            or sol in grid[:, subcol]
            or sol in grid[3*row:3*(row+1), 3*col:3*(col+1)]
            )

start_time = time.time()

# Solve all Sudoku puzzles and sum top-left 3 digit numbers.
s = 0
i = 0
for grid in grids:
    i += 1
    print('Grid', i)
    solve_sudoku(grid)

    n_str = ''
    for col in range(3):
        n_str = n_str + str(grid[0, col])
    s += int(n_str)

print(s)

print(time.time() - start_time)

#%% Comments.
""" Potential improvements:

    Extensions/Remarks:
1)  Add visualizations to solving process.
"""


from .types import *
from .serialize import JSONSerializable

import numpy as np

class Embedding(JSONSerializable):
    def __init__(self, **kw):
        super().__init__(**kw)

    def __call__(self, source: Input) -> Feature:
        raise NotImplementedError

class Identity(Embedding):
    """For fixed-length vector data: just check size and convert to numpy array"""
    def __init__(self, size):
        """size is both the Input and Feature size"""
        super().__init__(size=size)
        self.size = self.input_size = size

    def __call__(self, source):
        source, = np_coerce(source)
        if self.size is not None:
            assert source.shape[-1] == self.size, (source.shape, self.size)
        return source

class ProjectAndSort(Embedding):
    """
    for point cloud-like data.
    use with L2 distance to compute sliced optimal transport.

    if an Input is a 2D array [B x C],
    B being the batch dimension (order not meaningful)
    and C being the coordinate dimension (order meaningful)

    e.g.
    [
    [x0,y0,z0],
    [x1,y1,z1],
    [x2,y2,z2],
    [x3,y3,z3],
    ]
    would be a cloud of B=4 points in C=3 dimensional space

    This computes `n` pseudo-random projections down to 1-dimensional spaces,
    sorts along those lines,
    and then concatenates to make one feature vector.
    the L2 distance between feature vectors is the sliced OT distance between point clouds.
    """
    def __init__(self, input_size:Tuple[int,int]=None, n:int=16):
        """
        Args:
            input_size: input shape [B,C]; if None, lazy init on first __call__
            n: number of random projections.
        """
        super().__init__(input_size=input_size, n=n)
        assert len(input_size)==2, "ProjectAndSort expects fixed-size 2D array data"

        self.n = n
        if input_size is not None:
            self.init(input_size)
        else:
            self.input_size = None

    def init(self, input_size):
        self.input_size = tuple(input_size)

        self.size = input_size[0] * self.n

        proj = np.random.randn(input_size[1], self.n)
        proj = proj / np.linalg.norm(proj, axis=0, keepdims=True)
        self.proj = proj

    def __call__(self, source):
        source, = np_coerce(source)
        if self.input_size is None:
            # lazy init
            self.init(source.shape[-2:])
        else:
            assert source.shape[-2:] == self.input_size, (source.shape, self.input_size)

        # project coordinate dimension to n lines
        feat = source @ self.proj
        # sort along the lines
        feat = np.sort(feat, axis=-2)
        # flatten
        # feat = feat.T
        feat = feat.reshape((*feat.shape[:-2], -1))

        return feat / np.sqrt(self.size)


from app.models import db, Review, environment, SCHEMA
from sqlalchemy.sql import text

def seed_reviews():
    burnout_review_1 = Review(
        recomended=False,
        game_id=1,
        user_id=3,
        review_text='Unrealistic premise. People can work more than 60 hours a week without issue. Refunded.'
    )
    africanus_review_1 = Review(
        recomended=True,
        game_id=2,
        user_id=2,
        review_text='The gameplay is solid, if not spectacular, but the setting itself really sets it apart from the other grand strategy games out there.'
    )
    spacefield_review_1 = Review(
        recomended=True,
        game_id=3,
        user_id=1,
        review_text="It wasn't the industry-defining standard we were hoping for, but it was certainly fun."
    )
    db.session.add(burnout_review_1)
    db.session.add(africanus_review_1)
    db.session.add(spacefield_review_1)
    db.session.commit()

def undo_reviews():
    if environment == "production":
        db.session.execute(f"TRUNCATE table {SCHEMA}.reviews RESTART IDENTITY CASCADE;")
    else:
        db.session.execute(text("DELETE FROM reviews"))

    db.session.commit()