import matplotlib.pyplot as plt

import numpy as np
import copy
import math

import letritas

class Dataset():

    class Letra():
        def __init__(self, array_pixels, clase):
            self.array_pixels = array_pixels
            self.clase = clase

    def __init__(self, umbral=165, seed=None):
        self.datos_Bruto = []
        self.primera_Linea = []
        self.umbral = umbral
        self.permutacion = None
        self.tam_img = None
        self.datos = None

        self.seed = seed
        #random.seed(self.seed)
        np.random.seed(self.seed)

        self.procesarPrimeraFila()

    def recortar(self, imagen, porcentaje_umbral_recorte=0.05, redimensionar=True):
        '''
        Dada una imagen, se devuelve una imagen mas pequenya, ya recortada. Los cortes que
        se realizan son paralelos a los ejes y se realizan una vez que el porcentaje de
        pixeles negros encontrados en la columna o fila supera el "porcentajeUmbralRecorte"
        '''

        assert isinstance(porcentaje_umbral_recorte, (list, float)), 'Tipo de dato ' + str(type(porcentaje_umbral_recorte)) + '"porcentaje_umbral_recorte" incorrecto'

        ancho = imagen.shape[1]
        alto = imagen.shape[0]

        if isinstance(porcentaje_umbral_recorte, float):
            min_pixeles_arriba = alto * porcentaje_umbral_recorte
            min_pixeles_abajo = alto * porcentaje_umbral_recorte
            min_pixeles_izquierda = ancho * porcentaje_umbral_recorte
            min_pixeles_derecha = ancho * porcentaje_umbral_recorte
        else:
            min_pixeles_arriba = alto * porcentaje_umbral_recorte[0]
            min_pixeles_abajo = alto * porcentaje_umbral_recorte[1]
            min_pixeles_izquierda = ancho * porcentaje_umbral_recorte[2]
            min_pixeles_derecha = ancho * porcentaje_umbral_recorte[3]

        assert min_pixeles_arriba <= alto and min_pixeles_arriba >= 0, 'Valor de "min_pixeles_arriba" ' + str(min_pixeles_arriba) + ' incorrecto'
        assert min_pixeles_abajo <= alto and min_pixeles_abajo >= 0, 'Valor de "min_pixeles_abajo" ' + str(min_pixeles_abajo) + ' incorrecto'
        assert min_pixeles_izquierda <= ancho and min_pixeles_izquierda >= 0, 'Valor de "min_pixeles_izquierda" ' + str(min_pixeles_izquierda) + ' incorrecto'
        assert min_pixeles_derecha <= ancho and min_pixeles_derecha >= 0, 'Valor de "min_pixeles_derecha" ' + str(min_pixeles_derecha) + ' incorrecto'

        y_ini = 0
        y_fin = alto
        x_ini = 0
        x_fin = ancho

        y_ini = self.obtenerBordeLetra(imagen, min_pixeles_arriba, reverse=False)
        y_fin = self.obtenerBordeLetra(imagen, min_pixeles_abajo, max_tamanyo=alto,reverse=True)

        imagen_traspuesta = np.transpose(imagen)

        x_ini = self.obtenerBordeLetra(imagen_traspuesta, min_pixeles_izquierda, reverse=False)
        x_fin = self.obtenerBordeLetra(imagen_traspuesta, min_pixeles_derecha, max_tamanyo=ancho,reverse=True)

        if self.tam_img is None or not redimensionar:
            self.tam_img = [x_fin - x_ini, y_fin - y_ini]
            return imagen[y_ini:y_fin, x_ini:x_fin]
        else:
            imagen_recortada = imagen[y_ini:y_fin, x_ini:x_fin]
            return self.redimensionarImagen(imagen_recortada, x_fin - x_ini, y_fin - y_ini)

    def obtenerBordeLetra(self, imagen_letra, min_pixeles, max_tamanyo=0, reverse=False):
        '''
        Dada una imagen, se corta por un lado a partir de que se supera "min_pixeles"
        si no se supera nunca se devuelve el mayor valor encontrado
        '''

        l_valores = np.zeros(shape=imagen_letra.size)

        if reverse:
            # Se recorta la imagen_letra a partir de que se supera min_pixeles
            for i_fila, _ in enumerate(imagen_letra[0]):

                # Se obtiene el numero de pixeles que son negros en la imagen_letra
                l_pixeles_negros = np.bincount(imagen_letra[max_tamanyo - i_fila - 1 ])[:self.umbral]
                n_pixeles_negros = np.sum(l_pixeles_negros)

                # Si hay tantos o mas pixeles negros como el minimo numero
                # de pixeles se recorta (y_fin sera el numero de fila actual)
                l_valores[i_fila] += n_pixeles_negros
                if n_pixeles_negros >= min_pixeles:
                    return max_tamanyo - i_fila - 1
        else:
            # Se recorta la imagen_letra a partir de que se supera min_pixeles
            for i_fila, fila in enumerate(imagen_letra):

                # Se obtiene el numero de pixeles que son negros en la imagen_letra
                l_pixeles_negros = np.bincount(fila)[:self.umbral]
                n_pixeles_negros = np.sum(l_pixeles_negros)

                # Si hay tantos o mas pixeles negros como el minimo numero
                # de pixeles se recorta (y_fin sera el numero de fila actual)
                l_valores[i_fila] += n_pixeles_negros
                if n_pixeles_negros >= min_pixeles:
                    return  i_fila

        return int(np.amax(l_valores))

    def redimensionarImagen(self, imagen, tam_h_actual, tam_v_actual):
        '''
        Dada una imagen, la estira o encoge para que tenga las proporciones de "self.tam_img"
        '''

        tam_h_actual -= 1
        tam_v_actual -= 1

        tam_v_final = self.tam_img[1]
        tam_h_final = self.tam_img[0]

        imagen_redimensionada = []
        for i in range(tam_v_final):
            imagen_redimensionada.append([])
            for j in range(tam_h_final):
                imagen_redimensionada[i].append(imagen[(round(i/tam_v_final*tam_v_actual))][(round(j/tam_h_final*tam_h_actual))])

        return np.array(imagen_redimensionada, dtype=np.int)

    def convertirPixeles(self, letra):

        # Comprueba si los valores RGB de los pixeles sobrepasan un umbral
        for i_elem, elem in enumerate(letra):
            if elem > self.umbral:
                letra[i_elem] = 0
            else:
                letra[i_elem] = 1   # La info que importa (negro)

        return letra

    def procesarDatos(self, celdas):
        # Obtiene el string con las clases desde parametros por defecto
        string_clases = letritas.parametros_por_defecto()[3]

        # Crea objetos Letra con su clase y su array de pixeles
        for i_celda_letra, celda_letra in enumerate(celdas):
            letra = self.Letra(celda_letra, i_celda_letra % len(string_clases))
            self.datos_Bruto.append(letra)

        return

    def procesarPrimeraFila(self):
        for i, letra in enumerate(letritas.extrae_primera_fila()):
            letra = self.Letra(letra, i)
            self.primera_Linea.append(letra)
        return

    def procesarCuadraditos(self, tipo_atributo="cuadraditos", tamano=1,
                            porcentajeAgrupacion=0.01, solo_blanco_negro=False, random=False, hacer_recorte=True):
        # Comprueba el tipo de atributo (en funcion del mismo creara un dataset
        # de cuadraditos, filas o columnas)
        if tipo_atributo == "cuadraditos" and not random:

            # Convierte el array 1D devuelto por cuadraditos (usando la primera letra) en una fila
            # de un array 2D, de la que se extraen sus dimensiones
            primera_letra = self.datos_Bruto[0]
            if hacer_recorte:
                primera_letra.array_pixels = self.recortar(primera_letra.array_pixels, redimensionar=True)
            primer_dato = self.cuadraditos(primera_letra.array_pixels, primera_letra.clase, tamano, solo_blanco_negro=solo_blanco_negro)
            tam_fila_2d = primer_dato.shape[0]
            primer_dato = primer_dato.reshape(1, tam_fila_2d)

            # Crea el array 2D datos vacio con la dimension adecuada, y annade todas las letras a datos
            self.datos = np.empty((0, tam_fila_2d), dtype=int)
            self.datos = np.append(self.datos, primer_dato, axis=0)  # Primera letra

            for letra in self.datos_Bruto[1:]:  # Resto de letras
                if hacer_recorte:
                    letra.array_pixels = self.recortar(letra.array_pixels, redimensionar=True)

                dato = self.cuadraditos(letra.array_pixels, letra.clase, tamano, solo_blanco_negro=solo_blanco_negro)
                dato = dato.reshape(1, tam_fila_2d)

                self.datos = np.append(self.datos, dato, axis=0)
                #self.datos = np.append((self.datos, self.cuadraditos(letra.array_pixels, letra.clase, tamano)))

        elif tipo_atributo == "filas" and not random:

            # Convierte el array 1D devuelto por cuadraditosFilas (usando la primera letra) en una fila
            # de un array 2D, de la que se extraen sus dimensiones
            primera_letra = self.datos_Bruto[0]
            if hacer_recorte:
                primera_letra.array_pixels = self.recortar(primera_letra.array_pixels, redimensionar=True)
            primer_dato = self.cuadraditosFilas(primera_letra.array_pixels, primera_letra.clase, tamano, solo_blanco_negro=solo_blanco_negro)
            tam_fila_2d = primer_dato.shape[0]
            primer_dato = primer_dato.reshape(1, tam_fila_2d)

            # Crea el array 2D datos vacio con la dimension adecuada, y annade todas las letras a datos
            self.datos = np.empty((0, tam_fila_2d), dtype=int)
            self.datos = np.append(self.datos, primer_dato, axis=0)  # Primera letra

            for letra in self.datos_Bruto[1:]:  # Resto de letras
                if hacer_recorte:
                    letra.array_pixels = self.recortar(letra.array_pixels, redimensionar=True)

                dato = self.cuadraditosFilas(letra.array_pixels, letra.clase, tamano, solo_blanco_negro=solo_blanco_negro)
                dato = dato.reshape(1, tam_fila_2d)

                self.datos = np.append(self.datos, dato, axis=0)
                # self.datos = np.append(self.datos, self.cuadraditosFilas(letra.array_pixels, letra.clase, tamano))

        elif tipo_atributo == "columnas" and not random:

            # Convierte el array 1D devuelto por cuadraditosColumnas (usando la primera letra) en una fila
            # de un array 2D, de la que se extraen sus dimensiones
            primera_letra = self.datos_Bruto[0]
            if hacer_recorte:
                primera_letra.array_pixels = self.recortar(primera_letra.array_pixels, redimensionar=True)
            primer_dato = self.cuadraditosColumnas(primera_letra.array_pixels, primera_letra.clase, tamano, solo_blanco_negro=solo_blanco_negro)
            tam_fila_2d = primer_dato.shape[0]
            primer_dato = primer_dato.reshape(1, tam_fila_2d)

            # Crea el array 2D datos vacio con la dimension adecuada, y annade todas las letras a datos
            self.datos = np.empty((0, tam_fila_2d), dtype=int)
            self.datos = np.append(self.datos, primer_dato, axis=0)  # Primera letra

            for letra in self.datos_Bruto[1:]:  # Resto de letras
                if hacer_recorte:
                    letra.array_pixels = self.recortar(letra.array_pixels, redimensionar=True)

                dato = self.cuadraditosColumnas(letra.array_pixels, letra.clase, tamano, solo_blanco_negro=solo_blanco_negro)
                dato = dato.reshape(1, tam_fila_2d)

                self.datos = np.append(self.datos, dato, axis=0)
                #self.datos = np.append(self.datos, self.cuadraditosColumnas(letra.array_pixels, letra.clase, tamano))

        elif tipo_atributo == "patrones":

            primera_letra = self.datos_Bruto[0]

            if hacer_recorte:
                primera_letra.array_pixels = self.recortar(primera_letra.array_pixels, porcentaje_umbral_recorte=0.1, redimensionar=True)

            self.datos = np.array([self.patrones(primera_letra.array_pixels, primera_letra.clase, solo_blanco_negro=solo_blanco_negro)])

            for letra in self.datos_Bruto[1:]:  # Resto de letras
                if hacer_recorte:
                    letra.array_pixels = self.recortar(letra.array_pixels, redimensionar=True)

                dato = self.patrones(letra.array_pixels, letra.clase, solo_blanco_negro=False)

                self.datos = np.concatenate((self.datos, np.array([dato])))

        elif random:

            if tipo_atributo == "cuadraditos":
                n_pixeles_alto = tamano
                n_pixeles_ancho = tamano
            elif tipo_atributo == "filas":
                n_pixeles_alto = tamano
                n_pixeles_ancho = None
            elif tipo_atributo == "columnas":
                n_pixeles_alto = None
                n_pixeles_ancho = tamano
            else:
                raise ValueError('Tipo de "tipo_atributo" ' + str(tipo_atributo) + ' incorrecto.')

            primera_letra = self.datos_Bruto[0]

            if hacer_recorte:
                primera_letra.array_pixels = self.recortar(primera_letra.array_pixels, redimensionar=True)

            l_cuadraditros = self.crearCuadraditos(0, primera_letra.array_pixels.shape[1], 0, primera_letra.array_pixels.shape[0],
                                                      n_pixeles_ancho=n_pixeles_ancho, n_pixeles_alto=n_pixeles_alto)
            self.datos = np.array([self.cuadraditosRandom(primera_letra.array_pixels, primera_letra.clase, l_cuadraditros,
                                             porcentajeAgrupacion=porcentajeAgrupacion, solo_blanco_negro=solo_blanco_negro, random=random)])

            for letra in self.datos_Bruto[1:]:  # Resto de letras
                if hacer_recorte:
                    letra.array_pixels = self.recortar(letra.array_pixels, redimensionar=True)

                l_cuadraditros = self.crearCuadraditos(0, letra.array_pixels.shape[1], 0, letra.array_pixels.shape[0],
                                                          n_pixeles_ancho=n_pixeles_ancho, n_pixeles_alto=n_pixeles_alto)
                dato = self.cuadraditosRandom(letra.array_pixels, letra.clase, l_cuadraditros,
                                                 porcentajeAgrupacion=porcentajeAgrupacion, solo_blanco_negro=solo_blanco_negro, random=random)

                self.datos = np.concatenate((self.datos, np.array([dato])))

        else:
            raise ValueError('Tipo de "tipo_atributo" ' + str(tipo_atributo) + ' incorrecto.')

        return

    def cuadraditos(self, letra, clase, tamCuadrado=1, solo_blanco_negro=True):

        # Comprueba si los cuadraditos son bloques o pixeles
        if tamCuadrado == 1:

            # Aplana el array letra a 1D
            letra = np.array(np.reshape(letra, letra.size))

            # Codifica los pixeles de media a 0s o 1s y annade la clase
            if solo_blanco_negro:
                letra = self.convertirPixeles(letra)

            letra = np.append(letra, clase)
        else:

            # Crea un array 1D con los valores medios de cada bloque
            media = np.array([], dtype='int')

            # Recorre los bloques en los que se divide la imagen y calcula el valor medio
            # de cada uno. (Los "trozos" de imagen que no quepan en cuadrados se ignoran)
            for i in range(0, len(letra), tamCuadrado):
                if len(letra) - i < tamCuadrado:
                    break

                for j in range(0, letra.shape[1], tamCuadrado):
                    if letra.shape[1] - j < tamCuadrado:
                        break
                    media = np.append(media, np.mean(letra[i:(i+tamCuadrado), j:(j+tamCuadrado)]))

            # Codifica los pixeles de media a 0s o 1s y annade la clase
            if solo_blanco_negro:
                letra = self.convertirPixeles(media)
            else:
                letra = media

            letra = np.append(letra, clase)

        return letra

    def cuadraditosFilas(self, letra, clase, tamFila=1, solo_blanco_negro=True):
        # Crea un array 1D con los valores medios de cada fila
        media= np.array([], dtype='int')

        # Recorre las filas en las que se divide la imagen y calcula el valor medio
        # de cada una. (Los "trozos" de imagen que no quepan en filas se ignoran)
        for i in range(0, len(letra), tamFila):
            if len(letra) - i < tamFila:
                break
            media = np.append(media, int(np.mean(letra[i:(i+tamFila), :])))

        # Codifica los pixeles de media a 0s o 1s y annade la clase
        if solo_blanco_negro:
            letra = self.convertirPixeles(media)
        else:
            letra = media
        letra = np.append(letra, clase)

        return letra

    def cuadraditosColumnas(self, letra, clase, tamCol=1, solo_blanco_negro=True):
        # Crea un array 1D con los valores medios de cada columna
        media = np.array([], dtype='int')

        # Recorre las columnas en las que se divide la imagen y calcula el valor medio
        # de cada una. (Los "trozos" de imagen que no quepan en columnas se ignoran)
        for i in range(0, letra.shape[1], tamCol):
            if len(letra) - i < tamCol:
                break
            media = np.append(media, int(np.mean(letra[:, i:(i+tamCol)])))

        # Codifica los pixeles de media a 0s o 1s y annade la clase
        if solo_blanco_negro:
            letra = self.convertirPixeles(media)
        else:
            letra = media
        letra = np.append(letra, clase)

        return letra

    def cuadraditosRandom(self, imagen_letra, clase, l_cuadraditros, porcentajeAgrupacion=0.0, votacion="por_tamanyo", solo_blanco_negro=False, random=True):
        '''
        Dada una imagen y unas coordenadas que definen los cuadraditos en los que
        se ha dividido la imagen (las coordenadas estan en la lista l_cuadraditos).
        Se agrupan los cuadraditos segun "porcentajeAgrupacion" (100% significaria que
        todos los cuadraditos serian un atributo; por otra parte 0% significaria que cada
        cuadradito seria un atributo). En funcion de cual sea el color mayoritario en las
        agrupaciones que se realizaran de forma random, ese sera el valor del atributo
        del atributo en el diccionario a crear y devolver.
        Como hay cuadraditos mas grandes que otros se pueden configurar la votacion
        para que tengan mayor peso aquellos cuadraditos con mayor tamanyo
        '''

        # Se obtiene el numero de atributos
        num_cuadraditos = len(l_cuadraditros)

        # Si es la primera letra a transformar en datos, todavia no hay
        # una permutacion de los indices de los cuadraditos a utilizar
        if self.permutacion is None:
            if random:
                self.permutacion = np.random.permutation(np.arange(num_cuadraditos))
            else:
                self.permutacion = np.arange(num_cuadraditos)#np.random.permutation(np.arange(num_cuadraditos))

        elif len(self.permutacion) != num_cuadraditos:
            raise ValueError ("Algo ha ido mal el tamanyo de la permutacion " + str(len(self.permutacion)) +
                              " no coincide con el numero de cuadraditos " + str(num_cuadraditos))

        # Se ajusta el "porcentajeAgrupacion" para evitar la division por cero
        # y para no repetir agrupaciones. Si porcentajeAgrupacion = 0.1
        # y num_cuadraditos = 6, habra 4 grupos de atributos repetidos
        if porcentajeAgrupacion <= 0 or num_cuadraditos < 1/porcentajeAgrupacion:
            porcentajeAgrupacion = 1/num_cuadraditos

        atributos = []
        i_atributo = 0
        i_inferior = 0
        i_superior = porcentajeAgrupacion
        while i_superior <= 1:

            # Se obtiene la sublista de cuadraditos que conformaran un atributo
            l_cuadraditros_atributo = []
            for i in self.permutacion[round(num_cuadraditos*i_inferior):round(num_cuadraditos*i_superior)]:
                l_cuadraditros_atributo.append(l_cuadraditros[i])

            atributos.append(self.mediaColores(imagen_letra, l_cuadraditros_atributo))

            i_atributo += 1
            i_inferior = i_superior
            i_superior += porcentajeAgrupacion
            i_superior = 1 if (i_superior < 1 and i_superior+porcentajeAgrupacion > 1) else i_superior

        if solo_blanco_negro:
            atributos = self.convertirPixeles(atributos)

        return np.append(atributos, np.array(clase))

    def cuadraditosDiagonales(self):
        pass

    def patrones(self, imagen, clase, solo_blanco_negro=True):

        ancho_rotulador = 22

        mitad_v_imagen = imagen.shape[1]/2
        mitad_h_imagen = imagen.shape[0]/2

        l_corte_v = [0 for _ in range(8)]
        l_corte_h = [0 for _ in range(8)]

        l_corte_v[7] += imagen.shape[1]
        l_corte_h[7] += imagen.shape[0]

        l_corte_v[1] += l_corte_v[0] + ancho_rotulador
        l_corte_h[1] += l_corte_h[0] + ancho_rotulador

        l_corte_v[6] += l_corte_v[7] - ancho_rotulador
        l_corte_h[6] += l_corte_h[7] - ancho_rotulador

        l_corte_v[3] += int(mitad_v_imagen - ancho_rotulador/2)
        l_corte_h[3] += int(mitad_h_imagen - ancho_rotulador/2)

        l_corte_v[4] += int(mitad_v_imagen + ancho_rotulador/2)
        l_corte_h[4] += int(mitad_h_imagen + ancho_rotulador/2)

        l_corte_v[2] += int((l_corte_v[3] + l_corte_v[1]) / 2)
        l_corte_h[2] += int((l_corte_h[3] + l_corte_h[1]) / 2)

        l_corte_v[5] += int((l_corte_v[6] + l_corte_v[4]) / 2)
        l_corte_h[5] += int((l_corte_h[6] + l_corte_h[4]) / 2)

        atributos = []
        tam_l_cortes = len(l_corte_h)
        for i in range(0, tam_l_cortes - 1):
            for j in range(0, tam_l_cortes - 1):
                dato = self.mediaColores(imagen, [[(l_corte_v[j], l_corte_v[j+1]), (l_corte_h[i], l_corte_h[i+1])]])

                atributos.append(dato)

        if solo_blanco_negro:
            atributos = self.convertirPixeles(atributos)

        atributos.append(clase)
        return np.array(atributos)

    def diferenciaPixel(self, arreglo="+255"):
        """
        Para cada imagen se extrae como atributo la dieferencia del valor rgb de cada pixel
        con el pixel en la misma posicion de las imagenes a ordenador correspondientes a la clase
        """

        datos = []
        for foto in self.datos_Bruto:
            for letra in self.primera_Linea:
                if letra.clase == foto.clase:
                    resta = np.array(letra.array_pixels) - np.array(foto.array_pixels)
                    resta = np.append(np.append(resta,self.diferenciaPorcentajeAttr(foto, letra)) ,letra.clase)
                    datos.append(resta.tolist())
        if arreglo == "+255":
            self.datos = np.array(datos) + 255
        elif arreglo == "abs":
            self.datos = np.absolute(np.array(datos))
        else:
            raise ValueError ('Tipo de arreglo erroneo ' + str(arreglo) + ' solo se permite "+255" o "abs".')

        return self.datos

    def diferenciaPorcentajeAttr(self, foto, letra):
        sum_foto = np.sum(foto.array_pixels)/(len(foto.array_pixels)*len(foto.array_pixels[0]))
        sum_letra = np.sum(letra.array_pixels)/(len(letra.array_pixels)*len(letra.array_pixels[0]))
        return sum_letra - sum_foto

    def diferenciaPorcentaje(self, arreglo="+255"):

        datos = []
        for foto in self.datos_Bruto:
            sum_foto = np.sum(foto.array_pixels)/(len(foto.array_pixels)*len(foto.array_pixels[0]))
            for letra in self.primera_Linea:
                if letra.clase == foto.clase:
                    sum_letra = np.sum(letra.array_pixels)/(len(letra.array_pixels)*len(letra.array_pixels[0]))
                    datos.append([sum_letra - sum_foto,letra.clase])
        if arreglo == "+255":
            self.datos = np.array(datos) + 255
        elif arreglo == "abs":
            self.datos = np.absolute(np.array(datos))
        else:
            raise ValueError ('Tipo de arreglo erroneo ' + str(arreglo) + ' solo se permite "+255" o "abs".')

        return self.datos

    def votarBlancoNegro(self, imagen, l_cuadraditros_atributo, votacion=None):
        '''
        Se vota si hay mas blancos,
        '''

        # Por cada cuadradito "c", se incrementa el contador de votos del color en ese
        # cuadradito. Si se eligio la votacion por tamanyo cada cuadradito tiene tantos
        # votos como numero de pixeles en el cuadradito
        votacion_colores = {255: 0, 0: 0}
        for c in l_cuadraditros_atributo:
            color_mayoritario, n_votos_blanco, n_votos_negro = self.colorMayoritario(imagen,c[0][0],c[0][1],c[1][0],c[1][1])

            if votacion == "por_tamanyo":
                votacion_colores[255] += n_votos_blanco
                votacion_colores[0] += n_votos_negro
            else:
                votacion_colores[color_mayoritario] += 1

        if votacion_colores[255] >= votacion_colores[0]:
            return 0

        return 1

    def mediaColores(self, imagen, l_cuadraditros_atributo):
        '''
        Dada una imagen y una lista de coordenadas de inicio y fin de cuadraditos
        dentro de la imagen se devuelve la media de color de esos cuadraditos
        '''

        zonas_coordenadas = np.array([], dtype=np.int)

        for c in l_cuadraditros_atributo:
            # Se obtiene la zona de la imagen que esta dentro de las coordenas
            zona_coordenadas = imagen[c[1][0]:c[1][1], c[0][0]:c[0][1]]

            # Se cambia la forma del array para que este en 1D y asi poder contar cual es el elemento mayoritario
            zonas_coordenadas = np.append(zonas_coordenadas, np.reshape(zona_coordenadas, zona_coordenadas.size))

        return np.mean(zonas_coordenadas)

    def colorMayoritario(self, imagen, x_ini, x_fin, y_ini, y_fin, resultados=True):
        '''
        Dada una imagen y unas coordenadas de inicio y fin de la imagen se
        obtiene cual es el color mayoritario en el area de las coordenas
        y se devuelve dicho color junto con el resultado d ela votacion
        '''

        # Se obtiene la zona de la imagen que esta dentro de las coordenas
        zona_coordenadas = imagen[y_ini:y_fin, x_ini:x_fin]

        # Se cambia la forma del array para que este en 1D y asi poder contar cual es el elemento mayoritario
        zona_coordenadas = np.reshape(zona_coordenadas, zona_coordenadas.size)

        # Se realiza el conteo de elementos
        conteo = np.bincount(zona_coordenadas)

        # Si no hay pixeles blancos la longitud del conteo sera < 2,
        # asi que se devuelve que hay 0 pixeles blancos
        if conteo.size < 2:
            if resultados:
                return np.argmax(conteo), 0, conteo[0]

        else:
            if resultados:
                return np.argmax(conteo), conteo[255], conteo[0]

        return np.argmax(conteo)

    def crearCuadraditos(self, x_ini, x_fin, y_ini, y_fin, n_pixeles_ancho=None, n_pixeles_alto=None):
        '''
        Dada una imagen y unas coordenadas de inicio y fin de la imagen se
        crean divisiones, recortes, en la imagen que definiran las coordenadas
        de inicio y fin de cada cuadradito
        '''

        # None significa que se toma como tamanyo
        # el ancho (para n_pixeles_ancho) o el alto (para n_pixeles_alto)
        if n_pixeles_ancho is None:
            n_pixeles_ancho = x_fin - x_ini
        if n_pixeles_alto is None:
            n_pixeles_alto = y_fin - y_ini

        assert n_pixeles_ancho <= x_fin - x_ini and n_pixeles_alto >= 0, "Tamanyo de ancho incorrecto"
        assert n_pixeles_alto <= y_fin - y_ini and n_pixeles_ancho >= 0, "Tamanyo de alto incorrecto"

        l_cuadraditros = []

        mismo_tamano_cuadrado = True
        # Se crean los limites de los cuadraditos
        for coordenada_y in range(y_ini, y_fin, n_pixeles_alto):
            for coordenada_x in range(x_ini, x_fin, n_pixeles_ancho):

                # Se obtiene las coordenadas x de inicio y fin del recorte del cuadradito
                if coordenada_x + n_pixeles_ancho > x_fin:
                    #l_coordenadas = [(coordenada_x, x_fin)]
                    mismo_tamano_cuadrado = False
                else:
                    l_coordenadas = [(coordenada_x, coordenada_x + n_pixeles_ancho)]

                # Se obtiene las coordenadas y de inicio y fin del recorte del cuadradito
                if coordenada_y + n_pixeles_alto > y_fin:
                    #l_coordenadas.append((coordenada_y, y_fin))
                    mismo_tamano_cuadrado = False
                else:
                    l_coordenadas.append((coordenada_y, coordenada_y + n_pixeles_alto))

                if mismo_tamano_cuadrado:
                    l_cuadraditros.append(l_coordenadas)
                mismo_tamano_cuadrado = True

        return l_cuadraditros

    def quitaMargenes(self, corte_h, corte_v):
        '''
        Copia casi igual de extrae_cuadradito, pero
        solo elimina los margenes negros de una
        imagen y devuelve las coordenadas de la imagen
        '''
        alto = 200
        ancho = 150

        assert corte_h[1]-corte_h[0]+1 >= alto,  "Alto demasiado grande"
        assert corte_v[1]-corte_v[0]+1 >= ancho, "Ancho demasiado grande"

        margen_h = (corte_h[1] - corte_h[0] + 1 - alto)
        margen_v = (corte_v[1] - corte_v[0] + 1 - ancho)

        h0 = int(corte_h[0] +  margen_h // 2)
        h1 = int(corte_h[1] - (margen_h // 2 if margen_h % 2 == 0 else (1 + margen_h // 2)))
        v0 = int(corte_v[0] +  margen_v // 2)
        v1 = int(corte_v[1] - (margen_v // 2 if margen_v % 2 == 0 else (1 + margen_v // 2)))

        assert h1-h0+1==alto,  "H:{}-V:{}-C{}".format(corte_h, corte_v,[h0,h1])
        assert v1-v0+1==ancho, "H:{}-V:{}-C{}".format(corte_h, corte_v,[v0,v1])

        return h0, h1+1, v0, v1+1

    def mostrarImagen(self, imagen):
        '''
        Dada una imagen se muestra por pantalla
        '''
        plt.imshow(imagen, interpolation=None, cmap='gray')
        plt.show()

        return

    def mostrarImagenes(self, imagenes, columnas=10):
        '''
        Dado un grupo de imagenes se muestran por pantalla
        en forma de rejilla con numero de columnas "columnas"
        y el numero de filas que sean necesarias
        '''
        letritas.mostrar_imagenes2(imagenes, columnas)
        plt.show()

        return

    def todoBlancoNegro(self, imagen):
        '''
        Dada una imagen cambia todos los colores de la imagen
        por blancos y negros. El valor umbral donde da el color
        blanco viene dado por el valor "self.umbral"
        '''

        # Se crea una imagen en negro (todo ceros) donde se iran cambiando por blancos algunos pixeles
        imagen_aux = np.zeros(shape = (imagen.shape[0], imagen.shape[1]), dtype=np.int64)

        # Por cada pixel se comprueba que valor tiene
        for i_valor, valores_fila in enumerate(imagen):
           for j_valor, valor in enumerate(valores_fila):

              # Si el valor del pixel es mayor a self.umbral decimos que es blanco
              if valor > self.umbral:
                 imagen_aux[i_valor][j_valor] += 255

        return imagen_aux

    def crearDataset(self, l_atributos, l_clases=None, ruta="ConjuntosDatos/", nombre="prueba.data"):

        with open(ruta+nombre, 'w') as fichero:

            # Se escribe el numero de datos que hay
            fichero.write(str(len(l_atributos))+"\n")

            # Se escribe el nombre de los atributos que hay
            atributos_nombre = ""
            num_atributos = len(l_atributos[0])
            # Si l_clases es None la clase ya estaba en l_atributos
            if l_clases is not None:
                for i in range(num_atributos):
                    atributos_nombre += "x" + str(i) + ","
                atributos_nombre += "class"
            else:
                for i in range(num_atributos-1):
                    atributos_nombre += "x" + str(i) + ","
                atributos_nombre += "class"
            fichero.write(atributos_nombre+"\n")

            # Se escribe el nombre de los atributos que hay
            tipo_atributos = ""
            # Si l_clases es None la clase ya estaba en l_atributos
            if l_clases is not None:
                for i in range(num_atributos):
                    tipo_atributos += "Continuo,"
                tipo_atributos += "Nominal"
            else:
                for i in range(num_atributos-1):
                    tipo_atributos += "Continuo,"
                tipo_atributos += "Nominal"
            fichero.write(tipo_atributos+"\n")

            # Se escriben los valores de cada dato y su clase
            for i_dato, atributos in enumerate(l_atributos):
                dato = ""
                for valor in atributos:
                    dato += str(valor) + ","

                # Si l_clases es None la clase ya estaba en
                # l_atributos asi que se quita la ultima coma
                if l_clases is not None:
                    dato += str(l_clases[i_dato])
                else:
                    dato = dato[:-1]
                fichero.write(dato+"\n")

        fichero.close()


# write a program to guess the number using random

import random

n=random.randint(1,100)

while True:
    print('guess a number between 1 to 100 : ')
    n1 = int(input())
    if n1 == n:
        print('yeah!!..you have guessed the number !')
        break
    elif n1<n:
        print('Try to guess a higher number... ! ')
    elif n1>n:
        print('Try to guess a lower number... !')


class Settings():
	"""A class to represent the settings of the game."""
	def __init__(self):
		"""Initialize all the settings of the game."""
		self.screen_settings()
		self.ship_settings()
		self.hostile_settings()
		self.misc_settings()
		self.game_internal_settings()

	def screen_settings(self):
		# Screen settings.
		self.screen_width = 800
		self.screen_height = 600
		self.bg_color = (240, 240, 240)

	def ship_settings(self):
		# Ship settings.
		self.ship_speed_factor = 0.6
		self.ship_speed_acceleration = 1.1
		self.ship_limit = 3
		self.ship_max_limit = 10

		# Ship Immune settings
		self.ship_time_immune = 3
		self.ship_time_hit = 0

		# Ship Score settings (For incrementing ship's lives in prep_ships()).
		self.ship_lives_increment_score = 500
		self.ship_lives_increment_difficulty = 5
		self.ship_score_offset = 1

		# Calls the ship_weapons settings method.
		self.ship_weapons_settings()

	def ship_weapons_settings(self):
		# Ship bullet settings.
		self.shipbullets_allowed = 100
		# Ship missile settings.
		self.shipmissiles_allowed = 100

		# Ship Default Firing Mode (Based on Type of Projectiles)
		# 1 - Bullets
		# 2 - Missiles
		# 3 - Lasers
		self.ship_weapon_default = 1

		# Ship bullet settings.
		self.shipbullet_time_fire_interval = 0.3
		self.ship_bullet_speed_factor = 0.8
		self.shipbullet_time_fire = 0
		self.shipbullets_constant_firing = False
		self.shipbullet_sound_start_stop = 0

		# Ship Railgun settings.
		self.shiprailgun_time_fire = 0
		self.shiprailgun_sound_start_stop = 0

		# Ship missile settings.
		self.shipmissile_time_fire_interval = 0.3
		self.ship_missile_speed_factor = 0.85
		self.shipmissile_time_fire = 0
		self.shipmissiles_constant_firing = False
		self.shipmissile_sound_start_stop = 0

		# Calls the ship_upgrade settings method.
		self.ship_upgrade_settings()

	def ship_upgrade_settings(self):
		# Upgrades settings and probability based on Ship's default weapon.
		self.upgrades_speed_factor = 0.1

		if self.ship_weapon_default == 1:
			self.upgrades_railgun_p = 0.7		# Default 0.7
			self.upgrades_secondary_p = 0.25	# Default 0.25
			self.upgrades_missile_p = 0.045		# Default 0.045
			self.upgrades_laser_p = 0.005		# Default 0.005
		elif self.ship_weapon_default == 2:
			self.upgrades_railgun_p = 0.045		# Default 0.045
			self.upgrades_secondary_p = 0.25	# Default 0.25
			self.upgrades_missile_p = 0.7		# Default 0.7
			self.upgrades_laser_p = 0.005		# Default 0.005

		self.upgrades_total_no = 4

		self.upgrades_time_railgun_start = 0
		self.upgrades_time_railgun_duration = 10
		self.upgrades_time_railgun_max = 180
		self.upgrades_time_railgun_end = 0

		self.upgrades_time_secondary_start = 0
		self.upgrades_time_secondary_duration = 10
		self.upgrades_time_secondary_max = 180
		self.upgrades_time_secondary_end = 0

		self.upgrades_time_missile_start = 0
		self.upgrades_time_missile_duration = 10
		self.upgrades_time_missile_max = 180
		self.upgrades_time_missile_end = 0

		self.upgrades_time_laser_start = 0
		self.upgrades_time_laser_duration = 10
		self.upgrades_time_laser_max = 180
		self.upgrades_time_laser_end = 0

		self.upgrades_no_of_current_upgrades = 0

		self.upgrades_time_start = 0
		self.upgrades_time_duration = 10
		self.upgrades_time_max = 180
		self.upgrades_time_end = 0

	def hostile_settings(self):
		# Helicopter and helicopter bullet settings.
		self.helicopter_speed_factor = 0.2
		self.helicopter_points = 50

		# Helicopter bullet settings.
		self.helicopter_bullet_speed_factor = 0.4
		self.helicopter_bullet_points = 2

		# Rocket settings
		self.rocket_speed_factor = 0.1
		self.rocket_speed_acceleration = 1.1
		self.rocket_points = 100

		# Advanced Helicopter settings
		self.ad_heli_speed_factor = 0.22
		self.ad_heli_points = 150

		# Disabling this, disables all hostile spawns.
		# Enabling this, allows the toggling of the different hostile spawns.
		self.wave_hostile_spawn = True
		self.wave_heli_spawn = False
		self.wave_rocket_spawn = False
		self.wave_ad_heli_spawn = True

		# Number of Hostiles that will spawn per wave.
		# This is used during the process of wave creation in gf_hostiles.py
		self.helicopter_wave_limit = 10		# Default 10
		self.rocket_wave_limit = 10			# Default 10
		self.ad_heli_wave_limit = 15		# Default 5

	def misc_settings(self):
		# Parachute settings.
		self.parachute_speed_factor = 0.1
		self.parachute_points = 25

		# Explosion settings.
		self.explosion_time_disappear = 0.15
		self.explosion_time_create = 0

	def game_internal_settings(self):
		# Mouse settings.
		# Mouse start game settings.
		self.mouse_starttime_nowork_interval = 1
		self.mouse_start_time_click = 0
		self.mouse_working = False
		# mouse_start_smoothness is found in mouse_movements of game_functions.py.
		self.mouse_start_smoothness = 50

		# Points increment settings.
		self.points_speedup_scale = 1.5

		# Time settings.
		self.time_game = 0
		self.time_game_play = 0
		# Time game active settings.
		self.time_game_start = 0
		self.time_game_total_play = 0
		# Time game pause settings.
		self.time_game_pause_start = 0
		self.time_game_single_pause = 0
		self.time_game_total_pause = 0

	def increase_points(self):
		"""Increases the points of each hostile or hostile projectiles as
		the game progresses to a harder level."""
		self.hostile_points *= self.points_speedup_scale

"""	def increase_speeds(self):
		self.ship_speed_factor *= self.speedup_scale
		self.ship_bullet_speed_factor *= self.speedup_scale

		self.helicopter_speed_factor *= self.speedup_scale
		self.helicopter_bullet_speed_factor *= self.speedup_scale
		self.hostile_speed_factor *= self.speedup_scale
"""


import math

w, h, n = map(int, input().split())

def is_good(x: int) -> int:
    return ( math.floor((x / w)) * math.floor((x / h))) >= n

def pack_rectangles():
    if w == 0 and h == 0:
        print(0)
        return
    l = 0 # bad
    r = 1 # good
    while not is_good(r):
        r *= 2
    while r > l + 1:
        m = (l + r) // 2
        if is_good(m):
            r = m
        else:
            l = m
    print(r)

pack_rectangles()


import pandas

from sensor.constants.training_pipeline import TARGET_COLUMN
from sensor.entity.artifact_entity import (
    DataValidationArtifact,
    ModelTrainerArtifact,
    ModelEvaluationArtifact,
)
from sensor.entity.config_entity import ModelEvaluationConfig
from sensor.exceptions import SensorException
from sensor.logger import logging
from sensor.ml.metrics.classification_metric import get_classification_score
from sensor.ml.model.estimator import ModelResolver
from sensor.utils.main_utils import load_object, write_yaml_file

class ModelEvaluation:
    def __init__(
        self,
        model_evaluation_config: ModelEvaluationConfig,
        data_validation_artifact: DataValidationArtifact,
        model_trainer_artifact: ModelTrainerArtifact,
    ):
        try:
            self.model_eval_config = model_evaluation_config
            self.data_validation_artifact = data_validation_artifact
            self.model_trainer_artifact = model_trainer_artifact
        except Exception as error:
            raise SensorException(error)

    def initiate_model_evaluation(self) -> ModelEvaluationArtifact:
        try:
            valid_train_file_path = self.data_validation_artifact.valid_train_file_path
            valid_test_file_path = self.data_validation_artifact.valid_test_file_path

            # valid train and test dataframe
            train_df = pandas.read_csv(valid_train_file_path)
            test_df = pandas.read_csv(valid_test_file_path)

            df = pandas.concat([train_df, test_df])

            model_resolver = ModelResolver()

            trained_model_file_path = (
                self.model_trainer_artifact.trained_model_file_path
            )
            is_model_accepted = True
            if not model_resolver.is_model_exists():
                model_evaluation_artifact = ModelEvaluationArtifact(
                    trained_model_path=trained_model_file_path,
                    trained_model_metric_artifact=self.model_trainer_artifact.test_metric_artifact,
                    best_model_metric_artifact=None,
                    best_model_path=None,
                    improved_accuracy=None,
                    is_model_accepted=is_model_accepted,
                )
                logging.info(f"Model Evaluation Artifact: {ModelEvaluationArtifact}")
                return model_evaluation_artifact

            latest_model_path = model_resolver.get_best_model_path()
            latest_model = load_object(file_path=latest_model_path)
            train_model = load_object(file_path=trained_model_file_path)

            y_true = df[TARGET_COLUMN]
            y_train_pred = train_model.predict(df)
            y_latest_pred = train_model.predict(latest_model)

            train_model_metric = get_classification_score(y_true, y_train_pred)
            latest_metric = get_classification_score(y_true, y_latest_pred)

            improved_accuracy = train_model_metric.f1_score - latest_metric.f1_score
            if self.model_eval_config.model_evaluation_threshold < improved_accuracy:
                is_model_accepted = True
            else:
                is_model_accepted = False

            model_evaluation_artifact = ModelEvaluationArtifact(
                trained_model_path=trained_model_file_path,
                trained_model_metric_artifact=train_model_metric,
                best_model_metric_artifact=latest_metric,
                best_model_path=latest_model_path,
                improved_accuracy=improved_accuracy,
                is_model_accepted=is_model_accepted,
            )
            logging.info(f"Model Evaluation Artifact: {ModelEvaluationArtifact}")
            model_eval_report = model_evaluation_artifact.__dict__
            write_yaml_file(
                file_path=self.model_eval_config.model_evaluation_file_path,
                content=model_eval_report,
            )
            return model_evaluation_artifact
        except Exception as error:
            raise SensorException(error)


import weakref

from oslo_config import cfg

from vnfsvc.common import rpc as n_rpc
from vnfsvc.common import utils
from vnfsvc.openstack.common import importutils
from vnfsvc.openstack.common import log as logging
from vnfsvc.openstack.common import periodic_task
from vnfsvc.openstack.common.gettextutils import _

from stevedore import driver

LOG = logging.getLogger(__name__)

class Manager(n_rpc.RpcCallback, periodic_task.PeriodicTasks):

    # Set RPC API version to 1.0 by default.
    RPC_API_VERSION = '1.0'

    def __init__(self, host=None):
        if not host:
            host = cfg.CONF.host
        self.host = host
        super(Manager, self).__init__()

    def periodic_tasks(self, context, raise_on_error=False):
        self.run_periodic_tasks(context, raise_on_error=raise_on_error)

    def init_host(self):
        """Handle initialization if this is a standalone service.

        Child classes should override this method.

        """
        pass

    def after_start(self):
        """Handler post initialization stuff.

        Child classes can override this method.
        """
        pass

def validate_pre_plugin_load():
    """Checks if the configuration variables are valid.

    If the configuration is invalid then the method will return an error
    message. If all is OK then it will return None.
    """
    if cfg.CONF.core_plugin is None:
        msg = _('VNF core_plugin not configured!')
        return msg

class VNFSvcManager(object):
    """VNFSVC's Manager class.

    VNFSVC's Manager class is responsible for parsing a config file and
    instantiating the correct plugin that concretely implements
    vnfsvc_plugin_base class.
    The caller should make sure that VNFSvcManager is a singleton.
    """
    _instance = None

    def __init__(self, options=None, config_file=None):
        # If no options have been provided, create an empty dict
        if not options:
            options = {}

        msg = validate_pre_plugin_load()
        if msg:
            LOG.critical(msg)
            raise Exception(msg)

        plugin_provider = cfg.CONF.core_plugin
        LOG.info(_("Loading core plugin: %s"), plugin_provider)
        self.plugin = self._get_plugin_instance('vnfsvc.core_plugins',
                                                plugin_provider)

    def _get_plugin_instance(self, namespace, plugin_provider):
        try:
            # Try to resolve plugin by name
            mgr = driver.DriverManager(namespace, plugin_provider)
            plugin_class = mgr.driver
        except RuntimeError as e1:
            # fallback to class name
            try:
                plugin_class = importutils.import_class(plugin_provider)
            except ImportError as e2:
                LOG.exception(_("Error loading plugin by name, %s"), e1)
                LOG.exception(_("Error loading plugin by class, %s"), e2)
                raise ImportError(_("Plugin not found."))
        return plugin_class()

    @classmethod
    @utils.synchronized("manager")
    def _create_instance(cls):
        if not cls.has_instance():
            cls._instance = cls()

    @classmethod
    def has_instance(cls):
        return cls._instance is not None

    @classmethod
    def clear_instance(cls):
        cls._instance = None

    @classmethod
    def get_instance(cls):
        # double checked locking
        if not cls.has_instance():
            cls._create_instance()
        return cls._instance

    @classmethod
    def get_plugin(cls):
        # Return a weakref to minimize gc-preventing references.
        return weakref.proxy(cls.get_instance().plugin)


import torch
import torch.nn as nn
from torch.utils.data import Dataset
import torch.utils.data
import json

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

class Dataset(Dataset):

    def __init__(self):

        self.pairs = json.load(open('pairs_encoded.json'))
        self.dataset_size = len(self.pairs)

    def __getitem__(self, i):

        question = torch.LongTensor(self.pairs[i][0])
        reply = torch.LongTensor(self.pairs[i][1])

        return question, reply

    def __len__(self):
        return self.dataset_size

def create_masks(question, reply_input, reply_target):

    def subsequent_mask(size):
        mask = torch.triu(torch.ones(size, size)).transpose(0, 1).type(dtype=torch.uint8)
        return mask.unsqueeze(0)

    question_mask = (question!=0).to(device)
    question_mask = question_mask.unsqueeze(1).unsqueeze(1)         # (batch_size, 1, 1, max_words)

    reply_input_mask = reply_input!=0
    reply_input_mask = reply_input_mask.unsqueeze(1)  # (batch_size, 1, max_words)
    reply_input_mask = reply_input_mask & subsequent_mask(reply_input.size(-1)).type_as(reply_input_mask.data)
    reply_input_mask = reply_input_mask.unsqueeze(1) # (batch_size, 1, max_words, max_words)
    reply_target_mask = reply_target!=0              # (batch_size, max_words)

    return question_mask, reply_input_mask, reply_target_mask

class AdamWarmup:

    def __init__(self, model_size, warmup_steps, optimizer):

        self.model_size = model_size
        self.warmup_steps = warmup_steps
        self.optimizer = optimizer
        self.current_step = 0
        self.lr = 0

    def get_lr(self):
        return self.model_size ** (-0.5) * min(self.current_step ** (-0.5), self.current_step * self.warmup_steps ** (-1.5))

    def step(self):
        # Increment the number of steps each time we call the step function
        self.current_step += 1
        lr = self.get_lr()
        for param_group in self.optimizer.param_groups:
            param_group['lr'] = lr
        # update the learning rate
        self.lr = lr
        self.optimizer.step()

class LossWithLS(nn.Module):

    def __init__(self, size, smooth):
        super(LossWithLS, self).__init__()
        self.criterion = nn.KLDivLoss(size_average=False, reduce=False)
        self.confidence = 1.0 - smooth
        self.smooth = smooth
        self.size = size

    def forward(self, prediction, target, mask):
        """
        prediction of shape: (batch_size, max_words, vocab_size)
        target and mask of shape: (batch_size, max_words)
        """
        prediction = prediction.view(-1, prediction.size(-1))   # (batch_size * max_words, vocab_size)
        target = target.contiguous().view(-1)   # (batch_size * max_words)
        mask = mask.float()
        mask = mask.view(-1)       # (batch_size * max_words)
        labels = prediction.data.clone()
        labels.fill_(self.smooth / (self.size - 1))
        labels.scatter_(1, target.data.unsqueeze(1), self.confidence)
        loss = self.criterion(prediction, labels)    # (batch_size * max_words, vocab_size)
        loss = (loss.sum(1) * mask).sum() / mask.sum()
        return loss


import requests

# For local streaming, the websockets are hosted without ssl - http://
HOST = 'localhost:5000'
#===============================================================================
#update this API every time
#===============================================================================
with open('C:\@code\\text-generation-webui\API\HOST.txt', 'r') as f:
    HOST = f.read().strip().split('/')[2]

URI = f'http://{HOST}/api/v1/generate'

# For reverse-proxied streaming, the remote will likely host with ssl - https://
# URI = 'https://your-uri-here.trycloudflare.com/api/v1/generate'

def run(prompt):
    request = {
        'prompt': prompt,
        'max_new_tokens': 250,
        'do_sample': True,
        'temperature': 0.01,
        'top_p': 0.1,
        'typical_p': 1,
        'epsilon_cutoff': 0,  # In units of 1e-4
        'eta_cutoff': 0,  # In units of 1e-4
        'repetition_penalty': 1.18,
        'top_k': 40,
        'min_length': 0,
        'no_repeat_ngram_size': 0,
        'num_beams': 1,
        'penalty_alpha': 0,
        'length_penalty': 1,
        'early_stopping': False,
        'seed': -1,
        'add_bos_token': True,
        'truncation_length': 2048,
        'ban_eos_token': False,
        'skip_special_tokens': True,
        'stopping_strings': []
    }

    response = requests.post(URI, json=request)

    if response.status_code == 200:
        result = response.json()['results'][0]['text']
        print(prompt + result)

if __name__ == '__main__':
    prompt = "In order to make homemade bread, follow these steps:\n1)"

    text_1 = f"""
    Making a cup of tea is easy! First, you need to get some \
    water boiling. While that's happening, \
    grab a cup and put a tea bag in it. Once the water is \
    hot enough, just pour it over the tea bag. \
    Let it sit for a bit so the tea can steep. After a \
    few minutes, take out the tea bag. If you \
    like, you can add some sugar or milk to taste. \
    And that's it! You've got yourself a delicious \
    cup of tea to enjoy.
    """
    prompt = f"""
    You will be provided with text delimited by triple quotes.
    If it contains a sequence of instructions, \
    re-write those instructions in the following format:

    Step 1 - ...
    Step 2 - …
    …
    Step N - …
    \"\"\"{text_1}\"\"\"
    """

    run(prompt)


import tensorflow as tf

# to change.

def _stratified_sampling_V2(self, weights):
        N=self.num_samples
        indexes=[]
        j=tf.constant(0)
        cum_weights=tf.gather(weights, j)

        def update_j(j, cum_w, weights):
            j = j + 1
            cum_w = cum_w + tf.gather(weights, j)

            return j, cum_w, weights

        for i in range(N):
            subdivision=tf.random_uniform(minval=i/N, maxval=(i+1)/N, shape=())
            j, cum_weights, weights= tf.while_loop(cond=lambda l, *_: tf.less(cum_weights, subdivision),
                                             body=update_j,
                                             loop_vars=[j, cum_weights, weights])
            indexes.append(j)

        indexes=tf.stack(indexes)
        return indexes

def _stratified_sampling(self, weights):
    N=self.num_samples
    indexes = tf.constant(0, shape=[1])
    i = 0
    j = tf.constant(0)
    subdivisions = [tf.random_uniform(minval=i / N, maxval=(i + 1) / N, shape=()) for i in range(N)]
    subdivisions=tf.stack(subdivisions)
    cum_weights = [tf.reduce_sum(weights[:i]) for i in range(N)]
    cum_weights=tf.stack(cum_weights)

    def body(i, j, indexes):
        def indexes_f(i, j, indexes):
            indexes = tf.concat([indexes, tf.reshape(j, shape=[1])], axis=0)
            return i + 1, j, indexes

        def f_j(i, j, indexes):
            return i, j + tf.constant(1), indexes

        i, j, indexes = tf.cond(pred=tf.less(tf.gather(subdivisions,i), tf.gather(cum_weights,j)),
                                true_fn=lambda: indexes_f(i, j, indexes),
                                false_fn=lambda: f_j(i, j, indexes))
        return i, j, indexes

    i, _, indexes = tf.while_loop(cond=lambda i, *_: tf.less(i, N),
                                  body=body,
                                  loop_vars=[i, j, indexes],
                                  shape_invariants=[tf.TensorShape(dims=()), tf.TensorShape(dims=()),
                                                    tf.TensorShape([None])])

    indexes = indexes[1:]  # trick to remove the initialization of the indexes tensor
    return indexes

def _residual_sampling(self, weights):
    N=self.num_samples
    floor=tf.floor(tf.math.scalar_mul(N, weights))
    floor=tf.cast(floor, dtype=tf.int32)
    indexes=[]
    # takes the floor(Nwi) copies of ith indices
    for i in range(N):
        indexes=indexes + [tf.constant(i)]*floor[i]
    indexes_tensor=tf.stack(indexes)

    # residual samples and weights
    #Nr = tf.constant(N) - tf.reduce_sum(floor, axis=-1)
    Nr = tf.constant(N)-indexes.shape[0]
    res = tf.math.scalar_mul(N, weights) - tf.cast(floor, dtype=tf.float32)
    res = res / tf.reduce_sum(res, axis=-1)

    indexes_res = tf.multinomial(tf.expand_dims(res, axis=0), Nr, output_dtype=tf.int32)
    indexes_res = tf.squeeze(indexes_res, axis=0)
    indexes = tf.concat([indexes_tensor, indexes_res], axis=0)

    return indexes

def compute_ancestral_index(prev_sampling_weights, uniform_distribution):
  # FUNCTION ACTUALLY NOT USED....
  '''
  -args:
    -prev_sampling_weights: float tensor of shape (B,P)
    -uniform distribution: float tensor of dimension (B,P)
  -returns:
    -the current set of M indices > tensor of shape (B,P)
  '''
  batch_size = tf.shape(prev_sampling_weights)[0]
  num_particles = tf.shape(prev_sampling_weights)[1]

  # compute w_bar:
  W_0 = tf.expand_dims(tf.constant(0, dtype=tf.float32, shape=(batch_size,)), axis=-1)
  W_m = [tf.reduce_sum(prev_sampling_weights[:, :m], axis=-1) for m in range(num_particles)]
  W_m = tf.stack(W_m, axis=-1)
  W_m = tf.concat([W_0, W_m], axis=-1)

  indices_func = np.zeros(shape=tf.shape(prev_sampling_weights))

  # TRY TO REMOVE THIS DOUBLE FOR LOOP!!! > see this github repo as an example:
  # https://github.com/rlabbe/filterpy/blob/master/filterpy/monte_carlo/resampling.py
  for b in range(batch_size):
    for i in range(num_particles):
      unif = uniform_distribution[b, i]
      if unif >= W_m[b, i] and unif <= W_m[b, i + 1]:
        indices_func[b, i] = i + 1

  indices_func = tf.convert_to_tensor(indices_func, dtype=tf.int32)

  ancestral_index = tf.stack([tf.reduce_sum(indices_func[:, :i], axis=-1) for i in range(num_particles)], axis=-1)
  ancestral_index = tf.cast(ancestral_index, tf.int32)

  return ancestral_index  # tf.stop_gradient(ancestral_index)


import matplotlib

matplotlib.use("Qt5Agg")  # 声明使用QT5
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import pylab as mpl
from PyQt5.QtCore import pyqtSignal

# 创建一个matplotlib图形绘制类
class MyFigure(FigureCanvas):
    sig_change_size = pyqtSignal(float)
    def __init__(self, width=10, height=10, dpi=100):
        try:
            # 创建一个创建Figure
            self.fig = Figure(figsize=(width, height), dpi=dpi)
            # 在父类中激活Figure窗口
            super(MyFigure, self).__init__(self.fig)  # 此句必不可少，否则不能显示图形
            # 指定字体,显示中文
            mpl.rcParams['font.sans-serif'] = ['FangSong']
            mpl.rcParams['axes.unicode_minus'] = False

            # 创建一个子图，用于绘制图形用，111表示子图编号，如matlab的subplot(1,1,1)
            self.axes = self.fig.add_subplot(111)
        except Exception as e:
            print(e)

    def wheelEvent(self, event):
        angle = event.angleDelta() / 8  # 返回QPoint对象，为滚轮转过的数值，单位为1/8度
        angleY = angle.y()  # 竖直滚过的距离
        if angleY > 0:
            self.sig_change_size.emit(-0.1)
        else:  # 滚轮下滚
            self.sig_change_size.emit(0.1)


def writeFileDetails(conn, header):
    print("In writeFileDetails")
    if conn:
        cursor = conn.cursor()
        cursor.execute(
            "INSERT INTO claim_file_details ( "
            "File_Name, Claim_Type, "
            "Sender_ID, Receiver_ID, "
            "Submission_Date, Disposition_Flag, Claim_IDs, Record_Count) "
            "VALUES (%s, %s, %s, %s, %s, %s, %s, %s)",
            (header['FileName'], header['ClaimType'],
             header['SenderID'], header['ReceiverID'],
             header['TransactionDate'], header['DispositionFlag'], header['Claims'], int(header['RecordCount'])))
        conn.commit

def writeClaimMaster(conn, claims, header):
    print("In writeClaimMaster")
    if conn:
        cursor = conn.cursor()

        for clm in claims:
            claim = clm["claim"]
            cursor.execute(
                " INSERT INTO Claim_Master ("
                "Claim_ID, Sender_ID, Receiver_ID, Submission_Date, "
                "ID_Payer, Member_ID, Payer_ID, Provider_ID, Emirates_IDNumber, "
                "Gross, PatientShare, Net, VAT, Enc_Facility_ID, "
                "Enc_Type, Enc_Patient_ID, Enc_Start_Time, Enc_End_Time, Enc_Start_Type, "
                "Enc_End_Type) "
                "VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)",
                (claim["ClaimID"], header["SenderID"], header['ReceiverID'], header['TransactionDate'],
                 claim["IDPayer"], claim["MemberID"], claim["PayerID"], claim["ProviderID"], claim["EmiratesIDNumber"],
                 claim["Gross"], claim["PatientShare"], claim["Net"], claim["VAT"], claim["FacilityID"],
                 claim["FacilityType"], claim["PatientID"], claim["Start"], claim["End"], claim["StartType"],
                 claim["EndType"]))

        conn.commit

def writeClaimDiagnosis(conn, claims):
    if conn:
        cursor = conn.cursor()
        for clm in claims:
            diagnosis = clm["diagnosis"]
            for diag in diagnosis:
                cursor.execute(
                    "INSERT INTO Claim_Diagnosis ("
                    "Claim_ID, Diagnosis_Type, Diagnosis_Code) "
                    "VALUES (%s, %s, %s)",
                    (diag['ClaimID'], diag['Type'], diag['Code']))

        conn.commit

def writeClaimActivity(conn, claims):
    if conn:
        cursor = conn.cursor()
        for clm in claims:
            activity = clm["activity"]
            for acti in activity:
                cursor.execute(
                    "INSERT INTO Claim_Activity ("
                    "Activity_ID, Claim_ID, Act_Start_Time, Act_Type, Act_Code, "
                    "Act_Net, Act_Quantity, Ordering_Clinician, Clinician, "
                    "PriorAuthorization_ID, VAT, VAT_Percent) "
                    "VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)",
                    (acti['ID'], acti['ClaimID'], acti['Start'], acti['Type'], acti['Code'],
                     acti['Net'], acti['Quantity'], acti['OrderingClinician'], acti['Clinician'],
                     acti['PriorAuthorizationID'], float(acti['VAT']), float(acti['VATPercent'])))
        conn.commit

def writeClaimActObs(conn, claims):
    if conn:
        cursor = conn.cursor()
        for clm in claims:
            activity = clm["activity"]
            for acti in activity:
                observations = acti["Observations"]
                for obs in observations:
                    # print(obs)
                    cursor.execute(
                        "INSERT INTO Claim_Act_Observation ("
                        "Activity_ID, Claim_ID, Obs_Type, Obs_Code, Obs_Value, Obs_ValueType) "
                        "VALUES (%s, %s, %s, %s, %s, %s)",
                        (obs['ID'], obs['ClaimID'], obs['Type'], obs['Code'], obs['Value'], obs['ValueType']))
        conn.commit

def writeResubMaster(conn, claims, header):
    print("In writeResubMaster")
    if conn:
        cursor = conn.cursor()

        for clm in claims:
            claim = clm["claim"]
            cursor.execute(
                " INSERT INTO Resub_Master ("
                "Claim_ID, Sender_ID, Receiver_ID, Submission_Date, "
                "ID_Payer, Member_ID, Payer_ID, Provider_ID, Emirates_IDNumber, "
                "Gross, PatientShare, Net, VAT, Enc_Facility_ID, "
                "Enc_Type, Enc_Patient_ID, Enc_Start_Time, Enc_End_Time, Enc_Start_Type, "
                "Enc_End_Type, Resub_Type, Resub_Comment) "
                "VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)",
                (claim["ClaimID"], header["SenderID"], header['ReceiverID'], header['TransactionDate'],
                 claim["IDPayer"], claim["MemberID"], claim["PayerID"], claim["ProviderID"], claim["EmiratesIDNumber"],
                 claim["Gross"], claim["PatientShare"], claim["Net"], claim["VAT"], claim["FacilityID"],
                 claim["FacilityType"], claim["PatientID"], claim["Start"], claim["End"], claim["StartType"],
                 claim["EndType"], claim["ResubType"], claim["ResubComment"]))

        conn.commit

def writeRemitMaster(conn, claims, header):
    if conn:
        cursor = conn.cursor()

        for clm in claims:
            claim = clm["claim"]
            cursor.execute(
                " INSERT INTO Remittance_Master ("
                "Claim_ID, Sender_ID, Receiver_ID, Submission_Date, "
                "ID_Payer, Provider_ID, Payment_Reference, "
                "Date_Settlement, Enc_Facility_ID) "
                "VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s)",
                (claim["ClaimID"], header["SenderID"], header['ReceiverID'], header['TransactionDate'],
                 claim["IDPayer"], claim["ProviderID"], claim["PaymentReference"],
                 claim["DateSettlement"], claim["FacilityID"]))

        conn.commit

def writeRemitActivity(conn, claims):
    if conn:
        cursor = conn.cursor()
        for clm in claims:
            activity = clm["activity"]
            for acti in activity:
                cursor.execute(
                    "INSERT INTO Remittance_Activity ("
                    "Activity_ID, Claim_ID, Act_StartTime, Act_Type, Act_Code, "
                    "Act_Net, Act_Quantity, Ordering_Clinician, Clinician, "
                    "Payment_Amount, Denial_Code) "
                    "VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)",
                    (acti['ID'], acti['ClaimID'], acti['Start'], acti['Type'], acti['Code'],
                     acti['Net'], acti['Quantity'], acti['OrderingClinician'], acti['Clinician'],
                     float(acti['PaymentAmount']), acti['DenialCode']))
        conn.commit


import heapq

def find_parent(x):
  if x!= parents[x]:
    parents[x]=find_parent(parents[x])
  return parents[x]

def union(x,y):
  pre_x=parents[x]
  pre_y=parents[y]

  if pre_x < pre_y:
    parents[pre_y]=pre_x
  else:
    parents[pre_x]=pre_y

vertex,edge=0,0
parents=[]
edges=[]

sum_cost=0
with open("input43.txt","r") as file:
  vertex,edge=map(int,file.readline().split())
  graph=[[] for _ in range(vertex)]

  for _ in range(edge):
    vertex1,vertex2,cost=map(int,file.readline().split())
    heapq.heappush(edges,(cost,vertex1,vertex2))
    sum_cost+=cost

parents=[i for i in range(vertex)]
edge_count=0
result=0

while edge_count != vertex-1:
  cost,vertex1,vertex2=heapq.heappop(edges)

  if find_parent(vertex1) != find_parent(vertex2):
    union(vertex1,vertex2)
    edge_count+=1
    result+=cost

print(sum_cost-result)


from zeus.common import ClassFactory, ClassType
from zeus.modules.connections import OutlistSequential, Sequential
from zeus.modules.operators import ops

base_arch_code = {50: '111-2111-211111-211',
                  101: '111-2111-21111111111111111111111-211'}

class BN_Conv2d(ops.Module):
    """Base conv2D."""

    def __init__(self, in_channels, out_channels, kernel_size, stride, padding, dilation=1, groups=1, bias=False):
        super(BN_Conv2d, self).__init__()
        self.seq = Sequential(
            ops.Conv2d(in_channels, out_channels, kernel_size=kernel_size, stride=stride,
                       padding=padding, dilation=dilation, groups=groups, bias=bias),
            ops.BatchNorm2d(out_channels),
            ops.Relu()
        )

class ResNeXt_Block(ops.Module):
    """ResNeXt block with group convolutions."""

    expansion = 4

    def __init__(self, in_chnls, cardinality, group_depth, stride):
        super(ResNeXt_Block, self).__init__()
        self.group_chnls = cardinality * group_depth
        self.conv1 = BN_Conv2d(in_chnls, self.group_chnls,
                               1, stride=1, padding=0)
        self.conv2 = BN_Conv2d(self.group_chnls, self.group_chnls,
                               3, stride=stride, padding=1, groups=cardinality)
        self.conv3 = ops.Conv2d(
            self.group_chnls, self.group_chnls * 2, 1, stride=1, padding=0)
        self.bn = ops.BatchNorm2d(self.group_chnls * 2)
        self.short_cut = Sequential(
            ops.Conv2d(in_chnls, self.group_chnls *
                       2, 1, stride, 0, bias=False),
            ops.BatchNorm2d(self.group_chnls * 2)
        )

    def call(self, x):
        """Call function."""
        out = self.conv1(x)
        out = self.conv2(out)
        out = self.bn(self.conv3(out))
        out += self.short_cut(x)
        return ops.Relu()(out)

@ClassFactory.register(ClassType.NETWORK)
class ResNeXtDet(ops.Module):
    """ResNet for detection."""

    arch_settings = {
        50: (ResNeXt_Block, (3, 4, 6, 3)),
        101: (ResNeXt_Block, (3, 4, 23, 3))
    }

    def __init__(self, depth, num_stages=4, strides=(1, 2, 2, 2), out_indices=(0, 1, 2, 3),
                 zero_init_residual=False, frozen_stages=-1, code=None):
        """Init ResNet."""
        super(ResNeXtDet, self).__init__()
        self.out_indices = out_indices

        self.zero_init_residual = zero_init_residual
        self.block, stage_blocks = self.arch_settings[depth]
        self.stage_blocks = stage_blocks[:num_stages]
        self.inplanes = 64
        self._make_stem_layer()
        self.res_layers = []
        inplanes = self.inplanes
        planes = 1
        self.cardinality = 32
        if code is None:
            self.code = base_arch_code[depth].split('-')
        else:
            self.code = code.split('-')
        for i, num_blocks in enumerate(self.stage_blocks):
            stride = strides[i]
            res_layer, inplanes = self._make_layers(inplanes, planes,
                                                    num_blocks, stride=stride,
                                                    code=self.code[i])
            planes = planes * 2
            self.res_layers.append(res_layer)
        self.res_layers_seq = OutlistSequential(
            *self.res_layers, out_list=self.out_indices)

    def _make_layers(self, inplanes, d, blocks, stride, code):
        """Make layer."""
        strides = map(int, code)
        layers = []
        for stride in strides:
            layers.append(ResNeXt_Block(
                inplanes, self.cardinality, d, stride))
            inplanes = self.cardinality * d * 2
        return Sequential(*layers), inplanes

    def _make_stem_layer(self):
        """Make stem layer."""
        self.conv1 = BN_Conv2d(
            3, self.inplanes, kernel_size=7, stride=2, padding=3, bias=False)
        self.maxpool = ops.MaxPool2d(kernel_size=3, stride=2, padding=1)

    def call(self, x, **kwargs):
        """Forward compute of resnet for detection."""
        x = self.conv1(x)
        x = self.maxpool(x)
        outs = self.res_layers_seq(x)
        return tuple(outs)


from sklearn.datasets import load_iris
import pandas as pd
import numpy as np

from collections import defaultdict

def naive_bayes(X, Y):
    PCi = defaultdict(lambda: 0)
    for y in Y:
        PCi[y] += 1
    for k, v in PCi.items():
        PCi[k] /= len(Y)

    PXCi = defaultdict(lambda: 0)

data = load_iris()

X, Y, column_names = data['data'], data['target'], data['feature_names']
X = pd.DataFrame(X, columns=column_names)

print(X)
print(Y)

# data = pd.read_csv('data/tennis.csv')

# X = pd.get_dummies(data[['outlook', 'temp', 'humidity', 'windy']])
# Y = pd.DataFrame(data['play'])
# print(X, Y)

# # split data


# 2052번 지수연산
# 실패
# python은 소수점 아래 숫자가 많아지면 e로 표현한다. 이 부분을 숫자로 풀어줘야 되는 문제였다.

import sys

def input():
    return sys.stdin.readline().rstrip()

n = int(input())
result = "%.250f" %(2**(-n)) # 소수점 아래 250자리까지 표시하겠다.
last = len(result)
for i in range(last-1,1,-1):
    if result[i] != "0":
        last = i
        break

print(result[:last+1])


'''
O(log(n)) Time and O(1) Space
'''
def searchForRange(array, target):
    left, right = 0, len(array)-1
    left_extreme, right_extreme = None, None

    while left <= right:
        middle = (left + right)// 2
        if array[middle] == target:
            if middle == 0 or array[middle-1] != target:
                left_extreme = middle
                break
            else:
                right = middle - 1
            continue

        if array[middle] > target:
            right = middle - 1

        else:
            left = middle + 1

    left, right = 0, len(array)-1
    while left <= right:
        middle = (left + right)// 2
        if array[middle] == target:
            if middle == len(array)-1 or array[middle+1] != target:
                right_extreme = middle
                break
            else:
                left = middle + 1
            continue

        if array[middle] > target:
            right = middle - 1

        else:
            left = middle + 1

    if left_extreme is None or right_extreme is None:
        return [-1, -1]

    return [left_extreme, right_extreme]

'''
Given    : Sorted array of integers
Goal     : Find range of indices in the input array in which we can find the target number at every index
Expected : O(log(n))

Idea     : Do Binary-Search twice, and find the left and right extremes for the given target
'''

import unittest
class TestProgram(unittest.TestCase):
    def test_case_1(self):
        self.assertEqual(searchForRange([0, 1, 21, 33, 45, 45, 45, 45, 45, 45, 61, 71, 73], 45), [4, 9])
        print("Test Case: Passed")

if __name__ == "__main__":
    tester = TestProgram()
    tester.test_case_1()

# Kunal Wadhwa

03 AlgoExpert Hard/30 Search For Range.py


import copy
from typing import Dict, Set

from exasol_integration_test_docker_environment.abstract_method_exception import AbstractMethodException
from exasol_integration_test_docker_environment.lib.base.dependency_logger_base_task import DependencyLoggerBaseTask
from exasol_integration_test_docker_environment.lib.config.build_config import build_config
from exasol_integration_test_docker_environment.lib.docker.images.create.docker_image_analyze_task import \
    DockerAnalyzeImageTask
from exasol_integration_test_docker_environment.lib.docker.images.create.docker_image_create_task import \
    DockerCreateImageTask, DockerCreateImageTaskWithDeps
from exasol_integration_test_docker_environment.lib.docker.images.image_info import ImageInfo, ImageState
from exasol_integration_test_docker_environment.lib.docker.images.required_task_info import RequiredTaskInfoDict, \
    RequiredTaskInfo

class DockerBuildBase(DependencyLoggerBaseTask):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def _get_build_steps_to_rebuild(self):
        return set(build_config().force_rebuild_from)

    def get_goals(self) -> Set[str]:
        raise AbstractMethodException()

    def get_default_goals(self) -> Set[str]:
        raise AbstractMethodException()

    def get_goal_class_map(self) -> Dict[str, DockerAnalyzeImageTask]:
        raise AbstractMethodException()

    def register_required(self):
        self.analyze_tasks_futures = self.register_dependencies(self.create_analyze_tasks())

    def create_analyze_tasks(self) -> Dict[str, DockerAnalyzeImageTask]:
        goals = set(self.get_goals())
        self.goal_class_map = self.get_goal_class_map()
        self.available_goals = set(self.goal_class_map.keys())
        self._check_if_build_steps_to_rebuild_are_valid_goals()
        final_goals = self.get_default_goals()
        if len(goals) != 0:
            final_goals = set(goals)
        if final_goals.issubset(self.available_goals):
            tasks = {goal: self.goal_class_map[goal] for goal in final_goals}
            return tasks
        else:
            difference = goals.difference(self.available_goals)
            raise Exception(f"Unknown goal(s) {difference}, "
                            f"following goals are avaialable {self.available_goals}")

    def _check_if_build_steps_to_rebuild_are_valid_goals(self):
        build_steps_to_rebuild = self._get_build_steps_to_rebuild()
        if not build_steps_to_rebuild.issubset(self.available_goals):
            difference = build_steps_to_rebuild.difference(self.available_goals)
            raise Exception(f"Unknown build stages {difference} forced to rebuild, "
                            f"following stages are avaialable {self.available_goals}")

    def create_build_tasks(self, shortcut_build: bool = True) \
            -> Dict[str, DockerCreateImageTask]:
        image_infos = {goal: analyze_task_future.get_output()
                       for goal, analyze_task_future
                       in self.analyze_tasks_futures.items()}
        tasks = self._create_build_tasks_for_image_infos(image_infos, shortcut_build)
        return tasks

    def _create_build_tasks_for_image_infos(self, image_infos: Dict[str, ImageInfo], shortcut_build: bool):
        result = {goal: self._create_build_task_for_image_info(image_info, shortcut_build)
                  for goal, image_info in image_infos.items()}
        return result

    def _create_build_task_for_image_info(
            self, image_info: ImageInfo,
            shortcut_build: bool = True) -> DockerCreateImageTask:
        if self._build_with_depenencies_is_requested(image_info, shortcut_build):
            task_for_image_info = self._create_build_task_with_dependencies(image_info, shortcut_build)
            return task_for_image_info
        else:
            image_name = f"{image_info.target_repository_name}:{image_info.target_tag}"
            task_for_image_info = \
                self.create_child_task(DockerCreateImageTask,
                                       image_name=image_name,
                                       image_info=image_info)
            return task_for_image_info

    def _build_with_depenencies_is_requested(self, image_info: ImageInfo, shortcut_build: bool):
        needs_to_be_build = image_info.image_state == ImageState.NEEDS_TO_BE_BUILD.name
        result = (not shortcut_build or needs_to_be_build) and \
                 len(image_info.depends_on_images) > 0
        return result

    def _create_build_task_with_dependencies(
            self, image_info: ImageInfo,
            shortcut_build: bool = True) -> DockerCreateImageTask:
        required_tasks = \
            self._create_build_tasks_for_image_infos(
                image_info.depends_on_images, shortcut_build)
        required_task_infos = self._create_required_task_infos(required_tasks)
        image_info_copy = copy.copy(image_info)  # TODO looks not nice
        image_info_copy.depends_on_images = {}
        image_name = f"{image_info.target_repository_name}:{image_info.target_tag}"
        task_for_image_info = \
            self.create_child_task(DockerCreateImageTaskWithDeps,
                                   image_name=image_name,
                                   image_info=image_info_copy,
                                   required_task_infos=required_task_infos)
        return task_for_image_info

    def _create_required_task_infos(
            self, required_tasks: Dict[str, DockerCreateImageTask]) -> RequiredTaskInfoDict:
        result = {key: self._create_required_task_info(required_task)
                  for key, required_task in required_tasks.items()}
        return RequiredTaskInfoDict(result)

    def _create_required_task_info(self, required_task: DockerCreateImageTask) -> RequiredTaskInfo:
        required_task_info = RequiredTaskInfo(module_name=required_task.__module__,
                                              class_name=required_task.__class__.__name__,
                                              params=required_task.param_kwargs)
        return required_task_info


#!/usr/bin/env python3
N = int(input())
X = list(map(int, input().split()))

def main():
    ans = 10**9
    for i in range(1,101):
        dist = 0
        for x in X:
            dist += (i-x)**2

        ans = min(ans, dist)
    return ans

print(main())

## self AC


import numpy as np
#import scipy
from matplotlib import pyplot as plt
#%matplotlib inline
import random
from scipy.signal import hanning, tukey, boxcar
from scipy.spatial import distance
from scipy.ndimage import rotate
from math import sin, cos, radians, pi

from astropy.modeling import models
from astropy.modeling.models import Rotation2D, Gaussian2D

import pymc3 as pm

#!pip install iminuit # you can comment this out once it has run once
#import iminuit

#!pip install astropy
import astropy

from numpy.fft import ifft, fft, ifft2, fft2, fftshift, ifftshift, rfft, rfft2, fftfreq

from scipy.constants import au, c
z=au
k = 2*np.pi / 2.

def GaussHPBWVariationsLog(start,stop,step):
    '''
    Returns an array of values for hpbw in logspace
    '''
    standardDev_range = np.logspace(start,stop, step)
    return (standardDev_range)

def get_gaussian_visibilities(theta_s, b, w=2): # theta_s = hpbw
    """
    produce 2D gaussian for
    - Gaussian FWHM theta_s (in arcseconds)
    - 2d array of baseline lengths b ( in m)
    - wavelength in m
    """
    A = np.radians(1)/3600.
    F = 2*np.sqrt(2*np.log(2))
    theta_r = A*theta_s
    b_hpbw = w/theta_r
    #print(b_hpbw)
    return np.exp(-0.5*(F*b/b_hpbw)**2)

def get_q_gaussian(wavelenght):
    '''
    Calculates a q for Gaussian case
    - wavelenght in (m)
    Return: q
    '''

    r_F = np.sqrt((wavelenght*z)/(2*pi)) # np.sqrt((z/k)=(wavelenght*z)/(2*pi))
    q_new_values = np.linspace(10/(r_F), 0.001/r_F, 50)

    arr = np.sqrt(q_new_values[:, None]**2 + q_new_values[None, :]**2)
    arr1 = np.empty((50,50))
    for x in range(50):
      for y in range(50):
        arr1[x,y] = arr[-x,y]
    arr2 = np.concatenate((arr, arr1))

    arr3 = np.empty((100,50))
    for x in range(100):
      for y in range(50):
        arr3[x,y] = arr2[x,-y]
    arr4 = np.concatenate((arr2, arr3), axis=1)

    arr2 = arr[::-1, :]
    arr3 = arr[:,::-1]
    arr4 = arr[::-1, ::-1]

    arr12 = np.concatenate((arr, arr2))
    arr34 = np.concatenate((arr3, arr4))
    arrF = np.concatenate((arr12, arr34), axis=1)
    return arrF

def get_q_doubles(wavelenght):
    '''
    Provides array of baselines for Double's case
    - wavelenght in (m)
    Return: arrF = q; qx = q with constant x for each column of y
    '''
    r_F = np.sqrt((wavelenght*z)/(2*pi))

    q_double = np.linspace(10/(r_F), 0.001/r_F, 50)

    q = np.hypot(q_double[None, :], q_double[:, None])                ## q - main for doubles

    qx = q_double[None, :] * np.ones([len(q_double), 1])

    arr = q

    arr2 = arr[::-1, :]

    arr2 = arr[::-1, :]
    arr3 = arr[:,::-1]
    arr4 = arr[::-1, ::-1]

    arr12 = np.concatenate((arr, arr2))

    arr34 = np.concatenate((arr3, arr4))

    arrF = np.concatenate((arr12, arr34), axis=1)
    return arrF, qx

def get_gaussian_ps(HalfPowerBeamWidth, Orientation):
    '''
    Provides a plot of power spectrum for Gaussian source
    - hpbw
    - angle of orientation

    '''

    arrF = get_q_gaussian(2)
    array_x = np.arange(-50,50, 1)

    standardDev = HalfPowerBeamWidth
    WAVELENGTH=2
    A = np.radians(1)/3600.
    F = 2*np.sqrt(2*np.log(2))
    C = 2*A*F*np.pi
    q_gauss = arrF                           ###           setting q
    b = q_gauss*z/k

    Vis = get_gaussian_visibilities(standardDev, b, 2)
    FF = FresnelFilterNew(2, q_gauss)
    #SI = ScintilationIndexNew(Vis,FF)                        ### Only need the positive values for the Power Spectrum
    powerSpectrum_p = np.sum(FF, axis=0)
    powerSpectrum_point = []
    for i in powerSpectrum_p:
      if i > 0:
        powerSpectrum_point.append(i)
    plt.loglog(array_x, powerSpectrum_point)
    powerSpectrum_s = np.sum(Vis*FF, axis=0)
    powerSpectrum_source = []
    for i in powerSpectrum_s:
      if i > 0:
        powerSpectrum_source.append(i)
    plt.loglog(array_x, powerSpectrum_source)
    plt.show()
    plt.plot(array_x, powerSpectrum_source)
    plt.show()

def visibilityFT(imageArray):
    '''
    Transforms image plane data into visibility plane
    Returns Visibility
    '''
    imageArrayFFT = np.fft.fft2(imageArray)
    imageArrayFFTabs = np.abs(imageArrayFFT)
    b = np.fft.fftshift(imageArrayFFTabs)
      # Shift peak to be at 1
    if b.max() == 0:
        b=b
    else:
        b= b/b.max()
    return b

def getQ(radius, wavelenght, x=5):
    '''
    Obtains q-array, x - n.pixels at first r(r-in pixels) / first zero
    '
    '''
    z = (1.496*(10)**11) # metres  =  1 AU
    r_F = np.sqrt((wavelenght*z)/(2*pi)) # np.sqrt((z/k)=(wavelenght*z)/(2*pi))
    q = x*radius/radius.max()/r_F

    return q


import random

def obeb_hesapla(m, n):
    if m < n:
        m, n = n, m  # m'yi büyük, n'yi küçük sayıya ayarlayalım

    while n != 0:
        m, n = n, m % n

    return m

# Rastgele iki sayı seçelim
m = random.randint(1, 100)
n = random.randint(1, 100)

# Seçilen sayıları ekrana yazdıralım
print(f"m = {m}")
print(f"n = {n}")

# OBEB'i hesaplayalım
obeb = obeb_hesapla(m, n)

# Sonucu ekrana yazdıralım
print(f"OBEB(m, n) = {obeb}")

'''

Bu programda, obeb_hesapla(m, n) adlı bir fonksiyon tanımlanmıştır. Fonksiyon, verilen m ve n sayıları için OBEB hesaplar ve sonucu döndürür. Hesaplama için Euclid Algoritması kullanılır.

Programın ana kısmında, m ve n değişkenleri rastgele olarak 1 ile 100 arasında seçilir. Ardından, seçilen sayıları ekrana yazdırırız.

obeb_hesapla() fonksiyonunu m ve n değerleriyle çağırarak OBEB'i hesaplarız ve sonucu obeb değişkenine atarız.

Son olarak, hesaplanan OBEB'i ekrana yazdırırız.

Programı çalıştırdığınızda, rastgele seçilen m ve n değerlerine göre OBEB'ini göreceksiniz.

'''


from fastapi import FastAPI, HTTPException,status,Depends
import uvicorn
import  models,schemas,database
from database import engine
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy.orm import Session
import requests,json
from typing import List

app = FastAPI()
models.Base.metadata.create_all(engine)
get_db = database.get_db
@app.post('/thirdparty',status_code=status.HTTP_201_CREATED)
def create_user (request:schemas.newuser,db : Session=Depends(get_db)):
    new_user= models.user(account_no=request.account_no,name=request.name,Bank_name=request.Bank_name,branch=request.branch,IFSC_CODE=request.IFSC_CODE,adder_id=request.adder_id)
    db.add(new_user)
    db.commit()
    db.refresh(new_user)

@app.get('/thirdparty/{id}',response_model=List[schemas.thirdparty])
def getuser(id:int, db : Session=Depends(get_db)):
    user=db.query(models.user).filter(models.user.adder_id == id ).all()

    if not user :
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,detail=f" {id} do't have a third party")
    return user

@app.put('/thirdparty/update/{id}/{account_no}')
def update(id:int,account_no:int,request:schemas.thirdparty,db:Session = Depends(get_db)):
    # db.query(models.user).filter(models.user.account_no==request.account_no).first()
    # if not blog:
    #      raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,detail=f'detail not found id {id}')
    user=db.query(models.user).filter(models.user.adder_id==id,models.user.account_no==account_no).first()
    user.name=request.name
    user.account_no=request.account_no
    user.adder_id=request.adder_id
    user.Bank_name=request.Bank_name
    user.branch=request.branch
    user.IFSC_CODE=request.IFSC_CODE
    db.commit()
    return "updated"

@app.delete('/thirdparty/delete/{adder_id}/{account_no}')
def dele(adder_id:int,account_no:int,db:Session = Depends(get_db)):
    db.query(models.user).filter(models.user.account_no==account_no, models.user.adder_id==adder_id).delete(synchronize_session=False)
    # if not blog:
    #      raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,detail=f'detail not found id {id}')
    # db.query(models.user).filter(models.user.adder_id==id).update(request.dict())
    db.commit()
    return 'Done'

class AmountEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, schemas.Amount):
            return str(obj.amount)
        return super().default(obj)

@app.put('/thirdparty/transaction/{adder_id}/{account_no}')
def balance(adder_id: int,account_no:int, amount: schemas.Amount, db: Session = Depends(get_db)):
    user = db.query(models.user).filter(models.user.account_no == account_no,models.user.adder_id==adder_id).update(amount.dict())
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    db.commit()
    if user:
        details={
        "sender_account_number":adder_id,
        "amount":amount,
        "receiver_account_number":account_no
    }
    transaction=json.dumps(details,cls=AmountEncoder)
    response=requests.post("http://localhost:5000/tpt",data=transaction)
    try:
        response_data=json.loads(response.text)
    except:
        response_data=None
    return response_data

origins=[
    "http://localhost:4200",
    "http://localhost:5200"
]
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=["*"],
    allow_methods=["*"],
    allow_headers=["*"]
)
if __name__=="__main__":
    uvicorn.run("main:app",host="127.0.0.1",port=5200,reload=True,access_log=False)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sun Oct 10 20:15:38 2021

@author: chenhanchuan
"""

import numpy as np
import matplotlib.pyplot as plt
data = np.genfromtxt("/Users/chenhanchuan/Desktop/DS112/corporateSales.csv", delimiter = ",")

IQ = data[:,0]
Complaint = data[:,1]
Ethical = data[:,2]

#r = np.corrcoef(IQ,Complaint)

#plt.plot(IQ, Complaint, "o")
#plt.xlabel("IQ")
#plt.ylabel("Complaint")
#plt.title("r = {:.3f}".format(r[0,1]))

medianComplaint = np.median(Complaint)
meanIQ = np.mean(IQ)
MADComplaint = np.mean(np.absolute(Complaint-np.mean(Complaint)))
medianIQ = np.median(IQ)
stdEthical = np.std(Ethical)
stdIQ = np.std(IQ)
medianEthical = np.median(Ethical)

#r1 = np.corrcoef(Complaint, Ethical)
#plt.plot(Complaint, Ethical, "o")
#plt.xlabel("Complaint")
#plt.ylabel("Ethical")
#plt.title("r1 = {:.3f}".format(r1[0,1]))

r2 = np.corrcoef(IQ, Ethical)
plt.plot(IQ, Ethical, "o")
plt.xlabel("IQ")
plt.ylabel("Ethical")
plt.title("r2 = {:.3f}".format(r2[0,1]))


class Tree:
    def __init__(self, id):
        self.__root = {id: {}}

    def add(self, pid, id):
        if not self.__add(self.__root, pid, id):
            raise IdentificationError('Parent ID Error. No node with ID: {} found.'.format(pid))

    def __add(self, collection, parent, child):
        for node in collection:
            if node == parent:
                if child not in collection[parent]:
                    collection[parent][child] = {}
                return True
            if self.__add(collection[node], parent, child):
                return True
        return False

    def remove(self, id):
        if not self.__remove(self.__root, id):
            raise IdentificationError('Node ID Error. No node with ID: {} found.'.format(id))

    def __remove(self, collection, parent):
        for node in collection:
            if node == parent:
                del collection[parent]
                return True
            if self.__remove(collection[node], parent):
                return True
        return False

    def get(self, id):
        result = self.__get(self.__root, id)
        if result is None:
            raise IdentificationError('Node ID Error. No node with ID: {} found.'.format(id))

    def __get(self, collection, parent):
        for node in collection:
            if node == parent:
                return collection[parent]
            result = self.__get(collection[node], parent)
            if result is not None:
                return result
        return None

    def __str__(self):
        # return self.__print(self.__root)
        return str(self.__root)

    def __print(self, collection, level=0):
        result = []
        for node in collection:
            result.append("{}{}\n{}".format('|-'*level, node, self.__print(collection[node], level+1)))
        return ''.join(result)

    def to_dict(self):
        return self.__root

class IdentificationError(Exception):
    def __init__(self, arg):
        self.arg = arg

if __name__ == '__main__':
    t = Tree(1)
    t.add(1, 2)
    t.add(2, 3)
    t.add(1, 4)
    t.add(3, 5)
    t.add(4, 6)
    t.add(4, 7)
    t.add(2, 8)
    print(t)


import re
from setuptools import setup, find_packages

with open('kubewait/__init__.py', 'rt') as fd:
    version = re.search(r'^__version__\s*=\s*[\'"]([^\'"]*)[\'"]',
                        fd.read(), re.MULTILINE).group(1)

if not version:
    raise RuntimeError('Cannot find version information')

with open('README.rst') as fd:
    long_description = fd.read()

setup(
    name='kubewait',
    version=version,
    description='Pause container init until required kube services are ready,',
    long_description=long_description,
    keywords=['kubernetes', 'clustering', 'init-container'],
    author='Joe Black',
    author_email='me@joeblack.nyc',
    url='https://github.com/telephoneorg/kubewait',
    download_url=(
        'https://github.com/telephoneorg/kubewait/tarball/%s' % version),
    license='Apache 2.0',
    zip_safe=False,
    packages=find_packages(),
    package_data={'': ['LICENSE']},
    install_requires=[
        'pyrkube',
        'cement'
    ],
    tests_require=['pytest'],
    entry_points=dict(
        console_scripts=['kubewait = kubewait.cli:main']),
    classifiers=[
        'Development Status :: 3 - Alpha',
        'Intended Audience :: Developers',
        'Operating System :: OS Independent',
        'Natural Language :: English',
        "License :: OSI Approved :: Apache Software License",
        'Programming Language :: Python :: 3 :: Only',
        'Topic :: Internet :: WWW/HTTP',
        'Topic :: System :: Clustering',
    ]
)


from src.datastore.database import Database

class DatabaseService:
    def __init__(self, database_connection: Database, collection_name):
        self._database = database_connection
        self._collection_name = collection_name

    def find_by_videoId(self, videoId, cash=True, projection={}) -> list:
        '''
        :param videoId:
        :param cash:
        :param
        :return resultlist,count:
        '''
        # elements to project: 1 project, 0 ignore
        projection = {"comment": 1, "original_comment": 1, "author": 1, "created_at": 1, "lang": 1, "likes": 1,
                      "_id": 0} if projection == {} else projection

        if videoId is not None and videoId != "":
            # fetch from db
            cursor = self._database.find_by_video_id(self._collection_name, videoId, projection=projection)
            # convert cursor to list
            res = list(cursor)
        else:
            res = []

        return res

    def load_data(self, data, collection="") -> bool:
        """
        load data to database, raise exception
        :param data:
        """
        try:
            if collection:
                self.verify_collection_existence(collection)
                self._database.insert(collection, data)
            else:
                self.verify_collection_existence()
                self._database.insert(self._collection_name, data)
            return True

        except Exception as e:
            # Error occurred while inserting comments
            return False

    def verify_collection_existence(self, collection="") -> None:
        try:
            if collection:
                self._database.create_store(collection)
            else:
                self._database.create_store(self._collection_name)
        except Exception as e:
            pass