########################################
# ECE 366 Project 2                    #
# Jim Palomo                           #
########################################

import os.path as Path

# twoscomp: 2's Complement [return binary (string)]    (string -> string)
# Input: s = binary (string)
# Return: 2's complement binary (string)
def twoscomp(s):
    for j in reversed(range(len(s))):
        if s[j] == '1':
            break

    t = ""
    for i in range(0, j, 1):        # flip everything
        t += str(1-int(s[i]))

    for i in range(j, len(s), 1):   # until the first 1 from the right
        t += s[i]

    return t                        # return 2's complement binary (string)

# twoscomp_dec: 2's Complement [return decimal (int)]     [use for sign extend]
# Input: b = binary (string)
# Return: 2's complement decimal (int)
def twoscomp_dec(b):

    l = len(b)          # length of bit provided

    x = b[:1].zfill(l)  # save the first bit and fill with 0's until original length
    x = x[::-1]         # flip binary

    x = int(x, 2) * -1  # value of binary (unsigned: 10000..0) * -1

    y = int(b[1:], 2)   # value of binary without the first bit

    x += y              # add up differing values

    return x            # return 2's complement decimal (int)

# bin_to_dec: convert binary (string) to decimal (int)  [use for sign extend]
# Input: binary (string)
# Return: Decimal (int)
def bin_to_dec(b):
    if(b[0]=="0"):
        return int(b, base=2)
    else:
        return twoscomp_dec(b)

# zero_extend: zero extend / unsigned operation (for specific operations)
# Input: binary (string)
# Return: decimal (int)
def zero_extend(b):
    return int(b, base=2)   # given a binary string, get unsigned decimal

# Integer to binary

# itosbin: convert integer (int) to signed binary (string)
# Input: i = integer (int) | n = # of bits of desired binary
# Return: returns signed binary (string)
def itosbin(i, n):
    s = ""
    if i >= 0:
        s = bin(i)[2:].zfill(n)
    else:
        s = bin(0-i)[2:].zfill(n)
        s = twoscomp(s)

    return s

# hex_to_bin: convert hex (string) to binary (string)
# Input: line = hex (string)
# Return: unsigned binary (string)
def hex_to_bin(line):
    h = line.replace("\n", "")
    i = int(h, base=16)
    b = bin(i)
    b = b[2:].zfill(32)
    return b

# neg_int_to_hex:
# Input: x = input integer (int)
# Return: x = 2's complemented hexadecimal (string)
def neg_int_to_hex(x):
    x = bin(x & 0xffffffff)[2:]
    x = hex(int(x,2))[2:].zfill(8)
    x = "0x" + x

    return x

# int_to_hex: convert an decimal (int) to hex (string)
# Input: x = input integer (int)
# Return: hex (string)
def int_to_hex(x):
    if (x < 0):
        x = neg_int_to_hex(x)
    else:
        x = "0x" + str(hex(x))[2:].zfill(8)

    return x

# processR: process R-type instructions from machine code (string) to hex (string)
# Input: b = 32 bit binary instruction
# Return: MIPS equivalent instruction in hex (string)
def processR(b):
    b_op = b[0:6]
    b_rs = b[6:11]
    b_rt = b[11:16]
    b_rd = b[16:21]
    b_sa = b[21:26]
    b_fn = b[26:32]

    asm = ""

    if (b_fn == '100000'):      # ADD
        rs = int((b_rs), base=2)
        rt = int((b_rt), base=2)
        rd = int((b_rd), base=2)

        rs = "$" + str(rs)
        rt = "$" + str(rt)
        rd = "$" + str(rd)

        asm = "add " + rd + ", " + rs + ", " + rt

    elif (b_fn == '100010'):    # SUB
        rs = int((b_rs), base=2)
        rt = int((b_rt), base=2)
        rd = int((b_rd), base=2)

        rs = "$" + str(rs)
        rt = "$" + str(rt)
        rd = "$" + str(rd)

        asm = "sub " + rd + ", " + rs + ", " + rt

    elif (b_fn == '101010'):    # SLT
        rs = int((b_rs), base=2)
        rt = int((b_rt), base=2)
        rd = int((b_rd), base=2)

        rs = "$" + str(rs)
        rt = "$" + str(rt)
        rd = "$" + str(rd)

        asm = "slt " + rd + ", " + rs + ", " + rt

    elif (b_fn == '000000'):    # SLL
        rt = int((b_rt), base=2)
        rd = int((b_rd), base=2)
        sa = int((b_sa), base=2)

        rt = "$" + str(rt)
        rd = "$" + str(rd)
        sa = str(sa)

        asm = "sll " + rd + ", " + rt + ", " + sa

    elif (b_fn == '100110'):    # XOR
        rs = int((b_rs), base=2)
        rt = int((b_rt), base=2)
        rd = int((b_rd), base=2)

        rs = "$" + str(rs)
        rt = "$" + str(rt)
        rd = "$" + str(rd)

        asm = "xor " + rd + ", " + rs + ", " + rt

    elif (b_fn == '000010'):    # SRL
        rt = int((b_rt), base=2)
        rd = int((b_rd), base=2)
        sa = int((b_sa), base=2)

        rt = "$" + str(rt)
        rd = "$" + str(rd)
        sa = str(sa)

        asm = "srl " + rd + ", " + rt + ", " + sa

    elif (b_fn == '000110'):    # SRLV
        rs = int((b_rs), base=2)
        rt = int((b_rt), base=2)
        rd = int((b_rd), base=2)

        rs = "$" + str(rs)
        rt = "$" + str(rt)
        rd = "$" + str(rd)

        asm = "srlv " + rd + ", " + rt + ", " + rs

    elif (b_fn == '100001'):    # ADDU
        rs = int((b_rs), base=2)
        rt = int((b_rt), base=2)
        rd = int((b_rd), base=2)

        rs = "$" + str(rs)
        rt = "$" + str(rt)
        rd = "$" + str(rd)

        asm = "srlv " + rd + ", " + rs + ", " + rt

    elif (b_fn == '010000'):    # MFHI
        rd = int((b_rd), base=2)
        rd = "$" + str(rd)

        asm = "mfhi " + rd

    elif(b_fn == '010010'):     # MFLO
        rd = int((b_rd), base=2)
        rd = "$" + str(rd)

        asm = "mflo " + rd

    else:
        print (f'NO idea about op = {b_fn}')
    return asm

# processI: process I-type instructions from machine code (string) to hex (string)
# Input: b = 32 bit binary instruction
# Return: MIPS equivalent instruction in hex (string)
def processI(b):
    b_op = b[0:6]
    b_rs = b[6:11]
    b_rt = b[11:16]
    b_imm = b[16:]

    asm = ""

    if(b_op == '001000'):       # ADDI
        rs = int(b_rs, base=2)
        rt = int(b_rt, base=2)
        imm = bin_to_dec(b_imm)

        rs = "$" + str(rs)
        rt = "$" + str(rt)
        imm = str(imm)

        asm = "addi "+ rt + ", " + rs + ", " + imm

    elif (b_op == '001100'):    # ANDI
        rs = int(b_rs, base=2)
        rt = int(b_rt, base=2)
        imm = zero_extend(b_imm)

        rs = "$" + str(rs)
        rt = "$" + str(rt)
        imm = str(imm)

        asm = "andi "+ rt + ", " + rs + ", " + imm

    elif (b_op == '100011'):    # LW
        rs = int(b_rs, base=2)
        rt = int(b_rt, base=2)
        imm = bin_to_dec(b_imm)

        rs = "$" + str(rs)
        rt = "$" + str(rt)
        imm = str(imm)

        asm = "lw "+ rt + ", " + imm + "(" + rs + ")"

    elif (b_op == '101011'):    # SW
        rs = int(b_rs, base=2)
        rt = int(b_rt, base=2)
        imm = bin_to_dec(b_imm)

        rs = "$" + str(rs)
        rt = "$" + str(rt)
        imm = str(imm)

        asm = "sw "+ rt + ", " + imm + "(" + rs + ")"

    elif (b_op == '000100'):    # BEQ
        rs = int(b_rs, base=2)
        rt = int(b_rt, base=2)
        imm = bin_to_dec(b_imm)

        rs = "$" + str(rs)
        rt = "$" + str(rt)
        imm = str(imm)

        asm = "beq "+ rs + ", " + rt + ", " + imm

    elif (b_op == '000101'):    # BNE
        rs = int(b_rs, base=2)
        rt = int(b_rt, base=2)
        imm = bin_to_dec(b_imm)

        rs = "$" + str(rs)
        rt = "$" + str(rt)
        imm = str(imm)

        asm = "bne "+ rs + ", " + rt + ", " + imm

    elif (b_op == '001101'):    # ORI
        rs = int(b_rs, base=2)
        rt = int(b_rt, base=2)
        imm = zero_extend(b_imm)

        rs = "$" + str(rs)
        rt = "$" + str(rt)
        imm = str(imm)

        asm = "ori "+ rt + ", " + rs + ", " + imm

    elif (b_op == '001110'):    # XORI
        rs = int(b_rs, base=2)
        rt = int(b_rt, base=2)
        imm = zero_extend(b_imm)

        rs = "$" + str(rs)
        rt = "$" + str(rt)
        imm = str(imm)

        asm = "xori "+ rt + ", " + rs + ", " + imm

    elif (b_op == '001111'):    # LUI
        rt = int(b_rt, base=2)
        imm = bin_to_dec(b_imm)

        rt = "$" + str(rt)
        imm = str(imm)

        asm = "lui "+ rt + ", " + imm

    elif (b_op == '111111'):    # FW [Special Instruction]
        rs = int(b_rs, base=2)
        rt = int(b_rt, base=2)

        rs = "$" + str(rs)
        rt = "$" + str(rt)

        asm = "fw "+ rt + ", " + rs

    else:
        print (f'NO idea about op = {b_op}')
    return asm

# processJ: process J-type instructions from machine code (string) to hex (string)
# Input: b = 32 bit binary instruction
# Return: MIPS equivalent instruction in hex (string)
def processJ(b):
    b_op = b[0:6]
    b_imm = b[6:]

    asm = ""

    imm = bin_to_dec(b_imm)
    imm = str(imm)
    asm = "j " + imm

    return asm

# processMUL: process MUL instruction from machine code (string) to hex (string) [treated differently than MULT / NOT R, I, J Type]
# Input: b = 32 bit binary instruction
# Return: MIPS equivalent instruction in hex (string)
def processMUL(b):
    b_rs = b[6:11]
    b_rt = b[11:16]
    b_rd = b[16:21]
    b_sa = b[21:26]
    b_fn = b[26:32]

    asm = ""

    rs = int((b_rs), base=2)
    rt = int((b_rt), base=2)
    rd = int((b_rd), base=2)
    rs = "$" + str(rs)
    rt = "$" + str(rt)
    rd = "$" + str(rd)

    asm = "mul " + rd + ", " + rs + ", " + rt

    return asm

# process: determine whether the process provided by machine code (string) is MUL, R, I, or J type.
# Input: b = 32 bit binary instruction
# Return: MIPS equivalent instruction in hex (string) after determining instruction type
def process(b):
    b_op = b[0:6]
    b_fn = b[26:32]

    if (b_op == '011100' and b_fn == '000010'):  # MUL (special case due to MARS simulator, non-psuedo)
        return processMUL(b)
    elif (b_op == '000000'):        # R-type
        return processR(b)
    elif (b_op == '000010'):        # J-type
        return processJ(b)
    else:                           # I-type
        return processI(b)

# disassemble: disassembles 32 bit instructions from input .txt file and appends spliced instruction to a list
# Input: input_file = input .txt file (of 32-bit machine code) | asm_instr = output .txt file (hex equivalent of machine code)
# Return: list (instr) of all instructions from .txt file
def disassemble(input_file, asm_instr):
    instr = []    # create empty list of user inputs

    ''' reasons for list:
            1. able to append at the end of list to KEEP ORDER
            2. mutable (change elements in list if necessary)
            3. creating a list data structure using string methods (replace, split)
    '''

    line_count = 0

    # convert 32 bit machine code from input and write to output file
    for line in input_file:
        line_count += 1
        bin_str = hex_to_bin(line)
        asmline = process(bin_str)
        output_file.write(asmline + '\n')

        # splice asmline using string methods and append spliced instruction to list
        asm_instr.append(asmline)                   # save asmline into asm_instr
        asmline = asmline.replace("j", "j,")        # remove j and replace w/ "j,"
        asmline = asmline.replace(", $", ",")       # remove middle $ and replace w/ ","
        asmline = asmline.replace(" $", ",")        # remove first $ and replace w/ ","
        asmline = asmline.replace(")", ",")         # remove ")" and replace w/ ","
        asmline = asmline.replace(" ", "")          # remove extra spacing
        asmline = asmline.replace("($", ",")        # remove "($" and replace w/ ","
        asmline = asmline.split(",")                # split by "," and generate a list
        instr.append(asmline)                       # append to another list which results in a list-list data structure

    output_file.write("\n") # newline in output file to show finished
    input_file.close()      # close input file since we no longer need it

    return instr          # return list of listed spliced instructions (list-list) to main

# itosbin: convert decimal/integer (int) to binary (string)
# Input: i = decimal/integer (int) | n = amount of bits input (int)
# Return: (signed) binary string
def itosbin(i, n):
    s = ""
    if i >= 0:
        s = bin(i)[2:].zfill(n)
    else:
        s = bin(0-i)[2:].zfill(n)
        s = twoscomp(s)

    return s

# and32: perform logic AND on two 32 bit binary (strings)
# Input: x, y = 32-bit binary (strings)
# Return: ANDed binary string
def and32(x, y):
    s = ""
    for i in range(32):
        if (x[i] == '1') and (y[i] == '1'):
            s += '1'
        else:
            s += '0'

    return s

# or32: perform logic OR on two 32 bit binary (strings)
# Input: x, y = 32-bit binary (strings)
# Return: ORed binary string
def or32(x, y):
    s = ""
    for i in range(32):
        if (x[i] == '1') or (y[i] == '1'):
            s += '1'
        else:
            s += '0'

    return s

# xor32: perform logic XOR on two 32 bit binary (strings)
# Input: x, y = 32-bit binary (strings)
# Return: XORed binary string
def xor32(x, y):
    s = ""
    for i in range(32):
        if x[i] == y[i]:
            s += '0'
        else:
            s += '1'

    return s

# lui32: load upper immediate
# x = integer (string) | return = lui of x (int)

# lui32: load upper immediate of
# Input: x = decimal (string)
# Return: decimal (int)
def lui32(x):
    x = int(x) << 16
    x = itosbin(x, 32)
    x = bin_to_dec(x)
    return x

# j_pc_count: perform PC calculation for j jump instruction
# Input: pc = current value of PC before jump | addr = address from j-type 32 bit instruction
# Return: new value of PC (int)
def j_pc_count(pc, addr):
    # Eqn: pc = (pc & 0xf0000000) | (addr << 2)

    a = itosbin(pc, 32)
    b = '11110000000000000000000000000000'  # 0xf0000000
    c = and32(a,b)

    d = itosbin(addr << 2, 32)

    z = or32(c, d)

    z = bin_to_dec(z)

    return z

# accessDM: hash function for accessing data memory [O(1) access]
# Input: s = hex or integer/decimal (string)
# Return: data memory location of the data memory array
def accessDM(s):
    if (s[2:] == "0x"):
        s = int(s, base=16)
    else:
        s = int(s)

    s = int((s - 0x2000) / 4)

    return s

# outputRegisters: output all 32 registers + pc, hi, lo
# Input: reg = array holding register data | pc, hi, lo = special registers
# Return: outputted registers via console & output file
def outputRegisters(reg, pc, hi, lo, hexValue):
    pReg = "Register"
    pVal = "Value"
    print(f"{pReg:<15}{pVal:^12}")

    # output header output file
    row_item = [pReg, pVal]
    output = '{:<15}{:^12}'.format(row_item[0], row_item[1])
    output_file.write(output + "\n")

    # output 32 registers from reg array
    for i in range(len(reg)):
        pReg = "$" + str(i)
        if (hexValue == 0):
            pVal = str(reg[i])
        else:
            pVal = int_to_hex(reg[i])
        print(f"{pReg:<15}{pVal:>12}")

        # output to txt file
        row_item = [pReg, pVal]
        output = '{:<15}{:>12}'.format(row_item[0], row_item[1])
        output_file.write(output + "\n")

    # output special registers
    pReg = "pc"
    if (hexValue == 0):
        pVal = str(pc)
    else:
        pVal = int_to_hex(pc)

    print(f"{pReg:<15}{pVal:>12}")

    row_item = [pReg, pVal] # output to txt file
    output = '{:<15}{:>12}'.format(row_item[0], row_item[1])
    output_file.write(output + "\n")

    pReg = "hi"
    if (hexValue == 0):
        pVal = str(hi)
    else:
        pVal = int_to_hex(hi)
    print(f"{pReg:<15}{pVal:>12}")

    row_item = [pReg, pVal] # output to txt file
    output = '{:<15}{:>12}'.format(row_item[0], row_item[1])
    output_file.write(output + "\n")

    pReg = "lo"
    if (hexValue == 0):
        pVal = str(lo)
    else:
        pVal = int_to_hex(lo)
    print(f"{pReg:<15}{pVal:>12}")

    row_item = [pReg, pVal] # output to txt file
    output = '{:<15}{:>12}'.format(row_item[0], row_item[1])
    output_file.write(output + "\n" + "\n")

    print("\n")

# outputDataMem: output data memory array in similar format as MARS
# Input: mem = data memory array | hex_start = starting memory address | hex_end = ending memory address
#        address = user selected hex or decimal address output |  value = user selected hex or decimal value output
# Output: outputted data memory array in console and output file
def outputDataMem(mem, hex_start, hex_end, address, value):
    addr = v1 = v2 = v3 = v4 = v5 = v6 = v7 = v8 = ""

    # headers
    if (address == 0):      # [decimal address]
        addr = "Address"
        v1 = "Value (+0)"
        v2 = "Value (+4)"
        v3 = "Value (+8)"
        v4 = "Value (+12)"
        v5 = "Value (+16)"
        v6 = "Value (+20)"
        v7 = "Value (+24)"
        v8 = "Value (+28)"

        # output header to output .txt file [decimal]
        row_item = [addr, v1, v2, v3, v4, v5, v6, v7, v8]
        output = '|{:>10}|{:>15}|{:>15}|{:>15}|{:>15}|{:>15}|{:>15}|{:>15}|{:>15}|'.format(row_item[0], row_item[1], row_item[2], row_item[3], row_item[4], row_item[5], row_item[6], row_item[7], row_item[8])
        output_file.write(output + "\n")

    else:                   # [hexadecimal address]
        addr = "Address"
        v1 = "Value (+0)"
        v2 = "Value (+4)"
        v3 = "Value (+8)"
        v4 = "Value (+c)"
        v5 = "Value (+10)"
        v6 = "Value (+14)"
        v7 = "Value (+18)"
        v8 = "Value (+1c)"

        # output header to output .txt file [hex]
        row_item = [addr, v1, v2, v3, v4, v5, v6, v7, v8]
        output = '|{:^10}|{:>15}|{:>15}|{:>15}|{:>15}|{:>15}|{:>15}|{:>15}|{:>15}|'.format(row_item[0], row_item[1], row_item[2], row_item[3], row_item[4], row_item[5], row_item[6], row_item[7], row_item[8])
        output_file.write(output + "\n")

    print(f"|{addr:>15}|{v1:>15}|{v2:>15}|{v3:>15}|{v4:>15}|{v5:>15}|{v6:>15}|{v7:>15}|{v8:>15}|")

    j = 0

    if (value == 0):        # data memory [decimal values]
        for i in range(hex_start, hex_end, 4):
            if (j % 8 == 0):
                if (address == 1):
                    addr = "0x" + str(hex(j*4 + 0x2000))[2:].zfill(8)
                else:
                    addr = str(j*4 + 0x2000)

                if j < len(mem):
                    v1 = str(mem[j])
                else:
                    v1 = 0

                if j+1 < len(mem):
                    v2 = str(mem[j+1])
                else:
                    v2 = 0

                if j+2 < len(mem):
                    v3 = str(mem[j+2])
                else:
                    v3 = 0

                if j+3 < len(mem):
                    v4 = str(mem[j+3])
                else:
                    v4 = 0

                if j+4 < len(mem):
                    v5 = str(mem[j+4])
                else:
                    v5 = 0

                if j+5 < len(mem):
                    v6 = str(mem[j+5])
                else:
                    v6 = 0

                if j+6 < len(mem):
                    v7 = str(mem[j+6])
                else:
                    v7 = 0

                if j+7 < len(mem):
                    v8 = str(mem[j+7])
                else:
                    v8 = 0

                print(f"|{addr:>15}|{v1:>15}|{v2:>15}|{v3:>15}|{v4:>15}|{v5:>15}|{v6:>15}|{v7:>15}|{v8:>15}|")
                row_item = [addr, v1, v2, v3, v4, v5, v6, v7, v8]
                output = '|{:>10}|{:>15}|{:>15}|{:>15}|{:>15}|{:>15}|{:>15}|{:>15}|{:>15}|'.format(row_item[0], row_item[1], row_item[2], row_item[3], row_item[4], row_item[5], row_item[6], row_item[7], row_item[8])
                output_file.write(output + "\n")

            j += 1

    else:        # data memory [hexadecimal values]
        for i in range(hex_start, hex_end, 4):
            if (j % 8 == 0):
                if (address == 1):
                    addr = "0x" + str(hex(j*4 + 0x2000))[2:].zfill(8)
                else:
                    addr = str(j*4 + 0x2000)

                if j < len(mem):
                    if (mem[j] < 0):
                        v1 = neg_int_to_hex(mem[j])
                    else:
                        v1 = "0x" + str(hex(mem[j]))[2:].zfill(8)
                else:
                    v1 = "0x" + "".zfill(8)

                if j+1 < len(mem):
                    if (mem[j+1] < 0):
                        v2 = neg_int_to_hex(mem[j+1])
                    else:
                        v2 = "0x" + str(hex(mem[j+1]))[2:].zfill(8)
                else:
                    v2 = "0x" + "".zfill(8)

                if j+2 < len(mem):
                    if (mem[j+2] < 0):
                        v3 = neg_int_to_hex(mem[j+2])
                    else:
                        v3 = "0x" + str(hex(mem[j+2]))[2:].zfill(8)
                else:
                    v3 = "0x" + "".zfill(8)

                if j+3 < len(mem):
                    if (mem[j+3] < 0):
                        v4 = neg_int_to_hex(mem[j+3])
                    else:
                        v4 = "0x" + str(hex(mem[j+3]))[2:].zfill(8)
                else:
                    v4 = "0x" + "".zfill(8)

                if j+4 < len(mem):
                    if (mem[j+4] < 0):
                        v5 = neg_int_to_hex(mem[j+4])
                    else:
                        v5 = "0x" + str(hex(mem[j+4]))[2:].zfill(8)
                else:
                    v5 = "0x" + "".zfill(8)

                if j+5 < len(mem):
                    if (mem[j+5] < 0):
                        v6 = neg_int_to_hex(mem[j+5])
                    else:
                        v6 = "0x" + str(hex(mem[j+5]))[2:].zfill(8)
                else:
                    v6 = "0x" + "".zfill(8)

                if j+6 < len(mem):
                    if (mem[j+6] < 0):
                        v7 = neg_int_to_hex(mem[j+6])
                    else:
                        v7 = "0x" + str(hex(mem[j+6]))[2:].zfill(8)
                else:
                    v7 = "0x" + "".zfill(8)

                if j+7 < len(mem):
                    if (mem[j+7] < 0):
                        v8 = neg_int_to_hex(mem[j+7])
                    else:
                        v8 = "0x" + str(hex(mem[j+7]))[2:].zfill(8)
                else:
                    v8 = "0x" + "".zfill(8)

                print(f"|{addr:>15}|{v1:>15}|{v2:>15}|{v3:>15}|{v4:>15}|{v5:>15}|{v6:>15}|{v7:>15}|{v8:>15}|")
                row_item = [addr, v1, v2, v3, v4, v5, v6, v7, v8]
                output = '|{:<10}|{:>15}|{:>15}|{:>15}|{:>15}|{:>15}|{:>15}|{:>15}|{:>15}|'.format(row_item[0], row_item[1], row_item[2], row_item[3], row_item[4], row_item[5], row_item[6], row_item[7], row_item[8])
                output_file.write(output + "\n")

            j += 1
    print("\n")

# outputInstrStats: output instruction statistics (ALU, Jump, branch, memory, other)
# Input: total, alu, jump, branch, memory, other = current values that are held for each count variable
# Return: output instruction statistics on console and output .txt file
def outputInstrStats(total, alu, jump, branch, memory, other):
    print("Instruction Statistics, Version 1.0")
    output_file.write("\n\nInstruction Statistics, Version 1.0" + "\n")

    print(f"Total:\t{total}\n")
    output_file.write(f"Total:\t{total}\n\n")

    titles = ["ALU:", "Jump:", "Branch:", "Memory:", "Other:"]
    values = [alu, jump, branch, memory, other]
    percentages = [(alu/total)*100, (jump/total)*100, (branch/total)*100, (memory/total)*100, (other/total)*100]
    i = 0
    while i < len(titles):
        print(f"{titles[i]:<8}{values[i]:<8}{percentages[i]:.0f}%")
        output_file.write(f"{titles[i]:<8}{values[i]:<8}{percentages[i]:.0f}%" + "\n")

        i += 1

# findWidth: special instruction used to find the width of a 32-bit binary code
# Input: s = decimal (string)
# Return: width of the specific decimal translated in 32-bit binary
def findWidth(s):               # take in decimal string
    b = int(s)                  # convert string decimal to int decimal
    b = itosbin(b, 32)          # convert integer to binary
    return len(b.strip("0"))    # strip surrounding zeros from 1...1 & return length of remaining bits

# mul: multiplication instruction (non R, J, I type) but special non-psuedo instruction
# Input: x, y = decimal values (int)
# Output: decimal pair (int, int) (hi 32bit, lo 32bit)
def mul(x, y):
    product = x * y
    z = itosbin(product, 64)
    mhi, mlo = z[:len(z)//2], z[len(z)//2:]

    return bin_to_dec(mhi), bin_to_dec(mlo)

# srl: bit shift right by n amounts
# Input: b = binary (string) | n = amount of shifts (integer)
# Output: bit shifted decimal (integer)
def srl(b, n):
    r = 32 - n
    b = b[0:r].zfill(32)

    return bin_to_dec(b)

# sll: bit shift left by n amounts
# Input: b = binary (string) | n = amount of shifts (integer)
# Output: bit shifted decimal (integer)
def sll(b, n):
    b = b[n:32].ljust(32, '0')

    return bin_to_dec(b)

# Main ------------------------------------------------------------------------------------------

print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Project 2 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n")

input_file = input("Enter input file> ")                # ask for user input file

file_exists = 0                                         # temp variable to keep track of file exist state

# check if input file exists
while (file_exists != 1):
    if Path.isfile(input_file): # file exists
        print("File sucessfully loaded")
        input_file = open(input_file, "r")              # open input file in read mode (r)
        file_exists = 1                                 # file exists so set true
    else: # file does not exist, so ask for valid file
        print("File does not exist")
        file_exists = 0                                 # file does not exists so set false
        input_file = input("Enter input file> ")

output_file = input("Enter desired output file> ")      # ask for user output file name
output_file = open(output_file,"w")                     # create and open output file in write mode (w)

choice1 = choice2 = hexAddress = hexValue = 0

print("\nWhat data representation would you like?")
while (choice1 == 0 and choice2 == 0):
    x = input("Hexadecimal Address? (y = yes, n = no)> ")
    while (choice1 == 0) and (x != 'y' or x != 'n'):
        if (x == 'y'):
            hexAddress = 1
            choice1 = 1
        elif (x == 'n'):
            choice1 = 1
            break
        else:
            x = input("Hexadecimal Address? (y = yes, n = no)> ")
            continue

    y = input("Hexadecimal Values? (y = yes, n = no)> ")
    while (choice2 == 0) and (x != 'y' or x != 'n'):
        if (y == 'y'):
            hexValue = 1
            choice2 = 1
        elif (y == 'n'):
            choice2 = 1
            break
        else:
            y = input("Hexadecimal Value? (y = yes, n = no)> ")
            continue

print("\n")
# hardcoded for testing purposes
# input_file = open("test_files/project1_edit.txt", "r")
# output_file = open("test_files/asm.txt", "w")

asm_instr = []                                          # save default asm instruction

instr = disassemble(input_file, asm_instr)              # disassemble machine code from input file to readable MIPS
                                                        # place results into a list data structure; holds line number [starting at 0 for 1]

# registers
reg = [0] * 32              # create register from $0 to $31 (w/ pc, lo, hi)
pc = hi = lo = line = 0     # line = current instruction line number

# data memory
mem = [0] * 1024             # (0x3000 - 0x2000) / 4 = 1024 memory cells

# instruction statistics
total = alu = jump = branch = memory = other = 0

# output header
pLine = "line"
pInstr = "Instruction"
pResult = "Result"
pPC = "PC"

print(f"{pLine:<15}{pInstr:<35}{pResult:<25}{pPC:<15}")

# output header to output .txt file
row_item = [pLine, pInstr, pResult, pPC]
output = '{:<8}{:<24}{:<26}{:<8}'.format(row_item[0], row_item[1], row_item[2], row_item[3])

output_file.write(output + "\n")

# analyze instructions
while (int(pc/4) < len(instr)):     # int(pc/4) = current instruction
    cur = instr[int(pc/4)]          # give access to instr[] list-list
                                    # first list: separated machine code instructions (access to opcode, rs, rt, rd, sa, func, imm)
                                    # second list: holds the first list within itself and replicates "line numbers"

    line += 1                       # update for next instruction in instr list

    # instructions

    # branch instructions
    if (cur[0] == "j" or cur[0] == "beq" or cur[0] == "bne"):

        if (cur[0] == 'j'):         # J
            pInstr = asm_instr[int(pc/4)]
            pc = j_pc_count(pc, int(cur[1]))
            jump += 1

        elif (cur[0] == "beq"):     # BEQ
            if (reg[int(cur[1])] == reg[int(cur[2])]):
                pInstr = asm_instr[int(pc/4)]
                pc += 4 + (int(cur[3]) << 2)
            else:
                pInstr = asm_instr[int(pc/4)]
                pc += 4

            branch += 1

        else:                       # BNE
            if (reg[int(cur[1])] != reg[int(cur[2])]):
                pInstr = asm_instr[int(pc/4)]
                pc += 4 + (int(cur[3]) << 2)
            else:
                pInstr = asm_instr[int(pc/4)]
                pc += 4

            branch += 1

        # update result
        if (cur[0] == "beq" or cur[0] == "bne"):
            pResult = "branch to PC: " + str(pc)
        else:
            pResult = "jump to PC " + str(pc)

    # must be sw/lw
    elif (cur[0] == "sw" or cur[0] == "lw"):
        if (cur[0] == "sw"):    # SW
            mem[accessDM(str(int(cur[2]) + reg[int(cur[3])]))] = reg[int(cur[1])]
            pResult = "DM[" + str(int(cur[2]) + reg[int(cur[3])]) + "]" + " = " + str(reg[int(cur[1])])

        else:                   # LW
            reg[int(cur[1])] = mem[accessDM(str(int(cur[2]) + reg[int(cur[3])]))]
            # update results

            pResult = "$" + cur[1] + " = " + str(reg[int(cur[1])])

        pc += 4
        pInstr = asm_instr[int(pc/4) - 1]

        memory += 1

    else:   # must not lw/sw or branch instruction
        if (cur[0] == "addi"):      # ADDI
            reg[int(cur[1])] = reg[int(cur[2])] + int(cur[3])

        elif (cur[0] == "add"):     # ADD
            reg[int(cur[1])] = reg[int(cur[2])] + reg[int(cur[3])]

        elif (cur[0] == "sub"):     # SUB
            reg[int(cur[1])] = reg[int(cur[2])] - reg[int(cur[3])]

        elif (cur[0] == "slt"):     # SLT
            if (reg[int(cur[2])] < reg[int(cur[3])]):  # if x < y
                reg[int(cur[1])] = 1    # x = 1
            else: # x > y
                reg[int(cur[1])] = 0    # x = 0

        elif (cur[0] == "sll"):     # SLL
            reg[int(cur[1])] = sll(itosbin(reg[int(cur[2])], 32), int(cur[3]))

        elif (cur[0] == "xor"):     # XOR
            reg[int(cur[1])] = reg[int(cur[2])] ^ reg[int(cur[3])]

        elif (cur[0] == "srl"):     # SRL
            reg[int(cur[1])] = srl(itosbin(reg[int(cur[2])], 32), int(cur[3]))

        elif (cur[0] == "srlv"):    # SRLV
            reg[int(cur[1])] = srl(itosbin(reg[int(cur[2])], 32), reg[int(cur[3])])

        elif (cur[0] == "andi"):    # ANDI
            reg[int(cur[1])] = bin_to_dec(and32(itosbin(reg[int(cur[2])], 32), itosbin(int(cur[3]), 32)))

        elif (cur[0] == "ori"):     # ORI
            reg[int(cur[1])] = bin_to_dec(or32(itosbin(reg[int(cur[2])], 32), itosbin(int(cur[3]), 32)))

        elif (cur[0] == "xori"):    # XORI
            reg[int(cur[1])] = bin_to_dec(xor32(itosbin(reg[int(cur[2])], 32), itosbin(int(cur[3]), 32)))

        elif (cur[0] == "lui"):     # LUI
            reg[int(cur[1])] = lui32(cur[2])

        elif (cur[0] == "mfhi"):    # MFHI
            reg[int(cur[1])] = hi

        elif (cur[0] == "mflo"):    # MFLO
            reg[int(cur[1])] = lo

        elif (cur[0] == "mul"):     # MUL
            if pInstr.find("$" + cur[3]):
                hi_lo = mul(reg[int(cur[2])], reg[int(cur[3])])    # mul $x, $y
            else:
                hi_lo = mul(reg[int(cur[2])], int(cur[3]))         # mul $x, y

            hi = hi_lo[0]
            lo = hi_lo[1]
            reg[int(cur[1])] = lo

        elif (cur[0] == "fw"):      # FW [Special Instruction]
            reg[int(cur[1])] = findWidth(reg[int(cur[2])])

        else:
            print("Instruction not implemented")

        # set $0 as absolute zero
        if (cur[1] == '0'):
            reg[int(cur[1])] = 0

        # update outputs
        pc += 4

        if (cur[0] == 'slt' or cur[0] == 'mul'):
            other += 1
        else:
            alu += 1

        pResult = "$" + cur[1] + " = " + str(reg[int(cur[1])])
        pInstr = asm_instr[int(pc/4) - 1]

    # update print outputs
    pLine = line
    pPC = pc

    # print outputs

    print(f"{pLine:<15}{pInstr:<35}{pResult:<25}{pPC:<15}")

    # output to output .txt file
    row_item = [pLine, pInstr, pResult, pPC]
    output = '{:<8}{:<24}{:<26}{:<8}'.format(row_item[0], row_item[1], row_item[2], row_item[3])

    output_file.write(output + "\n")

print("\n")
output_file.write("\n")

# output registers
outputRegisters(reg, pc, hi, lo, hexValue)

# output Data Memory
outputDataMem(mem, 0x2000, 0x3004, hexAddress, hexValue)

# output instruction statistics
total = alu + jump + branch + memory + other
outputInstrStats(total, alu, jump, branch, memory, other)

output_file.close()

print("\nProgram Sucessfully Finished")     # print when program finishes


from model import NeRF
import torch
from vis import render_path_circle, vis_res

# render new view in the circle
model = NeRF.load_from_checkpoint('lightning_logs/version_34_10/checkpoints/epoch=401-step=401.ckpt')
model.eval()
model.cuda()
with torch.no_grad():
    x, y, res = render_path_circle(model)
res = res.cpu()
vis_res(x, y, res)


#!/usr/bin/python
#python 2.7
import sys

"""
This is a simple mapper that will ouput the store and the cost
of a sale. then this data will be output and sorted and finally
pass ove the reducer that will calculate the sales per store.
"""
for line in sys.stdin:
    data = line.strip().split("\t")
    if len(data) == 6:
        data, time, store, item, cost, payment = data
        print("{0}\t{1}".format(store, cost) )


#!/usr/bin/env python
import gym
import itertools
import matplotlib
matplotlib.use('Agg')
import numpy as np
import pandas as pd
import sys
import matplotlib.pyplot as plt

if "../" not in sys.path:
    sys.path.append("../")

from collections import defaultdict
from lib.envs.windy_gridworld import WindyGridworldEnv
from lib import plots

matplotlib.style.use('ggplot')

env = WindyGridworldEnv()

def create_epsilon_greedy_policy(Q, epsilon, nA):
    """
    Creates an epsilon-greedy policy based on a given Q-function and epsilon.

    Args:
        Q: A dictionary that maps from state -> action-values.
            Each value is a numpy array of length nA (see below)
        epsilon: The probability to select a random action . float between 0 and 1.
        nA: Number of actions in the environment.

    Returns:
        A function that takes the observation as an argument and returns
        the probabilities for each action in the form of a numpy array of length nA.

    """
    def policy_fn(observation):
        A = np.ones(nA) * (epsilon/nA)
        best_action = np.argmax(Q[observation])
        A[best_action] += (1.0 - epsilon)
        return A
    return policy_fn

def n_step_sarsa(env, num_episodes, n=5, discount_factor=1.0, alpha=0.5, epsilon=0.1):
    """
    (n step)SARSA algorithm: On-policy TD control. Finds the optimal epsilon-greedy policy.
    The algorithm looks forward n steps and then bootstraps from there to update the Q values.

    Args:
        env: OpenAI environment.
        num_episodes: Number of episodes to run for.
        n: future time steps to look ahead and calculate return for.
        discount_factor: Gamma discount factor.
        alpha: TD learning rate.
        epsilon: Chance the sample a random action. Float betwen 0 and 1.

    Returns:
        A tuple (Q, stats).
        Q is the optimal action-value function, a dictionary mapping state -> action values.
        stats is an EpisodeStats object with two numpy arrays for episode_lengths and episode_rewards.
    NOTE: some parts taken from https://github.com/Breakend/MultiStepBootstrappingInRL/blob/master/n_step_sarsa.py
    """

    # The final action-value function.
    # A nested dictionary that maps state -> (action -> action-value).
    Q = defaultdict(lambda: np.zeros(env.action_space.n))

    # Keeps track of useful statistics
    stats = plots.EpisodeStats(
        episode_lengths=np.zeros(num_episodes),
        episode_rewards=np.zeros(num_episodes))

    # The policy we're following
    policy = create_epsilon_greedy_policy(Q, epsilon, env.action_space.n)

    for i_episode in range(num_episodes):
        # Print out which episode we're on, useful for debugging.
        if (i_episode + 1) % 10 == 0:
            print("\rEpisode {}/{}.".format(i_episode + 1, num_episodes), end="")
            sys.stdout.flush()

        # initializations
        T = sys.maxsize
        tau = 0
        t = -1
        stored_actions = {}
        stored_rewards = {}
        stored_states = {}

        # initialize first state
        state = env.reset()
        action_probs = policy(state)
        action = np.random.choice(env.action_space.n, p=action_probs)

        stored_actions[0] = action
        stored_states[0] = state

        while tau < (T - 1):
            t += 1
            if t < T:
                state, reward, done, _ = env.step(action)

                stored_rewards[(t+1) % (n+1)] = reward
                stored_states[(t+1) % (n+1)] = state

                # Update statistics
                stats.episode_rewards[i_episode] += reward
                stats.episode_lengths[i_episode] = t

                if done:
                    T = t + 1
                else:
                    next_action_probs = policy(state)
                    action = np.random.choice(env.action_space.n, p=next_action_probs)
                    stored_actions[(t+1) % (n+1)] = action
            tau = t - n + 1

            if tau >= 0:
                # calculate G(tau:tau+n)
                G = np.sum([discount_factor**(i-tau-1)*stored_rewards[i%(n+1)] for i in range(tau+1, min(tau+n, T)+1)])

                if tau + n < T:
                    G += discount_factor**n * Q[stored_states[(tau+n) % (n+1)]][stored_actions[(tau+n) % (n+1)]]

                tau_s, tau_a = stored_states[tau % (n+1)], stored_actions[tau % (n+1)]

                # update Q value with n step return
                Q[tau_s][tau_a] += alpha * (G - Q[tau_s][tau_a])

    return Q, stats

if __name__=='__main__':
    Q, stats = n_step_sarsa(env, num_episodes=300, n=10)
    plots.plot_episode_stats(stats, file='results/n_step_sarsa/')


import argparse
import os
import ROOT
from pdb import set_trace

def main(args):
    # load everything needed
    ROOT.gROOT.ProcessLine(".x $CLAS12ROOT/RunRoot/LoadClas12Root.C")
    ROOT.gROOT.ProcessLine(".x $CHANSER/macros/Load.C")
    ROOT.gROOT.LoadMacro("Pi2.cpp+")
    ROOT.gROOT.ProcessLine(".L Run_Pi2.C")

    # iterate through the given input files
    for item in args['input']:
        _, fname = os.path.split(item)
        folder = fname.replace('.hipo', '')
        outputdir = os.path.join(args['output'], folder)
        print('Processing run: {}'.format(item))

        # check output path exists and make it otherwise
        if os.path.exists(outputdir):
            print('Skipping, path already exists: {}'.format(outputdir))
        else:
            # run the processline command
            print('Making output directory: {}'.format(outputdir))
            os.makedirs(outputdir)

            # run the processing
            ROOT.Run_Pi2(item, args['config'], outputdir)

if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description='A program to run the Chanser finalstate code on specific runs')
    parser.add_argument('-i', '--input',
                        help='Filename(s) for the input data',
                        nargs='*',
                        required=True)
    parser.add_argument('-o', '--output',
                        help='Path for output folder',
                        required=True)
    parser.add_argument('-c', '--config',
                        help='Path to finalstate config file',
                        required=True)
    args = vars(parser.parse_args())
    main(args)


from utils_libs import *
from utils_dataset import *
from utils_models import *
from general.fedgs import *
from general.utils import *

def train_FedSMOO(device, data_obj, act_prob,
                  learning_rate, batch_size, epoch, com_amount, test_per,
                  weight_decay, model_func, init_model, alpha_coef,
                  sch_step, sch_gamma, samlr, rand_seed=0, lr_decay_per_round=1, out='res/'):

    print('## use FedSMOO Method ##')

    n_client = data_obj.n_client
    client_x = data_obj.client_x; client_y=data_obj.client_y

    cent_x = np.concatenate(client_x, axis=0)
    cent_y = np.concatenate(client_y, axis=0)

    print("cent_x: ", cent_x.shape)
    print("cent_y: ", cent_y.shape)

    weight_list = np.asarray([len(client_y[i]) for i in range(n_client)])
    weight_list = weight_list / np.sum(weight_list) * n_client

    print("weight_list: ", weight_list.shape)
    print("weight_list: ", weight_list)
    print("client_x: ", client_x.shape)
    print("client_y: ", client_y.shape)

    train_all_clt_perf = np.zeros((com_amount, 2))
    test_all_clt_perf = np.zeros((com_amount, 2))

    train_cur_cld_perf = np.zeros((com_amount, 2))
    test_cur_cld_perf = np.zeros((com_amount, 2))

    x_distance_average = np.zeros((com_amount, 1)) # measures model weight distances not used in training

    n_par = len(get_mdl_params([model_func()])[0])

    print('## total {:d} parameters ##'.format(n_par))

    hist_params_diffs = np.zeros((n_client, n_par)) # .astype('float32') # lambda dual for weight
    hist_sam_diffs = np.zeros((n_client, n_par)) # .astype('float32') # s perturbation ################################### mu dual for sam
    # hist_gs_diffs = np.zeros((n_client, n_par)).astype('float32') # si

    print('-- create clients params ...')
    init_par_list=get_mdl_params([init_model], n_par)[0]
    client_params_list  = np.ones(n_client).astype('float32').reshape(-1, 1) * init_par_list.reshape(1, -1) # n_client X n_par
    client_models = list(range(n_client))
    # print('-- create global avg params ...')
    # avg_model = model_func().to(device)
    # avg_model.load_state_dict(copy.deepcopy(dict(init_model.named_parameters())))

    print('-- create global avg params ...')
    all_model = model_func().to(device) # model weights to be used for eval in a given round
    all_model.load_state_dict(copy.deepcopy(dict(init_model.named_parameters())))
    print("all_model: resnet torch model")

    print('-- create global cloud params ...')
    cur_cld_model = model_func().to(device)
    cur_cld_model.load_state_dict(copy.deepcopy(dict(init_model.named_parameters())))
    cld_mdl_param = get_mdl_params([cur_cld_model], n_par)[0]

    print('## start Federated Framework ##')

    for i in range(com_amount):
        inc_seed = 0
        while(True):
            np.random.seed(i + rand_seed + inc_seed)
            act_list    = np.random.uniform(size=n_client)
            act_clients = act_list <= act_prob
            selected_clients = np.sort(np.where(act_clients)[0])
            inc_seed += 1
            if len(selected_clients) != 0:
                break

        print('Communication Round', i + 1, flush = True)
        print('Selected Clients: %s' %(', '.join(['%2d' %item for item in selected_clients])))
        cld_mdl_param_tensor = torch.tensor(cld_mdl_param, dtype=torch.float32, device=device)

        del client_models
        client_models = list(range(n_client))

        # step 17 ---------------------------------------------------------------------
        gs_temp = np.mean(hist_sam_diffs * -1, axis=0) # s variable averaged across clients
        gs_normalized = samlr * gs_temp / (np.linalg.norm(gs_temp) + 1e-8)
        gs_diff_list = set_H_param_list(all_model, gs_normalized, device=device) # set to model params shape
        # ------------------------------------------------------------------------------

        for client in selected_clients:
            train_x = client_x[client]
            train_y = client_y[client]

            client_models[client] = model_func().to(device)

            model = client_models[client]
            # Warm start from current avg model
            model.load_state_dict(copy.deepcopy(dict(cur_cld_model.named_parameters())))

            for params in model.parameters():
                params.requires_grad = True

            # Scale down
            alpha_coef_adpt = alpha_coef / weight_list[client] # adaptive alpha coef
            hist_params_diffs_curr = torch.tensor(hist_params_diffs[client],
                                                  dtype=torch.float32, device=device) # lambda variable
            hist_sam_diffs_list = set_H_param_list(all_model,
                                                   hist_sam_diffs[client], device=device) # s variable

            client_models[client], hist_sam_diffs[client] = train_model_GS(device, model, model_func, alpha_coef_adpt,
                                                 cld_mdl_param_tensor, hist_params_diffs_curr, hist_sam_diffs_list, gs_diff_list,
                                                 train_x, train_y, learning_rate * (lr_decay_per_round ** i),
                                                 batch_size, epoch, 5, weight_decay,
                                                 data_obj.dataset, sch_step, sch_gamma, samlr, print_verbose=False)
            curr_model_par = get_mdl_params([client_models[client]], n_par)[0]

            # TODO
            # No need to scale up hist terms. They are -\nabla/alpha and alpha is already scaled.

            # step 14 - 19 ~17  ----------------------------------------------------
            hist_params_diffs[client] += curr_model_par-cld_mdl_param
            client_params_list[client] = curr_model_par

        avg_mdl_param_sel = np.mean(client_params_list[selected_clients], axis = 0)
        cld_mdl_param = avg_mdl_param_sel + np.mean(hist_params_diffs, axis = 0)
        #---------------------------------------------------------------------------
        ##################################### Training ends #################################################

        for client in selected_clients:
            x_distance_average[i] += np.linalg.norm(client_params_list[client] - cld_mdl_param)/len(selected_clients)

        # avg_model_sel = set_client_from_params(device, model_func(), avg_mdl_param_sel)
        all_model     = set_client_from_params(device, model_func(), np.mean(client_params_list, axis = 0))

        # cur_cld_model -> avg wts of selected clients
        cur_cld_model = set_client_from_params(device, model_func().to(device), cld_mdl_param)

        if (i + 1) % test_per == 0:

            loss_test, acc_test = get_acc_loss(device, cent_x, cent_y,
                                             all_model, data_obj.dataset, 0)
            print("**** Cur All Communication %3d, Cent Accuracy: %.4f, Loss: %.4f"
                  %(i+1, acc_test, loss_test), flush = True)

            train_all_clt_perf[i] = [loss_test, acc_test]

            loss_test, acc_test = get_acc_loss(device, data_obj.test_x, data_obj.test_y,
                                             all_model, data_obj.dataset, 0)
            print("**** Cur All Communication %3d, Test Accuracy: %.4f, Loss: %.4f"
                  %(i+1, acc_test, loss_test))
            test_all_clt_perf[i] = [loss_test, acc_test]

        # y = 1
        # if y:
        #     return

    return


# 이해가 어려움

x = list(input())
answer = 0
stack = []

for i in range(len(x)):
    if x[i] == '(':
        stack.append('(')

    else:
        if x[i-1] == '(': # ')'가 나오고 이전 문자가 '('
            stack.pop()
            answer += len(stack) # 현재 stack에 쌓인 '('개수(=쇠막대기 개수)만큼 개수를 더해준다.

        elif x[i-1] == ')': # ')'가 나오고 이전 문자도 ')'
            stack.pop()
            answer += 1

print(answer)

스터디_with 재홍다빈/201 - 자료구조 1 (연습)/10799_쇠막대기.py


# Given a list of numbers (hardcoded in the program), write a Python program to find the largest and
# smallest element of the list. Define two functions largest_number_<your-student-id> and
# smallest_number_<your-student-id> in your program. Do not use any built-in function.
list = [20,19,2,60,51]
def largest_number(num):
    max=num[0]
    for i in range(len(num)):
        if num[i] > max:
            max= num[i]
    print(f"largest: {max}")

def smallest_number(num):
    min= num[0]
    for i in range(len(num)):
        if num[i] < min:
             min = num[i]
    print(f"Smallest: {min}")

largest_number(list)
smallest_number(list)


# Description: Inference script for the Triplet Network
import tensorflow as tf
import numpy as np
from glob import glob
from natsort import natsorted
import os
from model import TripleNet, train_step, test_step
from utils import load_complete_data
from tqdm import tqdm
from sklearn.manifold import TSNE
import matplotlib.pyplot as plt
from matplotlib import style
import seaborn as sns
import pandas as pd
import pickle
from sklearn.cluster import KMeans
from scipy.optimize import linear_sum_assignment as linear_assignment

style.use('seaborn')

os.environ["CUDA_DEVICE_ORDER"]= "PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"]= '0'

# Thanks to: https://github.com/k-han/DTC/blob/master/utils/util.py
def cluster_acc(y_true, y_pred):
    """
    Calculate clustering accuracy. Require scikit-learn installed
    # Arguments
        y: true labels, numpy.array with shape `(n_samples,)`
        y_pred: predicted labels, numpy.array with shape `(n_samples,)`
    # Return
        accuracy, in [0,1]
    """
    y_true = y_true.astype(np.int64)
    assert y_pred.size == y_true.size
    D = max(y_pred.max(), y_true.max()) + 1
    w = np.zeros((D, D), dtype=np.int64)
    for i in range(y_pred.size):
        w[y_pred[i], y_true[i]] += 1
    ind = linear_assignment(w.max() - w)
    return sum([w[i, j] for i, j in zip(*ind)]) * 1.0 / y_pred.size

if __name__ == '__main__':

	n_channels  = 14
	n_feat      = 128
	batch_size  = 256
	test_batch_size  = 1
	n_classes   = 10

	with open('data/eeg/image/data.pkl', 'rb') as file:
		data = pickle.load(file, encoding='latin1')
		train_X = data['x_train']
		train_Y = data['y_train']
		test_X = data['x_test']
		test_Y = data['y_test']

	train_batch = load_complete_data(train_X, train_Y, batch_size=batch_size)
	val_batch   = load_complete_data(test_X, test_Y, batch_size=batch_size)
	test_batch  = load_complete_data(test_X, test_Y, batch_size=test_batch_size)

	triplenet = TripleNet(n_classes=n_classes)
	opt     = tf.keras.optimizers.Adam(learning_rate=3e-4)
	triplenet_ckpt    = tf.train.Checkpoint(step=tf.Variable(1), model=triplenet, optimizer=opt)
	triplenet_ckptman = tf.train.CheckpointManager(triplenet_ckpt, directory='experiments/best_ckpt', max_to_keep=5000)
	triplenet_ckpt.restore(triplenet_ckptman.latest_checkpoint)
	START = int(triplenet_ckpt.step) // len(train_batch)
	if triplenet_ckptman.latest_checkpoint:
		print('Restored from the latest checkpoint, epoch: {}'.format(START))

	EPOCHS = 3000
	cfreq  = 178 # Checkpoint frequency
	test_loss = tf.keras.metrics.Mean()
	test_acc  = tf.keras.metrics.SparseCategoricalAccuracy()
	tq = tqdm(test_batch)
	feat_X = []
	feat_Y = []
	for idx, (X, Y) in enumerate(tq, start=1):
		_, feat = triplenet(X, training=False)
		feat_X.extend(feat.numpy())
		feat_Y.extend(Y.numpy())
	feat_X = np.array(feat_X)
	feat_Y = np.array(feat_Y)
	print(feat_X.shape, feat_Y.shape)

	tsne = TSNE(n_components=2, verbose=1, perplexity=40, n_iter=700)
	tsne_results = tsne.fit_transform(feat_X)
	df = pd.DataFrame()
	df['label'] = feat_Y
	df['x1'] = tsne_results[:, 0]
	df['x2'] = tsne_results[:, 1]

	if not os.path.exists('./experiments/inference'): os.makedirs('./experiments/inference')
	df.to_csv('experiments/infer_triplet_embed2D.csv')

	df = pd.read_csv('experiments/infer_triplet_embed2D.csv')

	plt.figure(figsize=(16,10))

	sns.scatterplot(
	    x="x1", y="x2",
	    data=df,
	    hue='label',
	    palette=sns.color_palette("hls", n_classes),
	    legend="full",
	    alpha=0.4
	)

	plt.show()

	kmeans = KMeans(n_clusters=n_classes,random_state=45)
	kmeans.fit(feat_X)
	labels = kmeans.labels_
	kmeanacc = cluster_acc(feat_Y, labels)

	print('Accuracy score: {0:0.2f}'. format(kmeanacc))


import argparse
from typing import Tuple
from unittest.result import failfast
import scipy.sparse as sp
import numpy as np
import random as rd
import itertools
from random_choice import randint_choice
from sklearn.model_selection import train_test_split

from util.setting import log
from util.load_data import Data

class GNNLoader(Data):
    def __init__(self, args:argparse.Namespace) -> None:
        super().__init__(args)

        self.adj_type = args.adj_type

        self.curr_clone_type = -1

        # generate sparse adjacency matrices for system entity inter_data
        log.info("Converting interactions into sparse adjacency matrix")
        adj_list = self._get_relational_adj_list(self.inter_data)

        # generate normalized (sparse adjacency) metrices
        log.info("Generating normalized sparse adjacency matrix")
        self.norm_list = self._get_relational_norm_list(adj_list)

        # load the norm matrix (used for information propagation)
        self.A_in = sum(self.norm_list)

        # mess_dropout
        self.mess_dropout = eval(args.mess_dropout)

        # split functions into training/validation/testing sets for code clone
        if args.clone_test_supervised:
            log.info('Generating code clone training, validation, and testing sets')
            self.clone_test_size = args.clone_test_size
            self.clone_val_size = args.clone_val_size
            if args.dataset.find('bcb') == -1:
                self.clone_train_data, self.clone_val_data, self.clone_test_data = self._sample_clone_oj_split()
                self.n_clone_train, self.n_clone_val, self.n_clone_test_supervised = len(self.clone_train_data), len(self.clone_val_data), len(self.clone_test_data)
                # batch iter
                self.clone_data_iter = self.n_clone_train // self.batch_size_clone
                if self.n_clone_train % self.batch_size_clone:
                    self.clone_data_iter += 1

        # sample positive/negative paris from code clone dataset
        if args.clone_test_unsupervised:
            log.info('Sampling positive and negative pairs for code clone')
            self.clone_pos_pairs, self.clone_neg_pairs = self._sample_clone_pair()
            self.n_clone_test_unsupervised = len(self.clone_pos_pairs)

        # split functions into training/validation/testing sets for code classification
        if args.classification_test:
            log.info('Generating code classification training, validation, and testing sets')
            self.class_test_size = args.class_test_size
            self.class_val_size = args.class_val_size
            self.classification_train_data, self.classification_val_data, self.classification_test_data = self._sample_classification_split()
            self.n_classification_train, self.n_classification_val, self.n_classification_test = len(self.classification_train_data), len(self.classification_val_data), len(self.classification_test_data)
            # batch iter
            # Todo:
            self.classification_data_iter = self.n_classification_train // self.batch_size_classification
            if self.n_classification_train % self.batch_size_classification:
                self.classification_data_iter += 1

        # sample functions from code clone dataset
        if args.cluster_test:
            log.info('Sampling functions for code cluster')
            self.cluster_test_data = self._sample_cluster()
            self.n_cluster_test = len(self.cluster_test_data)

    def _get_relational_adj_list(self, inter_data) -> Tuple[list, list]:
        def _np_mat2sp_adj(np_mat:np.array, row_pre=0, col_pre=0) -> Tuple[sp.coo_matrix, sp.coo_matrix]:
            # to-node interaction: A: A->B
            a_rows = np_mat[:, 0] + row_pre # all As
            a_cols = np_mat[:, 1] + col_pre # all Bs
            # must use float 1. (int is not allowed)
            a_vals = [1.] * len(a_rows)

            # from-node interaction: A: B->A
            b_rows = a_cols
            b_cols = a_rows
            b_vals = [1.] * len(b_rows)

            # self.n_entity + 1:
            # we add a `ghost` entity to support parallel AST node embedding
            # retrival for program statements
            a_adj = sp.coo_matrix((a_vals, (a_rows, a_cols)), shape=(self.n_entity + 1, self.n_entity + 1))
            b_adj = sp.coo_matrix((b_vals, (b_rows, b_cols)), shape=(self.n_entity + 1, self.n_entity + 1))

            return a_adj, b_adj

        adj_mat_list = []

        r, r_inv = _np_mat2sp_adj(inter_data)
        adj_mat_list.append(r)
        # Todo: whether r_inv (inverse directions) helps infer code representations
        adj_mat_list.append(r_inv)

        return adj_mat_list

    def _get_relational_norm_list(self, adj_list:str) -> list:
        # Init for 1/Nt
        def _si_norm(adj):
            rowsum = np.array(adj.sum(axis=1))
            # np.power(rowsum, -1).flatten() may trigger divide by zero
            d_inv = np.power(rowsum, -1).flatten()
            d_inv[np.isinf(d_inv)] = 0.
            d_mat_inv = sp.diags(d_inv)
            norm_adj = d_mat_inv.dot(adj)
            return norm_adj

        # Init for 1/(Nt*Nh)^(1/2)
        def _bi_norm(adj):
            rowsum = np.array(adj.sum(axis=1))
            # np.power(rowsum, -1).flatten() may trigger divide by zero
            d_inv_sqrt = np.power(rowsum, -0.5).flatten()
            d_inv_sqrt[np.isinf(d_inv_sqrt)] = 0.
            d_mat_inv_sqrt = sp.diags(d_inv_sqrt)
            # Different from KGAT's implementation
            # bi_norm = adj.dot(d_mat_inv_sqrt).transpose().dot(d_mat_inv_sqrt)
            bi_norm = d_mat_inv_sqrt.dot(adj).dot(d_mat_inv_sqrt)
            return bi_norm

        if self.adj_type == 'bi':
            norm_list = [_bi_norm(adj) for adj in adj_list]
        else:
            norm_list = [_si_norm(adj) for adj in adj_list]

        return norm_list

    def _sample_cpg_split(self, inter_data:list) -> Tuple[list, list, list]:
        # we use the whole dataset to pretrain the model
        inter_train_data = inter_data

        _, inter_test_val_data = train_test_split(
            inter_data, test_size=self.ssl_test_size + self.ssl_val_size,
            random_state=2022)

        inter_val_data, inter_test_data = train_test_split(
            inter_test_val_data, test_size=self.ssl_test_size / (self.ssl_test_size + self.ssl_val_size),
            random_state=2022)

        return inter_train_data, inter_val_data, inter_test_data

    def sample_pos_pair(self, l, num):
        """randomly sample num (e.g., 100) non-repeated pairs from list (l) """
        pairs = itertools.combinations(l, 2)
        pool = tuple(pairs)
        n = len(pool)
        indices = sorted(rd.sample(range(n), num))
        return tuple(pool[i] for i in indices)

    def sample_neg_pair(self, l1, l2, num):
        "Random selection from itertools.product(*args, **kwds)"
        pairs = itertools.product(l1, l2)
        pool = tuple(pairs)
        n = len(pool)
        indices = sorted(rd.sample(range(n), num))
        return tuple(pool[i] for i in indices)

    def _sample_clone_pair(self, sample_clone_num=20000):
        """"""
        clone_pos_pairs = []
        clone_neg_pairs = []

        all_clone_family = self.all_clone_family

        exist_family_pair = [-1 for _ in range(self.classification_num)]
        for idx, family in enumerate(all_clone_family):
            while True:
                idx_neg = randint_choice(self.classification_num, size=1, replace=False)
                if idx_neg != idx and exist_family_pair[idx_neg] != idx:
                    exist_family_pair[idx] = idx_neg
                    break

            clone_pos_pairs_family = self.sample_pos_pair(family, sample_clone_num)
            clone_neg_pairs_family = self.sample_neg_pair(family, all_clone_family[idx_neg], sample_clone_num)

            clone_pos_pairs.extend(clone_pos_pairs_family)
            clone_neg_pairs.extend(clone_neg_pairs_family)

        log.debug('Code clone: #positive pairs {}'.format(len(clone_pos_pairs)))
        log.debug('Code clone: #negative pairs {}'.format(len(clone_neg_pairs)))

        assert(len(clone_pos_pairs) == len(clone_neg_pairs))

        return clone_pos_pairs, clone_neg_pairs

    def _sample_cluster(self):
        """"""
        cluster_test_data = []

        all_clone_family = self.all_clone_family
        for idx, family in enumerate(all_clone_family):
            cluster_test_data.extend([[func, idx] for func in family])

        log.debug('Code Cluster: #samples {}'.format(len(cluster_test_data)))

        return cluster_test_data

    def _sample_classification_split(self):
        """"""
        class_train_data, class_val_data, class_test_data = [], [], []

        all_clone_family = self.all_clone_family

        for idx, family in enumerate(all_clone_family):
            class_train_family, class_test_val_family = train_test_split(
                family, test_size=self.class_test_size+self.class_val_size,
                random_state=2022)

            class_val_family, class_test_family = train_test_split(
                class_test_val_family, test_size=self.class_test_size/(self.class_test_size+self.class_val_size),
                random_state=2022)

            class_train_data.extend([[func, idx] for func in class_train_family])
            class_val_data.extend([[func, idx] for func in class_val_family])
            class_test_data.extend([[func, idx] for func in class_test_family])

        log.debug('Code Classification [n_train, n_val, n_test] = [%d, %d, %d]' % (len(class_train_data), len(class_val_data), len(class_test_data)))

        if self.split_label:
            f = open('oj_classification_split.txt', 'w')

            # training/validation/test: 0/1/2
            for i in range(len(class_train_data)):
                f.write("%d %d %d\n" % (class_train_data[i][0][0], class_train_data[i][1], 0))

            for i in range(len(class_val_data)):
                f.write("%d %d %d\n" % (class_val_data[i][0][0], class_val_data[i][1], 1))

            for i in range(len(class_test_data)):
                f.write("%d %d %d\n" % (class_test_data[i][0][0], class_test_data[i][1], 2))

            f.close()

        return class_train_data, class_val_data, class_test_data

    def _generate_clone_bcb_split(self, curr_clone_type):
        self.curr_clone_type = curr_clone_type
        self.clone_train_data, self.clone_val_data, self.clone_test_data = self._sample_clone_bcb_split()
        self.n_clone_train, self.n_clone_val, self.n_clone_test_supervised = len(self.clone_train_data), len(self.clone_val_data), len(self.clone_test_data)
        # batch iter
        self.clone_data_iter = self.n_clone_train // self.batch_size_clone
        if self.n_clone_train % self.batch_size_clone:
            self.clone_data_iter += 1

    def _sample_clone_bcb_split(self):
        clone_train_data, clone_val_data, clone_test_data = [], [], []
        all_clone_type = self.all_clone_type
        for idx, clone_type in enumerate(all_clone_type):
            # idx == 5 represents negative samples
            if (idx == 5 or idx == self.curr_clone_type):
                clone_train_family, clone_test_val_family = train_test_split(
                    clone_type, test_size=self.clone_test_size+self.clone_val_size,
                    random_state=999)

                clone_val_family, clone_test_family = train_test_split(
                    clone_test_val_family, test_size=self.clone_test_size/(self.clone_test_size+self.clone_val_size),
                    random_state=999)

                clone_train_data.extend([[pair, [idx]] for pair in clone_train_family])
                clone_val_data.extend([[pair, [idx]] for pair in clone_val_family])
                clone_test_data.extend([[pair, [idx]] for pair in clone_test_family])

        log.debug('Code Clone (Type %d) [n_train, n_val, n_test] = [%d, %d, %d]' % (self.curr_clone_type, len(clone_train_data), len(clone_val_data) , len(clone_test_data)))

        if self.split_label:
            f = open('bcb_clone_split.txt', 'w')

            # training/validation/test: 0/1/2
            for i in range(len(clone_train_data)):
                f.write("%d %d %d %d\n" % (clone_train_data[i][0][0][0], clone_train_data[i][0][1][0], clone_train_data[i][1][0], 0))

            for i in range(len(clone_val_data)):
                f.write("%d %d %d %d\n" % (clone_val_data[i][0][0][0], clone_val_data[i][0][1][0], clone_val_data[i][1][0], 1))

            for i in range(len(clone_test_data)):
                f.write("%d %d %d %d\n" % (clone_test_data[i][0][0][0], clone_test_data[i][0][1][0], clone_test_data[i][1][0], 2))

            f.close()
        else:
            # Identify positives and negatives from different clone types
            for i in range(len(clone_train_data)):
                if clone_train_data[i][1][0] == 5:
                    # True Negatives
                    clone_train_data[i][1][0] = 0
                else:
                    # True Positive
                    clone_train_data[i][1][0] = 1

            for i in range(len(clone_val_data)):
                if clone_val_data[i][1][0] == 5:
                    # True Negatives
                    clone_val_data[i][1][0] = 0
                else:
                    # True Positive
                    clone_val_data[i][1][0] = 1

            for i in range(len(clone_test_data)):
                if clone_test_data[i][1][0] == 5:
                    # True Negatives
                    clone_test_data[i][1][0] = 0
                else:
                    # True Positive
                    clone_test_data[i][1][0] = 1

        return clone_train_data, clone_val_data, clone_test_data

    def _sample_clone_oj_split(self, sample_clone_num=20000):
        """"""
        clone_train_data, clone_val_data, clone_test_data = [], [], []

        all_clone_family = self.all_clone_family

        exist_family_pair = [-1 for _ in range(self.classification_num)]
        for idx, family in enumerate(all_clone_family):
            while True:
                idx_neg = randint_choice(self.classification_num, size=1, replace=False)
                if idx_neg != idx and exist_family_pair[idx_neg] != idx:
                    exist_family_pair[idx] = idx_neg
                    break

            # we follow the data distribution in ASTNN to generate our
            # clone/non-clone
            clone_pos_pairs_family = self.sample_pos_pair(family, int(sample_clone_num * 0.066))
            clone_neg_pairs_family = self.sample_neg_pair(family, all_clone_family[idx_neg], sample_clone_num)

            # split positive code clone pairs
            clone_train_family, clone_test_val_family = train_test_split(
                clone_pos_pairs_family, test_size=self.clone_test_size+self.clone_val_size,
                random_state=2022)

            clone_val_family, clone_test_family = train_test_split(
                clone_test_val_family, test_size=self.clone_test_size/(self.clone_test_size+self.clone_val_size),
                random_state=2022)

            clone_train_data.extend([[pair, [1]] for pair in clone_train_family])
            clone_val_data.extend([[pair, [1]] for pair in clone_val_family])
            clone_test_data.extend([[pair, [1]] for pair in clone_test_family])

            # split negative code clone pairs
            clone_train_family, clone_test_val_family = train_test_split(
                clone_neg_pairs_family, test_size=self.clone_test_size+self.clone_val_size,
                random_state=2022)

            clone_val_family, clone_test_family = train_test_split(
                clone_test_val_family, test_size=self.clone_test_size/(self.clone_test_size+self.clone_val_size),
                random_state=2022)

            clone_train_data.extend([[pair, [0]] for pair in clone_train_family])
            clone_val_data.extend([[pair, [0]] for pair in clone_val_family])
            clone_test_data.extend([[pair, [0]] for pair in clone_test_family])

        log.debug('Code Clone [n_train, n_val, n_test] = [%d, %d, %d]' % (len(clone_train_data), len(clone_val_data), len(clone_test_data)))

        if self.split_label:
            f = open('oj_clone_split.txt', 'w')

            # training/validation/test: 0/1/2
            for i in range(len(clone_train_data)):
                # pair[0] represent ojclone file_id
                f.write("%d %d %d %d\n" % (clone_train_data[i][0][0][0], clone_train_data[i][0][1][0], clone_train_data[i][1][0], 0))

            for i in range(len(clone_val_data)):
                f.write("%d %d %d %d\n" % (clone_val_data[i][0][0][0], clone_val_data[i][0][1][0], clone_val_data[i][1][0], 1))

            for i in range(len(clone_test_data)):
                f.write("%d %d %d %d\n" % (clone_test_data[i][0][0][0], clone_test_data[i][0][1][0], clone_test_data[i][1][0], 2))
            f.close()
            exit(-1)

        return clone_train_data, clone_val_data, clone_test_data

    def transfer_s_to_e(self, s_list:list) -> np.array:
        """"""
        s2e = []
        for s in s_list:
            s2e.append(self.stat_dict[s])
        return np.array(s2e)

    def _convert_csr_to_sparse_tensor_inputs(self, X:sp.csr_matrix) -> Tuple[list, list, list]:
        coo = X.tocoo()
        indices = np.mat([coo.row, coo.col]).transpose()
        return indices, coo.data, coo.shape

    def extract_stat_from_inter(self, inter_data:list) -> Tuple[list, list]:
        s1 = []
        s2 = []

        for pair in inter_data:
            s1.append(pair[0])
            s2.append(pair[1])

        return s1, s2

    def generate_clone_train_batch(self, i_batch:int) -> dict:
        """"""
        batch_data = {}
        start = i_batch * self.batch_size_clone
        if i_batch == self.clone_data_iter - 1:
            end = self.n_clone_train
        else:
            end = (i_batch + 1) * self.batch_size_clone

        f_y = self.clone_train_data[start: end]

        f1_clone = [f[0][0] for f in f_y]
        f2_clone = [f[0][1] for f in f_y]
        y_clone = [f[1] for f in f_y]

        batch_data['f1_clone'] = f1_clone
        batch_data['f2_clone'] = f2_clone
        batch_data['y_clone'] = y_clone

        return batch_data

    def generate_clone_val_batch(self, i_batch:int, last_batch:bool) -> dict:
        """"""
        batch_data = {}
        start = i_batch * self.batch_size_clone
        if last_batch:
            end = self.n_clone_val
        else:
            end = (i_batch + 1) * self.batch_size_clone

        f_y = self.clone_val_data[start: end]

        f1_clone = [f[0][0] for f in f_y]
        f2_clone = [f[0][1] for f in f_y]
        y_clone = [f[1] for f in f_y]

        batch_data['f1_clone'] = f1_clone
        batch_data['f2_clone'] = f2_clone
        batch_data['y_clone'] = y_clone

        return batch_data

    def generate_clone_test_batch(self, i_batch:int, last_batch:bool) -> dict:
        """"""
        batch_data = {}
        start = i_batch * self.batch_size_clone
        if last_batch:
            end = self.n_clone_test_supervised
        else:
            end = (i_batch + 1) * self.batch_size_clone

        f_y = self.clone_test_data[start: end]

        f1_clone = [f[0][0] for f in f_y]
        f2_clone = [f[0][1] for f in f_y]
        y_clone = [f[1] for f in f_y]

        batch_data['f1_clone'] = f1_clone
        batch_data['f2_clone'] = f2_clone
        batch_data['y_clone'] = y_clone

        return batch_data

    def generate_clone_train_feed_dict(self, model, batch_data):
        feed_dict = {
            # Clone
            model.f1_clone: batch_data['f1_clone'],
            model.f2_clone: batch_data['f2_clone'],
            model.y_clone: batch_data['y_clone'],
            # hardcode dropping probability as 0
            model.mess_dropout: [0,0,0,0,0,0]
        }
        return feed_dict

    def generate_classification_train_batch(self, i_batch:int) -> dict:
        """"""
        batch_data = {}

        start = i_batch * self.batch_size_classification
        if i_batch == self.classification_data_iter:
            end = self.n_classification_train
        else:
            end = (i_batch + 1) * self.batch_size_classification

        f_y = self.classification_train_data[start: end]

        batch_data['f_classification'] = [f[0] for f in f_y]
        # labels, e.g., 2
        batch_data['y_classification'] = [f[1] for f in f_y]
        batch_data['y_classification'] = np.array(batch_data['y_classification']).flatten()

        return batch_data

    def generate_classification_val_batch(self, i_batch:int, last_batch:bool) -> dict:
        """"""
        batch_data = {}
        start = i_batch * self.batch_size_classification
        if last_batch:
            end = self.n_classification_val
        else:
            end = (i_batch + 1) * self.batch_size_classification

        f_y = self.classification_val_data[start: end]

        batch_data['f_classification'] = [f[0] for f in f_y]
        # labels, e.g., 2
        batch_data['y_classification'] = [f[1] for f in f_y]

        return batch_data

    def generate_classification_test_batch(self, i_batch:int, last_batch:bool) -> dict:
        """"""
        batch_data = {}
        start = i_batch * self.batch_size_classification
        if last_batch:
            end = self.n_classification_test
        else:
            end = (i_batch + 1) * self.batch_size_classification

        f_y = self.classification_test_data[start: end]

        batch_data['f_classification'] = [f[0] for f in f_y]
        # labels, e.g., 2
        batch_data['y_classification'] = [f[1] for f in f_y]

        return batch_data

    def generate_classification_train_feed_dict(self, model, batch_data):
        feed_dict = {
            # Classification
            model.f_classification: batch_data['f_classification'],
            model.y_classification: batch_data['y_classification'],
            # hardcode dropping probability as 0
            model.mess_dropout: [0,0,0,0,0,0],
        }

        return feed_dict

    def generate_classification_val_feed_dict(self, model, batch_data):
        feed_dict = {
            model.f_classification: batch_data['f_classification'],
            # hardcode dropping probability as 0
            model.mess_dropout: [0,0,0,0,0,0],
        }
        return feed_dict

    def generate_clone_batch(self, i_batch:int, last_batch:bool, pos:bool) -> dict:
        batch_data = {}

        start = i_batch * self.batch_size_clone
        if last_batch:
            end = self.n_clone_test_unsupervised
        else:
            end = (i_batch + 1) * self.batch_size_clone

        if pos:
            f1_clone = [pair[0] for pair in self.clone_pos_pairs[start:end]]
            f2_clone = [pair[1] for pair in self.clone_pos_pairs[start:end]]
        else:
            f1_clone = [pair[0] for pair in self.clone_neg_pairs[start:end]]
            f2_clone = [pair[1] for pair in self.clone_neg_pairs[start:end]]

        batch_data['f1_clone'] = f1_clone
        batch_data['f2_clone'] = f2_clone

        return batch_data

    def generate_clone_feed_dict(self, model, batch_data):
        feed_dict = {
            model.f1_clone: batch_data['f1_clone'],
            model.f2_clone: batch_data['f2_clone'],
            # hardcode dropping probability as 0
            model.mess_dropout: [0,0,0,0,0,0],
        }
        return feed_dict

    def generate_cluster_batch(self, i_batch:int, last_batch:bool) -> dict:
        batch_data = {}

        start = i_batch * self.batch_size_cluster
        if last_batch:
            end = self.n_cluster_test
        else:
            end = (i_batch + 1) * self.batch_size_cluster

        f_y= self.cluster_test_data[start:end]

        batch_data['f_cluster'] = [f[0] for f in f_y]
        batch_data['cluster_label'] = [f[1] for f in f_y]

        return batch_data

    def generate_cluster_feed_dict(self, model, batch_data):
        feed_dict = {
            model.f_cluster: batch_data['f_cluster'],
            # hardcode dropping probability as 0
            model.mess_dropout: [0,0,0,0,0,0],
        }
        return feed_dict


import sys
input = sys.stdin.readline
n = int(input())
rgb_map = [None for _ in range(n + 1)]
dp = [[0 for _ in range(3)] for _ in range(n+1)]
for i in range(1,n + 1):
    r,g,b = map(int,input().split())
    rgb_map[i] = [r,g,b]

dp[1] = rgb_map[1][::]

for i in range(2, n+1):
    dp[i][0] = min(dp[i-1][1], dp[i-1][2]) + rgb_map[i][0]
    dp[i][1] = min(dp[i-1][0], dp[i-1][2]) + rgb_map[i][1]
    dp[i][2] = min(dp[i-1][0], dp[i-1][1]) + rgb_map[i][2]

print(min(dp[n]))


import sys,os
from scipy.stats import gaussian_kde
sys.path.append('/scratch1/BMC/gsd-fv3-dev/MAPP_2018/bhuang/JEDI-2020/JEDI-FV3/expCodes/METplus-diag/METplus_pkg//pyscripts/lib')
os.environ['PROJ_LIB'] = '/contrib/anaconda/anaconda3/latest/share/proj'
import numpy as np
import math
import matplotlib
matplotlib.use('agg')
import matplotlib.pyplot as plt

expnames=['global-workflow-CCPP2-Chem-NRT-clean','global-workflow-CCPP2-Chem-NRT-clean-cntlFreeFcst']
aodtyp='AERONET'
sensor='aeronet'
epison=0.01
wavs=['500']
#cycs='2021070900'
#cyce='2021073118'
fs=open('DATES.info', 'r')
fe=open('DATEE.info', 'r')
cycs=fs.read().replace('\n', '')
cyce=fe.read().replace('\n', '')
fs.close()
fe.close()

cyc1='runs_AERONET_%s_%s' % (cycs, cyce)
cyc2='%s-%s'  % (cycs, cyce)

nexps=len(expnames)
nwavs=len(wavs)

for iexp in range(nexps):
    expname=expnames[iexp]
    if expname == 'global-workflow-CCPP2-Chem-NRT-clean':
        expleg='DA'
        nflds=2
        fields=['cntlBckg', 'cntlAnal']
    else:
        expleg='NODA'
        nflds=1
        fields=['cntlBckg']
    print(expname)
    for ifld in range(nflds):
        field=fields[ifld]
        print(field)
        for iwav in range(nwavs):
            wav=wavs[iwav]
            datafile='./%s-%s-%sAOD-%s-lon-lat-obs-hofx-Cyc-%s-wav-%s.txt' \
                      % (expname, field, aodtyp, sensor, cyc2, wav)
            print(wav)
            f=open(datafile,'r')
            iline=0
            lonvec=[]
            latvec=[]
            obsvec=[]
            hfxvec=[]
            for line in f.readlines():
                lon=float(line.split()[0])
                lat=float(line.split()[1])
                obs=float(line.split()[2])
                hfx=float(line.split()[3])
                if ~np.isnan(obs):
                    lonvec.append(lon)
                    latvec.append(lat)
                    obsvec.append(obs)
                    hfxvec.append(hfx)
                iline=iline+1
            f.close()
            lonarr=np.array(lonvec)
            latarr=np.array(latvec)
            obsarr=np.array(obsvec)
            hfxarr=np.array(hfxvec)
            lonarr_nonan=lonarr[~np.isnan(obsarr)]
            latarr_nonan=latarr[~np.isnan(obsarr)]
            obsarr_nonan=obsarr[~np.isnan(obsarr)]
            hfxarr_nonan=hfxarr[~np.isnan(obsarr)]

            bias_all=hfxarr_nonan-obsarr_nonan
            biasm_all=np.mean(bias_all)
            maem_all=np.mean(np.absolute(bias_all))
            rmsem_all=np.sqrt(np.mean(np.square(bias_all)))
            brrmsem_all=np.sqrt(np.mean(np.square(bias_all-biasm_all)))
            meanarr=np.empty([1,4])
            meanarr[0,:]=[biasm_all, rmsem_all, maem_all, brrmsem_all]

            lonlatarr_nonan=np.column_stack([lonarr_nonan, latarr_nonan])

            lonlat_uni,indices_uni=np.unique(lonlatarr_nonan, axis=0, return_inverse='True')
            npts=len(lonlat_uni)
            iptarr=np.empty([npts,9])
            for ipt in range(npts):
                lonlat_ipt=lonlat_uni[ipt]
                indice_ipt=np.where(indices_uni==ipt)
                count_ipt=np.size(indice_ipt)  #len(indice_ipt)
                obs_ipt=obsarr_nonan[indice_ipt]
                hfx_ipt=hfxarr_nonan[indice_ipt]
                obsm_ipt=np.mean(obs_ipt)
                hfxm_ipt=np.mean(hfx_ipt)
                bias_ipt=hfx_ipt-obs_ipt
                biasm_ipt=np.mean(bias_ipt)
                if count_ipt > 1:
                    rmsem_ipt=np.sqrt(np.mean(np.square(bias_ipt)))
                    brrmsem_ipt=np.sqrt(np.mean(np.square(bias_ipt-biasm_ipt)))
                else:
                    rmsem_ipt=np.absolute(bias_ipt)
                    brrmsem_ipt=0
                maem_ipt=np.mean(np.absolute(bias_ipt))
                iptarr[ipt,:]=[lonlat_ipt[0], lonlat_ipt[1], count_ipt, obsm_ipt, hfxm_ipt, biasm_ipt, rmsem_ipt, maem_ipt, brrmsem_ipt]
            outfile='./%s-%s-%sAOD-%s-collect-lon-lat-count-obs-hofx-bias-rmse-mae-brrmse-Cyc-%s-wav-%s.txt' \
                      % (expname, field, aodtyp, sensor, cyc2, wav)
            np.savetxt(outfile, iptarr, delimiter = '\t')
            outfile1='./%s-%s-%sAOD-%s-averaged-bias-rmse-mae-brrmse-Cyc-%s-wav-%s.txt' \
                      % (expname, field, aodtyp, sensor, cyc2, wav)
            np.savetxt(outfile1, meanarr, delimiter = '\t')
exit


from datetime import date
# Maior ou menor de idade
menor = 0
maior = 0
for c in range(1, 8):
    anos = int(input(f"Em que ano a {c}ª pessoa nasceu? "))
    idade = date.today().year - anos
    if idade <= 18:
        menor += 1
    else:
        maior += 1
print(f"Ao todo tivemos {maior} pessoas maiores de idade\n"
      f"E também tivemos {menor} pessoas menores de idade")


# license()

list1 = range(10, 40, 1)  # from 10 .<40 step by 1
print(list1)

for i in list1:
    print(i, end=",")

print()

for i in range(10, 2, -2):
    print(i, end=" ")

print()

str1 = "python"
print(str1)

str1 = """
python
java
javascript
swift
"""
print(str1)

str1 = "python"
print(str1[0])

list1 = []
for i in str1:
    list1.append(i)

print(list1)


#!python3
"""
Telex Device - Telnet Server
"""
__author__      = "Jochen Krapf"
__email__       = "jk@nerd2nerd.org"
__copyright__   = "Copyright 2018, JK"
__license__     = "GPL3"
__version__     = "0.0.1"

#from threading import Thread
from _thread import start_new_thread
from socket import socket, AF_INET, SOCK_STREAM

#######

class TelnetSrv():
    RECV_BUFFER = 1024
    MSG_WELCOME = '-=TELEX=-\r\n'

    def __init__(self, port=23):
        super().__init__()

        self._port = port

        self.run = True
        self.clients = []

        self.SERVER = socket(AF_INET, SOCK_STREAM)
        self.SERVER.bind(('', self._port))

        self.SERVER.listen(10)
        #print("Waiting for connection...")
        #self.ACCEPT_THREAD = Thread(target=self.accept_incoming_connections, name='TelnetSaic')
        #self.ACCEPT_THREAD.start()
        self.ACCEPT_THREAD = start_new_thread(self.accept_incoming_connections, ())
        pass

    def __del__(self):
        self.run = False
        #print('__del__ in TelexWebSrv')
        self.SERVER.close()
        #super().__del__()

    # =====

    # =====

    def accept_incoming_connections(self):
        """Sets up handling for incoming clients."""
        while self.run:
            client, client_address = self.SERVER.accept()
            print("Telnet - client connected %s:%s" % client_address)
            #self.clients[client] = client_address
            self.clients.append(client)
            #Thread(target=self.handle_client, name='TelnetShc', args=(client,)).start()
            start_new_thread(self.handle_client, (client,))

    def handle_client(self, client):  # Takes client socket as argument.
        """Handles a single client connection."""
        client.send(bytes([255, 252, 34]))
        client.send(bytes([255, 251, 1]))
        client.send(bytes(self.MSG_WELCOME, "utf8"))
        #msg = "%s has joined the chat!" % name
        #self.broadcast(bytes(msg, "utf8"))

        while self.run:
            msg = client.recv(self.RECV_BUFFER)
            if not msg:   # client has been terminated
                client.close()
                #del self.clients[client]
                self.clients.remove(client)
                print('Telnet - client disconnected')
                #self.broadcast(bytes("%s has left the chat." % name, "utf8"))
                break

            if b'\xFF' in msg:
                continue

            # echo back to all clients
            self.broadcast(msg)
            #print(msg)
            try:
                aa = msg.decode('UTF8')
            except:
                aa = '?'
            print(aa, end='')
            #aa = txCode.BaudotMurrayCode.translate(aa)

            #for a in aa:
            #    self._rx_buffer.append(a)

    def broadcast(self, msg:bytes):
        """Broadcasts a message to all the clients."""
        for client in self.clients:
            client.send(msg)

#######


aws_storage_locations = {
    'us-east-1': 'US East (N. Virginia)',
    'us-east-2': 'US East (Ohio)',
    'us-west-1': 'US West (N. California)',
    'us-west-2': 'US West (Oregon)',
    'ca-central-1': 'Canada (Central)',
    'ap-south-1': 'Asia Pacific (Mumbai)',
    'ap-northeast-2': 'Asia Pacific (Seoul)',
    'ap-southeast-1': 'Asia Pacific (Singapore)',
    'ap-southeast-2': 'Asia Pacific (Sydney)',
    'ap-northeast-1': 'Asia Pacific (Tokyo)',
    'eu-central-1': 'EU (Frankfurt)',
    'eu-west-1': 'EU (Ireland)',
    'eu-west-2': 'EU (London)',
    'sa-east-1': 'South America (São Paulo)'
}

def get_storage_locations():
    return aws_storage_locations

def get_storage_location(region):
    return aws_storage_locations[region]

def get_storage_location_by_name(name):
    for region, location in aws_storage_locations.items():
        if location == name:
            return region
    return None

def get_storage_location_by_name_regex(name):
    for region, location in aws_storage_locations.items():
        if re.search(name, location):
            return region
    return None


import logging
import os

LOGGER = logging.getLogger()
LOGGER.setLevel(logging.NOTSET)

def print_os_environ():
    environ_keys = {}
    for k, v in sorted(os.environ.items()):
        LOGGER.info(f"{k}:{v}")
        environ_keys[k] = v

def show_modules():
    LOGGER.info(f'Info about modules in layer')
    LOGGER.info(f'all modules list\n: {str(help("modules"))}')


import urllib.request
import ssl
import json
import datetime
from bs4 import BeautifulSoup

class OpcvmDataAltaprofits():

    def __init__(self):
        self._base_url = "https://www.altaprofits.com/services/graphes/actifHistoData.jsp?isinList="

    def get_history(self, isin):
        historical_datas = {}
        #print(self._base_url + isin)
        req = urllib.request.urlopen(self._base_url + isin, context=ssl.SSLContext(ssl.PROTOCOL_SSLv23)).read()#.decode('iso-8859-1').encode('UTF-8')
        #print(str(req)[2:-1].replace("\\", ""))
        json_data = json.loads(str(req)[2:-1].replace('\\', ''))
        #print(json_data)

        if json_data['datas']['series']:
            for elemtab in json_data['datas']['series']:
                if(elemtab['datas']):
                    for data_opcvm in elemtab['datas']:
                        date_value = datetime.date(int(data_opcvm['date'][:4]), int(data_opcvm['date'][5:7]), int(data_opcvm['date'][8:10]))
                        historical_datas[date_value] = data_opcvm['value']
        return historical_datas
'''
test = OpcvmDataAltaprofits()
test_ret = test.get_history("FR0007016068")

for key_elem in test_ret:
    print(str(key_elem) + " " + str(test_ret[key_elem]))
'''


# Author: Jesús Ricardo Quintero Serrano
import serial
# import msvcrt       # No es necesario si no se utiliza el teclado para hacer algo
import serial.tools.list_ports
import logging
from datetime import datetime
import time

# Clase encargada de recibir datos del arduino y mandarle instrucciones
class Communication:
    def __init__(self, numDevice):
        # - Variables -
        self.arduino = serial.Serial(self.findArduino(numDevice), 9600)
        self.arduino.readline()

    # Detecta el puerto serial en el que se conecto el arduino //aun no valida que solo exista un arduino conectado
    def findArduino(self, numDevice):
        ports = serial.tools.list_ports.comports()
        commPort = 'None'
        numConnection = len(ports)

        for i in range(0,numConnection):
            port = ports[i]
            strPort = str(port)

            # Se valida si la descripcion es de arduino original o clon
            if 'USB-SERIAL CH340' in strPort or 'Arduino' in strPort:
                splitPort = strPort.split(' ')
                commPort = splitPort[numDevice]
        return commPort

    # Lee los datos del arduino del puerto serial y los regresa en una lista
    def readMessage(self):
        mensaje = self.arduino.readline()[:-2]
        datos = [int(x) for x in str(mensaje.decode("utf-8"))]
        return datos

    # Manda una instruccion de dispensar comida segun el numero al arduino (El arduino
    # debera estar programado para recibir un numero y dispensar la cantidad de comida correspondiente)
    def doAction(self, action):
        self.arduino.write(bytes(action))

    # Prende o apaga el led dependiendo del parametro state (true o false)
    def setLedState(self, state):
        if state:
            self.arduino.write(b'o')
        else:
            self.arduino.write(b'x')


#!/usr/bin/env python3
#
# make_choropleth_map.py: uses `Plotly` to create a choropleth map of
# the origin of the nefarious incidents, taken from a log file.

import iso3166
import sys

import numpy as np
import pandas as pd

import plotly.offline as po
import plotly.plotly as py
import plotly.graph_objs as go

if __name__ == '__main__':
    df = pd.read_csv(sys.argv[1])

    # Convert from two-character abbreviations to three-character
    # abbreviations because `Plotly` cannot handle them.
    locations = list(map(
        lambda x: iso3166.countries.get(x).alpha3, df['code'].values))

    data = [ dict(
        type = 'choropleth',
        locations = locations,
        z = np.log10(df['count']),
        text = df['name'],
        colorscale = [[0.00, "rgb(247, 247, 247)"],\
                      [0.25, "rgb(204, 204, 204)"],\
                      [0.50, "rgb(150, 150, 150)"],\
                      [0.75, "rgb( 99,  99,  99)"],\
                      [1.00, "rgb( 37,  37,  37)"]],
        autocolorscale = False,
        reversescale = False,
        colorbar = dict(
            autotick = True,
            title = dict(
                text='Incidents (log-10)'),
            ),
            titleside = 'bottom',
      ) ]

    layout = dict(
        title = 'Failed ssh access attempts',
        font = dict(family='Raleway', size=20),
        margin = 5,
        geo = dict(
            showframe = False,
            showcoastlines = True,
            projection = dict(
                type = 'Mercator'
            )
        )
    )

    figure = dict(data=data, layout=layout)
    py.iplot(figure, validate=False, filename='ssh-incidents')