import json
import os
import pickle
import random
from typing import Union

import numpy as np
import pandas as pd
import torch
from rdkit import RDLogger
from rdkit.Chem.Scaffolds import MurckoScaffold
from yaml import load, Loader, dump

from benchmark import moleculenet_reg, moleculenet_cls
from benchmark.const import Descriptors, DATA_PATH, CONFIG_PATH_SMILES, CONFIG_PATH

def generate_scaffold(smiles, include_chirality=False):
    """
    Obtain Bemis-Murcko scaffold from smiles
    Args:
        smiles: smiles sequence
        include_chirality: Default=False

    Return:
        the scaffold of the given smiles.
    """
    scaffold = MurckoScaffold.MurckoScaffoldSmiles(smiles=smiles, includeChirality=include_chirality)
    return scaffold

def split(dataset, frac_train=0.8, frac_valid=0.1):
    """
    Args:
        dataset(pandas.DataFrame): the dataset to split. Make sure each element in
            the dataset has key "smiles" which will be used to calculate the
            scaffold.
        frac_train(float): the fraction of data to be used for the train split.
        frac_valid(float): the fraction of data to be used for the valid split.
    """
    RDLogger.DisableLog('rdApp.*')  # turn off warning from rdkit
    N = len(dataset)

    # create dict of the form {scaffold_i: [idx1, idx....]}
    all_scaffolds = {}
    for i in range(N):
        try:
            scaffold = generate_scaffold(dataset['smiles'][i], include_chirality=True)
        except ValueError:  # not chemically reasonable smiles
            continue
        if scaffold not in all_scaffolds:
            all_scaffolds[scaffold] = [i]
        else:
            all_scaffolds[scaffold].append(i)

    # sort from largest to smallest sets
    all_scaffolds = {key: sorted(value) for key, value in all_scaffolds.items()}
    all_scaffold_sets = [scaffold_set for (scaffold, scaffold_set) in sorted(all_scaffolds.items(), key=lambda x: (len(x[1]), x[1][0]), reverse=True)]

    # get train, valid test indices
    train_cutoff = frac_train * N
    valid_cutoff = (frac_train + frac_valid) * N
    train_idx, valid_idx, test_idx = [], [], []
    for scaffold_set in all_scaffold_sets:
        if len(train_idx) + len(scaffold_set) > train_cutoff:
            if len(train_idx) + len(valid_idx) + len(scaffold_set) > valid_cutoff:
                test_idx.extend(scaffold_set)
            else:
                valid_idx.extend(scaffold_set)
        else:
            train_idx.extend(scaffold_set)

    assert len(set(train_idx).intersection(set(valid_idx))) == 0
    assert len(set(test_idx).intersection(set(valid_idx))) == 0

    # get train, valid test indices
    train_cutoff = frac_train * N
    valid_cutoff = (frac_train + frac_valid) * N
    train_idx, valid_idx, test_idx = [], [], []
    for scaffold_set in all_scaffold_sets:
        if len(train_idx) + len(scaffold_set) > train_cutoff:
            if len(train_idx) + len(valid_idx) + len(scaffold_set) > valid_cutoff:
                test_idx.extend(scaffold_set)
            else:
                valid_idx.extend(scaffold_set)
        else:
            train_idx.extend(scaffold_set)

    assert len(set(train_idx).intersection(set(valid_idx))) == 0
    assert len(set(test_idx).intersection(set(valid_idx))) == 0
    return train_idx, valid_idx, test_idx

class UnlabeledData:
    def __init__(self, file: str, size_limit: int, logp: bool = False):
        if os.path.exists(f"{file}.pt"):
            self.x, self.y = torch.load(f"{file}.pt")
            if size_limit > 0:
                self.x, self.y = self.x[:size_limit], self.y[:size_limit]
        else:
            df = pd.read_csv(f"{file}.csv")
            self.smiles = df['smiles']
            self.y = df['logP'] if logp else []
            if size_limit > 0: self.smiles = self.smiles[:size_limit]  # control the number of unlabeled data

            from benchmark.featurization import Featurizer  # do not move
            self.featurizer = Featurizer()
            self.x = None
            self.save_path = f"{file}.pt"

    def featurize_data(self, descriptor: Descriptors, **kwargs):
        self.x = self.featurizer(descriptor, smiles=self.smiles, **kwargs)

    def __call__(self, descriptor: Descriptors, save_mode=True, **kwargs):
        self.featurize_data(descriptor, **kwargs)
        if save_mode:
            torch.save([self.x, self.y], self.save_path)

class LabeledData:
    def __init__(self, file: Union[str, pd.DataFrame]):
        # Either load a .csv file or use a provided dataframe
        if type(file) is str:
            df = pd.read_csv(os.path.join(DATA_PATH, f"{file}.csv"))
        else:
            df = file

        if file == 'freesolv':
            df = df.rename(columns={'expt': 'y'})
        elif file == 'esol':
            df = df.rename(columns={'measured log solubility in mols per litre': 'y'})
        elif file == 'lipo':
            df = df.rename(columns={'exp': 'y'})
        elif file == 'bbbp':
            df = df.rename(columns={'p_np': 'y'})
        elif file == 'bace':
            df = df.rename(columns={'Class': 'y', 'mol': 'smiles'})
        elif file == 'tox21':
            df = df.drop(columns=['mol_id'])
            df = df.fillna(0.5)  # convert nan to 0.5
            cols = df.columns.tolist()
            df = df[cols[-1:] + cols[:-1]]  # reorder the columns
        elif file == 'toxcast':
            df = df.fillna(0.5)
        elif file == 'logp':
            df = df.rename(columns={'logp': 'y'})

        if 'y' in df:
            df['y'] = df['y'].astype('float')

        self.smiles_val, self.y_val = None, None
        if file in moleculenet_reg + moleculenet_cls + ['logp']:
            _split = [''] * len(df)
            train_idx, valid_idx, test_idx = split(df, frac_train=0.01 if file == 'logp' else 0.8)

            for i in train_idx:
                _split[i] = 'train'
            for i in valid_idx:
                _split[i] = 'val'
            for i in test_idx:
                _split[i] = 'test'
            df['split'] = _split
            self.smiles_val = df[df['split'] == 'val']['smiles'].tolist()
            if 'y' in df:
                self.y_val = df[df['split'] == 'val']['y'].tolist()
            else:
                y_val = df[df['split'] == 'val']
                self.y_val = [y_val.iloc[i, 1:-1].astype('float').tolist() for i in range(len(y_val))]
            assert len(self.y_val) != 0

        self.smiles_train = df[df['split'] == 'train']['smiles'].tolist()
        self.smiles_test = df[df['split'] == 'test']['smiles'].tolist()

        if 'y' in df:
            self.y_train = df[df['split'] == 'train']['y'].tolist()
            self.y_test = df[df['split'] == 'test']['y'].tolist()
        else:
            y_train = df[df['split'] == 'train']
            y_test = df[df['split'] == 'test']
            self.y_train = [y_train.iloc[i, 1:-1].astype('float').tolist() for i in range(len(y_train))]
            self.y_test = [y_test.iloc[i, 1:-1].astype('float').tolist() for i in range(len(y_test))]

        from benchmark.featurization import Featurizer  # do not move

        self.featurizer = Featurizer()
        self.x_train, self.x_test, self.x_val = None, None, None
        self.mean, self.mad = 0.0, 1.0
        self.augmented = 0

    def featurize_data(self, descriptor: Descriptors, **kwargs):
        self.x_train = self.featurizer(descriptor, smiles=self.smiles_train, **kwargs)
        self.x_test = self.featurizer(descriptor, smiles=self.smiles_test, **kwargs)

        self.y_train = [self.y_train[i] for i, g in enumerate(self.x_train) if g is not None]
        self.x_train = [g for g in self.x_train if g is not None]
        self.y_test = [self.y_test[i] for i, g in enumerate(self.x_test) if g is not None]
        self.x_test = [g for g in self.x_test if g is not None]
        if self.smiles_val is not None:
            self.x_val = self.featurizer(descriptor, smiles=self.smiles_val, **kwargs)
            self.y_val = [self.y_val[i] for i, g in enumerate(self.x_val) if g is not None]
            self.x_val = [g for g in self.x_val if g is not None]

    def shuffle(self):
        """ Shuffle training data """
        c = list(zip(self.smiles_train, self.y_train))        # Shuffle all lists together
        random.shuffle(c)
        self.smiles_train, self.y_train = zip(*c)
        self.smiles_train, self.y_train = list(self.smiles_train), list(self.y_train)

    def compute_mean_mad(self):
        """ Normalize the label to prevent training instability. """
        mean = sum(self.y_train) / len(self.y_train)
        ma = [abs(i - self.mean) for i in self.y_train]
        mad = sum(ma) / len(ma)
        self.mean, self.mad = mean, mad

    def __call__(self, descriptor: Descriptors, **kwargs):
        self.featurize_data(descriptor, **kwargs)

    def __repr__(self):
        return f"{len(self.y_train)} train/{len(self.y_test)} test"

def load_model(filename: str):
    """ Load a algorithm """
    if filename.endswith('.h5'):
        raise ValueError('The algorithm weight is Tensorflow-based')
    else:
        with open(filename, 'rb') as handle:
            model = pickle.load(handle)
    return model

def get_config(file: str):
    """ Load a yml config file"""
    if file.endswith('.yml') or file.endswith('.yaml'):
        with open(file, "r", encoding="utf-8") as read_file:
            config = load(read_file, Loader=Loader)
    if file.endswith('.json'):
        with open(file, 'r') as f:
            config = json.load(f)
    return config

def write_config(filename: str, args: dict):
    """ Write a dictionary to a .yml file"""
    args = {k: v.item() if isinstance(v, np.generic) else v for k, v in args.items()}
    with open(filename, 'w') as file:
        dump(args, file)

def get_benchmark_config(dataset: str, algorithm, descriptor):
    from models import GCN, MPNN, GAT, GIN
    list_of_algos = [GCN, MPNN, GAT, GIN]

    # Descriptor
    if type(descriptor) is not str:
        if not descriptor in [i for i in Descriptors]:
            raise ValueError(f"Chosen descriptor is not supported, please pick from: {[i.__str__() for i in Descriptors]}")
        descriptor = descriptor.name
    else:
        if not descriptor in [i.name for i in Descriptors]:
            raise ValueError(f"Chosen descriptor is not supported, please pick from: {[i.name for i in Descriptors]}")

    # Algorithm
    if type(algorithm) is not str:
        if algorithm not in list_of_algos:
            raise ValueError(f"Chosen algorithm is not supported, please pick from: {list_of_algos}")
        algorithm = algorithm.__name__
    else:
        if algorithm not in [i.__name__ for i in list_of_algos]:
            raise ValueError(f"Chosen algorithm is not supported, please pick from: {[i.__name__ for i in list_of_algos]}")

    combinations = {'ECFP': ['RF', 'SVM', 'GBM', 'KNN', 'MLP'], 'MACCS': ['RF', 'SVM', 'GBM', 'KNN'], 'PHYSCHEM': ['RF', 'SVM', 'GBM', 'KNN'], 'WHIM': ['RF', 'SVM', 'GBM', 'KNN'],
                    'GRAPH': ['GIN', 'GCN', 'MPNN', 'GAT', 'XGIN'], 'TOKENS': ['Transformer'], 'SMILES': ['CNN']}

    if algorithm not in combinations[descriptor]:
        raise ValueError(f'Given combination of descriptor and algorithm is not supported. Pick from: {combinations}')

    config_path = os.path.join(CONFIG_PATH, 'benchmark', dataset, f"{algorithm}_{descriptor}.yml")
    hyperparameters = get_config(config_path)

    return hyperparameters

def calc_rmse(true, pred):
    # Convert to 1-D numpy array if it's not
    if type(pred) is not np.array:
        pred = np.array(pred)
    if type(true) is not np.array:
        true = np.array(true)

    return np.sqrt(np.mean(np.square(true - pred)))

smiles_encoding = get_config(CONFIG_PATH_SMILES)


#
# Usage :
#   OS> <source osc_vis setup>
#   OS> <setup python>
#   OS> <source osc_vis python setup>
#   OS> <start python>
#   >>> import aida_6
#

#
# Plotters.
#

#////////////////////////////////////////
#////////////////////////////////////////
#////////////////////////////////////////
import random
import math

M_PI_2 = math.pi / 2.0
r = random.Random()

def rbw(aMean,aGamma):
  rval = 2.0 * r.random() - 1.0
  displ = 0.5 * aGamma * math.tan(rval * M_PI_2)
  return aMean + displ

#////////////////////////////////////////
#////////////////////////////////////////
#////////////////////////////////////////

import AIDA

import random

aida = AIDA.createAnalysisFactory()
tf = aida.createTreeFactory()
tree = tf.create()
del tf

histogramFactory = aida.createHistogramFactory(tree)
h = histogramFactory.createHistogram1D('h','Rand gauss',100,-5,5)
r = random.Random()
for I in range(0,10000):
  h.fill(r.gauss(0,1),1)

hbw = histogramFactory.createHistogram1D('h','Rand Breit Wigner',100,-5,5)
del histogramFactory
for I in range(0,10000):
  hbw.fill(rbw(0,1),1)

plotterFactory = aida.createPlotterFactory()
plotter = plotterFactory.create('')
del plotterFactory
plotter.createRegions(2,1,0)
plotter.setTitle('Two plotters')
plotter.currentRegion().plot(h)
plotter.next().plot(h)
# paper output :
plotter.show()

print('After exiting the GUI, ps and gif files are going to be produced.')
plotter.interact()

plotter.writeToFile('aida_6.ps')
plotter.writeToFile('aida_6.gif')

del plotter

del hbw
del h
del r
del tree
del aida


import numpy as np
from scipy.optimize import minimize
from scipy.optimize import NonlinearConstraint

def get_data():
    data = []
    with open("iris.data", "r") as file:
        for line in file.readlines():
            splitted_line = line.split(",")
            if len(splitted_line) == 5:
                data.append([list(map(float, splitted_line[:4])), encode(splitted_line[4][:-1])])
        return data

def encode(name):
    if name == 'Iris-setosa':
        return [1, -1, -1]
    elif name == 'Iris-versicolor':
        return [-1, 1, -1]
    elif name == 'Iris-virginica':
        return [-1, -1, 1]
    else:
        raise Exception("Encoding error")

def create_train_test_sets(train_test_ratio, data):
    np.random.shuffle(data)
    train_set_size = int(train_test_ratio * len(data))
    test_set_size = len(data) - train_set_size
    train_set = data[:train_set_size]
    test_set = data[-test_set_size:]
    return train_set, test_set

def split_data(data):
    class1 = []
    class2 = []
    class3 = []
    for row in data:
        if row[1][0] == 1:
            class1.append(row)
        elif row[1][1] == 1:
            class2.append(row)
        elif row[1][2] == 1:
            class3.append(row)
        else:
            raise Exception("https://tenor.com/view/thanos-impossible-marvel-shocked-gif-15104180")
    return class1, class2, class3

def make_2D_set(feature1, feature2, index, data):
    data_set = np.array([[row[0][feature1], row[0][feature2], row[1][index]] for row in data])
    return data_set

def make_4D_set(index, data):
    data_set = np.array([[row[0][0], row[0][1], row[0][2], row[0][3], row[1][index]] for row in data])
    return data_set

def linear_SVM(train_set):
    global TRAIN_SET
    global RECORD_SIZE
    global LAMBDA
    LAMBDA = 0.5
    TRAIN_SET = train_set
    a = TRAIN_SET[:, :4]
    constraint = NonlinearConstraint(constr, 0, np.inf)
    res = minimize(target, np.random.random(5), constraints=constraint)
    w = res.x[:4]
    b = res.x[4]
    return w, b

def target(w):
    return LAMBDA * np.linalg.norm(w[:4], 2) + ksi(w).sum()

def ksi(w):
    return np.maximum(0, 1 - ((np.matmul(TRAIN_SET[:, :4], w[:4]) - w[4]) * TRAIN_SET[:, 4]))

def f(x, w, b):
    return np.matmul(np.transpose(w), x) - b

def constr(w):
    return ((np.matmul(TRAIN_SET[:, :4], w[:4]) - w[4]) * TRAIN_SET[:, 4]) + ksi(w) - 1

def threshold_unipolar_function(x, a):
    if (x >= a):
        return 1
    elif (x < a):
        return -1

def predict(x, w_12, w_23, w_31, b_12, b_23, b_31):
    x_lpredict = [threshold_unipolar_function(np.matmul(w_12, x) - b_12, 0),
                  threshold_unipolar_function(np.matmul(w_23, x) - b_23, 0),
                  threshold_unipolar_function(np.matmul(w_31, x) - b_31, 0)]
    if (x_lpredict[2] == -1) and (x_lpredict[0] == 1):
        return [1, -1, -1]
    if (x_lpredict[0] == -1) and (x_lpredict[1] == 1):
        return [-1, 1, -1]
    if (x_lpredict[1] == -1) and (x_lpredict[2] == 1):
        return [-1, -1, 1]

if __name__ == "__main__":
    data = get_data()
    train_set, test_set = create_train_test_sets(0.9, data)
    set1, set2, set3 = split_data(train_set)
    w_12, b_12 = linear_SVM(make_4D_set(0, set1 + set2))
    print(w_12)
    print(b_12)
    """
    w_23, b_23 = linear_SVM(make_4D_set(1, set2 + set3))
    w_31, b_31 = linear_SVM(make_4D_set(2, set3 + set1))

    tset1, tset2, tset3 = split_data(test_set)
    errors1 = 0
    errors2 = 0
    errors3 = 0

    for row in tset1:
        if (predict(row[0], w_12, w_23, w_31, b_12, b_23, b_31) != [1, -1, -1]):
            errors1 += 1
    print(f"Class Iris-setosa: accuracy {(1 - errors1/len(tset1))*100:.2f}%")

    for row in tset2:
        if (predict(row[0], w_12, w_23, w_31, b_12, b_23, b_31) != [-1, 1, -1]):
            errors2 += 1
    print(f"Class Iris-versicolor: accuracy {(1 - errors2/len(tset2))*100:.2f}%")

    for row in tset3:
        if (predict(row[0], w_12, w_23, w_31, b_12, b_23, b_31) != [-1, -1, 1]):
            errors3 += 1
    print(f"Class Iris-virginica: accuracy {(1 - errors3/len(tset3))*100:.2f}%")
    print(f"Total accuracy {(1 - (errors1 + errors2 + errors3)/(len(tset1) + len(tset2) + len(tset3)))*100:.2f}%")
    """


import time

from tkinter import *
from tools.williams import williams
from tkinter import messagebox as mb

# Tkinter interface
class MainForm(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.frame = Frame(self, bg='#fafafa')
        self.parent = parent
        self.parent.resizable(width=False, height=False)

        self.window_w = 500
        self.window_h = 350

        self.centerWindow()
        self.initUI()
        self.showUI()

    def initUI(self):
        self.parent.title('Williams P+1')
        self.parent['bg'] = '#fafafa'

        self.frame = Frame(self.parent, bg='#fafafa')

        # Field N
        self.label_n = Label(self.frame, text='Entry N:', bg='#fafafa', font=20)
        self.entry_n = Entry(self.frame, width=40, justify='center')

        # Field B
        self.label_b = Label(self.frame, text='Entry B:', bg='#fafafa', font=20)
        self.entry_b = Entry(self.frame, width=40, justify='center')

        # Field P
        self.label_p = Label(self.frame, text='Entry P:', bg='#fafafa', font=20)
        self.entry_p = Entry(self.frame, width=40, justify='center')

        # Field Q next
        self.label_q = Label(self.frame, text='Entry Q:', bg='#fafafa', font=20)
        self.entry_q = Entry(self.frame, width=40, justify='center')

        # Field button
        self.btn_factorize = Button(self.frame, text='Factorization', bg='gray', command=self.button_click)

        # Field Result
        self.result = Text(self.frame)

    def showUI(self):
        self.frame.place(relx=0, rely=0, relwidth=1, relheight=1)

        # Field N
        self.label_n.place(x=20, y=20)
        self.entry_n.place(x=120, y=24)
        self.entry_n.insert(0, 4056187)

        # Field B
        self.label_b.place(x=20, y=60)
        self.entry_b.place(x=120, y=64)
        self.entry_b.insert(0, 5)

        # Field P
        self.label_p.place(x=20, y=100)
        self.entry_p.place(x=120, y=104)
        self.entry_p.insert(0, 1)

        # Field Q
        self.label_q.place(x=20, y=140)
        self.entry_q.place(x=120, y=144)
        self.entry_q.insert(0, 5)

        # Field button
        self.btn_factorize.place(x=380, y=25, width=110, height=60)

        # Field Result
        self.result.place(x=20, y=180, width=460, height=150)

    def button_click(self):
        try:
            n = int(self.entry_n.get())
            B = int(self.entry_b.get())
            P = int(self.entry_p.get())
            Q = int(self.entry_q.get())
        except ValueError:
            mb.showerror("Error", 'Please enter an integers!')
            return

        if B > 12:
            mb.showerror("Warning", 'Recommendation value B not more 11!')
            return

        start_time = time.time()
        res = williams(n, B, P, Q)
        stop_time = time.time()
        self.result.delete(1.0, END)

        if res == n:
            txt = 'Failed attempt.\nTry other parameter A.'
        elif res != -1:
            txt = f"Factorization:\n{n} = {res} * {n // res}\n" \
                  f"\nTime working - {stop_time - start_time} seconds"
        else:
            txt = 'Failed attempt.\nTry increasing parameter B.'

        self.result.insert(1.0, txt)

    # Centring window
    def centerWindow(self):
        sw = self.parent.winfo_screenwidth()
        sh = self.parent.winfo_screenheight()

        x = (sw - self.window_w) / 2
        y = (sh - self.window_h) / 2
        self.parent.geometry('%dx%d+%d+%d' % (self.window_w, self.window_h, x, y))


from InterfaceTest.common.configEmail import sendMail
from InterfaceTest.util.util import runTest

def main():
    errorTest = runTest('../testFile/test.xlsx')
    if len(errorTest) > 0:
        html = '接口自动化定期扫描，共有 ' + str(len(
            errorTest)) + ' 个异常接口，列表如下：' + '

接口	状态	接口地址	接口返回值
'
        for test in errorTest:
            html = html + '
' + test.api_purpose + '	' + str(test.status_code) + '	' + test.request_url + '	' + test.text + '
'
        html = html + '
'

        sendMail(html)

main()


from parse import parse_sam
from Bio.SeqIO.QualityIO import FastqGeneralIterator
import os

class Cleaner():

    def __init__(self, reference='', paired_1='', paired_2='', output_path="", cores=8):
        self.reference = reference
        self.paired_1 = paired_1
        self.paired_2 = paired_2
        self.output_path = output_path
        self.cores = cores
        self.bowtie_out_file = self.output_path+'/bowtie.gg.sam'
        self.best_hit_file = self.output_path+'/bowtie.gg.sam.bh'

    def call_bowtie(self):
        # assumes bowtie is installed in your machine
        cmd=" ".join([
            'bowtie2',
            '--fast-local --no-discordant -p ', str(self.cores),
            ' --no-unal --no-hd --no-sq -x ', self.reference,
            '-1', self.paired_1,
            '-2', self.paired_2,
            '-S', self.bowtie_out_file, '>>', self.bowtie_out_file+'.log', '2>&1'
        ])
        os.system(cmd)
        parse_sam(fi = self.bowtie_out_file, fox = self.best_hit_file)
        listf = {i.split()[0]:True for i in open(self.best_hit_file)}
        return listf

    def retrive(self, fi='', listf={}):
        fo = open(fi+".no-chl.fastq", "w")
        for _id,seq,qual in FastqGeneralIterator(open(fi)):
            header = _id.split(' ')[0]
            read = '@%s\n%s\n+\n%s' %(_id, seq, qual)
            try:
                listf[header]
            except Exception as e:
                fo.write(read+"\n")

    def process(self):
        self.call_bowtie()
        listf = self.call_bowtie()
        self.retrive(fi = self.paired_1, listf=listf)
        self.retrive(fi = self.paired_2, listf=listf)


import time
import os
from windowcapture import WindowCapture
import pyautogui
import cv2
import pytesseract
import numpy as np
import sys
sys.path.append("C:\\Users\\joshu\\OneDrive - Georgia Institute of Technology\\ReinforecementLearningPlayground\\")
from HelperFunctions import LoadX360CE, KeyboardRelay, DataUtil, Network
from Spaces import discrete

pytesseract.pytesseract.tesseract_cmd = 'C://Program Files//Tesseract-OCR//tesseract.exe'
custom_config = '--psm 10 --oem 3 -c tessedit_char_whitelist=0123456789'

class BorderlandsScienceEnvironment:
	def __init__(self, windowName, testing=False):
		self.windowCapture = WindowCapture(windowName=windowName)
		self.InitialFrame = None
		self.Keyboard = KeyboardRelay.KeyboardRelay()
		self.CurrentFrame = None
		self.CurrentScore = None
		self.PreviousScore = None
		self.CurrentTextAreas = None
		self.TargetTextAreas = None
		self.HighTextAreas = None
		self.TargetScore = None
		self.HighScore = None
		self.CurrentStep = None
		self.MaxSteps = None
		self.Testing = testing
		self.action_space = discrete.Discrete(6)

		# self.currentState = None
		# self.currentReward = None
		self.isDone = False
		self.Templates = None
		self.FrameBoundaries = None
		self.Bonus = None
		self.Setup()

	def Setup(self):
		if self.InitialFrame is None:
			if self.Testing:
				self.InitialFrame = cv2.blur(cv2.cvtColor(cv2.imread("temp.png"), cv2.COLOR_BGR2GRAY), (3, 3))
				self.CurrentFrame = cv2.blur(cv2.cvtColor(cv2.imread("temp.png"), cv2.COLOR_BGR2GRAY), (3, 3))
			else:
				self.InitialFrame = cv2.blur(self.windowCapture.getNextFrame(), (3, 3))
				self.CurrentFrame = cv2.blur(self.windowCapture.getNextFrame(), (3, 3))
		# self.InitialFrame = self.windowCapture.getNextFrame()
		self.Bonus = False, 100
		self.CurrentTextAreas = np.zeros(shape=(10, 1))
		self.TargetTextAreas = np.zeros(shape=(10, 1))
		self.HighTextAreas = np.zeros(shape=(10, 1))
		self.LoadTemplates()
		self.FrameBoundaries = self.EstablishFrameBoundaries()
		self.PopulateAreaMapping()
		self.CurrentStep = 0
		self.MaxSteps = 100
		return

	def PopulateAreaMapping(self):
		for i in range(1, 10):
			currentImage = cv2.imread(f"./Data/Templates/Current_{i}.png", 0)
			currentContours, _ = cv2.findContours(currentImage, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
			currentArea = np.round(cv2.contourArea(currentContours[0]), 1)
			self.CurrentTextAreas[i, 0] = currentArea

			targetImage = cv2.imread(f"./Data/Templates/Target_{i}.png", 0)
			targetContours, _ = cv2.findContours(targetImage, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
			targetArea = np.round(cv2.contourArea(targetContours[0]), 1)
			self.TargetTextAreas[i, 0] = targetArea

			highImage = cv2.imread(f"./Data/Templates/High_{i}.png", 0)
			highContours, _ = cv2.findContours(highImage, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
			highArea = np.round(cv2.contourArea(highContours[0]), 1)
			self.HighTextAreas[i, 0] = highArea
		print("Templates Loaded")
		return

	def EstablishFrameBoundaries(self):
		rowStart = self.Templates["Target Score Template"]["Cords"][0][0] - self.Templates["Target Score Template"][
			"Height"]
		rowEnd = self.InitialFrame.shape[0] - self.Templates["Target Score Template"]["Height"]

		colStart = self.Templates["Target Score Template"]["Cords"][0][1] - self.Templates["Target Score Template"][
			"Width"]
		colEnd = self.Templates["High Score Template"]["Cords"][1][1] + self.Templates["Target Score Template"]["Width"]
		return rowStart, rowEnd, colStart, colEnd

	def LoadTemplates(self):
		originalDimensions = (1056, 1936)
		# Load Current Score Template
		currentScoreTemplate = cv2.imread("./Data/Templates/currentScore.png", 0)

		# Load Target Score Template
		targetScoreTemplate = cv2.imread("./Data/Templates/targetScore.png.", 0)

		# Load High Score Template
		highScoreTemplate = cv2.imread("./Data/Templates/highScore.png", 0)

		if originalDimensions != self.InitialFrame.shape[:2]:
			xScale = self.InitialFrame.shape[0] / originalDimensions[0]
			yScale = self.InitialFrame.shape[1] / originalDimensions[1]
			currentScoreTemplate = cv2.resize(currentScoreTemplate, None, fx=xScale, fy=yScale,
			                                  interpolation=cv2.INTER_CUBIC)
			targetScoreTemplate = cv2.resize(targetScoreTemplate, None, fx=xScale, fy=yScale,
			                                 interpolation=cv2.INTER_CUBIC)
			highScoreTemplate = cv2.resize(highScoreTemplate, None, fx=xScale, fy=yScale,
			                               interpolation=cv2.INTER_CUBIC)

		templates = {"Current Score Template": {"Image": currentScoreTemplate},
		             "Target Score Template": {"Image": targetScoreTemplate},
		             "High Score Template": {"Image": highScoreTemplate}}

		for i in ["Current Score Template", "Target Score Template", "High Score Template"]:
			# Store width and height of template in w and h
			w, h = templates[i]["Image"].shape[::-1]
			templates[i]["Width"] = w
			templates[i]["Height"] = h
			# Perform match operations.
			res = cv2.matchTemplate(self.InitialFrame, templates[i]["Image"], cv2.TM_CCOEFF_NORMED)

			# Specify a threshold
			threshold = 0.75

			# Store the coordinates of matched area in a numpy array
			loc = np.where(res >= threshold)
			pt1 = loc[0][0], loc[1][0]
			pt2 = (pt1[0] + h, pt1[1] + w,)
			templates[i]["Cords"] = pt1, pt2

		self.Templates = templates

	def areaToScore(self, areas, whichToUse="Current"):
		resultString = ""
		if whichToUse == "Current":
			currentDict = self.CurrentTextAreas
		elif whichToUse == "Target":
			currentDict = self.TargetTextAreas
		elif whichToUse == "High":
			currentDict = self.HighTextAreas

		for i in areas:
			resultString += str(np.argmin(np.abs(currentDict - i)))

		return int(resultString)

	def getCropFromTemplate(self, template):
		pt1, pt2 = template["Cords"]
		return pt2[0], pt2[0] + int(template["Height"] * 2.5), pt1[1], pt2[1]

	def thresholdImage(self, image):
		image[image < 70] = 0
		image[image >= 70] = 255
		return image

	def getCurrentScore(self):
		try:
			if self.PreviousScore is None:
				self.PreviousScore = self.CurrentScore
			rowStart, rowEnd, columnStart, columnEnd = self.getCropFromTemplate(
				self.Templates["Current Score Template"])
			croppedScore = self.CurrentFrame[rowStart:rowEnd, columnStart:columnEnd]
			croppedScore = self.thresholdImage(croppedScore)
			contours, hierarchy = cv2.findContours(croppedScore, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
			areas = [np.round(cv2.contourArea(i), 1) for i in contours[::-1]]
			return self.areaToScore(areas, whichToUse="Current")
		except Exception as _exception:
			exc_type, exc_obj, exc_tb = sys.exc_info()
			fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
			print(exc_type, fname, exc_tb.tb_lineno)
			print(f"Exception in ''", _exception)

	def getTargetScore(self):
		try:
			rowStart, rowEnd, columnStart, columnEnd = self.getCropFromTemplate(self.Templates["Target Score Template"])
			croppedScore = self.CurrentFrame[rowStart:rowEnd, columnStart:columnEnd]
			croppedScore = self.thresholdImage(croppedScore)
			contours, hierarchy = cv2.findContours(croppedScore, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
			areas = [np.round(cv2.contourArea(i), 1) for i in contours[::-1]]
			return self.areaToScore(areas, whichToUse="Target")
		except Exception as _exception:
			exc_type, exc_obj, exc_tb = sys.exc_info()
			fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
			print(exc_type, fname, exc_tb.tb_lineno)
			print(f"Exception in ''", _exception)

	def getHighScore(self):
		try:
			rowStart, rowEnd, columnStart, columnEnd = self.getCropFromTemplate(self.Templates["High Score Template"])
			croppedScore = self.CurrentFrame[rowStart:rowEnd, columnStart:columnEnd]
			croppedScore = self.thresholdImage(croppedScore)
			contours, hierarchy = cv2.findContours(croppedScore, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
			areas = [np.round(cv2.contourArea(i), 1) for i in contours[::-1]]
			return self.areaToScore(areas, whichToUse="High")
		except Exception as _exception:
			exc_type, exc_obj, exc_tb = sys.exc_info()
			fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
			print(exc_type, fname, exc_tb.tb_lineno)
			print(f"Exception in ''", _exception)

	def getState(self):
		self.CurrentScore = self.getCurrentScore()
		self.TargetScore = self.getTargetScore()
		self.HighScore = self.getHighScore()

		return self.CurrentFrame[self.FrameBoundaries[0]:self.FrameBoundaries[1], self.FrameBoundaries[2]:self.FrameBoundaries[3]]

	def getReward(self):
		return self.CurrentScore - self.PreviousScore

	def getProgress(self):
		if self.CurrentScore >= self.HighScore and self.CurrentStep > self.MaxSteps:
			self.Bonus[0] = True
			return True
		elif self.CurrentStep > self.MaxSteps:
			return True

	def step(self, action):
		# Execute action
		self.Keyboard.OnlyPressKey(action)
		# Get State
		self.CurrentFrame = self.windowCapture.getNextFrame()
		currentState = self.getState()
		self.isDone = self.getProgress()
		# Get Reward
		currentReward = self.getReward()

		if self.Bonus[0]:
			currentReward += self.Bonus[1]
		return currentState, currentReward, self.isDone, "hey"

	def reset(self):
		self.Setup()
		if self.Testing:
			return self.getState()
		else:
			if self.CurrentFrame is None:
				self.CurrentFrame = self.windowCapture.getNextFrame()
			return self.getState()


__author__ = "Matthias Rost <mrost AT inet.tu-berlin.de>"

__all__ = ["PlanningCreator"]

from .base import BasePlanningCreator

class PlanningCreator(BasePlanningCreator):
    """
    The ``PlanningCreator`` for initial planning has no special methods or attributes.
    """

    def __init__(self, target_plan, level=1):
        super().__init__(target_plan, level)


import math

from gnuradio import gr, gr_unittest, analog, blocks

class test_cpfsk_bc(gr_unittest.TestCase):

    def setUp(self):
        self.tb = gr.top_block()

    def tearDown(self):
        self.tb = None

    def test_cpfsk_bc_001(self):
        # Test set/gets

        op = analog.cpfsk_bc(2, 1, 2)

        op.set_amplitude(2)
        a = op.amplitude()
        self.assertEqual(2, a)

        freq = 2 * math.pi / 2.0
        f = op.freq()
        self.assertAlmostEqual(freq, f, 5)

        p = op.phase()
        self.assertEqual(0, p)

    def test_cpfsk_bc_002(self):
        src_data = 10 * [0, 1]
        expected_result = [complex(2 * x - 1, 0) for x in src_data]

        src = blocks.vector_source_b(src_data)
        op = analog.cpfsk_bc(2, 1, 2)
        dst = blocks.vector_sink_c()

        self.tb.connect(src, op)
        self.tb.connect(op, dst)
        self.tb.run()

        result_data = dst.data()[0:len(expected_result)]
        self.assertComplexTuplesAlmostEqual(expected_result, result_data, 4)

if __name__ == '__main__':
    gr_unittest.run(test_cpfsk_bc)


from __future__ import print_function
import torch
import torch.nn as nn
import torch.nn.parallel
import torch.optim as optim
import torch.utils.data
import torchvision.datasets as dset
import torchvision.transforms as transforms
import torchvision.utils as vutils
import matplotlib.pyplot as plt
import numpy as np
from torch.autograd import Variable
import matplotlib.animation as animation

# Hyper Parameters
batch_size = 64
learning_rate = 0.0002
adam_momentum = 0.5

# GAN Settings
latent_size = 100
feature_size_g = 64
feature_size_d = 64

class Generator(nn.Module):
    def __init__(self):
       super(Generator, self).__init__()
       self.net = nn.Sequential(
            # latent_size
            nn.ConvTranspose2d(latent_size, feature_size_g * 8, 4, 1,0, bias=False),
            nn.BatchNorm2d(feature_size_g * 8),
            nn.ReLU(True),
            # (feature_size_g * 8) * 4 * 4
            nn.ConvTranspose2d(feature_size_g * 8, feature_size_g *4, 4, 2, 1,bias = False),
            nn.BatchNorm2d(feature_size_g * 4),
            nn.ReLU(True),
            # (feature_size_g * 4) * 8 * 8
            nn.ConvTranspose2d(feature_size_g * 4, feature_size_g *2, 4, 2, 1, bias = False),
            nn.BatchNorm2d(feature_size_g * 2),
            nn.ReLU(True),
            # (feature_size_g * 2) * 16 * 16
            nn.ConvTranspose2d(feature_size_g * 2, feature_size_g, 4, 2, 1, bias = False),
            nn.BatchNorm2d(feature_size_g),
            nn.ReLU(True),
            # (feature_size_g) * 32 * 32
            nn.ConvTranspose2d(feature_size_g, 3, 4, 2, 1, bias = False),
            nn.Tanh()
            # (feature_size_g) * 64 * 64
       )

    def forward(self, input):
        return self.net(input)

class Discriminator(nn.Module):
    def __init__(self):
       super(Discriminator, self).__init__()
       self.net = nn.Sequential(
            # 3 * 64 * 64
            nn.Conv2d(3, feature_size_d, 4, 2, 1, bias=False),
            nn.LeakyReLU(0.2, True),
            # feature_size_d * 32 * 32
            nn.Conv2d(feature_size_d, feature_size_d * 2, 4, 2, 1, bias=False),
            nn.BatchNorm2d(feature_size_d * 2),
            nn.LeakyReLU(0.2, True),
            # (feature_size_d * 2) * 16 * 16
            nn.Conv2d(feature_size_d * 2, feature_size_d * 4, 4, 2, 1, bias=False),
            nn.BatchNorm2d(feature_size_d * 4),
            nn.LeakyReLU(0.2, True),
            # (feature_size_d * 4) * 8 * 8
            nn.Conv2d(feature_size_d * 4, feature_size_d * 8, 4, 2, 1, bias=False),
            nn.BatchNorm2d(feature_size_d * 8),
            nn.LeakyReLU(0.2, True),
            # (feature_size_d * 8) * 4 * 4
            nn.Conv2d(feature_size_d * 8, 1, 4, 1, 0, bias=False),
            nn.Sigmoid()
            # feature_size_d * 8
       )

    def forward(self, input):
        return self.net(input)

# for conv and batch-normlize
def weights_init(m):
    if type(m) in [nn.ConvTranspose2d, nn.Conv2d]:
        nn.init.normal_(m.weight.data, 0.0, 0.02)
    elif type(m) == nn.BatchNorm2d:
        nn.init.normal_(m.weight.data, 1.0, 0.02)
        nn.init.constant_(m.bias.data, 0)

def train(netG, netD, num_epochs):
    # batch of latent vectors, used for visulize output
    fixed_latent_vector = torch.randn(batch_size, latent_size, 1, 1, device = device)

    optimG = optim.Adam(netG.parameters(), lr= learning_rate, betas=(adam_momentum, .999))
    optimD = optim.Adam(netD.parameters(), lr= learning_rate, betas=(adam_momentum, .999))

    # -w[y log(x) + (1-y) log(1-x)]
    criterion = nn.BCELoss().to(device)

    # list for stats
    img_list = []
    lossG_list = []
    lossD_list = []

    with torch.autograd.set_detect_anomaly(True):
        for epoch in range(num_epochs):
            for i, data in enumerate(dataloader):
                # extract batch
                real_images = data[0].to(device) # batch_size * 3 * 64 * 64
                b_size = real_images.shape[0]

                # 1 0 labels
                label_1 = torch.ones(b_size, device=device, requires_grad=False)
                label_0 = torch.zeros(b_size, device=device, requires_grad=False)

                ### G: max log(D(G(z)))
                ###   use label 1 for this loss

                netG.zero_grad()
                # noise z
                latent_vector = torch.randn(b_size, latent_size, 1, 1, device = device)
                # generate image batch
                fake_images = netG(latent_vector)
                # feed to netD, G(z) already calculated in fake_images
                outputs = netD(fake_images).reshape(-1)
                # loss with label = 1
                lossG = criterion(outputs, label_1)
                # step optim
                lossG.backward()
                optimG.step()

                ### D: max log(D(x)) + log(1 - D(G(z)))
                ###   use real sample x for loss[log(D(x))]
                ###   use generated sample z for loss[log(1-D(G(z)))]

                ## real batch
                netD.zero_grad()
                # feed batch to netD
                outputs = netD(real_images).reshape(-1)
                # real loss: log(D(x))
                loss_realD = criterion(outputs, label_1)

                ## fake batch
                # feed to D to classify. Detach since we'll need them one more time
                fake_detached = fake_images.detach()
                outputs = netD(fake_detached).reshape(-1)
                # fake loss: log(1-D(G(z)))
                loss_fakeD = criterion(outputs,label_0)

                # step optim
                lossD = loss_fakeD + loss_realD
                lossD.backward()
                optimD.step()

                # append to list
                lossG_list.append(lossG.item())
                lossD_list.append(lossD.item())

                # output stats
                if i % 50 == 0:
                    print('[{:d},{:d}]\td_loss: {:.4f}\tg_loss: {:.4f}'.format(epoch, i, lossD, lossG))

            # store result of each epoch
            with torch.no_grad():
                outputG = netG(fixed_latent_vector).detach().cpu()
            img_list.append(vutils.make_grid(outputG, padding = 2, normalize = True))

    return img_list, lossG_list, lossD_list

if __name__ == '__main__':
    device = torch.device("cuda:0" if (torch.cuda.is_available()) else "cpu")

    # load data
    image_transform = transforms.Compose([
        transforms.Resize(64),
        transforms.ToTensor(),
        transforms.Normalize(mean = (0.5,0.5,0.5),std = (0.5,0.5,0.5))])
    dataset = dset.CelebA(root = './data/celeba', download = True, transform = image_transform)
    dataloader = torch.utils.data.DataLoader(dataset, batch_size = batch_size, shuffle = True, num_workers = 2)

    # networks
    netG =Generator().to(device)
    netD = Discriminator().to(device)
    netG.apply(weights_init)
    netD.apply(weights_init)
    # print(netG)
    # print(netD)

    # train!
    res_img, res_lossG, res_lossD = train(netG, netD, 30)

    # plot loss
    plt.figure(figsize=(10,5))
    plt.plot(res_lossG,label="G")
    plt.plot(res_lossD,label="D")
    plt.xlabel("iter")
    plt.ylabel("loss")
    plt.legend()
    plt.show()

    # animation G
    fig = plt.figure(figsize=(8,8))
    plt.axis("off")
    ims = [[plt.imshow(np.transpose(i,(1,2,0)), animated=True)] for i in res_img]
    ani = animation.ArtistAnimation(fig, ims, interval=1000, repeat_delay=1000, blit=True)
    plt.show()


import os
import pandas as pd

from openclean.pipeline import stream

def test_write_stream(tmpdir):
    """Test writing a data stream to file."""
    # Create a data stream with three rows.
    data = [[1, 2, 3], [3, 4, 5], [5, 6, 7]]
    df = pd.DataFrame(data=data, columns=['A', 'B', 'C'])
    # Write data stream to file.
    filename = os.path.join(tmpdir, 'myfile.csv')
    stream(df).write(filename)
    # Read the created file.
    data = list()
    with open(filename, 'r') as f:
        for line in f:
            data.append(line.strip())
    assert data == ['A,B,C', '1,2,3', '3,4,5', '5,6,7']


# Step 3: Build a class-based Tkinter UI
from tkinter import *
from quiz_brain import QuizBrain

THEME_COLOR = "#375362"
FONT = ("Arial", 20, "italic")

class QuizInterface:
    def __init__(self, quiz_brain: QuizBrain):  # quiz_brain passed in must be of type QuizBrain when QuizBrain is init
        self.quiz = quiz_brain

        self.window = Tk()  # make window a property of this class
        self.window.title("Quizzer")
        # can code up UI inside init just like we did for other UIs
        self.window.config(padx=20, bg=THEME_COLOR)

        # score label
        self.score_label = Label(text="Score: 0", font=("Arial", 12, "bold"), bg=THEME_COLOR, fg="white")
        self.score_label.grid(column=1, row=0, pady=20)

        # canvas
        self.canvas = Canvas(width=300, height=250, bg="white")
        self.question_text = self.canvas.create_text(
            150,
            125,
            width=280,  # slightly less than the canvas width, used to get text to wrap and be on separate lines
            text="Question",
            font=FONT,
            fill=THEME_COLOR)
        self.canvas.grid(column=0, row=1, columnspan=2, pady=20)

        # buttons
        true_img = PhotoImage(file="images/true.png")   # self not used because it's only used to set up the button
        self.true_button = Button(image=true_img, command=self.press_true, bg=THEME_COLOR, bd=0, relief=GROOVE)
        self.true_button.grid(column=0, row=2, pady=20)
        false_img = PhotoImage(file="images/false.png")
        self.false_button = Button(image=false_img, command=self.press_false, bg=THEME_COLOR, bd=0, relief=GROOVE)
        self.false_button.grid(column=1, row=2, pady=20)

        # call get_next_question() when program runs and UI is initialized
        self.get_next_question()

        self.window.mainloop()  # like a never-ending while loop, always checking for updates in GUI

    # Step 4: Populate UI with questions from API
    def get_next_question(self):
        self.canvas.config(bg="white")  # reset canvas
        # Step 7: Update score
        self.score_label.config(text=f"Score: {self.quiz.score}")
        # check if we can get the next question, in case we're on the last question
        if self.quiz.still_has_questions():
            q_text = self.quiz.next_question()
            self.canvas.itemconfig(self.question_text, text=q_text)
        else:
            self.canvas.itemconfig(self.question_text, text="You've reached the end of the quiz!")
            # disable true and false buttons at the end of the quiz
            self.true_button.config(state="disabled")
            self.false_button.config(state="disabled")

    # Step 5: Go into quiz_brain and check the answer when a button is pressed
    def press_true(self):
        is_right = self.quiz.check_answer("True")
        self.give_feedback(is_right)

    def press_false(self):
        is_right = self.quiz.check_answer("False")
        self.give_feedback(is_right)

    # Step 6: Give user feedback after user enters question
    def give_feedback(self, is_right):
        # change canvas colour to green or red, delay for 1 second, then revert to original colour
        if is_right:
            self.canvas.config(bg="green")
        else:
            self.canvas.config(bg="red")

        # time.sleep() won't work since we are using mainloop that runs continuously
        self.window.after(1000, self.get_next_question)

Day 34: API Practice - GUI Quiz App/ui.py


import sys
import json
import shutil
import argparse
from pathlib import Path

WIN = sys.platform.startswith("win")
with (Path(__file__).parent / "mirrors.json").open(encoding="utf8") as f:
    mirrors = json.load(f)

pip = Path(f"~/{'pip/pip.ini' if WIN else '.pip/pip.conf'}").expanduser()
pip_dir = pip.parent

def new_file(mirror):
    if not pip_dir.exists():
        pip_dir.mkdir()
    with pip.open("w") as file:
        file.write("\n".join([f"[{k}]\n{v}" for k, v in mirrors[mirror].items()]))
    print("设置成功")

def remove_pip():
    if pip_dir.exists():
        shutil.rmtree(pip_dir)
    print("设置成功")

def run():
    parser = argparse.ArgumentParser()
    parser.add_argument("-s", "--source")
    arg = parser.parse_args().source
    if arg in mirrors:
        new_file(arg)
    elif arg == "pypi":
        remove_pip()
    else:
        options = ["官方", *mirrors, "退出"]
        print(
            "使用此工具可切换pip镜像源\n"
            + "\n".join([f"{index}、{item}" for index, item in enumerate(options)])
        )
        while True:
            opt = input("请输入序号: ")
            if opt in tuple(map(str, range(len(options)))):
                if opt == "0":
                    remove_pip()
                elif opt != str(len(options) - 1):
                    new_file(options[int(opt)])
                break
            else:
                print("不支持操作选项! 请输入正确序号")


from collections import deque

moves = [[2, 1], [-2, 1], [2, -1], [-2, -1], [-1, -2], [-1, 2], [1, -2], [1, 2]]

def is_valid(grid, visited, x, y):
    row = len(grid)
    col = len(grid[0])
    if x < 0 or y < 0 or x >= row or y >= col or visited[x][y] == 1:
        return False
    return True

def bfs(grid, start, end, distance, visited):
    i, j = start[0], start[1]
    queue = deque()
    queue.append(start)
    distance[i][j] = 0
    visited[i][j] = 1
    while queue:
        k, l = queue.popleft()
        for u, v in moves:
            if is_valid(grid, visited, k + u, l + v):
                visited[k + u][l + v] = 1
                distance[k + u][l + v] = distance[k][l] + 1
                queue.append((k + u, l + v))

    print(distance[end[0]][end[1]])

grid = [["", "B", "", ""], ["", "", "", ""], ["", "A", "", ""], ["", "", "", ""]]
row = len(grid)
col = len(grid[0])
visited = []
distance = []
for i in range(row):
    temp = []
    dist = []
    for j in range(col):
        temp.append(0)
        dist.append(-1)
    visited.append(temp)
    distance.append(dist)

start = ()
end = ()
for i in range(row):
    for j in range(col):
        if grid[i][j] == "A":
            start = (i, j)
        if grid[i][j] == "B":
            end = (i, j)
# print(start, end)
bfs(grid, start, end, distance, visited)
# for item in distance:
#     print(item)


class Solution:
    def originalDigits(self, s: str) -> str:

        output = []
        freq_table = Counter(s)
        classifiers = [  ('z', '0', 'zero'), ('w', '2', 'two'), ('u', '4', 'four'), ('x', '6', 'six'),
                        ('g', '8', 'eight'), ('o', '1', 'one'), ('r', '3', 'three'), ('f', '5', 'five'),
                        ('v', '7', 'seven'), ('i', '9', 'nine')
                     ]

        for classifier, num, word in classifiers:
            if classifier in freq_table:
                freq = freq_table[classifier]
                for ch in word:
                    freq_table[ch] -= freq
                output.append(num * freq)

        return ''.join(sorted(output))


import tensorflow as tf

class HeavyHittersTest(tf.test.TestCase):
  """TestCase for Heavy Hitters."""

  def assertSetAllEqual(self, x, y):
    """Assert two tensor lists contain the same set of items.

    Allow items to be in different order in these two lists.

    Args:
      x: A 1D tf.string
      y: A 1D tf.string

    Raises:
      ValueError: If x and y are different sets.
    """
    x = tf.expand_dims(x, axis=0)
    y = tf.expand_dims(y, axis=0)
    self.assertEqual(
        tf.size(tf.sets.difference(x, y)), 0, msg='Input sets are not equal.')
    self.assertEqual(
        tf.size(tf.sets.difference(y, x)), 0, msg='Input sets are not equal.')


import PIL.ExifTags
import PIL.Image
img = PIL.Image.open('billeder/hav3.jpg')
exif_data = img._getexif()

exif = {
    PIL.ExifTags.TAGS[k]: v
    for k, v in img._getexif().items()
    if k in PIL.ExifTags.TAGS
}

#print(exif)
print('Brightness', exif['BrightnessValue'])


dx = [-1,-1,0]
dy = [-1,0,-1]
n,m = map(int,input().split())
arr = [list(map(int,list(input()))) for _ in range(n)]

dp = [i[:] for i in arr]
ans = 0
for i in range(n):
    for j in range(m):
        if dp[i][j] == 0:
            continue
        mn = 1001
        for p in range(3):
            xi, yi = i + dx[p], j + dy[p]
            if 0<=xi<n and 0<=yi<m:
                mn = min(mn, dp[xi][yi])
            else:
                mn = 0
                break
        dp[i][j] = mn + 1
        ans = max(ans, dp[i][j])

print(ans**2)


import random
from prettytable import PrettyTable as pt

# Classes
class Farm():
    def __init__(self, name, money, totalValue):
        self.name = name
        self.money = money
        self.totalValue = totalValue

    def TotalValue(self):
        for i in animalList, plantList, productList:
            for j in i:
                farm.totalValue += (j.number * j.price)
        return round(farm.totalValue,2)

class Animal(Farm):
    def __init__(self, name, number, product, productionCoefficient, price):
        self.name = name
        self.number = number
        self.productionCoefficient = productionCoefficient
        self.price = price
        self.lastPrice = 0
        self.production = product
        self.weeklyProduction = 0

    def Buy(self):
        if farm.money > 0:
            print(">", self.name, "Market")
            print("--------------------------------------------")
            print("> Price            :", self.price)
            print("> Total Number     :", self.number)
            print("> Last Week Prices :", self.lastPrice, "$")
            print("> Total Money      :", farm.money, "$")
            print("> Max Buy Number   :", round((farm.money/self.price), 0))
            buyNumber = int(input("How much You want to Buy? "))
            farm.money = farm.money - (self.price * buyNumber)
            self.number = self.number + buyNumber
        else:
            print("\n> Not Enough Money!\n")

    def Sell(self):
        print(">", self.name, "Market")
        print("--------------------------------------------")
        print("> Price               :", self.price)
        print("> Total Number        :", self.number)
        print("> Last Week Prices    :", self.lastPrice, "$")
        print("> Total Money         :", farm.money, "$")
        print("> Max Buy Number      :", self.number)
        sellNumber = int(input("How much You want to Sell? "))
        if sellNumber <= self.number:
            farm.money = farm.money + (self.price * sellNumber)
            self.number = self.number - sellNumber
        else:
            print("\n> Error,You dont have!")

class Plant(Farm):
    def __init__(self, name, number, production, productionCoefficient, price):
        self.name = name
        self.number = number
        self.productionCoefficient = productionCoefficient
        self.price = price
        self.lastPrice = 0
        self.production = production
        self.weeklyProduction = 0

    def Buy(self):
        if farm.money > 0:
            print(">", self.name, "Market")
            print("--------------------------------------------")
            print("> Price            :", self.price)
            print("> Total Number     :", self.number)
            print("> Last Week Prices :", self.lastPrice, "$")
            print("> Total Money      :", farm.money, "$")
            print("> Max Buy Number   :", round((farm.money/self.price), 0))
            buyNumber = int(input("How much You want to Buy? "))
            farm.money = farm.money - (self.price * buyNumber)
            self.number = self.number + buyNumber
        else:
            print("\n> Not Enough Money!\n")

    def Sell(self):
        print(">", self.name, "Market")
        print("--------------------------------------------")
        print("> Price            :", self.price)
        print("> Total Number     :", self.number)
        print("> Last Week Prices :", self.lastPrice, "$")
        print("> Total Money      :", farm.money, "$")
        print("> Max Buy Number   :", self.number)
        sellNumber = int(input("How much You want to Sell? "))
        if sellNumber <= self.number:
            farm.money = farm.money + (self.price * sellNumber)
            self.number = self.number - sellNumber
        else:
            print("\n> Error, You dont have!")

class Urun(Farm):
    def __init__(self, name, number, price):
        self.name = name
        self.number = number
        self.price = price
        self.lastPrice = 0

    def Buy(self):
        if farm.money > 0:
            print(">", self.name, "Market")
            print("--------------------------------------------")
            print("> Price            :", self.price)
            print("> Total Number     :", self.number)
            print("> Last Week Prices :", self.lastPrice, "$")
            print("> Total Money      :", farm.money, "$")
            print("> Max Buy Number   :", round((farm.money/self.price), 0))
            buyNumber = int(input("How much You want to Buy? "))
            farm.money = farm.money - (self.price * buyNumber)
            self.number = self.number + buyNumber
        else:
            print("\n> Not Enough Money!\n")

    def Sell(self):
        print(">", self.name, "Market")
        print("--------------------------------------------")
        print("> Price            :", self.price)
        print("> Total Number     :", self.number)
        print("> Last Week Prices :", self.lastPrice, "$")
        print("> Total Money      :", farm.money, "$")
        print("> Max Buy Number   :", self.number)
        sellNumber = int(input("How much You want to Sell? "))
        if sellNumber <= self.number:
            farm.money = farm.money + (self.price * sellNumber)
            self.number = self.number - sellNumber
        else:
            print("\n> Error, You dont have!")

# Variables
week = 1

# Objects
farm = Farm("Farm", 5000, 0)
#
cow = Animal("Cow", 3, "Milk", 2, 750)
sheep = Animal("Sheep", 5, "Wool", 1, 250)
chicken = Animal("Chicken", 7, "Egg", 5, 50)
animalList = [cow, sheep, chicken]
#
cotton = Plant("Cotton", 3, "Fabric", 1, 200)
wheat = Plant("Wheat", 5, "Fame", 5, 500)
sunflower = Plant("Sunflower", 7, "Oil", 3, 100)
plantList = [cotton, wheat, sunflower]
#
milk = Urun("Milk", 0, 7)
wool = Urun("Wool", 0, 30)
egg = Urun("Egg", 0, 2)
fabric = Urun("Fabric", 0, 80)
fame = Urun("Fame", 0, 35)
oil = Urun("Oil", 0, 60)
feed = Urun("Feed", 200, 50)
fertilizer = Urun("Fertilizer", 300, 60)
productList = [milk, wool, egg, fabric, fame, oil, feed, fertilizer]

# Functions
def PricesChange():
    for i in animalList:
        i.lastPrice = i.price
        i.price = round(i.price * (random.uniform(0.9, 1.1)), 2)

    for i in plantList:
        i.lastPrice = i.price
        i.price = round(i.price * (random.uniform(0.85, 1.15)), 2)

    for i in productList:
        i.lastPrice = i.price
        i.price = round(i.price * (random.uniform(0.75, 1.25)), 2)

def Production():
    milk.number = milk.number + (cow.number * cow.productionCoefficient)
    wool.number = wool.number + (sheep.number * sheep.productionCoefficient)
    egg.number = egg.number + (chicken.number * chicken.productionCoefficient)
    fabric.number = fabric.number + (cotton.number * cotton.productionCoefficient)
    fame.number = fame.number + (wheat.number * wheat.productionCoefficient)
    oil.number = oil.number + (sunflower.number * sunflower.productionCoefficient)

    cow.weeklyProduction = cow.number * cow.productionCoefficient
    sheep.weeklyProduction = sheep.number * sheep.productionCoefficient
    chicken.weeklyProduction = chicken.number * chicken.productionCoefficient
    cotton.weeklyProduction = cotton.number * cotton.productionCoefficient
    wheat.weeklyProduction = wheat.number * wheat.productionCoefficient
    sunflower.weeklyProduction = sunflower.number * sunflower.productionCoefficient

def FeedConsumption():
    if feed.number > 0:
        feed.number -= (cow.number * 3)+(sheep.number * 2)+(chicken.number * 1)
        print("\nFeed Consumption Week :", int(feed.number/((cow.number * 3)+(sheep.number * 2)+(chicken.number * 1))), "Week")
        print("Feed Consumption        :", ((cow.number * 3) +(sheep.number * 2)+(chicken.number * 1)))

    else:
        print("Not Enough Souurces! Buy some Feed for the Animals. Your animals will die")
        print("Cow Died:", 2)
        print("Sheep Died:", 3)
        print("Chicken Died:", 5)
        cow.number  -= 2
        sheep.number -= 3
        chicken.number -= 5

        if cow.number <= 0:
            cow.number = 0
            print("You dont have any Cow!")

        if sheep.number <= 0:
            sheep.number = 0
            print("You dont have any Sheep!")

        if chicken.number <= 0:
            chicken.number = 0
            print("You dont have any Chicken!")

def FertilizerConsumption():
    if fertilizer.number > 0:
        fertilizer.number -= (cotton.number * 2)+(wheat.number * 2)+(sunflower.number * 3)
        print("\nFeed Consumption Week :", str(int(fertilizer.number/((cotton.number * 2)+(wheat.number * 2)+(sunflower.number * 3)))), "Week")
        print("Fertilizer Consumption  :", ((cotton.number * 2) +(wheat.number * 2)+(sunflower.number * 3)))

    else:
        print("Not Enough Souurces! Buy some Fertilizer for the Plants. Your plants will fade")
        print("Cotton Faded :", 2)
        print("Wheat Faded :", 2)
        print("Sunflower Faded :", 3)
        cotton.number  -= 2
        wheat.number -= 2
        sunflower.number -= 3

        if cotton.number <= 0:
            cotton.number = 0
            print("You dont have any Cotton!")

        if wheat.number <= 0:
            wheat.number = 0
            print("You dont have any Wheat!")

        if sunflower.number <= 0:
            sunflower.number = 0
            print("You dont have any Sunflower!")

def MarketplaceBuy(list):
    buyIndex = 1
    print("\n-----------------------------------------------")
    for i in list:
        print(buyIndex, i.name)
        print("Number:", i.number)
        print("-----------------------------------------------")
        buyIndex += 1
    buyInput = int(input("Enter the Product Number"))

    if buyInput == 0:
        print("\n> Enter a Valid Value!\n")

    else:
        try:
            list[buyInput-1].Buy()

        except:
            print("\n> Enter a Valid Value!\n")

def MarketplaceSell(list):
    sellIndex = 1
    print("\n-----------------------------------------------")
    for i in list:
        print(sellIndex, i.name)
        print("Number:", i.number)
        print("-----------------------------------------------")
        sellIndex += 1
    sellInput = int(input("Enter the Product Number"))

    if sellInput == 0:
        print("\n> Enter a Valid Value!\n")

    else:
        try:
            list[sellInput-1].Sell()

        except:
            print("\n> Enter a Valid Value!\n")

# Main Loop
while True:
    print("\n----------------------------------------")
    print("          Farm Simulator Game           ")
    print("----------------------------------------")
    print("> 1: My Farm")
    print("> 2: Next Week >", week, ". week")
    print("> 3: Prices")
    print("> 4: Marketplace")
    print("> 5: Statistics")
    print("> 6: Info")
    print("> 0: Exit")
    print("----------------------------------------")
    mainpagePage = int(input("Enter Page Number: "))

    # Exit
    if mainpagePage == 0:
        print("Quited Game")
        break

    # Farm
    elif mainpagePage == 1:
        while True:
            print("\n----------------------------------------")
            print("                My Farm                 ")
            print("----------------------------------------")
            print("> 1: Barn")
            print("> 2: Field")
            print("> 3: Inventory")
            print("> 0: Exit")
            farmPage = int(input("Enter Page Number: "))

            # Exit
            if farmPage == 0:
                break

            # Barn
            elif farmPage == 1:
                tb = pt()
                tb.field_names = ["Name", "Number", "Price", "Last Price", "Total Value", "Product", "Weekly Production"]
                for i in animalList:
                    tb.add_row([i.name, i.number, i.price, i.lastPrice,round((i.number*i.price),2), i.production, i.weeklyProduction])
                print(tb)

            # Field
            elif farmPage == 2:
                tb = pt()
                tb.field_names = ["Name", "Number", "Price", "Last Price", "Total Value", "Product", "Weekly Production"]
                for i in plantList:
                    tb.add_row([i.name, i.number, i.price, i.lastPrice,round((i.number*i.price),2) ,i.production, i.weeklyProduction])
                print(tb)

            # Inventory
            elif farmPage == 3:
                tb = pt()
                tb.field_names = ["Name", "Number", "Price", "Last Price","Total Value"]
                for i in productList:
                    tb.add_row([i.name, i.number, i.price, i.lastPrice,round((i.number*i.price),2)])
                print(tb)

            # Error
            else:
                print("\n> Enter a Valid Value!\n")

    # Next Week
    elif mainpagePage == 2:
        week += 1
        PricesChange()
        Production()
        FeedConsumption()
        FertilizerConsumption()

    # Prices
    elif mainpagePage == 3:
        print("\n----------------------------------------")
        print("           Prices This Week             ")
        print("----------------------------------------")
        tb = pt()
        tb.field_names = ["Name", "Number", "Price", "Last Price"]
        for i in animalList:
            tb.add_row([i.name, i.number, i.price, i.lastPrice])
        tb.add_row(["--------", "--------", "--------", "--------"])
        for i in plantList:
            tb.add_row([i.name, i.number, i.price, i.lastPrice])
        tb.add_row(["--------", "--------", "--------", "--------"])
        for i in productList:
            tb.add_row([i.name, i.number, i.price, i.lastPrice])
        print(tb)

    # Marketplace
    elif mainpagePage == 4:
        print("\n----------------------------------------")
        print("                 Marketplace              ")
        print("----------------------------------------\n")
        print("Animal")
        print("> 1: Buy")
        print("> 2: Sell")
        print("------------------------\n")
        print("Plant")
        print("> 3: Buy")
        print("> 4: Sell")
        print("------------------------\n")
        print("Produc")
        print("> 5: Buy")
        print("> 6: Sell")
        print("------------------------\n")
        print("> 0: Exit")
        print("------------------------")
        marketplacePage = int(input("Enter Page Number: "))

        # Exit
        if marketplacePage == 0:
            print("Mainpage.")

        # Animal Buy
        elif marketplacePage == 1:
            MarketplaceBuy(animalList)

        # Animal Sell
        elif marketplacePage == 2:
            MarketplaceSell(animalList)

        # Plant Buy
        elif marketplacePage == 3:
            MarketplaceBuy(plantList)

        # Plant Sell
        elif marketplacePage == 4:
            MarketplaceSell(plantList)

        # Product Buy
        elif marketplacePage == 5:
            MarketplaceBuy(productList)

        # Product Sell
        elif marketplacePage == 6:
            MarketplaceSell(productList)

        # Error
        else:
            print("\n> Enter a Valid Value!\n")

    # Statistics
    elif mainpagePage == 5:
        print("\n----------------------------------------")
        print("            Farm Statistics             ")
        print("----------------------------------------")
        farm.totalValue = 0
        print("> Total Farm Value :", farm.TotalValue())
        print("> Money            :", farm.money)

    # Info
    elif mainpagePage == 6:
        print("\n > Developer: ErenElagz")
        print("The Farm Game starts on a small farm where you have a barn and a field.")
        print("And you start the game with a few animals, a few fields and 5000$.")
        print("Your Goal is a game where you produce every week and sell your products in the market place and invest with the money you get.")
        print("But everything is not that simple! Prices change every week, sometimes the prices crash and sometimes they can fly.")
        print("So now it's your turn to sell what you have? will you wait?")

    # Error
    else:
        print("\n> Enter a Valid Value!\n")


from Clue import Clue
from Block import Block
import sys

class NewPuzzle:

	def readIn(self, inputFile):
		clues = []
		#gotta do responsible file io
		try:
			inputPuzzle = open(inputFile)
		except (IOError, FileNotFoundError) as e:
			print ("Could not read file: ", inputFile)
			sys.exit(0)

		with inputPuzzle:
			clueIDs = []
			allClues = inputPuzzle.readlines()
			for clue in allClues:
				clueElements = clue.split()
				#print("ClueElements: ", clueElements)
				try:
					id = int(clueElements[0])
					length = int(clueElements[1])
					bsi = int(clueElements[2])
				except (TypeError, ValueError) as e:
					print("Clue ",clue," is not formatted correctly.")
					sys.exit()

				#checks if you repeated IDs
				for clueID in clueIDs:
					if(id == clueID):
						print("You repeated ID ",id)
						sys.exit()

				#checks the clue length
				if(length < 3 or length > 12):
					print("Clue ",clue," has an invalid length")
					sys.exit()

				#checks the bsi
				if(bsi > (length - 2) or bsi < 0):
					print("Clue ",clue," has a Block Start Index that's out of bounds")
					sys.exit()
				#Clue constructor: id, length, blockStartIndex, block, connections
				#first read in the block and connections, then call clue constructor
				if( (len(clueElements[3]) == 2) and (len(clueElements[4]) == 2)
					and (clueElements[3].isalpha()) and (clueElements[4].isalpha()) ):
					clueBlock = Block(clueElements[3], clueElements[4])
				else:
					print("The block in clue ",clueElements[0]," is not formatted correctly")
					sys.exit()
				#gonna be at least one connection, because a puzzle of one clue is dumb
				#might as well check tho
				if len(clueElements) < 6:
					print ("Clue ",clueElements[0]," doesn't have the correct formatting.")
					sys.exit()
				#also don't want an out of bounds error, double check so not off by one
				clueConnections = []
				for i in range(5, len(clueElements) - 1,2):
					try:
						connection = (int(clueElements[i]), int(clueElements[i+1]))
						if(connection[1] == (bsi + 1) or connection[1] == (bsi)):
							print("Clue ",id," has a connection inside the block")
							sys.exit()
					except (TypeError, ValueError) as e:
						print("A connection on clue ",id," doesn't have the correct formatting")
						sys.exit()
					clueConnections.append(connection)
				for i in clueConnections:
					for j in clueConnections:
						if(i[1] == j[1] and j != i):
							print("Clue ",id," has two connections at the same index",i[1])
							sys.exit()
				#now that I have all the pieces, call Clue and append it to master list
				currentClue = Clue(id, length, bsi, clueBlock, clueConnections )
				clues.append(currentClue)

		self.clues = clues

	#see whittle in back of blue notebook
	#this basically just in version one finds the first clue that has only one potential solution
	#and in version two decides whether to call whittle or reverse whittle on the first clue
	def solve(self):
		# self.__reverseWhittle(self.clues[0])

		for clue in self.clues:
			if len(clue.potentialSolutions) == 1:
				clue.solved = True
				print("Clue",clue.id,"can be solved immediately. Its solution is",clue.potentialSolutions[0][:-1])
				self.__whittle(clue)

		print("Complete Puzzle solved")

	#always gonna call whittle on a solved clue
	def __whittle(self, clue):
		print("Whittling clue", clue.id)
		clueSolution = clue.potentialSolutions[0]
		for connection in clue.connections:
			#find the clue and where they're connected. Could be constant time with pointers, for now it's O(clues)
			connectedClue = self.__findConnectedClue(connection)
			primaryConnectionIndex = connection[1]
			secondaryConnectionIndex = self.__findSecondaryConnectionIndex(connectedClue, clue.id)

			if not connectedClue.solved:
				for word in connectedClue.potentialSolutions:
					#remove anything from connectedClue's potential solutions that doesn't match with the solved clue
					if clueSolution[primaryConnectionIndex] != word[secondaryConnectionIndex]:
						connectedClue.potentialSolutions.remove(word)

				if len(connectedClue.potentialSolutions) == 1:
					#mark it solved and start whittling the connected clue
					connectedClue.solved = True
					print("Clue", connectedClue.id, "solution is", connectedClue.potentialSolutions[0][:-1])
					self.__whittle(connectedClue)

				elif len(connectedClue.potentialSolutions) == 0:
					#if all the potential solutions are eliminated, exit gracefully
					print("Clue ", connectedClue.id,"has no solution.")
					sys.exit()
				else:
					#if, after whittling there still exists multiple potential solutions because it relies
					#on another connection to be solved, reverse whittle the connected clue to solve it
					print("Couldn't solve clue ", connectedClue.id,"by whittling. Starting to reverse whittle.")
					print("Its potential solutions are: ",connectedClue.potentialSolutions)
					self.__reverseWhittle(connectedClue, False)

	#call this on whittled clue that still isn't solved
	#or on the first clue if it needs its connections to get solved
	def __reverseWhittle(self, clue, calledFromReverseWhittle):
		#don't reverse whittle a solved clue. That's pointless and dumb and could fuck shit up for you
		if clue.solved == True:
			print("Reverse whittle was called on a solved clue. Terminating thread")
			#self.__whittle(clue)
		else:
			#get a connected clue for later
			connectedClue = self.__findConnectedClue(clue.connections[0])
			print("Reverse Whittling clue", clue.id)
			for connection in clue.connections:
				#get the connection data
				connectedClue = self.__findConnectedClue(connection)
				primaryConnectionIndex = connection[1]
				secondaryConnectionIndex = self.__findSecondaryConnectionIndex(connectedClue, clue.id)

				if connectedClue.solved:
					#remove anything from the original clue's potential solutions that doesn't fit with the connections
					for word in connectedClue.potentialSolutions:
						for potentialSolution in clue.potentialSolutions:
							if potentialSolution[primaryConnectionIndex] != word[secondaryConnectionIndex]:
								#print("Potential Solution",potentialSolution[:-1],"doesn't match",word[:-1],"at",primaryConnectionIndex,"and",secondaryConnectionIndex)
								#print("Removing", potentialSolution[:-1])
								clue.potentialSolutions.remove(potentialSolution)

			if len(clue.potentialSolutions) == 1:
				#mark it solved and whittle it, solving its connections
				clue.solved = True
				print("Clue",clue.id,"solution is",clue.potentialSolutions[0][:-1])
				self.__whittle(clue)
			elif len(clue.potentialSolutions) == 0:
				#exit gracefully
				print("Clue",clue.id,"has no solution")
				sys.exit()
			else:
				if calledFromReverseWhittle == False:
					print("Reverse whittling clue",clue.id,"didn't work. Reverse whittling clue",connectedClue.id)
					self.__reverseWhittle(connectedClue, True)
				else:
					print("Reverse whittling",clue.id,"again didn't work. Terminating thread")
				#reverseWhittle last connected clue

	#this one needs to return a Clue object
	#also this is apparently how you signal a private function. It's more of a "private" function, because
	#real privacy doesn't exist in python
	def __findConnectedClue(self, connection):
		for clue in self.clues:
			if clue.id == connection[0]:
				return clue

	#this one needs to return an int
	#pass in connectedClue, clue.id
	def __findSecondaryConnectionIndex(self, clue, connectionID):
		for connection in clue.connections:
			if connection[0] == connectionID:
				return connection[1]

	def print(self):
		for clue in self.clues:
			clue.print()


# -*- coding: utf-8 -*-
"""
A set of pre-processing operations in the input dataset:
1. Interpolation of missing data
2. Indentification of saturated pixels
3. Estimation of noise level for each imaged voxel
4. Estimation of global time constants

@authors: agiovann epnev
"""

import numpy as np

#%%
def interpolate_missing_data(Y):
    """
    Interpolate any missing data using nearest neighbor interpolation.
    Missing data is identified as entries with values NaN
    Input:
    Y   np.ndarray (3D)
        movie, raw data in 3D format (d1 x d2 x T)

    Outputs:
    Y   np.ndarray (3D)
        movie, data with interpolated entries (d1 x d2 x T)
    coor list
        list of interpolated coordinates
    """
    coor=[];
    if np.any(np.isnan(Y)):
        raise Exception('The algorithm has not been tested with missing values (NaNs). Remove NaNs and rerun the algorithm.')
        # need to
        for idx,row in enumerate(Y):
            nans=np.where(np.isnan(row))[0]
            n_nans=np.where(~np.isnan(row))[0]
            coor.append((idx,nans))
            Y[idx,nans]=np.interp(nans, n_nans, row[n_nans])

    return Y, coor

#%%

def get_noise_fft(Y, noise_range = [0.25,0.5], noise_method = 'logmexp', max_num_samples_fft=10000):
    """Estimate the noise level for each pixel by averaging the power spectral density.
    Inputs:
    Y: np.ndarray
    Input movie data with time in the last axis
    noise_range: np.ndarray [2 x 1] between 0 and 0.5
        Range of frequencies compared to Nyquist rate over which the power spectrum is averaged
        default: [0.25,0.5]
    noise method: string
        method of averaging the noise.
        Choices:
            'mean': Mean
            'median': Median
            'logmexp': Exponential of the mean of the logarithm of PSD (default)

    Output:
    sn: np.ndarray
        Noise level for each pixel
    """
    T = np.shape(Y)[-1]
    if T > max_num_samples_fft:
        Y=np.concatenate((Y[...,1:np.int(max_num_samples_fft/3)],
                         Y[...,np.int(T/2-max_num_samples_fft/3/2):np.int(T/2+max_num_samples_fft/3/2)],
                         Y[...,-np.int(max_num_samples_fft/3):]),axis=-1)

        T = np.shape(Y)[-1]

    dims = len(np.shape(Y))
    ff = np.arange(0,0.5+1./T,1./T)
    ind1 = ff > noise_range[0]
    ind2 = ff <= noise_range[1]
    ind = np.logical_and(ind1,ind2)
    if dims > 1:
        xdft = np.fft.rfft(Y,axis=-1)
        psdx = (1./T)*abs(xdft)**2
        psdx[...,1:] *= 2
        sn = mean_psd(psdx[...,ind], method = noise_method)

    else:
        xdft = np.fliplr(rfft(Y))
        psdx = (1./T)*(xdft**2)
        psdx[1:] *=2
        sn = mean_psd(psdx[ind], method = noise_method)

    return sn

def mean_psd(y, method = 'logmexp'):
    """
    Averaging the PSD
    Inputs:
    y: np.ndarray
        PSD values
    method: string
        method of averaging the noise.
        Choices:
            'mean': Mean
            'median': Median
            'logmexp': Exponential of the mean of the logarithm of PSD (default)
    """

    if method == 'mean':
        mp = np.sqrt(np.mean(y/2,axis=-1))
    elif method == 'median':
        mp = np.sqrt(np.median(y/2,axis=-1))
    else:
        mp = np.log((y+1e-10)/2)
        mp = np.mean(mp,axis=-1)
        mp = np.exp(mp)
        mp = np.sqrt(mp)
#        mp = np.sqrt(np.exp(np.mean(np.log(y/2),axis=-1)))

    return mp

#%%

def preprocess_data(Y, sn = None , n_processes=4, backend='multithreading', n_pixels_per_process=100,  noise_range = [0.25,0.5], noise_method = 'logmexp', compute_g=False,  p = 2, g = None,  lags = 5, include_noise = False, pixels = None,max_num_samples_fft=10000):
    """
    Performs the pre-processing operations described above.
    """

    Y,coor=interpolate_missing_data(Y)

    if sn is None:
        sn = get_noise_fft(Y, noise_range = noise_range, noise_method = noise_method)

    return Y, sn


'''
간단한 아이디어 2개
1. 숫자의 길이가 n이면, n-1번 이내에 최댓값을 만들 수 있음
2. 주어진 k가 n이상이면 2씩 낮춰서 n으로 만들어준다

이거 수학적으로 증명 가능한데 1번은 n개의 숫자를 움직이는 경우 생각하면 되고
2번은 홀수번 움직여서 같은 숫자를 만들 수 없다 증명하면 됨

'''

n,k = map(str,input().split(" "))
k=int(k)
m=len(n)

while k>m:
    k-=2

ans=-1

def solution(n,k):
    global ans
    if k==0:
        return
    for i in range(m):
        for j in range(i+1,m):
            if not (i==0 and n[j]=='0'):
                if k==1:
                    ans=max(ans,int(n[0:i]+n[j]+n[i+1:j]+n[i]+n[j+1:]))
                solution(n[0:i]+n[j]+n[i+1:j]+n[i]+n[j+1:],k-1)

solution(n,k)
print(ans)


from ...other import basicComponent
from .bscChromo import basicChromo
from statistics import mean, stdev
import unittest

class basicRepresentation(basicComponent):

    last_ID = 0

    __slots__ = ('chromo', 'mapped', 'ID', 'attrs', 'hsh', 'val_min', 'val_max')

    def __init__(self, *args, **kargs):

        super().__init__(*args, **kargs)

        self.chromo = kargs.get('chromo', None)
        self.mapped = kargs.get('mapped', None)

        self.ID = kargs.get('ID', self.__get_next_ID())

        self.attrs = kargs.get('attrs', {})

        self.hsh = kargs.get('hsh', None)

        self.val_min = kargs.get('val_min', None)
        self.val_max = kargs.get('val_max', None)

    def __del__(self):
        del self.chromo
        del self.mapped
        del self.attrs
        del self.val_min
        del self.val_max
        self.ID, self.hsh = None, None
        super().__del__()

    ''' chromosome '''
    # Returns chromosome
    def get_chromo(self, return_copy=True):
        if return_copy:
            return self.chromo.copy()
        return self.chromo

    def __len__(self):
        return self.get_chromo(return_copy=False).__len__()
    # Applies maps
    def _map(self, chromo):
        self.log.exception('_map not implemented', err=NotImplementedError)

    # Returns chromosome mapped
    def get_mapped(self, return_copy=True):
        if self.mapped is None or self.get_chromo(return_copy=False).get_fit() is None:
            self.mapped = self._map(self.get_chromo(return_copy=False))
        if return_copy:
            self.mapped.copy()
        return self.mapped

    # Returns min/max/range of values encodable post mapping
    def get_valmin(self):
        return self.val_min
    def get_valmax(self):
        return self.val_max
    def get_valrange(self):
        return self.val_max - self.val_min

    ''' Inheritance '''
    # Sets chromosome
    def set_chromo(self, new_chromo, set_copy=False, clear_attrs=True):
        if isinstance(new_chromo, list):
            self.get_chromo(return_copy=False).set_chromo(new_chromo,\
                                                        clear_fit=clear_attrs)
        elif isinstance(new_chromo, basicChromo):
            if not set_copy:
                self.chromo = new_chromo
            else:
                self.chromo = new_chromo.copy()
        else:
            self.log.exception('Attempted to set a chromo without a proper '+\
                               'chromosome', err=TypeError)

        if clear_attrs:
            self.clear_attrs()
            self.set_fit(None)

    # Fancy inheriting, accepts new chromo and then compiles information from
    #   parents
    def inherit(self, new_chromo, *parents):
        self.set_chromo(new_chromo)
        # Adds informatoin about the parents
        if len(parents) == 1:
            # Set new chromo
            pfit = parents[0].get_fit()
            p_ID = parents[0].get_ID()
            plen = len(parents[0])
            self.update_attrs({'pfits':[pfit],\
                               'avg_pfit':pfit,\
                               'stdev_pfit':0,\
                               'range_pfit':0,\
                               'max_pfit':pfit,\
                               'min_pfit':pfit,\
                               'pIDs':[p_ID],\
                               'plens':[plen],\
                               'avg_plen':plen,\
                               'stdev_plen':0,\
                               'range_plen':0,\
                               'min_plen':plen,\
                               'max_plen':plen})
        elif len(parents) > 1:
            # Get some values from parents
            pfits = [parent.get_fit() for parent in parents]
            plens = [len(parent.get_chromo(return_copy=False)) for parent in parents]
            min_pfit, max_pfit = min(pfits), max(pfits)
            min_plen, max_plen = min(plens), max(plens)
            self.update_attrs({'pfits':pfits,\
                               'avg_pfit':mean(pfits),\
                               'stdev_pfit':stdev(pfits),\
                               'range_pfit':max_pfit-min_pfit,\
                               'max_pfit':max_pfit,\
                               'min_pfit':min_pfit,\
                               'pIDs':[parent.get_ID() for parent in parents],\
                               'plens':plens,\
                               'avg_plen':mean(plens),\
                               'stdev_plen':stdev(plens),\
                               'range_plen':max_plen-min_plen,\
                               'min_plen':min_plen,\
                               'max_plen':max_plen})

    ''' Fitness '''
    # Returns fitness
    def get_fit(self):
        return self.get_chromo(return_copy=False).get_fit()
    # Sets the fitness, also places it in attrs for easy info compilation
    def set_fit(self, new_fit):
        self.set_attr('fit', new_fit)
        self.get_chromo(return_copy=False).set_fit(new_fit)
    # Clears fitness
    def clear_fit(self):
        self.get_chromo(return_copy=False).set_fit(None)
        try:
            self.del_attr('fit')
        except:
            pass
        return
    # If comparing against another individual, will check if mapped chromosome
    #    is the same.  if given a chromosome, will check if chromsome is the same
    #   if given an integer or a float, will check if int/float is the same
    def __eq__(self, other):
        if isinstance(other, basicRepresentation):
            return (self.get_mapped().__eq__(other.get_mapped()))
        if isinstance(other, basicChromo):
            return (self.get_chromo(return_copy=False).__eq__(other))
        elif isinstance(other, (int, float)):
            return self.get_fit().__eq__(other)
        else:
            try:
                return self.get_fit().__eq__(float(other))
            except:
                pass
        self.log.exception('Must compare another individual or an int/float',\
                           err=TypeError)
    # Sees if fitnesses are equal to, can take int, float, or individual
    def eq_fit(self, other):
        if isinstance(other, (basicRepresentation, basicChromo)):
            return (self.get_fit().__eq__(other.get_fit()))
        elif isinstance(other, (int, float)):
            return self.get_fit().__eq__(other)
        else:
            try:
                return self.get_fit().__eq__(float(other))
            except:
                pass
        self.log.exception('Must compare another individual or an int/float',\
                           err=TypeError)
    # Sees if two chromosomes are equal
    def eq_chromo(self, other):
        if isinstance(other, (basicRepresentation, basicChromo)):
            return (self.get_chromo(return_copy=False).\
                        __eq__(other.get_chromo(return_copy=False)))
        self.log.exception('Must compare another indv to another indv or chromo')
    # Sees if two mapped solutions are equal
    def eq_mapped(self, other):
        if isinstance(other, basicRepresentation):
            return (self.get_mapped().__eq__(other.get_mapped()))
        self.log.exception('Must compare another indv to another indv')

    # Sees if fitnesses are greater than, can take int, float, or individual
    def __gt__(self, other):
        if isinstance(other, basicRepresentation):
            return (self.get_fit().__gt__(other.get_fit()))
        elif isinstance(other, (int, float)):
            return (self.get_fit().__gt__(other))
        else:
            try:
                return self.get_fit().__gt__(float(other))
            except:
                pass
        self.log.exception('Must compare another individual or an int/float',\
                           err=TypeError)
    # Sees if fitnesses are greater or equal to, can take int, float, or individual
    def __ge__(self, other):
        if isinstance(other, basicRepresentation):
            return (self.get_fit().__ge__(other.get_fit()))
        elif isinstance(other, (int, float)):
            return (self.get_fit().__ge__(other))
        else:
            try:
                return self.get_fit().__ge__(float(other))
            except:
                pass
        self.log.exception('Must compare another individual or an int/float',\
                           err=TypeError)
    # Sees if fitnesses are less than, can take int, float, or individual
    def __lt__(self, other):
        if self.get_fit() is None:
            self.log.exception('Cannot compare indv with no fit', err=ValueError)
        if other is None:
            self.log.exception('Cannot compare indv with None', err=TypeError)
        elif isinstance(other, basicRepresentation):
            if other.get_fit() is None:
                self.log.exception('Cannot compare indv with no fit', err=ValueError)
            return (self.get_fit().__lt__(other.get_fit()))
        elif isinstance(other, (int, float)):
            return (self.get_fit().__lt__(other))
        else:
            try:
                return self.get_fit().__lt__(float(other))
            except:
                pass

        self.log.exception('Must compare another individual or an int/float',\
                           err=TypeError)
    # Sees if fitnesses are less or equal to, can take int, float, or individual
    def __le__(self, other):
        if isinstance(other, basicRepresentation):
            return (self.get_fit().__le__(other.get_fit()))
        elif isinstance(other, (int, float)):
            return (self.get_fit().__le__(other))
        else:
            try:
                return self.get_fit().__le__(float(other))
            except:
                pass
        self.log.exception('Must compare another individual or an int/float',\
                           err=TypeError)

    ''' Utility '''
    # Returns hash of contained mapped chromosome
    def __hash__(self):
        if self.mapped is None or self.get_chromo(return_copy=False).get_fit() is None:
            self.hsh = tuple(self.get_mapped()).__hash__()
        return self.hsh
    def set_hash(self, new_hash):
        self.hsh = new_hash
    def get_hash(self):
        return self.__hash__()

    # Returns copy of the individual
    def copy(self, copy_ID=False):
        if copy_ID:
            return basicRepresentation(log_name=self.log.getLogKey(),\
                                      chromo=self.get_chromo(return_copy=True),\
                                      fit=self.get_fit(),\
                                      attrs=self.get_attrs(return_copy=True),\
                                      ID=self.get_ID(),\
                                      val_min=self.get_valmin(),\
                                      val_max=self.get_valmax())
        return basicRepresentation(log_name=self.log.getLogKey(),\
                                   chromo=self.get_chromo(return_copy=True),\
                                   fit=self.get_fit(),\
                                   attrs=self.get_attrs(return_copy=True),\
                                   val_min=self.get_valmin(),\
                                   val_max=self.get_valmax())
    def __copy__(self):
        return self.copy()

    ''' attrs '''

    def clear_attrs(self):
        self.attrs = {}

    def set_attr(self, attr_name, value):
        self.attrs.__setitem__(attr_name, value)

    def get_attr(self, attr_name):
        return self.attrs.__getitem__(attr_name)

    def get_attrs(self, return_copy=True, add_len=True):
        if add_len:
            self.add_len_to_attrs()
        if return_copy:
            return self.attrs.copy()
        return self.attrs

    def update_attrs(self, dct):
        if not isinstance(dct, dict):
            self.log.exception('update_attrs takes a dictionary', err=TypeError)
        self.attrs.update(dct)

    def incr_attr(self, *args):
        if len(args) == 2:
            self.attrs.__setitem__(args[0], self.attrs.get(args[0], 0) + \
                                    args[1])
        elif len(args) == 1:
            self.attrs.__setitem__(args[0], self.attrs.get(args[0], 0) + 1)
        else:
            self.log.exception('Should be 1-2 arguments for incr_attr',\
                               err=ValueError)

    def add_len_to_attrs(self):
        self.set_attr('chromo_len', self.get_chromo(return_copy=False).__len__())

    def del_attr(self, attr_name):
        del self.attrs[attr_name]

    ''' ID '''

    def get_ID(self):
        return self.ID

    @classmethod
    def __get_next_ID(self):
        ''' Returns next ID '''
        basicRepresentation.last_ID += 1
        return basicRepresentation.last_ID-1

    def to_dict(self, return_copy=True, extract_attrs=False):
        if extract_attrs:
            dct = {'ID':self.get_ID(),\
                    'chromo':self.get_chromo(return_copy=False)\
                                        .to_list(return_copy=return_copy),\
                    'mapped':self.get_mapped(return_copy=return_copy),\
                    'fit':self.get_fit()}
            dct.update(self.get_attrs())
            return dct
        return {'ID':self.get_ID(),\
                'chromo':self.get_chromo(return_copy=False)\
                                    .to_list(return_copy=return_copy),\
                'mapped':self.get_mapped(return_copy=return_copy),\
                'fit':self.get_fit(),\
                'attrs':self.get_attrs(return_copy=return_copy)}

class basicRepresentation_unittest(unittest.TestCase):

    def test_AAA_init(self):
        brep = basicRepresentation()

    def test_AAB_setchromo(self):
        logging.disable()
        brep = basicRepresentation()
        chromo = basicChromo(len=10, min=0, max=1, dtype=int)
        self.assertEqual(brep.get_chromo(return_copy=False), None, \
                         msg='failed to get chromo')
        brep.set_chromo(chromo)
        self.assertEqual(brep.get_chromo(return_copy=False), chromo, \
                         msg='failed to get chromo')
        logging.disable(logging.NOTSET)

    def test_AAC_map(self):
        logging.disable()
        brep = basicRepresentation()
        chromo = basicChromo(len=10, min=0, max=1, dtype=int)
        brep.set_chromo(chromo)
        self.assertEqual(brep.get_chromo(), chromo, msg='failed to get_chromo')
        self.assertRaises(NotImplementedError, brep.get_mapped)
        logging.disable(logging.NOTSET)

    def test_AAD_fit(self):
        logging.disable()
        brep = basicRepresentation()
        self.assertEqual(brep.get_fit(), None, msg='failed to get_fit')
        brep.set_fit(4)
        self.assertEqual(brep.get_fit(), 4, msg='failed to get_fit')
        logging.disable(logging.NOTSET)

    def test_AAE_copy(self):
        logging.disable()
        brep = basicRepresentation()
        brep.set_chromo(basicChromo(len=10, min=0, max=100, dtype=int))
        brep2 = brep.copy()
        logging.disable(logging.NOTSET)

    def test_AAF_comparison(self):
        logging.disable()
        brep = basicRepresentation()
        brep2 = basicRepresentation()
        brep.set_fit(10)
        brep2.set_fit(20)

        self.assertFalse(brep>brep2, msg='> failed')
        self.assertFalse(brep>=brep2, msg='>= failed')
        self.assertFalse(brep2<brep, msg='> failed')
        self.assertFalse(brep2<=brep, msg='>= failed')

        self.assertTrue(brep<brep2, msg='< failed')
        self.assertTrue(brep<=brep2, msg='<= failed')
        self.assertTrue(brep2>brep, msg='< failed')
        self.assertTrue(brep2>=brep, msg='<= failed')

        self.assertFalse(brep.eq_fit(brep2), msg='eq_fit failed')
        brep2.set_fit(10)
        self.assertTrue(brep.eq_fit(brep2), msg='eq_fit failed')

    def test_AAG_attrs(self):
        brep = basicRepresentation()
        self.assertTrue(brep.get_attrs(add_len=False) == {}, \
                        msg='Either get_attrs failed or started with attrs')
        brep.set_attr('x', 10)
        self.assertEqual(brep.get_attr('x'),10, msg='Failed to get_attr')
        brep.clear_attrs()
        self.assertEqual(brep.get_attrs(add_len=False),{}, msg='Failed to clear')
        brep.set_attr('x', 100)
        brep.del_attr('x')
        self.assertEqual(brep.get_attrs(add_len=False),{}, msg='Failed to del')
        brep.set_fit(10)
        self.assertEqual(brep.get_attrs(add_len=False),{'fit':10}, \
                         msg='Failed to add fit to attrs')
        brep.incr_attr('fit', 10)
        self.assertEqual(brep.get_attr('fit'),20, \
                         msg='incr_attr or get_attrs failed')
        brep.clear_attrs()
        brep.update_attrs({'test':4})
        self.assertEqual(brep.get_attrs(add_len=False), {'test':4}, msg='Failed to update')

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


nums=input().split(',')
nums=[int(x) for x in nums]
#偶数希望后面结果小，奇数希望后面结果大
# rec=[]
# for i in range(2,len(nums)):
#     j=len(nums)-i-1
#     if j%2==0:
s=str(nums[0])+'/('
for i in range(1,len(nums)-1):
    s=s+str(nums[i])+'/'
s+=str(nums[len(nums)-1])+')'
print(s)