import tensorflow as tf

from layers import *

batch_size = 1
img_layer = 3
ngf = 32
ndf = 64

def build_generator_resnet_9blocks(inputgen,name="generator"):
    """
    :param inputgen:1*256*256*3
    :param name: generator

    :return:out_gen
    """

    with tf.variable_scope(name):
        f = 7
        ks = 3
        pad_input = tf.pad(inputgen,[[0,0],[ks,ks],[ks,ks],[0,0]],"REFLECT")  # 1*262*262*3
        o_c1 = general_conv2d(pad_input,ngf,f,f,1,1,0.02,name="c1") # 1*256*256*64
        o_c2 = general_conv2d(o_c1, ngf*2, ks, ks, 2, 2, 0.02,"SAME", name="c2")  # 1*128*128*128
        o_c3 = general_conv2d(o_c2, ngf * 4, ks, ks, 2, 2, 0.02, "SAME", name="c3")  # 1*64*64*256

        o_r1 = build_resnet_block(o_c3,ngf*4,"r1")
        o_r2 = build_resnet_block(o_r1, ngf * 4, "r2")
        o_r3 = build_resnet_block(o_r2, ngf * 4, "r3")
        o_r4 = build_resnet_block(o_r3, ngf * 4, "r4")
        o_r5 = build_resnet_block(o_r4, ngf * 4, "r5")
        o_r6 = build_resnet_block(o_r5, ngf * 4, "r6")
        o_r7 = build_resnet_block(o_r6, ngf * 4, "r7")
        o_r8 = build_resnet_block(o_r7, ngf * 4, "r8")
        o_r9 = build_resnet_block(o_r8, ngf * 4, "r9")  # 1*64*64*256

        o_c4 = general_deconv2d(o_r9,[batch_size,128,128,ngf*2],ngf*2,ks,ks,2,2,0.02,"SAME","c4")
        o_c5 = general_deconv2d(o_c4, [batch_size, 256, 256, ngf], ngf, ks, ks, 2, 2, 0.02, "SAME", "c5")
        o_c6 = general_deconv2d(o_c5,[batch_size,256,256,3],img_layer,f,f,1,1,0.02,"SAME","c6",do_relu=False)

        out_gen = tf.nn.tanh(o_c6,"t1")

        return out_gen

def build_gen_discriminator(inputdisc,name="discriminator"):
    """
    :param inputdisc: 1*256*256*3
    :param name:
    :return:
    """

    with tf.variable_scope(name):
        f = 4

        o_c1 = general_conv2d(inputdisc,ndf,f,f,2,2,0.02,"SAME","c1",do_norm=False,relufactor=0.2)  # 1*128*128*64
        o_c2 = general_conv2d(o_c1, ndf*2, f, f, 2, 2, 0.02, "SAME", "c2",relufactor=0.2)  # 1*64*64*128
        o_c3 = general_conv2d(o_c2, ndf * 4, f, f, 2, 2, 0.02, "SAME", "c3", relufactor=0.2)  # 1*32*32*256
        o_c4 = general_conv2d(o_c3, ndf * 8, f, f, 1, 1, 0.02, "SAME", "c4", relufactor=0.2)  # 1*32*32*512
        o_c5 = general_conv2d(o_c4, 1, f, f, 1, 1, 0.02, "SAME", "c5", do_norm=False,do_relu=False)  # 1*32*32*1

        return o_c5


#!/usr/bin/python

import math

fout = open('model.inp', 'w')

height = 16 #feet
rings = 9
el_per_ring = 8
r_del = 2 * math.pi / el_per_ring

nodes = []

elements = []

orientations = []

r_top = 2
r_bot = 3
r_asg = 6
r_mid = 8
bif_w = 3

def max_orient_dotp(n1, n2):
    global orientations

    dx = n2[0] - n1[0]
    dy = n2[1] - n1[1]
    dz = n2[2] - n1[2]
    dl = math.sqrt(dx**2 + dy**2 + dz**2)

    maxdp = 0
    maxidx = None
    for i, o in enumerate(orientations):
        dp = (o[0]*dx + o[1]*dy + o[2]*dz) / dl
        if dp > maxdp:
            maxdp = dp
            maxidx = i

    return (maxdp, maxidx)

def add_orientation(n1, n2):
    global orientations

    dx = n2[0] - n1[0]
    dy = n2[1] - n1[1]
    dz = n2[2] - n1[2]
    dl = math.sqrt(dx**2 + dy**2 + dz**2)

    orientations.append([dx/dl, dy/dl, dz/dl, 0, 0, 1])

    return len(orientations) - 1

def add_element(n1, n2, n3, dimensions, material):
    global nodes, elements, orientations

    (maxdp, maxidx) = max_orient_dotp(nodes[n1], nodes[n2])
    if abs(maxdp) > .99:
        elements.append({
            'nodes': [n1, n2, n3],
            'dimensions': dimensions,
            'material': material,
            'orientation': maxidx,
        })
    else:
        dx = nodes[n2][0] - nodes[n1][0]
        dy = nodes[n2][1] - nodes[n1][1]
        dz = nodes[n2][2] - nodes[n1][2]
        dl = math.sqrt(dx**2 + dy**2 + dz**2)
        orientations.append([dx/dl, dy/dl, dz/dl, 0, 0, 1])
        elements.append({
            'nodes': [n1, n2, n3],
            'dimensions': dimensions,
            'material': material,
            'orientation': len(orientations) - 1,
        })

def trunk_rad(i):
    if i < 5:
        return r_bot
    else:
        return r_top

# horizontal trunk segments
for i in range(rings):

    z = i * float(height) / rings
    # this is a logistic function for smooth tapering
    #r = r_top + (r_bot - r_top) / (1 + math.exp((12./rings) * i - 6))
    # this is a step function for easy construction
    r = trunk_rad(i)

    for j in range(el_per_ring):

        r_this = j * r_del - ((i + 1) * r_del / 2)

        r_next = r_this + r_del

        x = r * math.cos(r_this)
        y = r * math.sin(r_this)

        x_next = r * math.cos(r_next)
        y_next = r * math.sin(r_next)

        x2 = (x + x_next) / 2
        y2 = (y + y_next) / 2

        nodes.append([x, y, z])
        nodes.append([x2, y2, z])

        n1 = len(nodes) - 2
        n2 = n1 + 1
        if j == el_per_ring - 1:
            n3 = i * el_per_ring * 2
        else:
            n3 = n2 + 1
        el = [n1, n2, n3]
        (maxdp, maxidx) = max_orient_dotp(nodes[n1], nodes[n2])

        if abs(maxdp) < .99:
            maxidx = add_orientation(nodes[n1], nodes[n2])

        elements.append({
            'nodes': el,
            'section': 'RECT',
            'dimensions': '.292,.125', # two by four, 3.5" x 1.5"
            'material': 'WOOD',
            'orientation': maxidx,
        })

# diagonal trunk segments
for i in range(rings - 1):
    j1 = i * el_per_ring * 2
    j2 = (i + 1) * el_per_ring * 2

    for j in range(el_per_ring + el_per_ring):

        # these elements are cut in thirds to brace bifrost
        if (j1+1, j2+1) in [ \
                (75, 93), (75, 91), (73, 91), \
                (67, 85), (67, 83), (65, 83), \
                (89, 107), (89, 105), (87, 105), \
                (81, 99), (81, 97), (95, 97), \
                (103, 121), (103, 119), (101, 119), \
                (111, 113), (111, 127), (109, 127)]:
            for k in range(1, 6):
                mx = nodes[j1][0] + (nodes[j2][0] - nodes[j1][0]) / 6 * k
                my = nodes[j1][1] + (nodes[j2][1] - nodes[j1][1]) / 6 * k
                mz = nodes[j1][2] + (nodes[j2][2] - nodes[j1][2]) / 6 * k

                nodes.append([mx, my, mz])

            l = len(nodes)

            (maxdp, maxidx) = max_orient_dotp(nodes[j1], nodes[l-4])
            if abs(maxdp) < .99:
                maxidx = add_orientation(nodes[j1], nodes[l-4])
            elements.append({
                'nodes': [j1, l-5, l-4],
                'section': 'RECT',
                'dimensions': '.292,.125', # two by four, 3.5" x 1.5"
                'material': 'WOOD',
                'orientation': maxidx,
            })

            (maxdp, maxidx) = max_orient_dotp(nodes[l-4], nodes[l-2])
            if abs(maxdp) < .99:
                maxidx = add_orientation(nodes[l-4], nodes[l-2])
            elements.append({
                'nodes': [l-4, l-3, l-2],
                'section': 'RECT',
                'dimensions': '.292,.125',
                'material': 'WOOD',
                'orientation': maxidx,
            })

            (maxdp, maxidx) = max_orient_dotp(nodes[l-2], nodes[j2])
            if abs(maxdp) < .99:
                maxidx = add_orientation(nodes[l-2], nodes[j2])
            elements.append({
                'nodes': [l-2, l-1, j2],
                'section': 'RECT',
                'dimensions': '.292,.125',
                'material': 'WOOD',
                'orientation': maxidx,
            })
        else:
            mx = nodes[j1][0] + (nodes[j2][0] - nodes[j1][0]) / 2
            my = nodes[j1][1] + (nodes[j2][1] - nodes[j1][1]) / 2
            mz = nodes[j1][2] + (nodes[j2][2] - nodes[j1][2]) / 2

            nodes.append([mx, my, mz])

            (maxdp, maxidx) = max_orient_dotp(nodes[j1], nodes[j2])
            if abs(maxdp) < .99:
                maxidx = add_orientation(nodes[j1], nodes[j2])
            elements.append({
                'nodes': [j1, len(nodes) - 1, j2],
                'section': 'RECT',
                'dimensions': '.292,.125',
                'material': 'WOOD',
                'orientation': maxidx,
            })

        if j%2 == 0:
            j2 = (i + 1) * el_per_ring * 2 + ((j2 + 2) % (el_per_ring * 2))
        else:
            j1 = i * el_per_ring * 2 + ((j1 + 2) % (el_per_ring * 2))

# roots
for n in [33, 37, 41, 45]:
    r2dl = math.sqrt(nodes[n-1][0] ** 2 + nodes[n-1][1] ** 2) # root 2D length
    r2dn = [nodes[n-1][0] / r2dl * r_mid, nodes[n-1][1] / r2dl * r_mid, 0] # root 2D end node
    rm = [(nodes[n-1][0] + r2dn[0]) / 2, (nodes[n-1][1] + r2dn[1]) / 2, (nodes[n-1][2] + r2dn[2]) / 2] # root midpoint
    nodes.append(rm)
    nodes.append(r2dn)
    (maxdp, maxidx) = max_orient_dotp(nodes[n-1], nodes[len(nodes) - 1])
    if abs(maxdp) < .99:
        maxidx = add_orientation(nodes[n-1], nodes[len(nodes) - 1])
    elements.append({
        'nodes': [n-1, len(nodes) - 2, len(nodes) - 1],
        'section': 'RECT',
        'dimensions': '.292,.292',
        'material': 'WOOD',
        'orientation': maxidx,
    })

# midgard
z_mid = nodes[68][2]
for n in [75, 77, 79, 65]:
    mn = [-r_mid, nodes[n-1][1], z_mid]
    mm = [(nodes[n-1][0] - r_mid) / 2, nodes[n-1][1], z_mid]
    nodes.append(mm)
    nodes.append(mn)
    (maxdp, maxidx) = max_orient_dotp(nodes[n-1], nodes[len(nodes) - 1])
    if abs(maxdp) < .99:
        maxidx = add_orientation(nodes[n-1], nodes[len(nodes) - 1])
    elements.append({
        'nodes': [n-1, len(nodes) - 2, len(nodes) - 1],
        'section': 'RECT',
        'dimensions': '.292,.125',
        'material': 'WOOD',
        'orientation': maxidx,
    })
for i in [(354, 356), (356, 358), (358, 360)]:
    mx = (nodes[i[0]-1][0] + nodes[i[1]-1][0]) / 2
    my = (nodes[i[0]-1][1] + nodes[i[1]-1][1]) / 2
    mz = (nodes[i[0]-1][2] + nodes[i[1]-1][2]) / 2
    s_mid = [mx, my, mz]
    nodes.append(s_mid)

    (maxdp, maxidx) = max_orient_dotp(nodes[i[0]-1], nodes[i[1]-1])
    if abs(maxdp) < .99:
        maxidx = add_orientation(nodes[i[0]-1], nodes[i[1]-1])
    elements.append({
        'nodes': [i[0]-1, len(nodes) - 1, i[1]-1],
        'section': 'RECT',
        'dimensions': '.292,.125',
        'material': 'WOOD',
        'orientation': maxidx,
    })

# midgard supports
for i in [(353, 59), (355, 59), (355, 61), (357, 61), (357, 63), (359, 63)]:
    mx = (nodes[i[0]-1][0] + nodes[i[1]-1][0]) / 2
    my = (nodes[i[0]-1][1] + nodes[i[1]-1][1]) / 2
    mz = (nodes[i[0]-1][2] + nodes[i[1]-1][2]) / 2
    s_mid = [mx, my, mz]
    nodes.append(s_mid)

    (maxdp, maxidx) = max_orient_dotp(nodes[i[0]-1], nodes[i[1]-1])
    if abs(maxdp) < .99:
        maxidx = add_orientation(nodes[i[0]-1], nodes[i[1]-1])
    elements.append({
        'nodes': [i[0]-1, len(nodes) - 1, i[1]-1],
        'section': 'RECT',
        'dimensions': '.292,.125',
        'material': 'WOOD',
        'orientation': maxidx,
    })

# bifrost
for i in [(236, 241), (233, 238), (270, 275), (267, 272), (300, 305), (297, 302), \
        (216, 221), (213, 218), (250, 255), (287, 252), (320, 325), (317, 322)]:
    mx = (nodes[i[0]-1][0] + nodes[i[1]-1][0]) / 2
    my = (nodes[i[0]-1][1] + nodes[i[1]-1][1]) / 2
    mz = (nodes[i[0]-1][2] + nodes[i[1]-1][2]) / 2
    s_mid = [mx, my, mz]
    nodes.append(s_mid)

    (maxdp, maxidx) = max_orient_dotp(nodes[i[0]-1], nodes[i[1]-1])
    if abs(maxdp) < .99:
        maxidx = add_orientation(nodes[i[0]-1], nodes[i[1]-1])
    elements.append({
        'nodes': [i[0]-1, len(nodes)-1, i[1]-1],
        'section': 'RECT',
        'dimensions': '.292,.125',
        'material': 'WOOD',
        'orientation': maxidx,
    })

for i in [(236, 370, 241, 216, 376, 221), \
        (233, 371, 238, 213, 377, 218), \
        (89, 90, 91, 81, 82, 83), \
        (270, 372, 275, 250, 378, 255), \
        (267, 373, 272, 287, 379, 252), \
        (103, 104, 105, 111, 112, 97), \
        (300, 374, 305, 320, 380, 325), \
        (297, 375, 302, 317, 381, 322)]:
    n1 = nodes[i[0]-1]
    n2 = nodes[i[1]-1]
    n3 = nodes[i[2]-1]
    #n4 = nodes[i[3]-1]
    n5 = nodes[i[4]-1]
    #n6 = nodes[i[5]-1]
    vx = n3[0] - n1[0]
    vy = n3[1] - n1[1]
    norm = [vy, -vx]
    ln = math.sqrt(norm[0] ** 2 + norm[1] ** 2)
    end_n = [n2[0] + norm[0] / ln * bif_w, n2[1] + norm[1] / ln * bif_w, n2[2]]
    mx = (n2[0] + end_n[0]) / 2
    my = (n2[1] + end_n[1]) / 2
    mz = (n2[2] + end_n[2]) / 2

    nodes.append([mx, my, mz])
    nodes.append(end_n)
    (maxdp, maxidx) = max_orient_dotp(nodes[i[1]-1], nodes[len(nodes)-1])
    if abs(maxdp) < .99:
        maxidx = add_orientation(nodes[i[1]-1], nodes[len(nodes)-1])
    elements.append({
        'nodes': [i[1]-1, len(nodes)-2, len(nodes)-1],
        'section': 'BOX',
        'dimensions': '.592,.833,.08,.08,.08,.08',
        'material': 'ACRY',
        'orientation': maxidx,
    })

    mx = (n2[0] + n5[0]) / 2
    my = (n2[1] + n5[1]) / 2
    mz = (n2[2] + n5[2]) / 2
    nodes.append([mx, my, mz])
    (maxdp, maxidx) = max_orient_dotp(nodes[i[1]-1], nodes[i[4]-1])
    if abs(maxdp) < .99:
        maxidx = add_orientation(nodes[i[1]-1], nodes[i[4]-1])
    elements.append({
        'nodes': [i[1]-1, len(nodes)-1, i[4]-1],
        'section': 'RECT',
        'dimensions': '.458,.125',
        'material': 'WOOD',
        'orientation': maxidx,
    })

# asgard
z_asg = nodes[113][2]
ldv = math.sqrt(nodes[116-1][0] ** 2 + nodes[116-1][1] ** 2)
udv = [nodes[116-1][0] / ldv, nodes[116-1][1] / ldv]
for n in [113, 115, 117, 119]:
    node = nodes[n-1]
    dp = node[0] * udv[0] + node[1] * udv[1]
    mn = [node[0] + udv[0] * (r_asg - dp), node[1] + udv[1] * (r_asg - dp), z_asg]
    mm = [(node[0] + mn[0]) / 2, (node[1] + mn[1]) / 2, z_asg]
    nodes.append(mm)
    nodes.append(mn)
    (maxdp, maxidx) = max_orient_dotp(nodes[n-1], nodes[len(nodes)-1])
    if abs(maxdp) < .99:
        maxidx = add_orientation(nodes[n-1], nodes[len(nodes)-1])
    elements.append({
        'nodes': [n-1, len(nodes)-2, len(nodes)-1],
        'section': 'RECT',
        'dimensions': '.292,.125',
        'material': 'WOOD',
        'orientation': maxidx,
    })
for i in [(407, 409), (409, 411), (411, 413)]:
    mx = (nodes[i[0]-1][0] + nodes[i[1]-1][0]) / 2
    my = (nodes[i[0]-1][1] + nodes[i[1]-1][1]) / 2
    mz = (nodes[i[0]-1][2] + nodes[i[1]-1][2]) / 2
    s_mid = [mx, my, mz]
    nodes.append(s_mid)
    (maxdp, maxidx) = max_orient_dotp(nodes[i[0]-1], nodes[i[1]-1])
    if abs(maxdp) < .99:
        maxidx = add_orientation(nodes[i[0]-1], nodes[i[1]-1])
    elements.append({
        'nodes': [i[0]-1, len(nodes)-1, i[1]-1],
        'section': 'RECT',
        'dimensions': '.292,.125',
        'material': 'WOOD',
        'orientation': maxidx,
    })

# asgard supports
for i in [(406, 97), (408, 97), (408, 99), (410, 99), (410, 101), (412, 101)]:
    mx = (nodes[i[0]-1][0] + nodes[i[1]-1][0]) / 2
    my = (nodes[i[0]-1][1] + nodes[i[1]-1][1]) / 2
    mz = (nodes[i[0]-1][2] + nodes[i[1]-1][2]) / 2
    s_mid = [mx, my, mz]
    nodes.append(s_mid)
    (maxdp, maxidx) = max_orient_dotp(nodes[i[0]-1], nodes[i[1]-1])
    if abs(maxdp) < .99:
        maxidx = add_orientation(nodes[i[0]-1], nodes[i[1]-1])
    elements.append({
        'nodes': [i[0]-1, len(nodes) - 1, i[1]-1],
        'section': 'RECT',
        'dimensions': '.292,.125',
        'material': 'WOOD',
        'orientation': maxidx,
    })

## entrance to niflheim
#for i in [2, 4, 147, 148, 20]:
#    for idx in range(len(elements['2x4'])):
#        if elements['2x4'][idx][1] == i - 1:
#            del elements['2x4'][idx]
#            break
#
## entrance to midgard
#for i in [247, 248, 96]:
#    for idx in range(len(elements['2x4'])):
#        if elements['2x4'][idx][1] == i - 1:
#            del elements['2x4'][idx]
#            break

# collate element sets
elsets = []
for el in elements:
    k = (el['section'], el['dimensions'], el['material'], el['orientation'])
    if k not in elsets:
        elsets.append(k)

#########################
#  output ccx .inp file
#########################
fout.write('*NODE,NSET=Nall\n')
for i, node in enumerate(nodes):
    node_line = str(i + 1) + ', ' + str(node[0]) + ', ' + str(node[1]) + ', ' + str(node[2]) + '\n'
    fout.write(node_line)

fout.write('*NSET,NSET=NRf\n')
fout.write('61\n')

fout.write('*TRANSFORM,NSET=NRf\n')
n = nodes[61 - 1]
fout.write(str(n[0]) + ',' + str(n[1]) + ',0,0,0,1\n')

fout.write('*ELEMENT,TYPE=B32R\n')
for i, el in enumerate(elements):
    n = el['nodes']
    el_line = str(i + 1) + ', ' + str(n[0] + 1) + ', ' + str(n[1] + 1) + ', ' + str(n[2] + 1) + '\n'
    fout.write(el_line)

for i, elset in enumerate(elsets):
    fout.write('*ELSET,ELSET=ES' + str(i + 1) + '\n')
    line = []
    for j, el in enumerate(elements):
        if elset == (el['section'], el['dimensions'], el['material'], el['orientation']):
            line.append(j)
            if len(line) == 16:
                fout.write(','.join([str(x + 1) for x in line]) + '\n')
                line = []
    fout.write(','.join([str(x + 1) for x in line]) + '\n')

fout.write('*ELSET,ELSET=EAll,GENERATE\n')
fout.write('1,' + str(len(elements)) + '\n')

fout.write('*BOUNDARY\n')
for i in [1,3,5,7,9,11,13,15,346,348,350,352]:
    fout.write(str(i) + ',1,3\n')

fout.write('*MATERIAL,NAME=WOOD\n')
fout.write('*ELASTIC,TYPE=ENGINEERING CONSTANTS\n')
fout.write('1.8E8,6.9E6,6.9E6,.337,.337,.372,8.1E6,8.1E6\n9.E5\n')
fout.write('*DENSITY\n')
fout.write('34.\n')

fout.write('*MATERIAL,NAME=ACRY\n')
fout.write('*ELASTIC\n')
fout.write('6.0E7,.37\n')
fout.write('*DENSITY\n')
fout.write('74.3\n')

for i, o in enumerate(orientations):
    fout.write('*ORIENTATION,NAME=O' + str(i + 1) + '\n')
    fout.write(','.join([str(x) for x in o]) + '\n')

for i, elset in enumerate(elsets):
    fout.write('*BEAM SECTION,ELSET=ES' + str(i + 1) + ',MATERIAL=' + elset[2] + ',SECTION=' + elset[0] + ',ORIENTATION=O' + str(elset[3] + 1) + '\n')
    fout.write(elset[1] + '\n') # dimensions

fout.write('*STEP\n')
fout.write('*STATIC\n')

fout.write('*DLOAD\n')
fout.write('EAll,GRAV,3.22E1,0.,0.,-1.\n')

fout.write('*CLOAD\n')
# midgard
load = math.pi * 16 * 100
fout.write('354,3,-' + str(load / 4 / 6) + '\n')
fout.write('356,3,-' + str(load / 4 / 3) + '\n')
fout.write('358,3,-' + str(load / 4 / 3) + '\n')
fout.write('360,3,-' + str(load / 4 / 6) + '\n')
fout.write('353,3,-' + str(load / 2 / 6) + '\n')
fout.write('355,3,-' + str(load / 2 / 3) + '\n')
fout.write('357,3,-' + str(load / 2 / 3) + '\n')
fout.write('359,3,-' + str(load / 2 / 6) + '\n')
fout.write('75,3,-' + str(load / 4 / 6) + '\n')
fout.write('77,3,-' + str(load / 4 / 3) + '\n')
fout.write('79,3,-' + str(load / 4 / 3) + '\n')
fout.write('65,3,-' + str(load / 4 / 6) + '\n')
#print 'midgard:', load
# bifrost
#fout.write('382,3,-200.\n383,3,-200.\n')
#fout.write('385,3,-200.\n386,3,-200.\n')
#fout.write('388,3,-200.\n389,3,-200.\n')
#fout.write('391,3,-200.\n392,3,-200.\n')
#fout.write('394,3,-200.\n395,3,-200.\n')
#fout.write('397,3,-200.\n398,3,-200.\n')
#fout.write('400,3,-200.\n401,3,-200.\n')
#fout.write('403,3,-200.\n404,3,-200.\n')
#print 'bifrost:', 200 * 16
# asgard
#load = math.pi * 9 * 100
#fout.write('407,3,-' + str(load / 4 / 6) + '\n')
#fout.write('409,3,-' + str(load / 4 / 3) + '\n')
#fout.write('411,3,-' + str(load / 4 / 3) + '\n')
#fout.write('413,3,-' + str(load / 4 / 6) + '\n')
#fout.write('406,3,-' + str(load / 2 / 6) + '\n')
#fout.write('408,3,-' + str(load / 2 / 3) + '\n')
#fout.write('410,3,-' + str(load / 2 / 3) + '\n')
#fout.write('412,3,-' + str(load / 2 / 6) + '\n')
#fout.write('113,3,-' + str(load / 4 / 6) + '\n')
#fout.write('115,3,-' + str(load / 4 / 3) + '\n')
#fout.write('117,3,-' + str(load / 4 / 3) + '\n')
#fout.write('119,3,-' + str(load / 4 / 6) + '\n')
#print 'asgard:', load

#fout.write('*EL PRINT,ELSET=EAll\n')
#fout.write('S\n')

fout.write('*EL FILE\n')
fout.write('S\n')

#fout.write('*NODE PRINT,NSET=NRf\n')
#fout.write('RF,U\n')

fout.write('*NODE FILE\n')
fout.write('RF,U\n')

fout.write('*END STEP\n')

#fout.write('*STEP,PERTURBATION\n')
#fout.write('*BUCKLE\n')
#fout.write('1\n')
#fout.write('*END STEP\n')


import torch
from .synth import SynthData
from .fscd import build as build_fscd
from .gmot import build as build_gmot
from .coco import build as build_coco

class JOINTFSCD(torch.utils.data.Dataset):
    def __init__(self, args, datasets) -> None:
        super().__init__()

        self.datasets = datasets
        self.args = args
        self.lens = [len(d) for d in datasets]

    def __len__(self):
        return sum(self.lens)

    def __getitem__(self, idx):
        try:
            for dataset in self.datasets:
                d_len = len(dataset)
                if idx < d_len:
                    return self._check(dataset[idx])
                idx -= d_len
        except Exception as e:
            print(e)
        return dataset[idx-1] #should never happen

    def _check(self, tmp):
        if any([len(t.boxes)==0 for t in tmp['gt_instances']]):
            return self[int(torch.rand(1)*sum(self.lens))]
        return tmp

    def set_epoch(self, epoch,**b):
        for d in self.datasets:
            d.set_epoch(epoch)

def build(split, args):
    datasets = []
    for d_name in args.dataset_file.split('_')[1:]:
        if 'gmot' in d_name:
            datasets.append(build_gmot(split, args))
        elif 'fscd' in d_name:
            datasets.append(build_fscd(split, args))
        elif 'synth' in d_name:
            datasets.append(SynthData(args))
        elif 'coco' in d_name:
            datasets.append(build_coco(split, args))

    return JOINTFSCD(args, datasets)


import random
import matplotlib.pyplot as plt

# Перемешиваем массив
def monty_hall_without_change(choices):
    random.shuffle(choices)
    return choices[random.randrange(len(choices))]

# Перемешиваем массив
def monty_hall_with_change(choices):
    random.shuffle(choices)
    # Первый выбор
    first_choice = random.randrange(len(choices))
    # Ведущий открывает дверь с козлом
    for i in range(len(choices)):
        if i != first_choice and choices[i] == 'к':
            host_choice = i
            break
    # Второй выбор отменяет первое решение
    for i in range(len(choices)):
        if i != first_choice and i != host_choice:
            return choices[i]

# К - козел, а - автомобиль
# По условию задачи имеем двух козлов и один автомобиль
choices = ['k', 'k', 'a']
# Количество опытов
N = 100000

# Вариант с неизменным выбором
win_count = 0
for _ in range(N):
    result = monty_hall_without_change(choices)
    if result == 'a':
        win_count += 1
P_without_change = round(win_count/N, 3)

# Вариант с изменением выбора
win_count = 0
for _ in range(N):
    result = monty_hall_with_change(choices)
    if result == 'a':
        win_count += 1
P_with_change = round(win_count/N, 3)

# Вероятность выиграть - частота выигранных опытов
print(f'Вероятность выиграть без изменения двери {P_without_change}')
print(f'Вероятность выиграть c изменением двери {P_with_change}')

fig, ax = plt.subplots()

fruits = ['Без изменения двери', 'C изменением двери']
option = [P_without_change, P_with_change]
bar_labels = ['Без изменения двери', 'C изменением двери']
bar_colors = ['tab:red', 'tab:blue']

ax.bar(fruits, option, label=bar_labels, color=bar_colors)

ax.set_ylabel('Процент вероятности выигрыша')
ax.set_title('Распределение вероятности выигрыша c изменением и без изменения двери')
ax.legend(title='Вариант')

plt.show()


#!/usr/bin/env python

"""The setup script."""

from setuptools import setup, find_packages

with open("README.rst") as readme_file:
    readme = readme_file.read()

with open("HISTORY.rst") as history_file:
    history = history_file.read()

def get_requirements(requirements_file="requirements.txt"):
    """Get the contents of a file listing the requirements.
    :arg requirements_file: path to a requirements file
    :type requirements_file: string
    :returns: the list of requirements, or an empty list if
              `requirements_file` could not be opened or read
    :return type: list
    """

    try:
        lines = open(requirements_file).readlines()
    except FileNotFoundError:
        lines = []
    dependencies = []
    for line in lines:
        maybe_dep = line.strip()
        if maybe_dep.startswith("#"):
            # Skip pure comment lines
            continue
        if maybe_dep.startswith("git+"):
            # VCS reference for dev purposes, expect a trailing comment
            # with the normal requirement
            __, __, maybe_dep = maybe_dep.rpartition("#")
        else:
            # Ignore any trailing comment
            maybe_dep, __, __ = maybe_dep.partition("#")
        # Remove any whitespace and assume non-empty results are dependencies
        maybe_dep = maybe_dep.strip()
        if maybe_dep:
            dependencies.append(maybe_dep)
    return dependencies

setup(
    author="Michal Konečný",
    author_email="michal.konecny@packetseekers.eu",
    python_requires=">=3.7",
    classifiers=[
        "Development Status :: 2 - Pre-Alpha",
        "Intended Audience :: Developers",
        "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
        "Natural Language :: English",
        "Programming Language :: Python :: 3",
        "Programming Language :: Python :: 3.7",
        "Programming Language :: Python :: 3.8",
    ],
    description="Interactive map of the Fedora Infrastructure applications ",
    entry_points={
        "console_scripts": [
            "fedora_infra_map=fedora_infra_map.cli:main",
        ],
    },
    install_requires=get_requirements(),
    license="GNU General Public License v3",
    long_description=readme + "\n\n" + history,
    include_package_data=True,
    keywords="fedora_infra_map",
    name="fedora_infra_map",
    packages=find_packages(include=["fedora_infra_map", "fedora_infra_map.*"]),
    test_suite="tests",
    tests_require=get_requirements("requirements_test.txt"),
    url="https://github.com/zlopez/fedora_infra_map",
    version="0.1.0",
    zip_safe=False,
)


import json
from .models import *

def cookieCart(request):
    try:
        cart = json.loads(request.COOKIES['cart'])
        print("\nFrom cookieCart function. We got our cart started!")
    except:
        cart = {}
        print("From cookieCart function. We didn't get past this point!")
    print('Cart:', cart)
    items = []
    order = {'get_cart_total':0, 'get_cart_items':0, 'shipping':False}
    cartItems = order['get_cart_items']

    for i in cart:
        try:
            cartItems += cart[i]['quantity']

            product = Product.objects.get(id=i)
            total = (product.price * cart[i]["quantity"])

            order['get_cart_total'] += total
            order['get_cart_items'] += cart[i]["quantity"]

            item = {
                'product':{
                    'id':product.id,
                    'name':product.name,
                    'price':product.price,
                    'imageURL':product.imageURL,
                    },
                'quantity':cart[i]['quantity'],
                'get_total':total,
                }
            items.append(item)

            if product.digital == False:
                order['shipping'] = True
        except:
            pass
        print("Cart is now: {}".format(cart))
    print("Final cart composition: {}".format(cart))
    return {'cartItems':cartItems, 'order':order, 'items':items}

def cartData(request):
    if request.user.is_authenticated and hasattr(request.user, 'profile'):
        customer = request.user.profile
        print("\nThe user profile is {}\n".format(customer))
        order, created = Order.objects.get_or_create(customer=customer, complete=False)
        items = order.orderitem_set.all()
        cartItems = order.get_cart_items
        print("\n\nFrom within cartData function: User is authenticated!\n")
    else:
        cookieData = cookieCart(request)
        cartItems = cookieData['cartItems']
        order = cookieData['order']
        items = cookieData['items']
        print("From cartData function: User is not authenticated!")
    return {'cartItems':cartItems, 'order':order, 'items':items}

def guestOrder(request, data):

    print('User is not logged in..')

    print('COOKIES:', request.COOKIES)
    name = data['form']['name']
    email = data['form']['email']

    cookieData = cookieCart(request)
    items = cookieData['items']

    customer, created = Customer.objects.get_or_create(
        email=email,
    )
    customer.name = name
    customer.save()

    order = Order.objects.create(
        customer=customer,
        complete=False,
    )

    for item in items:
        product = Product.objects.get(id=item['product']['id'])

        orderItem = OrderItem.objects.create(
            product=product,
            order=order,
            quantity=item['quantity']
        )

    return customer, order


import os
import random
import hydra
import logging
import pyrootutils
from omegaconf import DictConfig, OmegaConf
from pandas import DataFrame
from rich.progress import track

from src.datamodules.components.dataset_base import DatasetBase

import pandas
pandas.options.mode.chained_assignment = None

root = pyrootutils.setup_root(
    search_from=__file__,
    indicator=[".git", "setup.py"],
    pythonpath=True,
    dotenv=True,
)
# LOAD ENV VARIABLES & INSTANTIATE LOGGER
CONFIG_DIR = os.path.join(root, "config")

logger = logging.getLogger(__name__)

OmegaConf.register_new_resolver(
    "dotsplit", lambda name: name.split(".")[-1], replace=True
)

REPLACE_TOKEN_RATE = 0.002
SKIP_TOKEN_RATE = 0.002
ADD_TOKEN_RATE = 0.002

SWAP_EVENT_RATE = 0.00
SKIP_EVENT_RATE = 0.00
REPEAT_EVENT_RATE = 0.00

REPLACE_TOKEN_CODE = 64
SKIP_TOKEN_CODE = 128
ADD_TOKEN_CODE = 256

SWAP_EVENT_CODE = 8
SKIP_EVENT_CODE = 16
REPEAT_EVENT_CODE = 32

@hydra.main(version_base=None, config_path=CONFIG_DIR, config_name="train.yaml")
def main(cfg: DictConfig):
    dataset: DatasetBase = hydra.utils.instantiate(cfg.dataset)

    annotations = dataset.annotations
    vocab = dataset.vocab

    for i, row in track(
        annotations.iterrows(), description="inducing anomalies", total=len(annotations)
    ):
        req_file = row["MESSAGE"]

        anomaly_code: int = 0
        dir = os.path.join(cfg.dataset.files_dir)
        with open(os.path.join(dir, "documents", req_file), "r") as file:  # type: ignore
            tokens = file.read().split(" ")

        if random.random() < REPLACE_TOKEN_RATE:
            tokens = replace_token(tokens, vocab)
            anomaly_code += REPLACE_TOKEN_CODE

        if random.random() < SKIP_TOKEN_RATE:
            tokens = skip_token(tokens)
            anomaly_code += SKIP_TOKEN_CODE

        if random.random() < ADD_TOKEN_RATE:
            tokens = add_token(tokens, vocab)
            anomaly_code += ADD_TOKEN_CODE

        if random.random() < SWAP_EVENT_RATE:
            replacement = annotations.iloc[i + 1, 1]  # type: ignore
            mem = row["TIMESTAMP"]
            annotations.at[i, "TIMESTAMP"] = replacement
            annotations.at[i + 1, "TIMESTAMP"] = mem  # type: ignore
            anomaly_code += SWAP_EVENT_CODE

        if random.random() < SKIP_EVENT_RATE:
            annotations.drop(i, inplace=True)
            annotations.sort_index(inplace=True)
            annotations.reset_index(drop=True, inplace=True)
            anomaly_code += SKIP_EVENT_CODE  # assuming the code will be assigned to the succeeding event

        if random.random() < REPEAT_EVENT_RATE:
            annotations.loc[i + 0.5] = annotations.loc[i]  # type: ignore
            annotations.sort_index(inplace=True)
            annotations.reset_index(drop=True, inplace=True)
            anomaly_code += REPEAT_EVENT_CODE

        mut_dir = os.path.join(dir, "documents_mut")
        if not os.path.exists(mut_dir):
            os.mkdir(mut_dir)

        with open(os.path.join(mut_dir, req_file), "w") as file:  # type: ignore
            file.write(" ".join(tokens))

        annotations.at[i, "CODE"] = anomaly_code

    annotations["CODE"] = annotations["CODE"].astype(int, errors="ignore")  # type: ignore
    path_splits = list(os.path.split(cfg.dataset.annotations))
    location = os.path.join(*path_splits[:-1], "annotations_mut.csv")
    annotations.to_csv(location, index=False)

#######################################
# Anomalies in the content of messages
#######################################

def replace_token(tokens, vocab):
    idx = random.choice(range(len(tokens)))
    replacement = vocab.sample()
    tokens[idx] = replacement.iloc[0, 0]
    return tokens

def skip_token(tokens):
    idx = random.choice(range(len(tokens)))
    tokens.pop(idx)
    return tokens

def add_token(tokens, vocab):
    idx = random.choice(range(len(tokens)))
    replacement = vocab.sample()
    tokens.insert(idx, replacement.iloc[0, 0])
    return tokens

if __name__ == "__main__":
    main()


#CAPITALIZE
def capitalize(name):
    """
    input: name --> a string in the form "first last"
    output: returns a string with each of the two words capitalized
    note: this is the one we started in class
    """
    space_index = name.find(" ")
    first = name[:space_index]
    first = first.capitalize()
    last = name[space_index+1:]
    last = last.capitalize()
    return first + " " + last
print(capitalize("beth sanders"))

#INIT
def init(name):
    """
    Input: name --> a string in the form "first last"
    Returns: a string in the form "F. Last" where it's a capitalized first inital
    and capitalized last name
    """
    space_index = name.find(" ")
    first = name[:1]
    first = first.capitalize()
    last = name[space_index+1:]
    last = last.capitalize()
    return first + ". " + last
print(init("daniel erwing"))

#PART_PIG_LATIN
def part_pig_latin(name):
    """
    Input: A string that is a single lower case word
    Returns: that string in fake pig latin -> move the first letter of the word to the end and add "ay"
    so: "hello" --> "ellohay"
    """
    first_letter = name[:1]
    mid_letter = name[1:len(name)-1]
    last_letter = name[len(name)-1:len(name)]
    pig_latin = last_letter + mid_letter + first_letter + "ay"
    return pig_latin
print(part_pig_latin("Hello"))
print(part_pig_latin("Mary"))

#MAKE_OUT_WORD
def make_out_word(out, word): #defined function with input out and word
  if len(out)==4: #if the length of the out input is 4
    first=out[:2] #first is assigned to the first two charaters
    last=out[2:] #last is assigned from the second character to the last
  return first + word + last #return the first 2 chars of out +word +the rest of the out input after the 2nd char
print(make_out_word("<<>>","Same"))

#MAKE_TAGS
def make_tags(tag, word): #defined function with tag and word inputs
  return "<" + tag + ">" + word + "</" + tag + ">" # return tags between "<" & ">" and "</" & ">"
    #in between the tags and their pairs of "<" and ">" word input occurs
print(make_tags('i', 'Yay'))
print(make_tags('i', 'Hello'))
print(make_tags('cite', 'Yay'))


# attachedLocalSpace
#
# closestPolygonAndWeights
#   input:
#     p     a point in world space
#     mesh  a mesh node the p attach to
#
#   return:
#     the vertex id list of polygon nearest to p
#     vertex weights with which the point on nearest polygon can be combined.
#
import pymel.core as pm
import pymel.core.datatypes as dt
import maya.cmds as cmds
import maya.OpenMaya as om

def pointInTriangle(a,b,c,p):
    v0 = b - a
    v1 = c - a
    v2 = p - a

    dot00 = v0.dot(v0)
    dot01 = v0.dot(v1)
    dot02 = v0.dot(v2)
    dot11 = v1.dot(v1)
    dot12 = v1.dot(v2)

    inverDeno = 1 / (dot00 * dot11 - dot01 * dot01)

    u = (dot11 * dot02 - dot01 * dot12) * inverDeno
    v = (dot00 * dot12 - dot01 * dot02) * inverDeno

    if v < -1e-3 or v > 1 or u < -1e-3 or u > 1:
        return False,u,v

    return u + v <= 1 + 1e-3,u,v

def meshNodeAndMatrix(mesh):
    meshNode = pm.PyNode(mesh)
    parentNode = meshNode.parent(0)
    invWorldMat = parentNode.worldInverseMatrix.get()
    worldMat = parentNode.worldMatrix.get()
    return meshNode, worldMat, invWorldMat

def createMeshIntersector(mesh):
    meshNode, worldMat, invWorldMat = meshNodeAndMatrix(mesh)
    itersector = om.MMeshIntersector()
    # triIdArray = om.MIntArray()
    # for i in triIdList:
    #     triIdArray.append(i)

    om.MMeshIntersector.create(itersector, meshNode.__apimobject__(), invWorldMat)
    return itersector

def closestPolygonAndWeights(p, mesh, meshIntersector):
    meshNode, worldMat, invWorldMat = meshNodeAndMatrix(mesh)

    pointOnMesh = om.MPointOnMesh()
    meshIntersector.getClosestPoint(p, pointOnMesh)

    polyId = pointOnMesh.faceIndex()
    triId = pointOnMesh.triangleIndex()
    cp = pointOnMesh.getPoint()

    u_util = om.MScriptUtil()
    u_util.createFromDouble(0)
    u_ptr = u_util.asFloatPtr()

    v_util = om.MScriptUtil()
    v_util.createFromDouble(0)
    v_ptr = v_util.asFloatPtr()

    pointOnMesh.getBarycentricCoords(u_ptr, v_ptr)
    triVids = meshNode.getPolygonTriangleVertices(polyId, triId)
    return triVids, u_util.getFloat(u_ptr), v_util.getFloat(v_ptr)

def closestMatrix(u, v, mesh, vids):
    meshNode, worldMat, invWorldMat = meshNodeAndMatrix(mesh)

    p3 = [ dt.Point(meshNode.getPoint(i)) * worldMat for i in vids ]
    xAxis = p3[1] - p3[0];
    zAxis = p3[2] - p3[0];

    orgP = p3[0] + xAxis * u + zAxis * v;

    yAxis = xAxis.cross(zAxis);
    yAxis.normalize();
    xAxis.normalize();
    zAxis = xAxis.cross(yAxis);
    zAxis.normalize();

    return dt.Matrix(
        xAxis.x, xAxis.y, xAxis.z, 0.0,
        yAxis.x, yAxis.y, yAxis.z, 0.0,
        zAxis.x, zAxis.y, zAxis.z, 0.0,
        orgP.x, orgP.y, orgP.z, 1.0 );

def makeAttachLocalSpace(attachedTransNode, mesh, pIds, wList):
    if not cmds.pluginInfo("skelTree",q=True,l=True):
        cmds.loadPlugin("skelTree")

    node = cmds.createNode("attachedLocalSpace")
    cmds.connectAttr("{}.outMesh".format(mesh),"{}.inMesh".format(node))

    transNode = cmds.listRelatives(mesh, p=True)[0]
    cmds.connectAttr("{}.worldMatrix".format(transNode),"{}.inWorldMatrix".format(node))
    for i in range(len(pIds)):
        cmds.setAttr("{}.mInPList[{}].inPntId".format(node, i), pIds[i])
        cmds.setAttr("{}.mInPList[{}].inWeight".format(node, i), wList[i])

    rootTransNode = cmds.group(em=True, n="attachedGroup")
    cmds.connectAttr("{}.outTranslate".format(node), "{}.translate".format(rootTransNode),f=True)
    cmds.connectAttr("{}.outRotate".format(node), "{}.rotate".format(rootTransNode),f=True)
    cmds.parent(attachedTransNode, rootTransNode)

def transformAttachToMesh(transNode, mesh):
    p=cmds.xform(transNode, q=True, ws=True, t=True)
    vIds, w = closestPolygonAndWeights(dt.Point(p), mesh)
    makeAttachLocalSpace(transNode, mesh, vIds, w)

def transformAttachToMeshSel():
    transList = cmds.ls(sl=True)
    if len(transList) < 2:
        print("Two nodes should be selected! the first one should be attached node and the second one should be target mesh.")

    targetMesh = cmds.ls(transList[-1],dag=True,type="mesh",noIntermediate=True)[0]
    for trans in transList[:-1]:
        transformAttachToMesh(trans, targetMesh)

# transformAttachToMeshSel()


# 알파벳으로 이루어진 문자열을 입력 받아 각 알파벳을 1부터 26까지의 숫자로 변환하여 출력하라.

# [제약 사항]
# 문자열의 최대 길이는 200이다.

# [입력]
# 알파벳으로 이루어진 문자열이 주어진다.

# [출력]
# 각 알파벳을 숫자로 변환한 결과값을 빈 칸을 두고 출력한다.

Alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
Alphabet = list(Alphabet)
Number = list(range(1, 27))

Alpha_num = dict(zip(Alphabet, Number))

input_alpha = input()

for alpha in list(input_alpha):
    print(f'{Alpha_num[alpha]}', end = ' ')


#!/usr/bin/python3

# from os import SCHED_OTHER
from enum import Enum, auto
from re import X
from which_pyqt import PYQT_VER
if PYQT_VER == 'PYQT5':
	from PyQt5.QtCore import QLineF, QPointF
elif PYQT_VER == 'PYQT4':
	from PyQt4.QtCore import QLineF, QPointF
else:
	raise Exception('Unsupported Version of PyQt: {}'.format(PYQT_VER))

import math

# Used to compute the bandwidth for banded version
MAXINDELS = 3
SEQRETURNLEN = 100

# Used to implement Needleman-Wunsch scoring
MATCH = -3
INDEL = 5
SUB = 1

# Indicates the direction the previous cell in the matrix
class Direction(Enum):
	LEFT = auto()
	TOP = auto()
	DIAGONAL = auto()

# Contains the costVal, previous cell which helped calculate that, and the direction the previous cell came from
# Space: O(1)
class Cost:
	def __init__(self, cost:int, prev:tuple, dir:Direction):
		self.costVal = cost
		self.prev = prev
		self.direction = dir

	def __eq__(self, other):
		return (self.costVal, self.prev, self.direction) == (other.costVal, other.prev, self.direction)

class GeneSequencing:
	def __init__( self ):
		pass

	# Print the cost dictionary
	def printDict(self, seq1, seq2):
		table_data = [[]]
		# Put the first row aka listing the seq1
		for i in range(-1, self.numColumns):
			if i == -1:
				table_data[0].append(" ")
			elif i == 0:
				table_data[0].append("_")
			else:
				table_data[0].append(seq1[i-1])

		for i in range(0, self.numRows):
			table_data.append([])
			last = len(table_data)-1
			for j in range(-1, self.numColumns):
				if j == -1 and i == 0:
					table_data[last].append("_")
				elif j == -1:
					table_data[last].append(seq2[i-1])
				else:
					string = "" #f"({i},{j}):"
					item = self.costDict.get(tuple((i, j)))
					if type(item) == Cost:
						string += f"{item.costVal}"
					else:
						string += " "
					table_data[last].append(string)

		formatString = "{: >5} "
		for row in table_data:
			for item in row:
				print(formatString.format(item), end="")
			print()
		print()

	# Traverse through the matrix and build up the alignment strings
	# Time: O(x), Space: O(1) [x=max(len(seq1), len(seq2))]
	def getAlignmentStrings(self, seq1, seq2, cell:tuple):
		alignment1, alignment2 = "", ""
		while not (cell[0] == 0 and cell[1] == 0):
			cost = self.costDict.get(cell)
			if cost.direction == Direction.LEFT:
				alignment1 += seq1[cell[1]-1]
				alignment2 += "-"
			elif cost.direction == Direction.TOP:
				alignment1 += "-"
				alignment2 += seq2[cell[0]-1]
			elif cost.direction == Direction.DIAGONAL:
				alignment1 += seq1[cell[1]-1]
				alignment2 += seq2[cell[0]-1]
			cell = cost.prev

		#Reverse strings and cut to 100, Time: O(x)
		return alignment1[::-1][:100], alignment2[::-1][:100]

	# Check the banded setting and return the value, Time: O(1)
	def checkBanded(self, trueVal, falseVal):
		if self.banded:
			return trueVal
		else:
			return falseVal

	# Given two sequences, find the optimal alignment of Insert/Deletion, Substitution or Match
	#    @required _seq1_(top of matrix) and _seq2_(side of matrix) are two sequences to be aligned
	#    @required _banded_ is a boolean for computing banded alignment or full alignment
	# 	 @required align_length_ = how many base pairs to use in computing the alignment
	# UNBAN_Time: O(mn) UNBAN_Space: O(mn) [seq1=m, seq2=n]
	# BAN_Time: O(kn) BAN_Space: O(kn) [k=2(MAXINDELS)+1, seq2=n]
	def align(self, seq1, seq2, banded, align_length):
		#Cut sequences and check for matching
		if len(seq1) > align_length:
			seq1 = seq1[:align_length]
		if len(seq2) > align_length:
			seq2 = seq2[:align_length]
		if seq1 == seq2:
			return {'align_cost':len(seq1)*MATCH, 'seqi_first100':seq1, 'seqj_first100':seq2}

		self.banded = banded
		self.numColumns = len(seq1)+1
		self.numRows = len(seq2)+1

		# CostDict => Key[tuple((rowIndex, columnIndex))] : [Cost(val:int, prevCellTuple, prevDirection)]
		# UNBAN_Space: O(mn), BAN_Space: O(kn)
		self.costDict = dict()

		self.costDict[tuple((0,0))] = Cost(0, None, None)

		# Fill first row, UNBAN_Time: O(n), BAN_Time: O(k+1)
		numFirstRow = self.checkBanded(min(1+MAXINDELS,self.numColumns), self.numColumns)
		for i in range(1, numFirstRow):
			self.costDict[tuple((0,i))] = Cost(i*INDEL, tuple((0, i-1)), Direction.LEFT)

		#Fill first col, UNBAN_Time: O(m), BAN_Time: O(k+1)
		numFirstCol = self.checkBanded(min(1+MAXINDELS,self.numRows), self.numRows)
		for i in range(1, numFirstCol):
			self.costDict[tuple((i,0))] = Cost(i*INDEL, tuple((i-1, 0)), Direction.TOP)

		#Run algorithm for all cells, UNBAN_Time: O((m-1)*(n-1)), BAN_Time: O(k*n)
		for rowIndex in range(1, self.numRows):
			colStart = self.checkBanded(max(rowIndex-MAXINDELS,1), 1)
			colEnd = self.checkBanded(min(rowIndex+MAXINDELS+1,self.numColumns), self.numColumns)

			# Calculate costs with priority: left > top > diagonal
			for colIndex in range(colStart, colEnd):
				minCost = Cost(math.inf, None, None)

				# Calculate diagonal cost if match/sub
				diagonalPrevCell = tuple((rowIndex-1, colIndex-1))
				diagonalPrevCost = self.costDict.get(diagonalPrevCell)
				if diagonalPrevCost is not None:
					diagonalCost = Cost(diagonalPrevCost.costVal, diagonalPrevCell, Direction.DIAGONAL)
					if (seq1[colIndex-1] == seq2[rowIndex-1]):
						diagonalCost.costVal += MATCH
					else:
						diagonalCost.costVal += SUB
					if diagonalCost.costVal < minCost.costVal:
						minCost = diagonalCost

				# Calculate top cost if indel
				topPrevCell = tuple((rowIndex-1, colIndex))
				topPrevCost = self.costDict.get(topPrevCell)
				if topPrevCost is not None:
					topCost = Cost(topPrevCost.costVal+INDEL, topPrevCell, Direction.TOP)
					if topCost.costVal <= minCost.costVal:
						minCost = topCost

				# Calculate left cost if indel
				leftPrevCell = tuple((rowIndex, colIndex-1))
				leftPrevCost = self.costDict.get(leftPrevCell)
				if leftPrevCost is not None:
					leftCost = Cost(leftPrevCost.costVal+INDEL, leftPrevCell, Direction.LEFT)
					if leftCost.costVal <= minCost.costVal:
						minCost = leftCost

				self.costDict[tuple((rowIndex,colIndex))] = minCost
				# self.printDict(seq1, seq2)

		cell = tuple((len(seq2), len(seq1)))
		cost = self.costDict.get(cell)
		score = math.inf
		if cost is not None: # This would happen if it is outside of the band
			score = cost.costVal
		if score != math.inf:
			alignment1, alignment2 = self.getAlignmentStrings(seq1, seq2, cell)
		else:
			alignment1 = alignment2 = "No Alignment Possible"
		# print(alignment1)
		# print(alignment2)

		return {'align_cost':score, 'seqi_first100':alignment1, 'seqj_first100':alignment2}


import os
import sys
import json

data = dict()
data["node"] = dict()
data["link"] = dict()

def loadDataDirectory(dirPath):
    '''
    Given the directory path to where the
    network tree is stored, this will traverse
    through the directory and grab all of the
    geojson files.
    '''
    for dirName, subDir, fileList in os.walk(dirPath):
        for fileName in fileList:
            if "json" in fileName:
                absPath = os.path.join(dirName, fileName)
                loadGeojson(absPath)

def loadGeojson(path):
    '''
    Opens given geojson file
    Checks the contents of the json file
    Sorts it by the type of content by storing it into
    a dict
    '''
    geofile = None
    geodata = None

    try:
        geofile = open(path, 'r')
        geodata = json.load(geofile)
    except Exception as e:
        print("{} does not exist or JSON file failed to parse\n{}\e".format(path,e))

    if not geodata:
        return
    if not "properties" in geodata:
        return
    if not "prmname" in geodata["properties"]:
        return

    #set directory path of geojson file to get csv files
    geodata["dirpath"] = os.path.dirname(path)
    # #set directory path of csv/other files related to geojson file
    # geodata["geofolder"] = os.path.join(geodata["dirpath"], geofolder)

    if geodata["properties"]["type"] in ['Diversion', 'Return Flow']:
        data["link"][geodata["properties"]["prmname"]] = geodata
    else:
        data["node"][geodata["properties"]["prmname"]] = geodata

def generatePRI():

    result = ''
    result += '..       ***** NODE DEFINITIONS *****\n'
    result += '..       \n'
    result += nodeData()

    result += '..       \n'
    result += '..       \n'
    result += '..       \n'
    result += 'LINK     DIVR     SOURCE    SINK    1.000    0.00\n'
    result += 'LD     Continuity Link\n'
    result += '..       \n'

    result += '..       ***** INFLOW DEFINITIONS *****\n'
    result += '..       \n'
    result += inflowData()
    result += '..       \n'

    result += '..       ***** STORAGE LINK DEFINITIONS *****\n'
    result += '..       \n'
    result += rstoData()

    result += divrData()
    result += "STOP\n"

    return result

def nodeData():
    nodeOutput = ''
    nodeSorted = data["node"].keys()
    nodeSorted.sort()

    for node in nodeSorted:
        geojson = data["node"][node]

        name = geojson["properties"]["prmname"]
        desc = geojson["properties"]["description"]
        initStorage = ''
        endStorage = ''
        areaCapFactor = ''

        if "initialstorage" in geojson["properties"]:
            initStorage = geojson["properties"]["initialstorage"]
        if "endingstorage" in geojson["properties"]:
            endStorage = geojson["properties"]["endingstorage"]
        if "areacapfactor" in geojson["properties"]:
            initStorage = geojson["properties"]["areacapfactor"]

        nodeOutput += "NODE     {} {} {} {}\n".format(name, initStorage, areaCapFactor, endStorage)
        nodeOutput += "ND       {}\n".format(desc)
        nodeOutput += "..         \n"

    return nodeOutput

def inflowData():
    inflowOutput = ''
    inflowSorted = data["node"].keys()
    inflowSorted.sort()

    for inflow in inflowSorted:
        geojson = data["node"][inflow]

        if not "inflows" in geojson["properties"] or not geojson["properties"]["inflows"]:
            continue

        name = geojson["properties"]["prmname"]

        desc = geojson["properties"]["inflows"]["default"]["description"]

        inflowOutput += "LINK      {:<10}{:<10}{:<10}{:<10}{:<10}\n".format("INFL","SOURCE", name, "1.000","0.00")
        #inflowOutput += "LINK      INFL      SOURCE    {}   1.000     0.00\n".format(name)
        inflowOutput += "LD        {}\n".format(desc)
        inflowOutput += "IN        A={} B={} C={} E={} F={}\n".format("","SOURCE_" + name, "FLOW_LOC(KAF)", "1MON", "")
        inflowOutput += "..        \n"

    return inflowOutput

def rstoData():
    rstoOutput = ''
    rstoSorted = data["node"].keys()
    rstoSorted.sort()

    for rsto in rstoSorted:
        geojson = data["node"][rsto]

        if not geojson["properties"]["type"] in ["Surface Storage", "Groundwater Storage"]:
            continue

        name = geojson["properties"]["prmname"]
        desc = geojson["properties"]["description"]
        costs = geojson["properties"]["costs"]

        bounds = ''
        if "bounds" in geojson["properties"]:
            bounds = geojson["properties"]["bounds"]

        boundTable = getBounds(geojson)

        lowerConst = boundTable["lowerConst"]
        upperConst = boundTable["upperConst"]
        BL = boundTable["BL"]
        BU = boundTable["BU"]
        QL = boundTable["QL"]
        QU = boundTable["QU"]
        EV = ''
        PS = ''
        LD = "LD        {}\n".format(desc)

        link = "LINK      {:<10}{:<10}{:<10}{:<10}{:<10}{:<10}\n".format("RSTO",name, name, "1.000",lowerConst,upperConst)

        #COSTS
        if costs["type"] == "Monthly Variable":
            EV = "EV        A={} B={} C={} F={}\n".format("",name,"EVAP_RATE(FT)", desc)
            for month in ["JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"]:
                PS += "PS        MO={} A={} B={} C={} D={} E={} F={}\n".format(month,"UCD CAP1", name, "Q(K$-KAF)-P","",month,"")
        elif costs["type"] == "Annual Variable":
            monthLabel = "JAN-DEC"
            PS = "PS        MO={} A={} B={} C={} D={} E={} F={}\n".format(monthLabel,"UCD CAP1","DUMMY","Q(K$-KAF)-P","","", "")
        else: #All variables
            PS = "PS        MO={} A={} B={} C={} D={} E={} F={}\n".format("ALL","UCD CAP1","DUMMY","BLANK","","", "")

        QI = "QI        A={} B={} C={} D={} E={} F={}\n".format("", name, "STOR", "", "1MON", "")

        rstoOutput += link + LD + QL + QU + BL + BU + EV + PS + QI + "..      \n"

    return rstoOutput

def getBounds(geojson):
    boundsTable = dict()
    boundsTable["lowerConst"] = ''
    boundsTable["upperConst"] = ''
    boundsTable["BU"] = ''
    boundsTable["BL"] = ''
    boundsTable["QL"] = ''
    boundsTable["QU"] = ''

    boundsList = geojson["properties"]["bounds"]

    for bounds in boundsList:

        #list , months
        if bounds["type"] in ["LBM","UBM"]:
            filename = "{}.csv".format(bounds["type"])
            filepath = os.path.join(geojson["dirpath"], filename)
            boundscsv = open(filepath, 'r')
            boundslist = []
            for line in boundscsv:
                line = line.strip()
                splitdata = line.split(",")
                if splitdata[0] in ["JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"]:
                    boundslist.append(splitdata[1])

            mboundkey = "BU"
            if bounds["type"] == "LBM":
                mboundkey = "BL"

            boundsTable[mboundkey] = "{}        {}\n".format(mboundkey, ','.join(boundslist))

        #constants
        if bounds["type"] == "LBC":
            boundsTable["lowerConst"] = bounds["bound"]
        if bounds["type"] == "UBC":
            boundsTable["upperConst"] = bounds["bound"]

        #Time Series
        if bounds["type"] == "LBT":
            boundsTable["QL"] = "QL        A={} B={} C={} D={} E={} F={}\n".format("",geojson["properties"]["prmname"], "STOR_LBC(KAF)","", "1MON", geojson["properties"]["description"])
        if bounds["type"] == "UBT":
            boundsTable["QU"] = "QU        A={} B={} C={} D={} E={} F={}\n".format("",geojson["properties"]["prmname"], "STOR_LBC(KAF)","", "1MON", geojson["properties"]["description"])

    return boundsTable

def divrData():
    divrOutput = ''
    divrSorted = data["link"].keys()
    divrSorted.sort()

    for divr in divrSorted:
        geojson = data["link"][divr]

        if geojson["properties"]["type"] != "Diversion":
            continue

        name      = geojson["properties"]["prmname"]
        origin    = geojson["properties"]["origin"]
        terminus = geojson["properties"]["terminus"]
        amplitude = geojson["properties"]["amplitude"]
        desc      = geojson["properties"]["description"]

        bounds = ''
        if "bounds" in geojson["properties"]:
            bounds = geojson["properties"]["bounds"]

        boundTable = getBounds(geojson)

        lowerConst = boundTable["lowerConst"]
        upperConst = boundTable["upperConst"]
        BL = boundTable["BL"]
        BU = boundTable["BU"]
        QL = boundTable["QL"]
        QU = boundTable["QU"]

        costTable = getCosts(geojson)
        cost = costTable["cost"]
        PQ = costTable["PQ"]

        QI = "QI        A={} B={} C={} D={} E={} F={}\n".format("", name, "FLOW_DIV(KAF)", "", "1MON", "")

        link = "LINK      {:<10}{:<10}{:<10}{:<10}{:<10}\n".format("DIVR",origin, terminus, amplitude, cost, lowerConst, upperConst)
        LD = "{:<10}{}\n".format("LD",desc)

        divrOutput += link + LD + QL + QU + BL + BU + PQ + QI + "..      \n"

    return divrOutput

def getCosts(geojson):
    costTable = dict()
    costTable["cost"] = ''
    costTable["PQ"] = ''
    costTable["QI"] = ''

    if not "costs" in geojson["properties"]:
        return costTable

    origin    = geojson["properties"]["origin"]
    terminus = geojson["properties"]["terminus"]
    costs = geojson["properties"]["costs"]

    if "cost" in costs:
        costTable["cost"] = costs["cost"]

    if costs["type"] == "Monthly Variable":
        PQ = ''
        for month in ["JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"]:
            PQ += "{:<10}MO={} A={} B={} C={} D={} E={} F={}\n".format("PQ", month, "", origin + "_" + terminus, "Q(K$-KAF)", "", month, "", "")
        costTable["PQ"] = PQ
    else:
        costTable["PQ"] = "{:<10}MO={} A={} B={} C={} D={} E={} F={}\n".format("PQ", "ALL", "", "DUMMY", "BLANK", "", "", "", "")

    return costTable

if __name__ == '__main__':
    if len(sys.argv) == 2:
        loadDataDirectory(sys.argv[1])
        #print(generatePRI())
        # print(nodeData())
        # print(inflowData())
        # print(rstoData())
        print(divrData())


# 골드 2

import sys
from collections import deque
from itertools import permutations

input = sys.stdin.readline

def can_move_to(x, y, z):
    return 0 <= x < n and 0 <= y < n and 0 <= z < n and cube[x][y][z] == "1"

def bfs(x, y, z):
    visited = [[[0] * n for _ in range(n)] for _ in range(n)]
    visited[x][y][z] = 1
    queue = deque([(x, y, z)])

    while queue:
        x, y, z = queue.popleft()
        for dx, dy, dz in delta:
            nx, ny, nz = x + dx, y + dy, z + dz
            if can_move_to(nx, ny, nz) and visited[nx][ny][nz] == 0:
                if nx == ny == nz == n - 1:
                    if visited[x][y][z] == 12:
                        print(12)
                        exit()
                    return visited[x][y][z]
                visited[nx][ny][nz] = visited[x][y][z] + 1
                queue.append((nx, ny, nz))

    return -1

def recursion(depth):
    if depth == n:
        if cube[0][0][0] == "0" or cube[n - 1][n - 1][n - 1] == "0":
            return
        move_counts = bfs(0, 0, 0)
        if move_counts != -1:
            global min_move_counts
            min_move_counts = min(move_counts, min_move_counts)
        return

    for i in range(4):
        recursion(depth + 1)
        cube[depth] = [line[::-1] for line in zip(*cube[depth])]  # 판 90도 회전

n = 5
squares = [[input().split() for _ in range(n)] for _ in range(n)]
delta = [(-1, 0, 0), (1, 0, 0), (0, -1, 0), (0, 1, 0), (0, 0, -1), (0, 0, 1)]  # (dx, dy, dz)
min_move_counts = 125

for case in permutations(squares):
    cube = list(case)
    recursion(0)

print(min_move_counts if min_move_counts < 125 else -1)


from lexer import Lexer

class AST(object):
    def __str__(self):
        return self.__class__.__name__ + ": "

class USEStatement(AST):
    def __init__(self, db_name):
        self.db_name = db_name
        self.token = self.op = 'USE'

    def __str__(self):
        return "{0}{1}".format(super(USEStatement, self).__str__(),
                               {'db_name': self.db_name.__str__()}.__str__())

class SELECTStatement(AST):
    def __init__(self, col_lst, table_name):
        self.col_val = col_lst
        self.table_name = table_name
        self.token = self.op = 'SELECT'
        self.where_clause = None
        self.order_by = None

    def add_where(self, where_clause):
        self.where_clause = where_clause

    def add_order_by(self, order_by):
        self.order_by = order_by

    def __str__(self):
        return "{0}{1}".format(super(SELECTStatement, self).__str__(),
                               {'table_name': self.table_name.__str__(),
                                'col_val': self.col_val.__str__(),
                                'where_clause': self.where_clause.__str__(),
                                'order_by': self.order_by.__str__()}.__str__())

class INSERTStatement(AST):
    def __init__(self, table_name, col_lst, val_lst):
        self.table_name = table_name
        self.col_lst = col_lst
        self.val_lst = val_lst

    def __str__(self):
        return "{0}{1}".format(super(INSERTStatement, self).__str__(),
                               {'table_name': self.table_name.__str__(),
                                'col_lst': self.col_lst.__str__(),
                                'val_lst': self.val_lst.__str__()}.__str__())

class DELETEStatement(AST):
    def __init__(self, table_name, condition = None):
        self.table_name = table_name
        self.condition = condition

    def __str__(self):
        return "{0}{1}".format(super(DELETEStatement, self).__str__(),
                               {'table_name': self.table_name.__str__(),
                                'where_clause': self.condition.__str__()}.__str__())

class ColList(AST):
    def __init__(self, col):
        self.col = [col]

    def add_col(self, col):
        self.col.append(col)

    def __str__(self):
        return "{0}{1}".format(super(ColList, self).__str__(), ', '.join(c.__str__() for c in self.col))

class ValList(AST):
    def __init__(self, val):
        self.val = [val]

    def add_val(self, val):
        self.val.append(val)

    def __str__(self):
        return "{0}{1}".format(super(ValList, self).__str__(), ', '.join(c.__str__() for c in self.val))

class Identifier(AST):
    def __init__(self, token):
        self.token = token
        self.value = token.val

    def __str__(self):
        return self.value

class Literal(AST):
    def __init__(self, token):
        self.token = token
        self.value = token.val

    def __str__(self):
        return self.value

class ComparisionOp(AST):
    def __init__(self, left, op, right):
        self.left = left
        self.token = self.op = op
        self.right = right

    def __str__(self):
        return super(ComparisionOp, self).__str__() + \
               {'operator':self.token.val.__str__(),
                'left_operand': self.left.__str__(),
                'right_operand': self.right.__str__()}.__str__()

class NegOp(AST):
    def __init__(self, op, right):
        self.token = self.op = op
        self.right = right

    def __str__(self):
        return super(NegOp, self).__str__() + {'operand':self.right.__str__()}.__str__()

class NULL(AST):
    def __init__(self):
        pass

    def __str__(self):
        return 'NULL'

class Parser:
    def __init__(self, lexer):
        self.lexer = lexer
        self.current_token = self.lexer.next()

    def error(self):
        raise Exception('Invalid syntax')

    def next(self, token_type):
        # compare the current token type with the passed token
        # type and if they match then assign the next token to
        # the self.current_token, otherwise raise an exception.
        if not self.current_token:
            self.error()
        if self.current_token.type == token_type:
            self.current_token = self.lexer.next()
        else:
            self.error()

    def identifier(self):
        token = self.current_token
        if token.type == 'IDENTIFIER':
            self.next('IDENTIFIER')
            return Identifier(token)
        else:
            self.error()

    def col_list(self):
        """ col_list := IDENTIFIER | IDENTIFIER SEPARATOR col_list"""
        node_id = self.identifier()
        node = ColList(node_id)

        while self.current_token.type == 'SEPARATOR':
            self.next('SEPARATOR')
            node_id = self.identifier()
            node.add_col(node_id)
        return node

    def select(self):
        """ select := SELECT col_list FROM IDENTIFIER WHERE conditions ORDER BY IDENTIFIER;"""
        col_list = self.col_list()
        self.next('FROM')
        table_name = self.identifier()
        node = SELECTStatement(col_list, table_name)
        if self.current_token.type == 'WHERE':
            self.next('WHERE')
            where_clause = self.condition()
            node.add_where(where_clause)
        if self.current_token.type == 'ORDER':
            self.next('ORDER')
            if self.current_token.type == 'BY':
                self.next('BY')
                order_by_identifier = self.identifier()
                node.add_order_by(order_by_identifier)
            else:
                self.error()
        self.next('EOL')
        return node

    def insert(self):
        """ insert := INSERT INTO IDENTIFIER LP col_list RP VALUES LP val_list RP;"""
        if self.current_token.type == 'INTO':
            self.next('INTO')
            table_name = self.identifier()
            self.next('LP')
            col_list = self.col_list()
            self.next('RP')
            self.next('VALUES')
            self.next('LP')
            val_list = self.val_list()
            self.next('RP')
            self.next('EOL')
            return INSERTStatement(table_name, col_list, val_list)
        else:
            self.error()

    def delete(self):
        """ delete := DELETE FROM IDENTIFIER WHERE condition;"""
        self.next('FROM')
        table_name = self.identifier()
        if self.current_token.type == 'WHERE':
            self.next('WHERE')
            condition = self.condition()
        else:
            condition = None
        self.next('EOL')
        return DELETEStatement(table_name, condition)

    def use(self):
        """ use := USE IDENTIFIER;"""
        db_name = self.identifier()
        self.next('EOL')
        return USEStatement(db_name)

    def val(self):
        """ val := STRING_LITERAL | NUMBER | SQL_FUNCTION """
        token = self.current_token
        if token.type == 'STRING_LITERAL' or token.type == 'NUMBER' or token.type == 'SQL_FUNCTION':
            self.next(token.type)
            return Literal(token)
        else:
            self.error()

    def val_list(self):
        """ val_list := val | val SEPARATOR val_list"""
        node_id = self.val()
        node = ValList(node_id)

        while self.current_token.type == 'SEPARATOR':
            self.next('SEPARATOR')
            node_id = self.val()
            node.add_val(node_id)
        return node

    def null(self):
        """ null := NULL """
        if self.current_token.type == 'NULL':
            self.next('NULL')
            return NULL()
        else:
            self.error()

    def condition(self):
        """ condition := identifier EQ_OP val
            condition := identifier IS NULL
            condition := identifier IS NOT NULL
        """
        left = self.identifier()
        op = self.current_token
        if op.type == 'IS_OP':
            self.next('IS_OP')
            if self.current_token.type == 'NEG_OP':
                self.next('NEG_OP')
                neg_node = NegOp(self.current_token, self.null())
                node = ComparisionOp(left, op, neg_node)
            else:
                node = ComparisionOp(left, op, self.null())
        elif op.type == 'EQ_OP':
            self.next('EQ_OP')
            node = ComparisionOp(left, op, self.val())
        else:
            node = None
            self.error()
        return node

    def parse(self):
        token = self.current_token
        if token.type == 'SELECT':
            self.next('SELECT')
            return self.select()
        elif token.type == 'INSERT':
            self.next('INSERT')
            return self.insert()
        elif token.type == 'DELETE':
            self.next('DELETE')
            return self.delete()
        elif token.type == 'USE':
            self.next('USE')
            return self.use()

if __name__ == "__main__":

    for f in open("operations.sql"):
        print(Parser(Lexer(f)).parse())


from heapq import heapify

class Solution:
    def max_heapify(self, heap, root, heap_len):
        p = root
        while p * 2 + 1 < heap_len:
            # 找到当前节点的左右孩子节点
            l, r = p * 2 + 1, p * 2 + 2
            # 找到孩子节点中较大的节点位置
            if heap_len <= r or heap[r] < heap[l]:
                nex = l
            else:
                nex = r
            # 如果大孩子节点比当前节点值大，那么当前节点与孩子节点进行交换
            if heap[p] < heap[nex]:
                heap[p], heap[nex] = heap[nex], heap[p]
                p = nex
            else:
                break
    def min_heapify(self, heap, root, heap_len):
        p = root
        while p*2+1 < heap_len:
            l, r = p*2 + 1, p*2 + 2
            if heap_len <= r or heap[r] > heap[l]:
                nex = l
            else:
                nex = r
            if heap[p] > heap[nex]:
                heap[p], heap[nex] = heap[nex], heap[p]
                p = nex
            else:
                break

    def build_heap(self, heap):
        for i in range(len(heap) - 1, -1, -1):
            self.max_heapify(heap, i, len(heap))

    def heap_sort(self, nums):
        self.build_heap(nums)
        for i in range(len(nums) - 1, -1, -1):
            nums[i], nums[0] = nums[0], nums[i]
            self.max_heapify(nums, 0, i)

    def sortArray(self, nums):
        self.heap_sort(nums)
        return nums

    def sortArray_min(self, nums):
        n = len(nums)
        for i in range(n-1, -1, -1):
            self.min_heapify(nums, i, n)
        for i in range(n-1, -1, -1):
            nums[i], nums[0] = nums[0], nums[i]
            self.min_heapify(nums, 0, i)
        return nums

s = Solution()
unsorted_arr = [7,8,9,10, 1,2,4,5]
print(unsorted_arr)
res = s.sortArray(unsorted_arr)
print(res)
res = s.sortArray_min(unsorted_arr)
print(unsorted_arr)
print(res)

from collections import heapq
heapq.heappushpop()


# -*- coding: utf-8 -*-
from datetime import datetime

from app.baseModel import BaseModel, fields, pydantic_model_creator

class Hits(BaseModel):
    """ 自动化测试触发的问题记录 """

    date = fields.CharField(128, default=datetime.now, description="问题触发日期")
    hit_type = fields.CharField(128, default="", description="问题类型")
    hit_detail = fields.TextField(default="", description="问题内容")
    test_type = fields.CharField(8, default="", description="测试类型，接口、appUi、webUi")
    project_id = fields.IntField(index=True, description="服务id")
    report_id = fields.IntField(index=True, description="测试报告id")
    env = fields.CharField(128, index=True, description="运行环境")
    desc = fields.TextField(default="", description="备注")

    class Meta:
        table = "auto_test_hits"
        table_description = "自动化测试触发问题记录"

    @classmethod
    def make_pagination(cls, form):
        """ 解析分页条件 """
        filters = []
        if form.date.data:
            filters.append(cls.date == form.date.data)
        if form.report_id.data:
            filters.append(cls.report_id == form.report_id.data)
        if form.hit_type.data:
            filters.append(cls.hit_type == form.hit_type.data)
        if form.test_type.data:
            filters.append(cls.test_type == form.test_type.data)
        return cls.pagination(
            page_num=form.pageNum.data,
            page_size=form.pageSize.data,
            filters=filters,
            order_by=cls.id.desc()
        )

HitsPydantic = pydantic_model_creator(Hits, name="Hits")


import copy
import os
import torch

class StateCacher(object):
    def __init__(
            self,
            model,
            optimizer,
            criterion,
            memory_cache=True,
            cache_dir=None,
    ):
        # Check if the optimizer is already attached to a scheduler
        self.optimizer = optimizer
        self._check_for_scheduler()

        self.model = model
        self.criterion = criterion
        self.in_memory = memory_cache
        self.cache_dir = cache_dir

        if self.cache_dir is None:
            import tempfile

            self.cache_dir = tempfile.gettempdir()
        else:
            if not os.path.isdir(self.cache_dir):
                raise ValueError("Given `cache_dir` is not a valid directory.")

        # Save the original state of the model and optimizer so they can be restored if
        # needed
        self.cached = {}
        self.model_device = next(self.model.parameters()).device
        self.store("model", self.model.state_dict())
        self.store("optimizer", self.optimizer.state_dict())

    def store(self, key, state_dict):
        if self.in_memory:
            self.cached.update({key: copy.deepcopy(state_dict)})
        else:
            fn = os.path.join(self.cache_dir, "state_{}_{}.pt".format(key, id(self)))
            self.cached.update({key: fn})
            torch.save(state_dict, fn)

    def retrieve(self, key):
        if key not in self.cached:
            raise KeyError("Target {} was not cached.".format(key))

        if self.in_memory:
            return self.cached.get(key)
        else:
            fn = self.cached.get(key)
            if not os.path.exists(fn):
                raise RuntimeError(
                    "Failed to load state in {}. File doesn't exist anymore.".format(fn)
                )
            state_dict = torch.load(fn, map_location=lambda storage, location: storage)
            return state_dict

    def _check_for_scheduler(self):
        for param_group in self.optimizer.param_groups:
            if "initial_lr" in param_group:
                raise RuntimeError("Optimizer already has a scheduler attached to it")

    def reset(self):
        """Restores the model and optimizer to their initial states."""

        self.model.load_state_dict(self.retrieve("model"))
        self.optimizer.load_state_dict(self.retrieve("optimizer"))
        self.model.to(self.model_device)

    def __del__(self):
        """Check whether there are unused cached files existing in `cache_dir` before
        this instance being destroyed."""

        if self.in_memory:
            return

        for k in self.cached:
            if os.path.exists(self.cached[k]):
                os.remove(self.cached[k])


"""
https://open.kattis.com/problems/reachableroads
Author: https://github.com/smh997/
"""
numcities = int(input())
for i in range(numcities):
    cities = int(input())
    r = int(input())
    unvisited = set(range(int(cities)))
    connections = {x: [] for x in unvisited}
    for j in range(r):
        a, b = map(int, input().split())
        connections[a].append(b)
        connections[b].append(a)
    adds = -1
    while unvisited:
        adds += 1
        to_check = [unvisited.pop()]
        while to_check:
            hub = to_check.pop()
            for endpoint in connections[hub]:
                if endpoint in unvisited:
                    unvisited.remove(endpoint)
                    to_check.append(endpoint)
    print(adds)


import requests
from bs4 import BeautifulSoup
import numpy as np
import pandas as pd
# import time

url = r'https://oilprice.com/'

# Request
r1 = requests.get(url)
r1.status_code

# We'll save in coverpage the cover page content
coverpage = r1.content

# Soup creation
soup1 = BeautifulSoup(coverpage, 'html5lib')

# This doesn't work with oilprice.com!
coverpage_news = soup1.find_all('h2', class_='newsBlock__title')
len(coverpage_news)

coverpage_news[0].get_text()
coverpage_news[-1].get_text()

for data in soup1.find_all('h2'):
    print(data)

almsot_data = soup1.find_all('div', class_='newsBlock')
type(almsot_data) # == bs4.element.ResultSet
len(almsot_data )
first_half_almost_data = almsot_data[0]

data  = first_half_almost_data.find_all('a', class_='newsBlock__article')
data[0]['href']
data[0].get_text()


# ele usou reflect pra comparar com imageJ
import numpy as np
from numpy import asarray
from PIL import Image
from scipy import ndimage

# Funções de abrir a imagem do ImageJ

def openImageJ(path_image):
    image_in = Image.open(path_image)
    image_np = np.array(image_in)
    print('Imagem filtrada no ImageJ')
    printImage(image_np)

def printImage(image):
    print(image)
    print(image.dtype)
    print(image.min(), image.max())

# Função de converter a imagem em um numpy array
def converting(image):
    img_array = np.array(image).astype(int)
    print('Imagem Original')
    printImage(img_array)
    return img_array

# Função de realizar a convolução
def convolution(img_array, k):
    im = ndimage.convolve(img_array, k, mode='reflect')
    print("Imagem após somente a convolução")
    printMinMax(im)
    im = replaceNegativeValues(im)
    return im

# Função de exibir o máx e min
def printMinMax(im):
    print()
    print(im)
    print(im.min(),im.max())

# Função de converter para int para permitir valores negativos
def replaceNegativeValues(im):
    im = np.where(im < 0, 0, im)
    print('Imagem após convolução e substituição zero')
    printMinMax(im)
    return im

# Função de converter array em imagem tipo usint uint8
def convertUint8(im):
    image_out = Image.fromarray(im.astype('uint8'))
    image_out.show()
    return image_out

# Abrir Imagem Original
image = Image.open('../Images/Filo.jpg')
image.show()

#RESPOSTA DA ALTERNATIVA A
print('-------------------Alternativa A-----------------------')
# Imagem filtrada usando ImageJ para comparação
openImageJ('../Images/ImageJ/Filo-ImageJ-a.tif')

# Converter imagem original em array
img_array = converting(image)

# Kernel (A) -  # Convolução usando filtro no modo reflect
K_A = np.array([[0, 0, 0],
                [0, 1, 0],
                [0, 0, 0]])

# Aplicando convolução
im = convolution(img_array, K_A)

# Convertendo array em imagem tipo usint uint8 e salvando imagem
img_out = convertUint8(im)
img_out.save('../Images/a.jpg')

#RESPOSTA DA ALTERNATIVA B

print('-------------------Alternativa B-----------------------')
# Imagem filtrada usando ImageJ para comparação
openImageJ('../Images/ImageJ/Filo-ImageJ-b.tif')

# Kernel (B) -  # Convolução usando filtro no modo reflect
K_B = np.array([[1, 0, -1],
                [0, 0, 0],
                [-1, 0, 1]])

# Aplicando convolução
im = convolution(img_array, K_B)

# Convertendo array em imagem tipo usint uint8 e salvando imagem
img_out = convertUint8(im)
img_out.save('../Images/b.jpg')

#RESPOSTA DA ALTERNATIVA C

print('-------------------Alternativa C-----------------------')
# Imagem filtrada usando ImageJ para comparação
openImageJ('../Images/ImageJ/Filo-ImageJ-c.tif')

# Kernel (C) -  # Convolução usando filtro no modo reflect
K_C = np.array([[0, -1, 0],
                [-1, 4, -1],
                [0, -1, 0]])

# Aplicando convolução
im = convolution(img_array, K_C)

# Convertendo array em imagem tipo usint uint8 e salvando imagem
img_out = convertUint8(im)
img_out.save('../Images/c.jpg')

#RESPOSTA DA ALTERNATIVA C

print('-------------------Alternativa D-----------------------')
# Imagem filtrada usando ImageJ para comparação
openImageJ('../Images/ImageJ/Filo-ImageJ-d.tif')

# Kernel (D) -  # Convolução usando filtro no modo reflect
K_D = np.array([[-1, -1, -1],
                [-1, 8, -1],
                [-1, -1, -1]])

# Aplicando convolução
im = convolution(img_array, K_D)

# Convertendo array em imagem tipo usint uint8 e salvando imagem
img_out = convertUint8(im)
img_out.save('../Images/d.jpg')

print('-------------------Alternativa E-----------------------')
# Imagem filtrada usando ImageJ para comparação
openImageJ('../Images/ImageJ/Filo-ImageJ-e.tif')

# Kernel (E) -  # Convolução usando filtro no modo reflect
K_E = np.array([[0, -1, 0],
                [-1, 5, -1],
                [0, -1, 0]])

# Aplicando convolução
im = convolution(img_array, K_E)

# Convertendo array em imagem tipo usint uint8 e salvando imagem
img_out = convertUint8(im)
img_out.save('../Images/e.jpg')

print('-------------------Alternativa F-----------------------')
# Imagem filtrada usando ImageJ para comparação
openImageJ('../Images/ImageJ/Filo-ImageJ-f.tif')

# Kernel (F) -  # Convolução usando filtro no modo reflect
K_F = np.array([[1, 1, 1],
                [1, 1, 1],
                [1, 1, 1]])

# Multiplicando pela constante
result_f = K_F*(1/9)

# Aplicando convolução
im = convolution(img_array, result_f)

# Convertendo array em imagem tipo usint uint8 e salvando imagem
img_out = convertUint8(im)
img_out.save('../Images/f.jpg')

print('-------------------Alternativa G-----------------------')
# Imagem filtrada usando ImageJ para comparação
openImageJ('../Images/ImageJ/Filo-ImageJ-g.tif')

# Kernel (G) -  # Convolução usando filtro no modo reflect
K_G = np.array([[1, 2, 1],
                [2, 4, 2],
                [1, 2, 1]])

# Multiplicando pela constante
result_g = K_G*(1/16)

# Aplicando convolução
im = convolution(img_array, result_g)

# Convertendo array em imagem tipo usint uint8 e salvando imagem
img_out = convertUint8(im)
img_out.save('../Images/g.jpg')

print('-------------------Alternativa H-----------------------')
# Imagem filtrada usando ImageJ para comparação
openImageJ('../Images/ImageJ/Filo-ImageJ-h.tif')

# Kernel (H) -  # Convolução usando filtro no modo reflect
K_H = np.array([[1, 4, 6, 4, 1],
                [4, 16, 24, 16, 4],
                [6, 24, 36, 24, 6],
                [4, 16, 24, 16, 4],
                [1, 4, 6, 4, 1]])

# Multiplicando pela constante
result_h = K_H*(1/256)

# Aplicando convolução
im = convolution(img_array, result_h)

# Convertendo array em imagem tipo usint uint8 e salvando imagem
img_out = convertUint8(im)
img_out.save('../Images/h.jpg')

print('-------------------Alternativa I-----------------------')
# Imagem filtrada usando ImageJ para comparação
openImageJ('../Images/ImageJ/Filo-ImageJ-i.tif')

# Kernel (I) -  # Convolução usando filtro no modo reflect
K_I = np.array([[1, 4, 6, 4, 1],
                [4, 16, 24, 16, 4],
                [6, 24, -476, 24, 6],
                [4, 16, 24, 16, 4],
                [1, 4, 6, 4, 1]])

# Multiplicando pela constante
result_i = K_I * (-1/256)

# Aplicando convolução
im = convolution(img_array, result_i)

# Convertendo array em imagem tipo usint uint8 e salvando imagem
img_out = convertUint8(im)
img_out.save('../Images/i.jpg')


#!/bin/python3

import argparse
import shutil
import os

PATH_BACKEND = "/home/exploit/backend/"

vuln_manager_src = 'vuln_manager_samples/%s.xml'
vuln_manager_dst = PATH_BACKEND + 'vulnerability_manager/nvd_db/nvdcve-2.0-Demo.xml'

rss_server_src = 'rss_server/entries_rss/%s.xml'
rss_server_dst = 'rss_server/enabled_entries_rss/%s.xml'

def simulate(test_name):

    path = '/'.join(vuln_manager_dst.split('/')[:-1])

    if not os.path.isdir(path):
        os.makedirs(path, True)
    shutil.copy(vuln_manager_src % (test_name), vuln_manager_dst)

    path = '/'.join(rss_server_dst.split('/')[:-1])
    if not os.path.isdir(path):
        os.makedirs(path, True)
    shutil.copy(rss_server_src % (test_name), rss_server_dst % (test_name))

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('testName', type=str)

    args = parser.parse_args()
    simulate(args.testName)


from racetrack import Racetrack
import pygame
import sys
import argparse
import time
import LAO_search
import BLAO_search

import pygame.locals

class Application:
    def __init__(self, filename: str, scale=20, fps=30):
        self.running = True
        self.displaySurface = None
        self.scale = scale
        self.fps = fps
        self.windowTitle = "Racetrack MDP: " + filename

        self.track = Racetrack(filename)
        self.dim = self.track.get_dimensions()

        self.windowHeight = self.dim[0] * self.scale
        self.windowWidth = self.dim[1] * self.scale

        self.blockSizeX = int(self.windowWidth / self.dim[1])
        self.blockSizeY = int(self.windowHeight / self.dim[0])

    def execute(self, search_method: str, save: str):
        bidirectional = False
        path_end = None
        if bidirectional:
            path, path_end = BLAO_search.search(self.track, search_method)
        else:
            path = LAO_search.search(self.track, search_method)

        pygame.init()
        self.displaySurface = pygame.display.set_mode((self.windowWidth, self.windowHeight), pygame.HWSURFACE)
        self.displaySurface.fill((255, 255, 255))
        pygame.display.flip()
        pygame.display.set_caption(self.windowTitle)

        print("Results")
        #print("Path Length:", len(path))
        #print("States Explored:", statesExplored)

        self.drawExplored(path, set())
        self.drawPolicy(path, set())
        self.drawPolicy(path_end, set(), True)
        self.drawTrack()
        self.drawStart()
        self.drawObjective()

        pygame.display.flip()
        if save is not None:
            pygame.image.save(self.displaySurface, save)
            self.running = False

        clock = pygame.time.Clock()

        while self.running:
            pygame.event.pump()
            keys = pygame.key.get_pressed()
            clock.tick(self.fps)

            if any(keys):
                raise SystemExit

    def getColor(self, pathLength, index):
        step = 255 / pathLength
        green = index * step
        red = 255 - green
        return red, green, 0

    def drawPolicy(self, path, seen_nodes: set, invert=False, optimum=True):
        if path is None:
            return
        seen_nodes.add(path.state[:2].tobytes())
        p = path
        if invert:
            if optimum:
                color = (128, 0, 255)
            else:
                color = (128, 0, 0)
        else:
            if optimum:
                color = (0, 255, 255)
            else:
                color = (0, 255, 0)

        self.drawArrow(p.state[0], p.state[1], p.state[2], p.state[3], color)

        actions = p.get_recommended_actions()
        if actions is not None:
            success, fail = actions
            if success.state[:2].tobytes() not in seen_nodes:
                seen_nodes = self.drawPolicy(success, seen_nodes, invert, optimum)
            optimum = False
            if fail.state[:2].tobytes() not in seen_nodes:
                seen_nodes = self.drawPolicy(fail, seen_nodes, invert, optimum)
        return seen_nodes

    def drawExplored(self, path, seen_nodes: set):
        if path is None:
            return
        seen_nodes.add(path.state[:2].tobytes())
        p = path
        color = (30, 30, 30)

        self.drawArrow(p.state[0], p.state[1], p.state[2], p.state[3], color)

        for actions in p.children:
            if actions is not None:
                success, fail = actions
                if success.state[:2].tobytes() not in seen_nodes:
                    seen_nodes = self.drawExplored(success, seen_nodes)
                if fail.state[:2].tobytes() not in seen_nodes:
                    seen_nodes = self.drawExplored(fail, seen_nodes)
        return seen_nodes

    # Simple wrapper for drawing a wall as a rectangle
    def drawWall(self, row, col):
        pygame.draw.rect(self.displaySurface, (0, 0, 0), (col * self.blockSizeX, row * self.blockSizeY, self.blockSizeX, self.blockSizeY), 0)

    # Simple wrapper for drawing a circle
    def drawCircle(self, row, col, color, radius=None):
        if radius is None:
            radius = min(self.blockSizeX, self.blockSizeY) / 4
        pygame.draw.circle(self.displaySurface, color, (int(col * self.blockSizeX + self.blockSizeX / 2), int(row * self.blockSizeY + self.blockSizeY / 2)), int(radius))

    def drawSquare(self, row, col, color):
        pygame.draw.rect(self.displaySurface, color, (col * self.blockSizeX, row * self.blockSizeY, self.blockSizeX, self.blockSizeY), 0)

    # Draws the objectives to the display context
    def drawObjective(self):
        for obj in self.track.get_objectives():
            self.drawCircle(obj[0], obj[1], (0, 0, 0))

    # Draws start location of path
    def drawStart(self):
        for state in self.track.get_start():
            pygame.draw.rect(self.displaySurface, (0, 0, 255), (state[1] * self.blockSizeX + self.blockSizeX / 4, state[0] * self.blockSizeY + self.blockSizeY / 4, self.blockSizeX * 0.5, self.blockSizeY * 0.5), 0)

    # Draws arrow
    def drawArrow(self, row, col, row_accel, col_accel, color):
        pygame.draw.rect(self.displaySurface, color, (col * self.blockSizeX + self.blockSizeX / 4, row * self.blockSizeY + self.blockSizeY / 4, self.blockSizeX * 0.5, self.blockSizeY * 0.5), 0)

    # Draws the full maze to the display context
    def drawTrack(self):
        for row in range(self.dim[0]):
            for col in range(self.dim[1]):
                if self.track.is_wall(row, col):
                    self.drawWall(row, col)

if __name__ == "__main__":
    parser = argparse.ArgumentParser()

    parser.add_argument('--filename', default="small_track.txt", type=str,
                        help='path to racetrack file - default ')
    parser.add_argument('--method', dest="search", type=str, default="dblao",
                        choices=["lao", "blao", "dblao"],
                        help='search method - default dblao')
    parser.add_argument('--scale', dest="scale", type=int, default=20,
                        help='scale - default: 20')
    parser.add_argument('--fps', dest="fps", type=int, default=30,
                        help='fps for the display - default 30')
    parser.add_argument('--save', dest="save", type=str, default=None,
                        help='save output to image file - default not saved')

    args = parser.parse_args()
    app = Application(args.filename, args.scale, args.fps)
    app.execute(args.search, args.save)