# 문자열 내 마음대로 정렬하기
# https://programmers.co.kr/learn/courses/30/lessons/12915

def solution(strings, n):
    answer = []

    strings.sort()
    strings.sort(key=lambda key: key[n])
    answer = strings
    return answer

print(solution(	["sun", "bed", "car"], 1))
print(solution(	["abce", "abcd", "cdx"], 2))


import numpy as np
import pandas as pd
from abc import abstractmethod
from keras.optimizers import RMSprop

from buld.utils import plot_stat_loss_vs_accuracy, plot_conf_mtx

class AbstractMlTradingModel(object):

    def __init__(self, size_hidden, size_input, size_output, dropout=0.2, kernel_init='glorot_uniform') -> None:
        super().__init__()
        self.size_hidden = size_hidden
        self.size_input = size_input
        self.size_output = size_output
        self.dropout = dropout
        self.kernel_init = kernel_init
        self._model = None
        self._history = None
        self._create()

    @abstractmethod
    def name(self):
        pass

    @abstractmethod
    def _create(self):
        pass

    # |--------------------------------------------------------|
    # |                                                        |
    # |--------------------------------------------------------|
    def compile(self, loss='categorical_crossentropy', lr=0.00001, rho=0.9, epsilon=None, decay=0.0):
        self._model.compile(loss=loss,  # measure how accurate the model during training
                            optimizer=RMSprop(lr=lr, rho=rho, epsilon=epsilon, decay=decay),
                            # this is how model is updated based on data and loss function
                            metrics=['accuracy'])

    # |--------------------------------------------------------|
    # |                                                        |
    # |--------------------------------------------------------|
    def fit(self, x_train, y_train, x_test, y_test, epochs, batch_size, verbose=0):
        self._history = self._model.fit(x_train,
                                        y_train,
                                        batch_size=batch_size,
                                        epochs=epochs,
                                        validation_data=(x_test, y_test),
                                        # validation_split = 0.1,
                                        verbose=verbose)

    # |--------------------------------------------------------|
    # |                                                        |
    # |--------------------------------------------------------|
    def evaluate(self, x_test, y_test):
        score = self._model.evaluate(x_test, y_test, verbose=0)
        print(f'Total loss:    {score[0]} (is it close to 0 ?)')
        print(f'Total accuracy:{score[1]} (is it close to 1 and close to train accuracy ?)')
        return score

    # |--------------------------------------------------------|
    # |                                                        |
    # |--------------------------------------------------------|
    def plot_evaluation(self, size_input, size_output, iteration_id, title=''):
        print(f'\nsize.model.features(size_input) = {size_input}')
        print(f'\nsize.model.target  (size_output)= {size_output}')

        print('\nplot_accuracy_loss_vs_time...')
        history_dict = self._history.history
        print(history_dict.keys())

        #plot_stat_loss_vs_time(history_dict, title=f'{iteration_id}model Loss over time{title}')
        #plot_stat_accuracy_vs_time(history_dict, title=f'{iteration_id}model Accuracy over time{title}')
        plot_stat_loss_vs_accuracy(history_dict, title=f'{iteration_id}model Loss, Accuracy over time{title}')

        hist = pd.DataFrame(self._history.history)
        hist['epoch'] = self._history.epoch
        print(hist.tail())

    # |--------------------------------------------------------|
    # |                                                        |
    # |--------------------------------------------------------|
    def predict(self,  x_train, y_train, x_test, y_test, names_output=[0,1], iteration_id=''):
        y_train_pred = self._model.predict(x_train)
        print(f'labeled   as {y_test[0]} highest confidence for {np.argmax(y_test[0])}')
        print(f'predicted as {y_train_pred[0]} highest confidence for {np.argmax(y_train_pred[0])}')
        Y_true = np.argmax(y_train, axis=1)
        Y_pred = np.argmax(y_train_pred, axis=1)
        plot_conf_mtx(Y_true, Y_pred,  names_output, f'files/output/{iteration_id}Confusion matrix on train.png')

        y_test_pred = self._model.predict(x_test)
        print(f'labeled   as {y_test[0]} highest confidence for {np.argmax(y_test[0])}')
        print(f'predicted as {y_test_pred[0]} highest confidence for {np.argmax(y_test_pred[0])}')
        Y_true = np.argmax(y_test, axis=1)
        Y_pred = np.argmax(y_test_pred, axis=1)
        plot_conf_mtx(Y_true, Y_pred,  names_output, f'files/output/{iteration_id}Confusion matrix on test.png')

        x_all = np.concatenate((x_train, x_test), axis=0)
        y_all = np.concatenate((y_train, y_test), axis=0)
        y_pred = self._model.predict(x_all)
        print(f'labeled   as {y_all[0]} highest confidence for {np.argmax(y_all[0])}')
        print(f'predicted as {y_pred[0]} highest confidence for {np.argmax(y_pred[0])}')
        Y_true = np.argmax(y_all, axis=1)
        Y_pred = np.argmax(y_pred, axis=1)
        plot_conf_mtx(Y_true, Y_pred,  names_output, f'files/output/{iteration_id}Confusion matrix on all.png')
    # |--------------------------------------------------------|
    # |                                                        |
    # |--------------------------------------------------------|
    def summary(self):
        self._model.summary()

    # |--------------------------------------------------------|
    # |                                                        |
    # |--------------------------------------------------------|
    def save(self, folder, filename, iteration_id=''):
        print(f'\nSave model as {folder}{iteration_id}model{filename}.model')
        self._model.save(f'{folder}{iteration_id}model{filename}.model')


"""
Application Loader
"""
from .receiver import Receiver as ReceiverApp
from .cli import CommandLine as CommandLineApp
from .default import Default as DefaultApp
from .log_parser import LogParser as LogParserApp
from .. import VERSION
from ..framework.constants import APP_TYPE

class Loader:
    '''Bootstrap Factory
    '''
    @staticmethod
    def create(platform, options):
        '''Initial bootstrap instance
        '''
        print("[Info] Python driver version: {0} ".format(VERSION))

        active_app = None
        if platform == APP_TYPE.DEFAULT:
            active_app = DefaultApp(**options)

        if platform == APP_TYPE.CLI:
            active_app = CommandLineApp(**options)

        if platform == APP_TYPE.RECEIVER:
            active_app = ReceiverApp(**options)

        if platform == APP_TYPE.LOG_PARSER:
            active_app = LogParserApp(**options)

        if active_app is None:
            raise ValueError('no matched bootstrap')

        return active_app


import unittest
'''
        Combination Sum
==================================
Given a set of candidate numbers (candidates) (without duplicates)
and a target number (target), find all unique combinations in candidates
where the candidate numbers sums to target.
The same repeated number may be chosen from candidates unlimited number of times.
Note:
All numbers (including target) will be positive integers.
The solution set must not contain duplicate combinations.

Input: candidates = [2,3,6,7], target = 7,
A solution set is:
[
  [7],
  [2,2,3]
]
Input: candidates = [2,3,5], target = 8,
A solution set is:
[
  [2,2,2,2],
  [2,3,3],
  [3,5]
]
'''

def combinationSum(candidates, target):
    """
    :type candidates: List[int]
    :type target: int
    :rtype: List[List[int]]
    """
    # Depth first search
    def backtrack(nums, res, path, remain, start):
        if remain < 0:
            return
        if remain == 0:
            res.append(path)
            return
        for i in range(start, len(nums)):
            # start = i reuse same element
            backtrack(nums, res, path+[nums[i]], remain-nums[i], i)

    candidates.sort()
    res = []
    backtrack(candidates, res, [], target, 0)
    return res

class TestCombinationSum(unittest.TestCase):
    def test_combination_sum(self):
        self.assertEqual(combinationSum([1], 1), [[1]])
        self.assertEqual(combinationSum([1, 2], 4), [
                         [1, 1, 1, 1], [1, 1, 2], [2, 2]])
        self.assertEqual(combinationSum([2, 3, 5], 8), [
                         [2, 2, 2, 2], [2, 3, 3], [3, 5]])
        self.assertEqual(combinationSum([2, 3, 6, 7], 7), [[2, 2, 3], [7]])

if __name__ == '__main__':
    unittest.main()


"""Conway\'s Game of Life."""

#---------------------- Askisi 1 ------------------------
from __future__ import unicode_literals
from ast import Continue

def board(n):
    """Kataskeuastis board (pinaka paixnidiou).

    n -- parametros diastasis pinaka

    Kataskeuazei anaparastasi pinaka paixnidiou me n x n kelia, opou
    kanena keli den einai zwntano arxika.

    O pinakas anaparistatai ws le3iko (dict) me n * n stoixeia.
    Ka8e keli antistoixei se ena stoixeio me key (kleidi) to tuple (i,j),
    opou i o ari8mos grammis kai j o ari8mos stilis pou brisketai to keli.
    (H ari8misi grammwn kai sthlwn einai apo 0 ews n-1. To panw aristera keli
    brisketai sto (0,0).)
    H timi (value) tou stoixeiou einai True 'h False analoga
    ean to keli einai zwntano 'h oxi.

    Paradeigmata:

    >>> game = board(3)
    >>> len(game)
    9
    >>> game
    {(0, 0): False, (0, 1): False, (0, 2): False, (1, 0): False, (1, 1): False, (1, 2): False, (2, 0): False, (2, 1): False, (2, 2): False}
    >>> game[2,1]
    False
    """
    """GRAPSTE TON KWDIKA SAS EDW."""

    # Με dictionary comprehension:
    tableux = {(row_count, column_count): False for row_count in range(0,n) for column_count in range(0,n)}

    # Με for loop:
    #tableux = {}
    #for i in range(0,n):
    #    for j in range(0, n):
    #        tableux[(i,j)] = False

    return tableux

#---------------------- Askisi 2 ------------------------
def is_alive(board, p):
    """Elegxei ean ena keli einai zwntano.

    board -- o pinakas paixnidiou opou brisketai to keli
    p -- h 8esh tou keliou.

    To orisma p einai tuple tis morfis (i,j).
    Epistrefei True ean to keli einai zwntano, alliws False.

    Paradeigma:

    >>> is_alive(board(4), (3,2))
    False
    """
    """GRAPSTE TON KWDIKA SAS EDW."""

    if board[p] is True:
        return True
    else:
        return False

def set_alive(board, p, alive):
    """Dimioyrgei 'h afairei zwi apo ena keli.

    board -- o pinakas paixnidiou opou brisketai to keli
    p -- h 8esh tou keliou (tuple tis morfis (i,j))
    alive -- logiki timi.

    To keli ginetai zwntano ean h alive einai True. An h alive einai False,
    to keli pe8ainei.

    Paradeigmata:

    >>> game = board(4)
    >>> is_alive(game, (3,2))
    False
    >>> set_alive(game, (3,2), True)
    >>> is_alive(game, (3,2))
    True
    >>> set_alive(game, (3,2), False)
    >>> is_alive(game, (3,2))
    False
    """
    """GRAPSTE TON KWDIKA SAS EDW."""

    board[p] = alive
    return

def get_size(board):
    """Mege8os pinaka paixnidiou.

    board -- pinakas paixnidiou.

    Epistrefei n (timi int) ean to board anaparista pinaka paixnidiou n x n.

    Paradeigmata:

    >>> get_size(board(4))
    4
    >>> get_size(board(10))
    10
    """
    """GRAPSTE TON KWDIKA SAS EDW."""

    from math import sqrt
    return int(sqrt(len(board)))

#---------------------- Askisi 3 ------------------------
def copy_board(board):
    """Kataskeui antigrafou pinaka paixnidiou.

    board -- pinakas paixnidiou.

    Epistrefei ena neo pinaka paixnidiou pou einai antigrafo tou board.

    Paradeigmata:

    >>> game = board(10)
    >>> set_alive(game, (4,7), True)
    >>> game2 = copy_board(game)
    >>> game2 is game
    False
    >>> is_alive(game2, (4,7))
    True
    """
    """GRAPSTE TON KWDIKA SAS EDW."""

    tableux_copy = dict(board)
    return tableux_copy

#---------------------- Askisi 4 ------------------------
def get_iterator(board):
    """Iterator gia sarwsi stoixeiwn pinaka paixnidiou.

    board -- pinakas paixnidiou.

    Epistrefei iterator pou dinei ta kelia tou board arxizontas apo
    ta kelia tis grammis 0: (0,0), (0,1), (0,2),..., meta akolou8oun ta
    kelia tis grammis 1: (1,0), (1,1), (1,2),... ktl. mexri na e3antli8oun
    ola ta kelia. Gia ka8e keli, o iterator epistrefei tin 8esi tou kai
    logiki timi True 'h False analogws ean einai zwntano 'h oxi.

    Paradeigma:

    >>> game = board(3)
    >>> set_alive(game, (2, 1), True)
    >>> for cell in get_iterator(game):
    ...     print(cell)
    ...
    ((0, 0), False)
    ((0, 1), False)
    ((0, 2), False)
    ((1, 0), False)
    ((1, 1), False)
    ((1, 2), False)
    ((2, 0), False)
    ((2, 1), True)
    ((2, 2), False)
    """
    """GRAPSTE TON KWDIKA SAS EDW."""

    return board.items()

    # Άλλος τρόπος (ψιλοχαζός)
    #cells = []
    #for item in board.items():
        #cells.append(item)
    #return tuple(cells)

#---------------------- Askisi 5 ------------------------
def print_board(board):
    """Emfanizei pinaka paixnidiou.

    board -- pinakas paixnidiou.

    Emfanizei ton pinaka paixnidiou board opou me mauro tetragwno
    (xaraktiras unicode 11035 'h xaraktiras 'x' and den emfanizetai swsta)
    dinontai ta zwntana kelia, kai me aspro (xaraktiras unicode 11036 'h
    keno ' ' an den emfanizetai swsta) ta pe8amena.
    To panw aristera keli einai auto sti 8esi (0,0).

    Paradeigma:

    >>> game = board(5)
    >>> set_alive(game, (0,0), True)
    >>> set_alive(game, (2,2), True)
    >>> set_alive(game, (4,4), True)
    >>> set_alive(game, (3,4), True)
    >>> set_alive(game, (0,4), True)
    >>> print_board(game)
    ⬛⬜⬜⬜⬛
    ⬜⬜⬜⬜⬜
    ⬜⬜⬛⬜⬜
    ⬜⬜⬜⬜⬛
    ⬜⬜⬜⬜⬛
    """
    """GRAPSTE TON KWDIKA SAS EDW."""

    length = get_size(board)
    for row in range(length) :
        for column in range(length):
            if board[row, column]:
                print(chr(11035), end="")
            else:
                print(chr(11036), end="")
        print("")

#---------------------- Askisi 6 ------------------------
def neighbors(p):
    """Geitonika kelia.

    p -- 8esh keliou (tuple tis morfis (i,j)).

    Epistrefei synolo (set) pou periexontai oi 8eseis twn 8 geitonikwn
    keliwn tou p. Sto epistrefomeno synolo den periexetai to keli p.

    Paradeigmata:

    >>> neighbors((3,2)) == {(3, 3), (3, 1), (2, 1), (2, 3), (4, 3), (2, 2), (4, 2), (4, 1)}
    True
    >>> neighbors((0,0)) == {(0, 1), (-1, 1), (-1, 0), (-1, -1), (0, -1), (1, 0), (1, -1), (1, 1)}
    True
    >>> neighbors((0,10)) == {(-1, 9), (1, 10), (-1, 11), (0, 11), (-1, 10), (1, 9), (0, 9), (1, 11)}
    True
    """
    """GRAPSTE TON KWDIKA SAS EDW."""

    neighborhood = set()
    row, column = p

    for neighbor_row in range(-1, 2):
        neighboring_row = row + neighbor_row
        for neighbor_column in range(-1, 2):
            neighboring_column = column + neighbor_column
            cell = (neighboring_row, neighboring_column)
            neighborhood.add(cell)
    neighborhood.remove(p)

    return neighborhood

#---------------------- Askisi 7 ------------------------
def place_blinker(board, p = (0,0)):
    """Topo8etisi blinker.

    board -- pinakas paixnidiou.
    p -- keli topo8etisis (tuple (i,j) me proka8orismeni timi (0,0))

    Topo8etei 3 zwntanous organismous sto board
    se geitonika kelia tis idias stilis, arxizontas apo ti 8esi p kai
    proxwrontas stis parakatw grammes.

    Paradeigmata:

    >>> game = board(5)
    >>> place_blinker(game)
    >>> print_board(game)
    ⬛⬜⬜⬜⬜
    ⬛⬜⬜⬜⬜
    ⬛⬜⬜⬜⬜
    ⬜⬜⬜⬜⬜
    ⬜⬜⬜⬜⬜
    >>> place_blinker(game, (1,2))
    >>> print_board(game)
    ⬛⬜⬜⬜⬜
    ⬛⬜⬛⬜⬜
    ⬛⬜⬛⬜⬜
    ⬜⬜⬛⬜⬜
    ⬜⬜⬜⬜⬜
    >>> place_blinker(game, (4,4))
    >>> print_board(game)
    ⬛⬜⬜⬜⬜
    ⬛⬜⬛⬜⬜
    ⬛⬜⬛⬜⬜
    ⬜⬜⬛⬜⬜
    ⬜⬜⬜⬜⬛
    """
    """GRAPSTE TON KWDIKA SAS EDW."""

    row, column = p
    for next_row in range(row, row+3):
        cell = (next_row, column)
        if cell not in board.keys(): break
        set_alive(board, cell, True)
    return

def place_glider(board, p = (0,0)):
    """Topo8etisi glider.

    board -- pinakas paixnidiou.
    p -- keli topo8etisis (tuple (i,j) me proka8orismeni timi (0,0))

    Topo8etei 5 zwntanous organismous sto board se sximatismo glider
    arxizontas apo tin topo8esia p, opws fainetai sta parakatw paradeigmata.
    Simeiwste oti to idio to keli p den einai zwntano.

    Paradeigmata:

    >>> game = board(7)
    >>> place_glider(game)
    >>> print_board(game)
    ⬜⬜⬛⬜⬜⬜⬜
    ⬛⬜⬛⬜⬜⬜⬜
    ⬜⬛⬛⬜⬜⬜⬜
    ⬜⬜⬜⬜⬜⬜⬜
    ⬜⬜⬜⬜⬜⬜⬜
    ⬜⬜⬜⬜⬜⬜⬜
    ⬜⬜⬜⬜⬜⬜⬜
    >>> place_glider(game, (3,3))
    >>> print_board(game)
    ⬜⬜⬛⬜⬜⬜⬜
    ⬛⬜⬛⬜⬜⬜⬜
    ⬜⬛⬛⬜⬜⬜⬜
    ⬜⬜⬜⬜⬜⬛⬜
    ⬜⬜⬜⬛⬜⬛⬜
    ⬜⬜⬜⬜⬛⬛⬜
    ⬜⬜⬜⬜⬜⬜⬜
    """
    """GRAPSTE TON KWDIKA SAS EDW."""

    row, column = p
    keys = board.keys()
    row_index = row
    column_index = column +2

    if (row_index, column_index) in keys:
        set_alive(board,(row_index,column_index), True)

    row_index = row + 1
    for column_shift in range(0, 3, 2):
        column_index = column + column_shift
        if (row_index, column_index) in keys:
            set_alive(board,(row_index,column_index), True)

    row_index = row + 2
    for column_shift in range(1, 3):
        column_index = column + column_shift
        if (row_index, column_index) in keys:
            set_alive(board,(row_index,column_index), True)

    return

#---------------------- Askisi 8 ------------------------
def tick(board):
    """Proxwraei to paixnidi kata ena bima stin epomeni genea.

    board -- pinakas paixnidiou.

    Allazei ton pinaka board proxwrontas mia genea,
    symfwna me tous kanones tou Game of Life.

    Paradeigma:

    >>> game = board(6)
    >>> place_glider(game)
    >>> place_blinker(game, (3,4))
    >>> print_board(game)
    ⬜⬜⬛⬜⬜⬜
    ⬛⬜⬛⬜⬜⬜
    ⬜⬛⬛⬜⬜⬜
    ⬜⬜⬜⬜⬛⬜
    ⬜⬜⬜⬜⬛⬜
    ⬜⬜⬜⬜⬛⬜
    >>> tick(game)
    >>> print_board(game)
    ⬜⬛⬜⬜⬜⬜
    ⬜⬜⬛⬛⬜⬜
    ⬜⬛⬛⬛⬜⬜
    ⬜⬜⬜⬛⬜⬜
    ⬜⬜⬜⬛⬛⬛
    ⬜⬜⬜⬜⬜⬜
    """
    """GRAPSTE TON KWDIKA SAS EDW."""

    new_board = copy_board(board)

    alive_cells = [cell for cell in board.keys() if is_alive(board,cell) is True]  # λίστα από tuples όλων των ζωντανών κελιών του board.

    #alive_neighborhood = [neighbor for neighbor in neighbors(cell)for cell in board.keys if board[cell] is True]
    #dead_neighborhood = [neighbor for neighbor in neighbors(cell) for cell in board.keys if board[cell] is False]

    #n = get_size(board)

    living = [([],keli) for keli in alive_cells]  # Αρχικοποίηση λίστας που θα χρησιμοποιηθεί για την οργάνωση των ζωντανών κελιών.
                                                  # Θα αποτελείται από tuples που θα περιέχουν από μία λίστα και ένα tuple.
                                                  # Η λίστα με τη σειρά της θα περιέχει τα γειτονικά κελιά ενός ζωντανού κελιού σε μορφή tuples,
                                                  # ενώ το tuple (keli) θα περιέχει τις συντεταγμένες του συγκεκριμένου ζωντανού κελιού.

    for index_keli, keli in enumerate(alive_cells):                # keli -> συντεταγμένες ζωντανού κελιού [tuple]
                                                                   # με ένα συγκεκριμένο πλήθος ζωντανών γειτονικών κελιών
        for coordinates in neighbors(keli): # coordinates -> συντεταγμένες [tuple] γειτονικών κελιών ενός ζωντανού κελιού
            # Αν κάποιο κελί είναι νεκρό ή δεν υπάρχει στον πίνακα (δηλαδή, is_alive(new_board, coordinates) is False) το αγνοεί και πάει στο επόμενο.
            if coordinates in board.keys() and is_alive(board, coordinates) is True :
                living[index_keli][0].append(coordinates)

        zoi = living[index_keli][0]             # zoi -> λίστα που περιέχει τα ζωντανά γειτονικά κελιά του ζωντανού κελιού keli
        if len(zoi) < 2:                        # Άρα len(zoi) = το πλήθος των ζωντανών γειτονικών κελιών ενός ζωντανού κελιού
            set_alive(new_board, keli, False)   # keli -> συντεταγμένες ζωντανού κελιού [tuple]

        elif len(zoi) == 2 or len(zoi) == 3:
            set_alive(new_board, keli, True)

        elif len(zoi) > 3:
            set_alive(new_board, keli, False)

    dead_cells  = [cell for cell in board.keys() if is_alive(board,cell) is False] # λίστα από tuples όλων των νεκρών κελιών του board.

    dead = [([],keli) for keli in dead_cells] # Αρχικοποίηση λίστας που θα χρησιμοποιηθεί για την οργάνωση των νεκρών κελιών.
                                              # Θα αποτελείται από tuples που θα περιέχουν από μία λίστα και ένα tuple.
                                              # Η λίστα με τη σειρά της θα περιέχει τα γειτονικά κελιά ενός νεκρού κελιού σε μορφή tuples,
                                              # ενώ το tuple -> keli θα περιέχει τις συντεταγμένες του συγκεκριμένου νεκρού κελιού.

    for index_keli, keli in enumerate(dead_cells):                 # keli -> συντεταγμένες νεκρού κελίού

        for coordinates in neighbors(keli): # coordinates [tuple] -> συντεταγμένες γειτονικών κελιών ενός νεκρού κελιού [tuple]

           if coordinates in board.keys() and is_alive(board, coordinates) is True:
                dead[index_keli][0].append(coordinates)

        thanos = dead[index_keli][0]
                                                    # thanos -> λίστα που περιέχει τα ζωντανά γειτονικά κελιά του νεκρού κελιού keli
        if len(thanos) == 3:                        # Άρα len(thanos) = το πλήθος των ζωντανών γειτονικών κελιών ενός νεκρού κελιού
            set_alive(new_board, keli, True)        # keli -> συντεταγμένες νεκρού κελιού [tuple]
                                                    # με ένα συγκεκριμένο πλήθος ζωντανών γειτονικών κελιών
    for key in new_board.keys():
        board[key] = new_board[key]                 # Μεταγραφή των αποτελεσμάτων από το (αντίγραφο) λεξικό εργασίας, στο αρχικό λεξικό
                                                    # (in place) για να ενημερωθεί αντίστοιχα το λεξικό που αποτελεί το όρισμα εισόδου

#---------------------- Askisi 9 ------------------------

if __name__ == '__main__':
    """Paizei to paixnidi tis zwis gia 100 genies.

    generations -- ari8mos bimatwn.

    Paizei to paixnidi gia mia sygkekrimeni arxiki topo8etisi, gia
    100 genees. O pinakas tou paixnidiou emfanizetai se  ka8e bima.
    Afiste toulaxiston 2 kenes grammes anamesa se diadoxikous pinakes.
    """

    # Arxikos pinakas
    game = board(10)
    place_blinker(game, (1,2))
    place_glider(game, (2,4))

    from time import sleep

    """GRAPSTE TON KWDIKA SAS APO KATW."""

    gen_count = 1
    print_board(game)
    print("")
    while gen_count<=100:
        print("")
        tick(game)
        print_board(game)
        print("")
        sleep(1.5)
        gen_count += 1

Intro to Programming with Python/hw4/game_of_life.py


import json
import pandas as pd
from datetime import datetime
import re

ENCODING = "utf8"

def load_data(path):
    with open(path, encoding=ENCODING) as file:
        data = file.read()
    return json.loads(data)

def convert(data):
    sub_data = []
    qnt = []
    main_data = []
    history = []
    for row in data:
        if "price" in row.keys():
            sub_data.append(row)
            continue
        if "qnt" in row.keys():
            qnt.append(row)
            continue
        if "imt_name" in row.keys():
            main_data.append(row)
            continue
        if "history" in row.keys():
            history.append(row)
            continue

    main_data = pd.DataFrame(main_data).set_index("index")
    sub_data = pd.DataFrame(sub_data).set_index("index")
    qnt = pd.DataFrame(qnt).set_index("index")
    history = pd.DataFrame(history).set_index("index")

    show_parse_statistic(main_data, sub_data, qnt, history)

    indexes = list(set(main_data.index) & set(sub_data.index) & set(qnt.index))
    main_data = main_data.loc[indexes]
    sub_data = sub_data.loc[indexes]
    qnt = qnt.loc[indexes]

    options = convert_options(main_data)
    compositions = convert_compositions(main_data)
    history = convert_history(history, sub_data)
    sizes = convert_sizes(main_data)
    main_data = convert_main_data(sub_data, main_data, qnt)

    show_convert_statistic(main_data, options, history, compositions, sizes)

    options.to_csv("options.csv", encoding=ENCODING)
    main_data.to_csv("main_data.csv", encoding=ENCODING)
    history.to_csv("history.csv", encoding=ENCODING)
    compositions.to_csv("compositions.csv", encoding=ENCODING)
    sizes.to_csv("sizes.csv", encoding=ENCODING)

def show_parse_statistic(main_data, sub_data, qnt, history):
    """
    Выводит количество спрасенных страниц по категориям.
    """
    print(f"Собрано:")
    print(f"    Основные данные: {main_data.shape}")
    print(f"    Дополнительные данные: {sub_data.shape}")
    print(f"    Количество продаж: {qnt.shape}")
    print(f"    Исторические цены: {history.shape}")

def show_convert_statistic(main_data, options, history, compositions, sizes):
    """
    Выводит количество сконвертированных данных.
    """
    print(f"Конвертировано:")
    print(f"    Основные данные: {main_data.shape[0]}")
    print(f"    Опции: всего {options.shape[0]}, уникальных артикулов {options.index.nunique()}")
    print(f"    Материалы: всего {compositions.shape[0]}, уникальных артикулов {compositions.index.nunique()}")
    print(f"    Размеры: всего {sizes.shape[0]}, уникальных артикулов {sizes.index.nunique()}")
    print(f"    Исторические цены: всего {history.shape[0]}, уникальных артикулов {history.index.nunique()}")

def convert_sizes(main_data):
    """
    Извлекает размеры товаров в отдельный DataFrame
    """
    data = main_data[["article", "parse_date", "sizes"]].explode("sizes").dropna(axis=0)
    return data

def split_compositions(string):
    """
    Раделяет материалы на два столбца
    """
    # поиск слов или чисел
    finded = re.findall(r'([А-Яа-яA-Za-z /-]*[А-Яа-яA-Za-z]+|[0-9]+[0-9,/.]*)', string)
    if len(finded) > 1 and finded[0].split(",")[0].isnumeric():
        finded = finded[::-1]
    if len(finded) > 1:
        return list(zip(finded[::2],finded[1::2]))
    return (finded, float("nan"))

def convert_compositions(main_data):
    """
    Конвертирует материалы.
    """
    data = main_data[["article", "parse_date", "compositions"]].explode("compositions").dropna(axis=0)
    data["compositions"] = data["compositions"].apply(split_compositions)
    data = data.explode("compositions")
    data["name"] = data["compositions"].str[0]
    data["value"] = data["compositions"].str[1]
    data = data.dropna(how="all", subset=["name","value"])
    return data[["article", "parse_date", "name", "value"]]

def convert_main_data(sub_data, main_data, qnt):
    """
    Конвертирует основную информацию.
    """
    sub_data["salePrice"] = sub_data["salePrice"] / 100
    sub_data["price"] = sub_data["price"] / 100
    data =  pd.concat(
        [
            sub_data,
            main_data.drop(["article", "parse_date", "sizes", "options", "compositions"], axis=1),
            qnt["qnt"]
        ],
        axis=1)
    return data

def convert_options(data):
    """
    Конвертирует опции.
    """
    exploded = data[["article", "parse_date", "options"]].explode("options")
    exploded["name"] = exploded["options"].str[0]
    exploded["value"] = exploded["options"].str[1]
    return exploded.drop(columns="options")

def convert_history(history, sub_data):
    """
    Конвертирует исторические цены.
    """
    prices = history.drop(columns=["article", "parse_date", "history"]) \
            .rename(columns=lambda x: datetime.fromtimestamp(int(x)).date())
    prices = pd.concat([prices, sub_data["salePrice"]], axis=1) \
            .rename(columns={"salePrice": datetime.now().date()})
    prices = prices.reindex(sorted(prices.columns), axis=1).fillna(method="ffill", axis=1)
    prices = prices.stack().reset_index().rename(columns={"level_1": "date", 0: "price"}).set_index("index")
    prices["price"] = prices["price"] / 100
    prices = sub_data[["article", "parse_date"]].merge(prices, on="index").reset_index()
    prev = prices.sort_values("date") \
        .groupby('article', group_keys=True) \
        .apply(lambda x: x["price"].shift(1)) \
        .droplevel(0) \
        .rename("prevPrice")
    prices = pd.concat([prices, prev], axis=1).set_index("index")
    prices["priceChange"] = (prices["price"] - prices["prevPrice"]) / prices["prevPrice"]
    return prices

def main(path):
    convert(load_data(path))

if __name__ == "__main__":
    main(input("Введите имя файла: "))


# python3
import sys
import itertools
from collections import defaultdict

def pre_process():
    data = sys.stdin.read().strip().split()
    k, t, reads = int(data[0]), int(data[1]), data[2:]
    kmers = [kmer for read in reads for kmer in [read[j:j + k] for j in range(len(read) - k + 1)]]
    return t, build_deBruijn_graph(kmers)

def build_deBruijn_graph(kmers):
    graph = defaultdict(lambda: [set(), 0])
    for kmer in kmers:
        prefix, suffix = kmer[:-1], kmer[1:]
        if prefix != suffix:
            if suffix not in graph[prefix][0]:
                graph[prefix][0].add(suffix)
                graph[suffix][1] += 1
    return graph

def count_bubbles(t, graph):
    bubbles = 0
    paths = defaultdict(lambda: list())

    def dfs(path, start, current, depth):
        if current != start and graph[current][1] > 1: paths[(start, current)].append(path[:])
        if depth == t: return
        for next_node in graph[current][0]:
            if next_node not in path:
                path.append(next_node)
                dfs(path, start, next_node, depth + 1)
                path.remove(next_node)

    for node in graph.keys():
        if len(graph[node][0]) > 1: dfs(path=[node], start=node, current=node, depth=0)
    for path_list in paths.values():
        for pair in itertools.combinations(path_list, r=2):
            if len(set(pair[0]) & set(pair[1])) == 2: bubbles += 1
    return bubbles

def Solution():
    t, graph = pre_process()
    print(count_bubbles(t, graph))

if __name__ == "__main__":
    Solution()

Genome Assembly Programming Challenge/week3/Bubble Detection/bubble_detection.py


"""
gs_utils are common utlity functions for the app, such as file io.
"""
import json
import re
import io
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import FormatStrFormatter
from os.path import join
from os.path import exists, isfile, splitext
from os import listdir
from gs_datadict import OUTDIR, MODELDIR, LYRICDIR, ARTISTDIR, GENRES, CORESTOPS, GS_CONTRACT, \
    STOP_LYRICS, GS_STOP, CHAR_CONVERSION, QUOTEDASH_TABLE
import matplotlib.pyplot as plt
from wordcloud import WordCloud

trans_tmptbl = str.maketrans(CHAR_CONVERSION)

def clean_name(rawstr: str):
    """
    small wrangling utility to clean up artist names prior to searching on genius
    """
    cleanstr: str = rawstr.translate(trans_tmptbl)
    finalstr: str = cleanstr.translate(QUOTEDASH_TABLE).replace(" ", "")

    return finalstr

def get_files_list(ldir: str=LYRICDIR, incl_pre: list=None, excl_lst: list=None):
    """
    this is a simple file selector, creating a list that can be used by several tasks
    :param ldir: folder where lyrics files reside, my convention is LYRICDIR,
        usually STR (folder name), BUT can specify LIST of folders if necessary
    :param incl_pre: specify one or more genres for selecting artists, for example
        'rap' -> 'rap_KendrickLamar.lyr', 'rap_OutKast.lyr'..., or 'rock' or 'punk' etc.
    :param excl_lst: identify genre prefix(es) NOT to include, can specify prefix to
        exclude or specific artists to exclude
    :return: list of artist lyric files or None if error occurred
    """
    selected: list = []
    selectednum: int = 0
    if isinstance(ldir, str):
        # easier to deal with as a list
        dirs: list = [ldir]
    elif isinstance(ldir, list):
        dirs: list = ldir

    if isinstance(incl_pre, str):
        if incl_pre in GENRES:
            prefixes: list = [incl_pre]
        elif incl_pre == 'all':
            prefixes: list = GENRES
            print("get_files: including all genres")
        else:
            print("get_files: prefix %s not a recognized genre, Exiting" % incl_pre)
            return None
    elif isinstance(incl_pre, list):
        prefixes: list = []
        for pre in incl_pre:
            if pre in GENRES:
                prefixes.append(pre)
            elif pre == 'all':
                prefixes = GENRES
                print("get_files: including all genres")
            else:
                print("get_files: %s not a recognized genre, exiting" % pre)
                return None
    else:
        prefixes: list = GENRES

    if excl_lst:
        if isinstance(excl_lst, str):
            if excl_lst in prefixes:
                prefixes.remove(excl_lst)
                print("get_files: excluded %s genre" % excl_lst)
        else:
            for excl in excl_lst:
                if excl in prefixes:
                    prefixes.remove(excl)
                    print("get_files: excluded %s genre" % excl)

    numfil = len(prefixes)
    print("get_files: searching %d folders for %d genres --" % (len(dirs), numfil))

    for dirx in dirs:
        print("get_files: searching files in %s" % dirx)
        for fname in listdir(dirx):
            sep_loc = fname.find("_")
            dot_loc: int = fname.find(".")
            if sep_loc != -1:
                genre = fname[:sep_loc]
                artist: str = fname[sep_loc + 1: dot_loc]
            else:
                genre = "none"
                artist = "none"

            if genre not in prefixes:
                print("  %s genre not included, artist: %s, file: %s" % (genre, artist, fname))
                continue
            if excl_lst:
                if artist in excl_lst:
                    print("  %s - excluded artist, file: %s" % (artist, fname))
                    continue
            fqfil = join(dirx, fname)
            if isfile(fqfil):
                file_splits = splitext(fqfil)
                try:
                    file_splits.index('.lyr')
                except ValueError:
                    print("  get_files: not a lyrics file, file: %s" % fname)
                    continue
                else:
                    selected.append({"file": True, "name": fname, "path": fqfil})
                    selectednum += 1
                    # print("get_files: added %s to filter" % artist)
            else:
                print("  %s is not a file, continuing with folder" % fqfil)

    print("  -- get_files: COMPLETED, %d files selected --\n" % selectednum)

    return selected

def filter_for_end_of_track(lyf: str, ldir: str=LYRICDIR, eot: str="\nSONGBREAK\n"):
    """
    standardizes end-of-track indicator for lyrics files, can be used for other filters
    but this is a DESIGN DECISION with DOWNSTREAM IMPLICATIONS.
      Alter corpus source files ONLY if ALL downstream processes, known or planned, have
      the need for it! (i.e. you can't unring this bell)
        I scrub text 'just-in-time' (JIT), in-line with generator that streams lyrics
        Exception- this Fx adds a delimiter between songs and removes blank lines
    :param lyf: str filename for lyrics file
    :param ldir: str folder where lyf resides, expected to be with other lyrics
    :param eot: str to embed in .lyr file as marker for end of track
    :return: 0 if success, 13 if fail or known error
    """

    fq_lyf = join(ldir, lyf)
    if exists(fq_lyf):
        f_h = open(fq_lyf, mode="r")
        contents: str = f_h.read()
        f_h.close()
        sizein: int = len(contents)
        seppos: int = lyf.find("_")
        extpos: int = lyf.find(".")
        artst: str = lyf[seppos + 1: extpos]
        mark: str = "EmbedShare URLCopyEmbedCopy"
        mtch = re.split(mark, string=contents)

        if len(mtch) < 2:
            mark = "songbreak"
            mtch = re.split(mark, string=contents)
            if len(mtch) > 1:
                contents = re.sub(mark, repl=eot, string=contents)
                print("converted %d songbreak to eot in %s lyrics" % (len(mtch), artst))
            else:
                mark = re.sub(r"\n", repl="", string=eot)
                mtch = re.split(mark, string=contents)
                if len(mtch) > 1:
                    print("%s has %d %s delimiters, u good bro, skipping this one"
                          % (artst, len(mtch), mark))
                else:
                    mark = r"(?m)^\n\n"
                    mtch = re.split(mark, string=contents)
                    if len(mtch) > 1:
                        contents = re.sub(mark, repl=eot, string=contents)
                        print("converted %d double-blank-line to eot in %s lyrics" % (len(mtch), artst))
                    else:
                        print("\nError: no known song breaks in %s lyrics, EDIT MANUALLY" % artst)
                        return 13
        else:
            contents = re.sub(mark, repl=eot, string=contents)
            eotx = re.sub(r"\n", repl="", string=eot)
            print("converted %d %s to %s in %s lyrics" % (len(mtch), mark, eotx, artst))

        # set re MULTILINE mode to match caret (^) at start of each 'line'
        mtch = re.split(r"(?m)^\n", string=contents)
        if len(mtch) > 1:
            contents = re.sub(r"(?m)^\n", repl="", string=contents)
            print("filter_lyrics: removed %d blank lines in %s lyrics" % (len(mtch), artst))
        else:
            print("no blank lines for %s" % artst)

        f_h = open(fq_lyf, mode="w", newline="")
        sizeout = f_h.write(contents)
        f_h.close()
        print("filter_lyrics for %s - %d chars read in, %d written out" % (artst, sizein, sizeout))
        return 0

    else:
        print("filter_lyrics ERROR: could not locate %s file" % fq_lyf)
        return 13

def clean_lyrics_file(lyf: str):
    """
    read lyrics corpus (*.lyr file), scrub it, and write it back to a new file (append a
    version number to end of file).  perform the following edits on each line of file:
        1. remove punctuation and convert text to lower case
        2. removes words that match CORESTOPS (my appended list based on gensim eng stoplist)
        3. expands contractions, as per my contraction dictionary GS_CONTRACT
    :param lyf: str name of lyrics corpus
    :return: list of str for each track in lyrics corpus
    """
    ext_pos = lyf.find(".")
    lyfpre = lyf[:ext_pos]
    lyfpost = lyf[ext_pos:]
    fq_file = join(OUTDIR, lyf)
    fq2 = OUTDIR + lyfpre + "_cln" + lyfpost
    re_punc = re.compile(r'[.?!;:<>,(){}]')
    if exists(fq_file):
        f2_h = open(fq2, mode='w', newline="")
        for line in open(fq_file, mode='r', newline=""):
            if len(line) < 5:
                continue
            else:
                tmp = line.lower()
                for wrd, expand in GS_CONTRACT.items():
                    tmp = re.sub(wrd, repl=expand, string=tmp)
                for wrd, cnvrt in CHAR_CONVERSION.items():
                    tmp = re.sub(wrd, repl=cnvrt, string=tmp)
                line = re_punc.sub(repl="", string=line).split()
                line = " ".join(w for w in line if w not in CORESTOPS)
                f2_h.write(line)
        f2_h.close()
    print("\ncompleted cleaning corpus file: %s" % lyfpre)

    return

def read_tokens_to_list(lyf: str, wrdtokens: bool=True):
    """
    reads lines from a lyrics corpus file into python list- splits words to separate tokens
    -- memory-intensive! better alternative is to use an iterator-generator object
    -- this simple utility also assumes that the lyrics have already been scrubbed
    :param lyf: str name of lyrics file, assumed to be located in app OUTDIR
    :param wrdtokens: if True, splits each line into list of words
    :return: list of lyrics lines
    """
    lyriclst: list = []
    fqf = join(OUTDIR, lyf)
    f_h = open(fqf, mode="r", newline="")
    for line in f_h:
        if len(line) > 5:
            if wrdtokens:
                lyriclst.append(line.split())
            else:
                lyriclst.append(line)
    f_h.close()

    return lyriclst

def extract_words(sentstr, stops):
    """
    simple utility to word tokenize a text string and remove stop words
    :param sentstr: input string of text
    :param stops: list of stop words to remove
    :return:
    """
    words = re.sub(r"[^\w]", " ", sentstr).split()
    cleaned_text = [w.lower() for w in words if w.lower() not in stops]
    new_s: str = ""
    for x in cleaned_text:
        new_s = new_s + " " + x
    return new_s

def do_stops(twlst: list, stop1: list=GS_STOP, stop2: list=STOP_LYRICS):
    """
    do_stops is preprocessing function to remove word tokens based on a stop list
    :param twlst: list of list, list of dict, or list of str for Tweets
    :param stop1: list of stop words, defaults to GS_STOP
    :param stop2: list of stop words, defaults to STOP_ADD
    :return: list of tweets with word tokens and stop words removed
    """
    clean_list: list = []
    for twis in twlst:
        if isinstance(twis, list):
            tmp_wrds: list = [cw for cw in twis if cw not in stop1]
            if stop2 is not None:
                clean_list.append([cw for cw in tmp_wrds if cw not in stop2])
            else:
                clean_list.append(tmp_wrds)
        else:
            if isinstance(twis, dict):
                twemp: list = str(twis['text']).split()
            else:  # assume isinstance(twis, str)
                twemp: list = twis.split()

            tmp_wrds: list = [cw for cw in twemp if cw not in stop1]
            if stop2 is not None:
                clean_list.append(' '.join([str(cw) for cw in tmp_wrds if cw not in stop2]))
            else:
                clean_list.append(' '.join([str(cw) for cw in tmp_wrds]))

    return clean_list

def get_stop_file(stf: str):
    """
    this reads stopfile from the nlp models folder and returns it as a set
    :param stf: file name, to be prepended with MODELDIR
    :return: set of stop words
    """
    tmpset: set = set()
    fqfil = MODELDIR + stf
    f_h = open(fqfil, mode="r")
    for line in f_h:
        tmpset.add(line)

    adhoc: list = ['ha', 'oh', 'get', 'got', 'one', 'say', 'like', 'la', 'go', 'say',
                   'said', 'yeah', 'ya', 'u', 'da', 'give', 'thing', 'way', 'really',
                   'let', 'whoa', 'hey', 'na', 'put', 'doo', 'doo', 'let', 'fa', 'cata',
                   'hi', 'so', 'little', 'dit', 'songbreak', 'could']
    for wrd in adhoc:
        tmpset.add(wrd)

    return tmpset

def append_genre_registry(albdct: list, genre: str, outd: str=OUTDIR):
    """
    save a unique track ID (artist name + 3-digit counter) plus name of track for each song
    in the lyrics corpus, one artist file for each genre.
    entries are appended when this is called, so there is logic to verify that the artist's
    tracks have not already been added.
    PURPOSE: this allows TaggedDocument tags used in topic modeling to be mapped back to
        an artist and song- for example, if providing test lyrics and looking for the most
        similar lyrics, it is desirable to be able to return similar artists-songs!
    :param albdct: all artist's albums as list of dict
        'albumid': int, 'title': str, and for each track- song ID: song URL
    :param genre: name of genre registry to create or append
    :param outd: output directory, defaults to app OUTDIR
    :return 0 if save OK
    """

    if not genre in GENRES:
        print("save_artist_file: use out file= '<genre>_registry.json'! exiting")
        return 1
    else:
        outf: str = genre + "_registry.json"

    fqf = join(outd, outf)
    with open(fqf, mode='a') as f_h:
        if isinstance(albdct, list):
            for alb in albdct:
                json.dump(alb, f_h)
                f_h.write("\n")
        elif isinstance(albdct, dict):
            # typical course when processing after get_lyrics is run in build_corpus
            json.dump(albdct, f_h)
            f_h.write("\n")
            for ad, i in zip(albdct, range(1)):
                print("append_genre_registry: added tracks for %s" % ad[:-3])

    return 0

def retrieve_genre_registry(genre: str, indir: str=ARTISTDIR):
    """
    retrieve track lists for artists, useful in matching up document ID's when doing
    topic modeling and other doc2vec tasks with song lyrics
    :param genre: each genre has a registry file made up of track dicts for each artist
    :param indir: folder where json registry files reside, default is ARTISTDIR
    :return:
    """
    infile = genre + "_registry.json"
    fqf = join(indir, infile)
    if isfile(fqf):
        reg_lst: list = []
        with open(fqf, mode="r") as f_h:
            for line in f_h:
                reg_lst.append(json.loads(line))

        print("  retrieved %s registry with %d artist track lists" % (genre, len(reg_lst)))
        return reg_lst
    else:
        print("retrieve_genre_registry ERROR: %s not valid!" % fqf)
        return None

def get_artists_in_genre(incl_genres, lydir: str=LYRICDIR):
    """
    creates and displays a list of all artists for genres selected via incl_genres parm.
    selects all genres if incl_genres is left blank or if 'all' is passed as str or list
    :param incl_genres:
    :param lydir: folder for lyric files
    :return:
    """
    print("  -- create_genre_lists finds all artists with lyrics in genre --")
    if not incl_genres:
        search_gen = GENRES
    else:
        if incl_genres == "all":
            search_gen = GENRES
        else:
            if isinstance(incl_genres, str):
                if incl_genres in GENRES:
                    search_gen = [incl_genres]
            elif isinstance(incl_genres, list):
                search_gen: list = []
                for genx in incl_genres:
                    if genx in GENRES:
                        search_gen.append(genx)

    total_gen: int = len(search_gen)
    art_added: int = 0
    genre_artists: dict = {}
    genre_artists = genre_artists.fromkeys(search_gen)

    def add_artist(gn: str, ar: str, g_a: dict):
        """
        inner function to insert artist in appropriate dict for genre
        :param gn: str with genre
        :param ar: str with artist
        :param g_a: dict of genre-artists
        :return: 0 if artist inserted, 1 if not
        """
        found: bool = False
        for k, v in g_a.items():
            if k == gn:
                found = True
                if not v:
                    artsts: set = {ar}
                elif isinstance(v, list):
                    artsts: set = set(v)
                elif isinstance(v, set):
                    artsts: set = v

                if not ar in artsts:
                    artsts.add(ar)
        if found:
            g_a[gn] = artsts
        return g_a, found

    for fname in listdir(lydir):
        fqfil = join(lydir, fname)
        if isfile(fqfil):
            sep_pos = fname.find("_")
            ext_pos = fname.find(".")
            gen_pre = fname[:sep_pos]
            art_nam = fname[sep_pos + 1: ext_pos]
            if gen_pre in search_gen:
                genre_artists, was_added = add_artist(gen_pre, art_nam, genre_artists)
                if was_added:
                    art_added += 1

    print("      create_genre added %d artists across %d genres" % (art_added, total_gen))
    return genre_artists

def save_artist_info(artdct: dict, genre: str, outd: str = OUTDIR):
    """
    this is an optional method to save the artist info dict that is simply created as a
    step towards pulling albums and lyric tracks, it may allow recreation of a corpus
    from scratch easier.
    :param artdct: artist name, genius id, img file, lyric file, etc.
    :param genre: name of genre for this artist
    :param outd: output directory, defaults to app OUTDIR
    :return 0 if save OK
    """
    outf = genre + "_artistdb.info"
    fqf = join(outd, outf)
    with open(fqf, mode='a') as f_h:
        if isinstance(artdct, dict):
            json.dump(artdct, f_h)
            f_h.write("\n")

    return 0

def scrub_cloud(twl: list):
    """
    scrub_text can perform numerous text removal or modification tasks on tweets,
    there is tweet-specific content handled here which can be optionally commented out
    if resulting corpus loses too much detail for downstream tasks like sentiment analysis

    :param twl: list of tweets
    :return: list of words OR str of words if rtn_list= False
    """
    from gs_datadict import GS_STOP, STOP_LYRICS, CHAR_CONVERSION
    import re

    for tweetxt in twl:
        if isinstance(tweetxt, str):
            # remove newlines in tweets, they cause a mess with many tasks
            tweetxt = tweetxt.replace("\n", " ")
            # remove standalone period, no need in a tweet
            tweetxt = re.sub(r"\.", " ", tweetxt)
            # expand contractions using custom dict of contractions
            tweetxt = re.sub(GS_STOP, "", tweetxt)
            # convert ucs-2 chars appearing in english tweets
            tweetxt = re.sub(STOP_LYRICS, "", tweetxt)
            # parsing tweet punc: don't want to lose sentiment or emotion
            tweetxt = re.sub(CHAR_CONVERSION, "", tweetxt)
            # parameter "utf-8" escapes ucs-2 (\uxxxx), "ascii" removes multi-byte
            binstr = tweetxt.encode("ascii", "ignore")
            tweetxt = binstr.decode()
            # now, tokenize and run words through cleaning:
            splitstr = tweetxt.split()
            stokens: list = []
            for w in splitstr:
                if len(w) < 2:
                    continue
                # lower case all alpha words
                if str(w).isalpha():
                    w: str = str(w).lower()
                    stokens.append(w)
            splitstr: list = []
            for wrd in stokens:
                wrd = wrd.strip()
                splitstr.append(wrd)

    return splitstr

def get_cloud_input(batch_words):
    """
    get lyrics token lists from object and process to prep for cloud
    :param batch_words:
    :return:
    """
    wrdct: dict = {}
    cur_artist: str = ""
    for wrds, artst in batch_words:
        for word in wrds:
            if wrdct.get(word):
                wrdct[word] += 1
            else:
                wrdct[word] = 1
        if not cur_artist.startswith(artst):
            if not cur_artist == "":
                print("streaming done for %s" % artst)
            cur_artist = artst

    return wrdct

def do_cloud(cloud_words: list, opt_stops: list = None, maxwrd: int = 120):
    """
    wordcloud package options can be explored via '?wordcloud' (python- show docstring)
    background_color="white" - lighter background makes smaller words more legible,
    max_words= this can prevent over clutter, mask=shape the cloud to an image,
    stopwords=ad-hoc removal of unwanted words, contour_width=3,
    :param cloud_words: list of list of word tokens
    :param opt_stops: list of words (str) to remove prior to creating wordcloud
    :param maxwrd: int typically from 80 to 120 for total words to appear in cloud
    :return:
    """
    from wordcloud import WordCloud
    import io
    import matplotlib.pyplot as plt

    cloud_text = io.StringIO(newline="")
    for tok in cloud_words:
        if isinstance(tok, str):
            cloud_text.write(tok + " ")
        else:
            for a_tw in tok:
                if isinstance(a_tw, list):
                    cloud_text.write(" ".join([str(x) for x in a_tw]) + " ")
                if isinstance(a_tw, str):
                    # if simple list of text for each tweet:
                    cloud_text.write(a_tw + " ")

    wordcld = WordCloud(width=800, height=800, max_words=maxwrd,
                        background_color='white',
                        stopwords=opt_stops, min_word_length=4,
                        min_font_size=10).generate(cloud_text.getvalue())

    # plot the WordCloud image
    plt.figure(figsize=(8, 8), facecolor=None)
    plt.imshow(wordcld)
    plt.axis("off")
    plt.tight_layout(pad=0)
    plt.show()

    return

def check_outliers(lobj):
    """
    goes through a lyrics object and checks for few extreme values for
    calculated attributes such as tf and idf
    """
    artvals: list = []
    artistlst: list = list(lobj.artists.copy())
    artistct: int = len(artistlst)
    for i in range(artistct):
        if lobj.tfidf_artist.get(artistlst[i]):
            artvals.append(list(lobj.tfidf_artist[artistlst[i]].values()))

    for i in range(artistct):
        hicut = np.percentile(a=artvals[i], q=98)
        locut = np.percentile(a=artvals[i], q=2)
        voc_size = len(artvals[i])
        removed: int = 0
        for_deletion: list = []
        tmpdct: dict = lobj.tfidf_artist[artistlst[i]]
        for wrd, tfival in tmpdct.items():
            if tfival > hicut or tfival < locut:
                for_deletion.append(wrd)
        if for_deletion:
            for wrd in for_deletion:
                tmpdct.pop(wrd)
                removed += 1

        lobj.tfidf_artist[artistlst[i]] = tmpdct
        pct_del = round((removed / voc_size), ndigits=3)
        print("outliers removed %d tfidf_artist, %.3f percent, for %s" % (removed, pct_del, artistlst[i]))

    return artistlst, artvals

def plot_artist_tfidf(lobj, artst: str):

    artvals: list = list(lobj.tfidf_artist[artst].values())
    fig, ax1 = plt.subplots()
    ax1.xaxis.set_major_formatter(FormatStrFormatter('%.4f'))

    finalmin: float = 0.0006
    tfimed = np.median(artvals)
    tfistd = np.std(artvals)
    finalmax = tfimed + (3 * tfistd)
    xrang = finalmax - finalmin
    num_bins = int(round(xrang / 0.0002, ndigits=0) + 2)

    ax1.set_xlim(finalmin, finalmax)
    plt.xlim(finalmin, finalmax)

    ax1.hist(artvals, bins=num_bins, density=False, range=(finalmin, finalmax))

    plt.ylabel('Occurences')
    plt.xlabel('tfidf value')
    plt.suptitle("tfidf for words of %s" % artst)
    plt.show()

    return

def plot_artist_tf(lobj, artst: str):
    artvals: list = list(lobj.tf_by_artist[artst].values())
    tot_wrds: int = len(artvals)

    fig, ax1 = plt.subplots()
    ax1.xaxis.set_major_formatter(FormatStrFormatter('%.4f'))

    finalmin: float = 0.002
    tfimed = np.median(artvals)
    tfistd = np.std(artvals)
    finalmax = tfimed + (3 * tfistd)
    xrang = finalmax - finalmin
    num_bins = int(round(xrang / 0.0002, ndigits=0) + 2)

    ax1.set_xlim(finalmin, finalmax)
    plt.xlim(finalmin, finalmax)
    ax1.hist(artvals, bins=num_bins, density=False, range=(finalmin, finalmax))
    plt.ylabel('Occurences')
    plt.xlabel('tfidf value')
    plt.suptitle("tf for %d words for artist: %s" % (tot_wrds, artst))
    plt.show()

    return

def compare_artist_tfidf(lobj, artistlst: list = None):
    """
    within a lyrics object, compare high-tf words between artists
    ASSUMES TWO ARTISTS WILL ALWAYS BE NAMED!
    """
    num_bins: int = 200
    artvals: list = []
    plots: int = 0
    for artist in artistlst:
        artvals.append(list(lobj.tfidf_artist[artist].values()))
        plots += 1

    fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=plots)
    ax1.xaxis.set_major_formatter(FormatStrFormatter('%.3f'))
    ax2.xaxis.set_major_formatter(FormatStrFormatter('%.3f'))

    totmx: float = 0.09
    totmn: float = 0.002
    for i in range(plots):
        tfimx = np.max(artvals[i])
        tfimn = np.min(artvals[i])
        if i == 0:
            ax1.set_xlim(tfimn, tfimx)
            ax1.hist(artvals[i], num_bins, density=False, range=(tfimn, tfimx))
        else:
            ax2.set_xlim(tfimn, tfimx)
            ax1.hist(artvals[i], num_bins, density=False, range=(tfimn, tfimx))

    # color1 = np.random.uniform(15, 80, len(art1_vals))
    # the histogram of the data
    # n, bins, patches = ax1.hist(artvals[0], num_bins, density=False, range=(totmn, totmx))
    # n2, bins2, patches2 = ax2.hist(artvals[1], num_bins, density=False, range=(totmn, totmx))

    # add a 'best fit' line
    # mu = np.mean(artvals[0])  # mean of distribution
    # sigma = np.std(artvals[0])  # standard deviation of distribution
    # y = ((1 / (np.sqrt(2 * np.pi) * sigma)) *
    #     np.exp(-0.5 * (1 / sigma * (bins - mu)) ** 2))
    # ax1.plot(bins, y, '--')

    # fig, ax = plt.subplots()
    # ax.hist(art1_vals, bins=30, linewidth=0.01, edgecolor="white")
    # ax.xaxis.set_major_formatter(FormatStrFormatter('%.3f'))
    plt.ylabel('Occurences')
    plt.xlabel('tfidf value')
    plt.suptitle("tfidf for words of %s vs %s" % (artistlst[0], artistlst[1]))
    plt.show()

    return


import awele
import sys

sys.path.append("..")
import game
game.game=awele
sys.path.append("./Joueurs")
import awele_alea
import awele_joueur_humain
import awele_alphaBeta
import awele_minMax
import awele_PremierCoupValide
import Ciri
import Geralt
import pedro
import Oracle
import random
global N,j1,j2
j1,j2 = 1,2
epsilon = 0.1#marge pr tatonner
N = 10
#Apprentissage avec un "oracle" a valeurs aléatoires param aléa, il faut bcp d'iterations vu que c'est du aléatoire
"""PB AVEC POIDS QUI CHANGEMENT PAS. dans les j """

#courbe ratio victoire de mon apprenant
game.joueur1 = joueur_ref = Oracle
game.joueur2 = joueur_ap =Geralt

game.joueurinter1 = game.joueur1
game.joueurinter2 = game.joueur2

def Train():
    g1 = JoueN(joueur_ap,joueur_ref) #g1= nombre de victoire de joueur ap

    it = 0
    while it <250: #tant que it (compteur) est inferieur au nombre de partie
        j=int(random.random()*joueur_ap.getNbParams())
        s=random.random()
        if(s>0.5):
            joueur_ap.addParam(j, epsilon)
        else :
            joueur_ap.addParam(j,-epsilon)
        g2 = JoueN(joueur_ap,joueur_ref)
        print (joueur_ap.getParams())
        print(g1)
        print(g2)
        if(g2<g1) :
            if(s>0.5) : joueur_ap.addParam(j,-epsilon)
            else : joueur_ap.addParam(j,epsilon)
        else : g1 = g2
        it+=1

def JoueN(joueur1,joueur2): # joue 10 partie (variable N) et compte le nombre de victoire de leleve
    global j1,j2
    victoires=0
    for i in range(N):
        game.joueur1 = awele_alea #permet de tirer des coups aleatoire au debut, sinon tjr meme partie
        game.joueur2 = awele_alea
        jeu = game.initialiseJeu()
        while not game.finJeu(jeu):
            coup = game.saisieCoup(jeu) #joues different coups tant que cest pas la fin du jeu
            game.joueCoup(jeu,coup)
            if len(game.getCoupsJoues(jeu)) == 4: #apres 4 coups aleatoire,le jeu commence vraiment
                game.joueur2=joueur2
                game.joueur1=joueur1
            if i == N/2 :
                game.joueur1=joueur2 #apres 5 partie, on echange les joeuur , pour quon ai pas le meme joueur qui commence
                game.joueur2=joueur1
                j1,j2 = 2,1
        g=game.getGagnant(jeu)

        if g == j1: #on compte le nbre de victoire de leleve
            victoires+=1
            print(g)
    j1,j2 = 1,2
    return victoires

Train()
print (joueur_ap.getParams())


# ---
# jupyter:
#   jupytext:
#     formats: ipynb,py:light
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.5
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

import numpy as np

def AND(x1,x2):
    x=np.array([x1,x2])
    w=np.array([0.5,0.5])
    b=-0.7
    tmp=np.sum(w*x)+b
    if tmp<=0:
        return 0
    else:
        return 1

AND(0,0)

AND(1,0)

AND(0,1)

AND(1,1)

def NAND(x1,x2):
    x=np.array([x1,x2])
    w=np.array([-0.5,-0.5])
    b=0.7
    tmp=np.sum(w*x)+b
    if tmp<=0:
        return 0
    else:
        return 1

NAND(0,0)

NAND(1,0)

NAND(0,1)

NAND(1,1)

def OR(x1,x2):
    x=np.array([x1,x2])
    w=np.array([0.5,0.5])
    b=-0.2
    tmp=np.sum(w*x)+b
    if tmp<=0:
        return 0
    else:
        return 1

OR(0,0)

OR(1,0)

OR(0,1)

OR(1,1)


################################################################################
# oops/inst/juno/__init__.py
#
# Utility functions for managing SPICE kernels while working with juno data
# sets.
################################################################################

import numpy as np

import os
import julian
import spicedb
import cspyce
import oops

from oops.body import Body

################################################################################
# Routines for managing the loading of C and SP kernels
################################################################################

# Make sure the leap seconds have been loaded
oops.spice.load_leap_seconds()

# We load CK and SPK files on a very rough month-by-month basis. This is simpler
# than a more granular approach involving detailed calendar calculations. We
# divide the period October 1, 1997 to October 1, 2017 up into 240 "months" of
# equal length. Given any TDB, we quickly determine the month within which it
# falls. Each month is associated with a list of kernels that should be loaded
# whenever information is needed about any time within that month +/- 12 hours.
# The kernels needed for a given month only get loaded when they are needed, and
# are only loaded once. For any geometry calculation involving Juno, a quick
# call to load_ck(time) or load_spk(time) will ensure that the information is
# available.

################################################################################

#*******************************************************************************
class Juno(object):
    """An instance-free class to hold Juno-specific parameters."""

    START_TIME = '2011-08-01'
    STOP_TIME  = '2025-08-01'
    MONTHS = 168        # 14 years * 12 months/year

    TDB0 = julian.tdb_from_tai(julian.tai_from_iso(START_TIME))
    TDB1 = julian.tdb_from_tai(julian.tai_from_iso(STOP_TIME))
    DTDB = (TDB1 - TDB0) / MONTHS
    SLOP = 43200.

    CK_LOADED = np.zeros(MONTHS, dtype='bool')      # True if month was loaded
    CK_LIST   = np.empty(MONTHS, dtype='object')    # Kernels needed by month
    CK_DICT   = {}      # Dictionary keyed by filespec returns kernel info
                        # object, but only if loaded.

    SPK_LOADED  = np.zeros(MONTHS, dtype='bool')
    SPK_LIST    = np.empty(MONTHS, dtype='object')
    SPK_DICT    = {}

    loaded_instruments = []

    initialized = False

    #===========================================================================
    @staticmethod
    def initialize(ck='reconstructed', planets=None, asof=None,
                   spk='reconstructed', gapfill=True,
                   mst_pck=True, irregulars=True):
        """Intialize the Juno mission internals.

        After the first call, later calls to this function are ignored.

        Input:
            ck,spk      Used to specify which C and SPK kernels are used.:
                        'reconstructed' for the reconstructed kernels (default);
                        'predicted' for the predicted kernels;
                        'none' to allow manual control of the C kernels.
            planets     A list of planets to pass to define_solar_system. None
                        or 0 means all.
            asof        Only use SPICE kernels that existed before this date;
                        None to ignore.
            gapfill     True to include gapfill CKs. False otherwise.
            mst_pck     True to include MST PCKs, which update the rotation
                        models for some of the small moons.
            irregulars  True to include the irregular satellites;
                        False otherwise.
        """
        if Juno.initialized: return

        (ck, spk) = ('NONE', 'NONE')

        # Define some important paths and frames
        Body.define_solar_system(Juno.START_TIME, Juno.STOP_TIME,
                                 asof=asof,
                                 planets=planets,
                                 mst_pck=mst_pck,
                                 irregulars=irregulars)

        ignore = oops.path.SpicePath('JUNO', 'JUPITER')

        spicedb.open_db()

        spk = spk.upper()
        if spk == 'NONE':

            # This means no SPK will ever be loaded; handling is manual
            Juno.initialize_kernels([], Juno.SPK_LIST)
            Juno.SPK_LOADED = np.ones(Juno.MONTHS, dtype='bool')
        else:
            kernels = spicedb.select_spk(-61, name='JUNO_-SPK-' + spk,
                                              time=(Juno.START_TIME,
                                                    Juno.STOP_TIME),
                                              asof=asof)
            Juno.initialize_kernels(kernels, Juno.SPK_LIST)

        ck = ck.upper()
        if ck == 'NONE':

            # This means no CK will ever be loaded; handling is manual
            Juno.initialize_kernels([], Juno.CK_LIST)
            Juno.CK_LOADED = np.ones(Juno.MONTHS, dtype='bool')
        else:
            kernels = spicedb.select_ck(-61, name='JUNO_-CK-' + ck,
                                             time=(Juno.START_TIME,
                                                   Juno.STOP_TIME),
                                             asof=asof)
            Juno.initialize_kernels(kernels, Juno.CK_LIST)

        # Load extra kernels if necessary
        if gapfill and ck not in ('PREDICTED', 'NONE'):
            _ = spicedb.furnish_ck(-61, name='JUNO_-CK-GAPFILL')

        spicedb.close_db()

        Juno.initialized = True

    #===========================================================================
    @staticmethod
    def reset():
        """Reset the internal parameters.

        Can be useful for debugging.
        """
        Juno.loaded_instruments = []

        Juno.CK_LOADED = np.zeros(Juno.MONTHS, dtype='bool')
        Juno.CK_LIST = np.empty(Juno.MONTHS, dtype='object')
        Juno.CK_DICT = {}

        Juno.SPK_LOADED = np.zeros(Juno.MONTHS, dtype='bool')
        Juno.SPK_LIST = np.empty(Juno.MONTHS, dtype='object')
        Juno.SPK_DICT = {}

        Juno.initialized = False

    #===========================================================================
    @staticmethod
    def load_ck(t):
        """Ensure that the C kernels applicable at or near the given time have
        been furnished.

        The time can be tai or tdb.
        """
        Juno.load_kernels(t, t, Juno.CK_LOADED, Juno.CK_LIST,
                                   Juno.CK_DICT)

    #===========================================================================
    @staticmethod
    def load_cks(t0, t1):
        """Ensure that all the C kernels applicable near or within the time
        interval tdb0 to tdb1 have been furnished.

        The time can be tai or tdb.
        """
        Juno.load_kernels(t0, t1, Juno.CK_LOADED, Juno.CK_LIST,
                                     Juno.CK_DICT)

    #===========================================================================
    @staticmethod
    def load_spk(t):
        """Ensure that the SPK kernels applicable at or near the given time have
        been furnished.

        The time can be tai or tdb.
        """
        Juno.load_kernels(t, t, Juno.SPK_LOADED, Juno.SPK_LIST,
                                   Juno.SPK_DICT)

    #===========================================================================
    @staticmethod
    def load_spks(t0, t1):
        """Ensure that all the SPK kernels applicable near or within the time
        interval tdb0 to tdb1 have been furnished.

        The time can be tai or tdb.
        """
        Juno.load_kernels(t0, t1, Juno.SPK_LOADED, Juno.SPK_LIST,
                                     Juno.SPK_DICT)

    #===========================================================================
    @staticmethod
    def load_kernels(t0, t1, loaded, lists, kernel_dict):
        """Load kernal pool."""

        from oops.unittester_support import TESTDATA_PARENT_DIRECTORY

        kdir = os.path.join(TESTDATA_PARENT_DIRECTORY, '../SPICE/Juno/')
        gkdir = os.path.join(TESTDATA_PARENT_DIRECTORY, '../SPICE/General/')

        cspyce.furnsh(kdir + 'CK/juno_sc_rec_131006_131012_v01.bc')
        cspyce.furnsh(kdir + 'SPK/spk_rec_131005_131014_131101.bsp')
        cspyce.furnsh(kdir + 'CK/juno_sc_rec_161211_161217_v01.bc')
        cspyce.furnsh(kdir + 'SPK/juno_rec_161115_170106_170113.bsp')
        cspyce.furnsh(kdir + 'CK/juno_sc_rec_170702_170708_v01.bc')
        cspyce.furnsh(kdir + 'SPK/juno_rec_170608_170728_170803.bsp')
        cspyce.furnsh(kdir + 'CK/juno_sc_rec_171023_171025_v01.bc')
        cspyce.furnsh(kdir + 'SPK/juno_rec_170918_171121_171127.bsp')
        cspyce.furnsh(kdir + 'CK/juno_sc_rec_171215_171217_v01.bc')
        cspyce.furnsh(kdir + 'SPK/juno_rec_171121_180113_180117.bsp')
        cspyce.furnsh(kdir + 'CK/juno_sc_rec_180523_180524_v01.bc')
        cspyce.furnsh(kdir + 'SPK/juno_rec_180429_180621_180626.bsp')
        cspyce.furnsh(kdir + 'CK/juno_sc_rec_180906_180907_v01.bc')
        cspyce.furnsh(kdir + 'SPK/juno_rec_180812_181004_181011.bsp')
        cspyce.furnsh(kdir + 'CK/juno_sc_rec_190405_190406_v01.bc')
        cspyce.furnsh(kdir + 'SPK/juno_rec_190312_190504_190509.bsp')
        cspyce.furnsh(kdir + 'CK/juno_sc_rec_190911_190912_v01.bc')
        cspyce.furnsh(kdir + 'SPK/juno_rec_190817_191010_191022.bsp')
        cspyce.furnsh(kdir + 'CK/juno_sc_rec_200405_200411_v01.bc')
        cspyce.furnsh(kdir + 'SPK/juno_rec_200316_200508_200512.bsp')
        cspyce.furnsh(kdir + 'CK/juno_sc_rec_200719_200725_v01.bc')
        cspyce.furnsh(kdir + 'SPK/juno_rec_200629_200822_200826.bsp')
        cspyce.furnsh(kdir + 'CK/juno_sc_rec_201108_201114_v01.bc')
        cspyce.furnsh(kdir + 'SPK/juno_rec_201014_201205_201208.bsp')
        cspyce.furnsh(kdir + 'CK/juno_sc_rec_201227_210102_v01.bc')
        cspyce.furnsh(kdir + 'SPK/juno_rec_201205_210127_210210.bsp')
        cspyce.furnsh(kdir + 'CK/juno_sc_rec_210221_210227_v01.bc')
        cspyce.furnsh(kdir + 'SPK/juno_rec_210127_210321_210329.bsp')
        cspyce.furnsh(kdir + 'CK/juno_sc_rec_210221_210227_v01.bc')
        cspyce.furnsh(kdir + 'SPK/juno_rec_210127_210321_210329.bsp')
        cspyce.furnsh(kdir + 'CK/juno_sc_rec_190528_190529_v01.bc')
        cspyce.furnsh(kdir + 'SPK/juno_rec_190504_190626_190627.bsp')

        cspyce.furnsh(kdir + 'CK/juno_sc_rec_160710_160716_v01.bc')
        cspyce.furnsh(kdir + 'CK/juno_sc_rec_160717_160723_v01.bc')
        cspyce.furnsh(kdir + 'SPK/spk_rec_160522_160729_160909.bsp')

        cspyce.furnsh(kdir + 'CK/juno_sc_rec_170827_170902_v01.bc')
        cspyce.furnsh(kdir + 'CK/juno_sc_rec_170903_170909_v01.bc')
        cspyce.furnsh(kdir + 'SPK/spk_rec_170728_170918_170922.bsp')

        cspyce.furnsh(kdir + 'CK/juno_sc_rec_180715_180716_v01.bc')
        cspyce.furnsh(kdir + 'SPK/spk_rec_180620_180812_180821.bsp')

        cspyce.furnsh(gkdir + 'LSK/naif0012.tls')
        cspyce.furnsh(kdir + 'SCLK/jno_sclkscet_00128.tsc')
        cspyce.furnsh(kdir + 'FK/juno_v12.tf')
        cspyce.furnsh(kdir + 'IK/juno_junocam_v03.ti')
        cspyce.furnsh(kdir + 'IK/juno_jiram_v02.ti')
        cspyce.furnsh(kdir + 'SPK/de421.bsp')
        cspyce.furnsh(kdir + 'SPK/de432s.bsp')
### This would be best handled by creating a text file that contains a list of the
### file names to be loaded (starting with "ck/, "spk/" etc.). Maintain this file
### separately from the Python code. The Python code reads the list and furnishes
### inside a big loop. When a new SPK or CK is released, we just add it to the list
### and update it in the repo. See hosts/solar for how to allow a Python module to
### locate a file within its own directory path. The kernels can live inside the
### OOPS-Resources/SPICE tree, so you can determine the value of "kdir" from the
### value of (unittester_support.OOPS_RESOURCES_ + 'SPICE/Juno/').
###
### Even better, adopt the Cassini module's method of just loading the CKs and SPKs
### as they are requested, because there are so many of them. It'll just furnish the
### CKs and SPKs when it needs them, in the background, silently.
###
### Other notes...
###
### There are a lot of duplicated files on Dropbox between
### OOPS-Resources/SPICE/Juno and test_data/juno/kernels. Better to keep a single
### set in the former. If kernels start to change out from underneath us in a way
### that breaks unit tests, that would be the time to start keeping a specific
### subset inside test_data/juno.
###
### The set of CKs and SPKs on Dropbox is currently incomplete. We need to start
### maintaining it, and continue to do so once we are generating metadata tables.
###
### I see on the NAIF ftp server that there are multiple versions of the CKs and
### SPKs, as there were for Cassini. We probably never need to worry about anything
### but the reconstructed. However, in order to allow for multiple future versions,
### I suggest you rename SPICE/Juno/CK to SPICE/Juno/CK-reconstructed and
### SPICE/Juno/SPK to SPICE/Juno/SPK-reconstructed. This will make for simpler file
### management going forward.
###
### The other day, you asked me to add a few kernels to SPICE.db. It's not clear to
### me why that was necessary. The kernel management method I described above should
### be sufficient for all Juno kernel management, and is the reason I've concluded
### we should get rid of the sqlite database.

        return

## TODO:
        # Find the range of months needed
        m1 = int((t0 - Juno.TDB0) // Juno.DTDB)
        m2 = int((t1 - Juno.TDB0) // Juno.DTDB) + 1

        m1 = max(m1, 0)         # ignore time limits outside mission duration
        m2 = min(m2, Juno.MONTHS - 1)

        # Load any months not already loaded
        for m in range(m1, m2+1):
          if not loaded[m]:
            for kernel in lists[m]:
                filespec = kernel.filespec
                if filespec not in kernel_dict:
                    spicedb.furnish_kernels([kernel])
                    kernel_dict[filespec] = kernel
                loaded[m] = True

    ########################################
    # Initialize the kernel lists
    ########################################

    #===========================================================================
    @staticmethod
    def initialize_kernels(kernels, lists):
        """After initialization, lists[m] is a the KernelInfo objects needed
        within the specified month.
        """
        for i in range(Juno.MONTHS):
            lists[i] = []

        for kernel in kernels:

            # Find the range of months applicable, extended by 12 hours
            t0 = cspyce.str2et(kernel.start_time) - Juno.SLOP
            t1 = cspyce.str2et(kernel.stop_time)  + Juno.SLOP

            m1 = int((t0 - Juno.TDB0) // Juno.DTDB)
            m2 = int((t1 - Juno.TDB0) // Juno.DTDB) + 1

            m1 = max(m1, 0)     # ignore time limits outside mission duration
            m2 = min(m2, Juno.MONTHS - 1)

            # Add this kernel to each month's list
            for m in range(m1, m2+1):
                lists[m] += [kernel]

    ############################################################################
    # Routines for managing the loading other kernels
    ############################################################################

    #===========================================================================
    @staticmethod
    def load_instruments(instruments=[], asof=None):
        """Load the SPICE kernels and defines the basic paths and frames for
        the Juno mission.

        It is generally only be called once.

        Input:
            instruments an optional list of instrument names for which to load
                        frames kernels. The frames for JUNOCAM are always loaded.

            asof        if this specifies a date or date-time in ISO format,
                        then only kernels that existed before the specified date
                        are used. Otherwise, the most recent versions are always
                        loaded.
        """

        # Load the default instruments on the first pass
        if Juno.loaded_instruments == []:
            instruments += ['JUNOCAM']

        # On later calls, return quickly if there's nothing to do
        if instruments == []: return

        # Check the formatting of the "as of" date
        if asof is not None:
            (day, sec) = julian.day_sec_from_iso(asof)
            asof = julian.ymdhms_format_from_day_sec(day, sec)

        # Furnish instruments and frames
        spicedb.open_db()
        _ = spicedb.furnish_inst(-61, inst=instruments, asof=asof)
        spicedb.close_db()

    ############################################################################
    # Routines for managing text kernel information
    ############################################################################

### TODO: finish these routines...

    #===========================================================================
    @staticmethod
    def spice_instrument_kernel(inst, asof=None):
        """Return a dictionary containing the Instrument Kernel information.

        Also furnishes it for use by the SPICE tools.

        Input:
            inst        one of "JUNOCAM", etc.
            asof        an optional date in the past, in ISO date or date-time
                        format. If provided, then the information provided will
                        be applicable as of that date. Otherwise, the most
                        recent information is always provided.

        Return:         a tuple containing:
                            the dictionary generated by textkernel.from_file()
                            the name of the kernel.
        """
        if asof is not None:
            (day,sec) = julian.day_sec_from_iso(stop_time)
            asof = julian.ymdhms_format_from_day_sec(day, sec)

        spicedb.open_db()
        kernel_info = spicedb.select_inst(-61, types='IK', inst='JUNOCAM', asof=asof)
        spicedb.furnish_kernels(kernel_info, fast=True)
        spicedb.close_db()

        return (spicedb.as_dict(kernel_info), spicedb.as_names(kernel_info)[0])

    #===========================================================================
    @staticmethod
    def spice_frames_kernel(asof=None):
        """Return a dictionary containing the Juno Frames Kernel information.

        Also furnishes the kernels for use by the SPICE tools.

        Input:
            asof        an optional date in the past, in ISO date or date-time
                        format. If provided, then the information provided will
                        be applicable as of that date. Otherwise, the most
                        recent information is always provided.

        Return:         a tuple containing:
                            the dictionary generated by textkernel.from_file()
                            an ordered list of the names of the kernels
        """
        if asof is not None:
            (day,sec) = julian.day_sec_from_iso(stop_time)
            asof = julian.ymdhms_format_from_day_sec(day, sec)

        spicedb.open_db()
        kernel_list = spicedb.select_inst(-61, types='FK', asof=asof)
        spicedb.furnish_kernels(kernel_info, fast=True)
        spicedb.close_db()

        return (spicedb.as_dict(kernel_list), spicedb.as_names(kernel_list))

    #===========================================================================
    @staticmethod
    def used_kernels(time, inst, return_all_planets=False):
        """Return the list of kernels associated with a Juno observation at
        a selected range of times.
        """
        if return_all_planets:
            bodies = [1, 199, 2, 299, 3, 399, 4, 499, 5, 599, 6, 699,
                      7, 799, 8, 899]
            if time[0] >= TOUR:
                bodies += body.SATURN_MOONS_LOADED
            else:
                bodies += body.JUPITER_MOONS_LOADED
        else:
            if time[0] >= TOUR:
                bodies = [6, 699] + body.SATURN_MOONS_LOADED
            else:
                bodies = [5, 599] + body.JUPITER_MOONS_LOADED

        return spicedb.used_basenames(time=time, inst=inst, sc=-61,
                                      bodies=bodies)


import subprocess
import pandas as pd
from utility import master
from data_analysis.bucket_slabs import bucket
from data_extraction.repo_rate import get_repo_rate
import os
from definition import ROOT_PATH

PROJECT_ROOT = os.path.dirname(os.path.abspath(ROOT_PATH))

# print(os.getcwd())

# Extract data from PaisaBazaar website in respective directory i.e. data_extraction
subprocess.run(['python', r'data_extraction/index.py'])

# Create bucketed data master sheet
# 1. Create general format for bucket_master.csv
df_kotak = pd.read_csv(r'kotak_slabs.csv')
df_kotak.drop(columns=df_kotak.columns.difference(['Tenure', 'General Rate']), inplace=True)
df_kotak = df_kotak.rename(columns={'General Rate': 'Kotak'})

# 2. Get buckets for each bank
for bank in master:
    bank.bucket_df = bucket(bank.name, bank.df)

# 3. Concatenate each banks bucketed dataframe to bucket_master.csv as columns
bucket_master = df_kotak
for bank in master:
    bank.bucket_df = bank.bucket_df.rename(columns={'General Rate': bank.name})
    del bank.bucket_df['Bank Name']
    bucket_master = bucket_master.merge(bank.bucket_df, on='Tenure', how='left')

bucket_master = bucket_master.fillna(method='ffill')

# 4. Store as .csv file
bucket_master.to_csv('bucket_master.csv', mode='w', index=False)

# Extract bank historical data for future use
subprocess.run(['python', r'bank_historical_data/extract_historical.py'])

# Revenue Extraction from Yahoo Financials
# Currently not required not dashboard hence commented out
# subprocess.run(['python', r'extract_revenue.py'])

# Extract RBI Repo Rate and store as .txt file for quick access
repo_rate = str(get_repo_rate())
with open('repo_rate.txt', 'w+') as file:
    file.write(repo_rate)


from odoo import models, fields, api, _
from odoo.exceptions import UserError, ValidationError
import json
import logging
from slack_sdk.webhook import WebhookClient

class SudoAccessApproval(models.Model):
    _name = 'sudo_aws_access.approval'
    _description = 'AWS Access for team'
    _inherit = ['mail.thread', 'mail.activity.mixin']

    requester_user = fields.Many2one('res.users', string='Requester User', required=False)
    approval_user = fields.Many2many('res.users', string='Approval User', required=False,domain=lambda self: self.default_user_ids())

    current_access_user = fields.Many2one('res.users', string='Current Access User', required=False, )

    approval = fields.Selection(
        string='Approval',
        selection=[('approve', 'Approved'),
                   ('reject', 'Rejected'), ],
        required=False, )
    state = fields.Selection(
        string='Status',
        selection=[('approve', 'Approved'),
                   ('reject', 'Rejected'), ],
        required=False, )

    account_name = fields.Char(string='AWS Account')

    team_member = fields.Many2one('res.users',
                                  string='Team Member',
                                  required=False
                                  )
    role_name = fields.Char(
        string='role name',
        required=False)

    access_type = fields.Selection(
        [
            ('l1access', 'L1 Access'),
            ('l2access', 'L2 Access'),
            ('psaccess', 'PS Access'),
            ('readonlyaccess', 'Read Only Access'),
            ('supportaccess', 'Support Access'),
            ('billingaccess', 'Billing Access'),

        ])
    login_link = fields.Char("Login Link", compute='compute_login_link', widget="url")
    role_edit_link = fields.Char("Role Edit Link", default="", required=False, widget="url")
    weep_commands = fields.Html("Weep Commands", default="", required=False)
    status = fields.Selection(
        string='Status',
        selection=[('enable', 'Enable'),
                   ('disable', 'Disable'), ],
        required=False, )
    reject_reason = fields.Text(string="Rejection Reason")

    def compute_login_link(self):
        for record in self:
            if record.role_name:
                record.login_link = "https://consolemeurl.com/role/{role}".format(role=record.role_name)
            else:
                record.login_link = ''

    def approve_action(self):
        for rec in self:
            access_to_user = self.env['sudo_aws_access.main'].sudo().search(
                [('team_member', '=', rec.current_access_user.id),('role_name', '=', rec.role_name)])
            if access_to_user:
                access_to_user.write({
                    # 'status': 'disable',
                    'team_member': self.requester_user.id,
                })
            rec.approval = 'approve'
            rec.state = 'approve'
        webhook = self.env['cmdb.webhook'].sudo().search([('name', '=', 'slack-approval-notification')])
        cmdb_acces_approval = self.env.ref("sudo_aws_access.sudo_aws_access_approval_access")
        ids_cmdb_user = [usr.partner_id.name for usr in cmdb_acces_approval.users if usr.partner_id.name]
        aprroval_cmdb_user = [usr.partner_id.id for usr in cmdb_acces_approval.users]
        requester_user = self.requester_user.name
        current_access_user_id = self.current_access_user.id

        for rec in webhook:
            if rec.webhook_url:
                web_hook_url = rec.webhook_url
                url = web_hook_url
                webhook = WebhookClient(url)
                webhook_noti_body ="Your Request has been Approved:-%s" % (
                    str(requester_user))
                response = webhook.send(text=webhook_noti_body)
            else:
                pass
        group_user_send = aprroval_cmdb_user
        group_user_send.append(current_access_user_id)
        self.message_post(
            subject="",
            # body='Request Approved',
            body="Your Request Has been Approved:%s" % (
                str(requester_user)),
            message_type='notification',
            partner_ids=group_user_send
        )
        mailqueue = self.env["mail.mail"]
        mailqueue.sudo().process_email_queue()

    def reject_action(self):
        if self.state == 'reject':
            raise UserError(_("Already Rejected!!"))
        else:
            return {
                'name': "Rejection Wizard",
                'type': 'ir.actions.act_window',
                'view_type': 'form',
                'view_mode': 'form',
                'res_model': 'sudo_aws_access.reject.reason',
                'view_id': self.env.ref('sudo_aws_access.sudo_aws_access_reject_reason').id,
                'target': 'new'
            }

    def default_user_ids(self):
        group_user = []
        all_users = self.env['res.users'].search([])
        for rec in all_users:
            if rec.has_group('sudo_aws_access.sudo_aws_access_approval_access'):
                group_user.append(rec.id)
            else:
                continue

        return [('id', 'in', group_user)]


import time
import datetime
import h5py
import os

#Function for serializing the imageBuffer
def serialize(imageBuffer,path,newline):
	#SERIALIZE WITH HDF5
	#Create Unique Trial names
	trial_fn = 'trial: '+ str(newline[0])#+', '+newline[1] #str(datetime.datetime.now())#time.strftime("%Y%m%d-%H%M%S")
	#Checks to see if path directory exists
	if not os.path.isdir(path):
		os.makedirs(path)
	hdfStart = time.time()
	h = h5py.File(os.path.join(path, trial_fn), 'w', libver='latest')
	for i in imageBuffer:
		h.create_dataset(i.title, data=i.img)
	hdfEnd = time.time()
	serialTime = hdfEnd - hdfStart
	# print("Time it took to serialize hdf5: %f ms" % ((serialTime)*1000))
	# print("Image Buffer Length: %d" % len(imageBuffer))
	# print("Image Buffer contains frames from: %d to %d" %(imageBuffer[0].frameNum,imageBuffer[len(imageBuffer) -1].frameNum))
	return serialTime


dict = {'One': 'Один', 'Two': 'Два', 'Three': 'Три', 'Four': 'Четыре'}
lol = open('test4.txt', 'r')
kek = open('done4.txt', 'w')
for line in lol:
    number = line.split(" - ")
    if number[0] in dict:
        word = dict[number[0]]
        kek.write(word + ' - ' + number[1])
lol.close()
kek.close()


# -*- coding: utf-8 -*-

"""
This file has written by Burak Topal and Melih Tolga Şahin.
Theese codes are mainframe of "fidelio project".
In theese codes, we used some third party tools like ffmpeg.
This is an open source project and source can be find at github.

"""
import hashlib
import shutil
import subprocess
import os
import threading

import numpy as np
import scipy.io.wavfile

from PIL import Image

class Fidelio(threading.Thread):
    """
    Core of fidelio project.
    Inherited from threading.Thread and this means this class calling as a thread.
    """
    def __init__(self, file_name, uploaded_file_path):
        threading.Thread.__init__(self)
        self.event = threading.Event()
        self.file_name = file_name
        self.finished = False
        self.samplerate = 0

        self.file_md5_name = self.create_md5('assets/' + file_name)
        # os.mkdir(self.file_md5_name)
        os.makedirs('assets/' + self.file_md5_name)
        self.path = os.path.join(os.path.dirname(__file__), 'assets', self.file_md5_name)

        self.samplerate, self.data = self.convert_to_wav(file_name, uploaded_file_path)

        self.candy_list = []
        self.candy_rainbow_list = []
        self.candy_triple_sort_list = []
        self.candy_reverse_list = []
        self.candy_reverse_dark_list = []
        self.candy_non_sort_list = []
        self.candy_tan_list = []

        self.candy_path = ''
        self.candy_rainbow_path = ''
        self.candy_triple_sort_path = ''
        self.candy_non_sort_path = ''
        self.candy_reverse_path = ''
        self.candy_reverse_dark_path = ''
        self.candy_tan_path = ''
        self.gif_path = ''

    def search(self):
        print('SEARCH BAŞLADI')
        counter = 0

        for row in range(0, 1080):

            y = []
            w = []
            z = []
            q = []

            for col in range(0, 1920):
                y.append([self.data[counter][0], np.sin(self.data[counter][0]), np.cos(self.data[counter][0])])
                z.append(
                    [0 - self.data[counter][0], 0 - np.sin(self.data[counter][0]), 0 - np.cos(self.data[counter][0])])
                w.append([255 - self.data[counter][0], 255 - np.sin(self.data[counter][0]),
                          255 - np.cos(self.data[counter][0])])
                q.append([np.tan(self.data[counter][0]), np.sin(self.data[counter][0]), np.cos(self.data[counter][0])])
                counter += 1

            self.candy_list.append(y)
            self.candy_rainbow_list.append(y)
            self.candy_triple_sort_list.append(y)
            self.candy_non_sort_list.append(y)
            self.candy_reverse_list.append(z)
            self.candy_reverse_dark_list.append(w)
            self.candy_tan_list.append(q)
        print('SEARCH BİTTİ')

    # 1
    def candy(self):

        liste = np.array(self.candy_list)
        liste.sort(axis=0)

        img = Image.fromarray(liste, 'RGB')
        self.candy_path = '/assets/' + self.file_md5_name + '/001.png'
        img.save(self.path + '/001.png')

    # 1
    def candy_rainbow(self):

        liste = np.array(self.candy_rainbow_list)
        liste.sort(axis=0)

        for x in liste:
            x.sort(axis=0)

        img = Image.fromarray(liste, 'RGB')
        self.candy_rainbow_path = '/assets/' + self.file_md5_name + '/002.png'
        img.save(self.path + '/002.png')

    # 1
    def candy_triple_sort(self):

        liste = np.array(self.candy_triple_sort_list)
        liste.sort(axis=0)
        liste = np.sort(liste)

        for z in liste:
            z.argsort(axis=0)

        img = Image.fromarray(liste, 'RGB')
        self.candy_triple_sort_path = '/assets/' + self.file_md5_name + '/003.png'
        img.save(self.path + '/003.png')

    # 1
    def candy_non_sort(self):

        liste = np.array(self.candy_non_sort_list)
        img = Image.fromarray(liste, 'RGB')
        self.candy_non_sort_path = '/assets/' + self.file_md5_name + '/004.png'
        img.save(self.path + '/004.png')

    # 2
    def candy_reverse(self):

        liste = np.array(self.candy_reverse_list)
        liste.sort(axis=0)

        img = Image.fromarray(liste, 'RGB')
        self.candy_reverse_path = '/assets/' + self.file_md5_name + '/005.png'
        img.save(self.path + '/005.png')

    # 3
    def candy_reverse_dark(self):

        liste = np.array(self.candy_reverse_dark_list)
        liste.sort(axis=0)

        img = Image.fromarray(liste, 'RGB')
        self.candy_reverse_dark_path = '/assets/' + self.file_md5_name + '/006.png'
        img.save(self.path + '/006.png')

    # 4
    def candy_tan(self):

        liste = np.array(self.candy_tan_list)
        liste.sort(axis=0)

        img = Image.fromarray(liste, 'RGB')
        self.candy_tan_path = '/assets/' + self.file_md5_name + '/007.png'
        img.save(self.path + '/007.png')

    def make_gif(self):
        a = os.path.join(os.path.dirname('__file__'), 'assets', self.file_md5_name)
        subprocess.call(['ffmpeg', '-framerate', '1/0.5', '-i', '%03d.png', 'output.gif'], cwd=a)
        self.gif_path = a + '/output.gif'

    def create_md5(self, fname):
        hash_md5 = hashlib.md5()
        with open(fname, "rb") as f:
            for chunk in iter(lambda: f.read(4096), b""):
                hash_md5.update(chunk)
        return hash_md5.hexdigest()

    def convert_to_wav(self, file_name, uploaded_file_path):
        path = os.path.join(os.path.dirname(__file__), uploaded_file_path)

        subprocess.call(['ffmpeg', '-i', path + '/' + file_name, '-acodec', 'pcm_u8', '-ar', '44100',
                         self.file_md5_name + '.wav'], cwd=self.path)

        new_path = os.path.join(os.path.dirname(__file__), 'assets', self.file_md5_name, self.file_md5_name + '.wav')

        samplerate, data = scipy.io.wavfile.read(new_path)
        self.samplerate = samplerate
        os.remove(new_path)

        return samplerate, data

    def get_images(self):
        images = [self.candy_path,
                  self.candy_rainbow_path,
                  self.candy_triple_sort_path,
                  self.candy_non_sort_path,
                  self.candy_reverse_path,
                  self.candy_reverse_dark_path,
                  self.candy_tan_path]
        return images

    def run(self):
        print('FİDELİO RUN')
        self.search()
        self.candy()
        self.candy_tan()
        self.candy_rainbow()
        self.candy_triple_sort()
        self.candy_reverse()
        self.candy_reverse_dark()
        self.candy_non_sort()
        self.make_gif()
        self.finished = True


agents = ['skye','may','fitz','simmons','caulson',\
          'hunter', 'mack', 'morse', 'triplett', \
          'hartley', 'deathlok', 'koenig', \
          'gonzales', 'fury']

#finished = False
#while not finished:            #while finish = False,execute the loop, so "not finished" = True
    #print "Hello"
    #finisished = True

#i = 0
#while i < 1:
    #cmd = raw_input("Enter an index between 0-%d => " %(len(agents)-1))         #This will keep asking the raw_input until the user enters "Stop"
    #if cmd == 'Stop':
        #i = 1
    #else:
        #idx = int(cmd)
        #print agents[idx].capitalize()

#IMPORTANT FOR HOMEWORK 3 PART 2
#def arrange_value(mylist):
    #mylist.sort()
#myvals = [ ]
#finished = False                                                    #Putting raw_inputs together in a list
#while not finished:
    #newval = raw_input("Enter a value (stop to end) => ")
    #if newval == 'stop':
        #finished = True
    #else:
        #myvals.append(newval)
        #arrange_value(myvals)
        #print myvals

#WRITE A FUNCTION TO CAPITALIZE ALL THE NAMES IN THE LIST AGENTS,THEN LIST THE AGENTS
#def capitalize_list(list):
    #i = 0
    #while i < len(list):
        #list[i] = list[i].capitalize()
        #i += 1
        #return list

#print capitalize_list(agents)

#FOR LOOPS
#animals = ['cat','dog','rabbit','fish','python']
#for a in animals:
    #a = a.capitalize()
    #print a

#print animals

#FOR LOOPS:LIST IN A LIST
#values = [ [1,2],[3,4] ]         #For this, 100 would be added to both lists within value instead of another list being created
#for a in values:
    #a.append(100)
    #print a

#print values


from django.shortcuts import render
from django.http import HttpResponseRedirect
from .forms import HommeForm
from . import models

# Create your views here.

def dateAjoute(request, id):         # pour afficher les nouveaux ajouts utilisateurs dans la base de données
    date = models.Homme.objects.get( pk = id)
    return render(request, "homme/dateAjoute.html", {"date": date})   # où traitement ==> "affiche(.html)" ==> (dateAjoute)

def update(request, id):
    datei = models.Homme.objects.get(pk=id)
    form = HommeForm(datei.dico())
    return render(request,"homme/ajout.html",{"form":form, "id": id})

def updatetraitement(request, id):
    hommeform = HommeForm(request.POST)
    if hommeform.is_valid():
        homme = hommeform.save(commit = False)
        homme.id = id
        homme.save()
        return HttpResponseRedirect("/antiquite/")
    else:
        return render(request, "homme/ajout.html", {"form": hommeform, "id": id})

def delete(request, id):
    datei = models.Homme.objects.get(pk=id)
    datei.delete()
    return HttpResponseRedirect("/antiquite/")

def ajout(request):
    if request.method == "POST":
        form = HommeForm(request)
        return render(request, "homme/ajout.html", {"form" : form})
    else:
        form = HommeForm()
        id = ""
        return render(request, "homme/ajout.html", {"form": form, "id": id})

def traitement(request):
    hommeform = HommeForm(request.POST)
    if hommeform.is_valid():
        homme = hommeform.save()
        return HttpResponseRedirect("/antiquite/")
    else:
        return render(request, "homme/ajout.html", {"form": hommeform})