import itertools
h, w = map(int, input().split())
map_lst = []
for i in range(h):
    map_lst.append(list(input()))
b_lst = [[-1] * w for i in range(h)]
b_lst[0][0] = 0
e_lst = [[0, 0]]
#be_r, be_c:調べる前の座標, r, c:調べる座標
def main(be_r, be_c, r, c, bw, cnt):
    # print(r, c)
    if b_lst[r][c] != -1:
        return
    if map_lst[be_r][be_c] == map_lst[r][c]:
        b_lst[r][c] = cnt
        if c < w-1: main(r, c, r, c+1, map_lst[r][c], cnt)
        if r < h-1: main(r, c, r+1, c, map_lst[r][c], cnt)
    else:
        b_lst[r][c] = cnt + 1
        e_lst.append([r, c])

cnt_b = 0
while True:
    tmp_lst = e_lst
    if tmp_lst == []:
        break
    e_lst = []
    # print(tmp_lst, b_lst)
    for i in tmp_lst:
        r, c = i[0], i[1]
        if c < w-1: main(r, c, r, c+1, map_lst[r][c], cnt_b)
        if r < h-1: main(r, c, r+1, c, map_lst[r][c], cnt_b)
    cnt_b += 1
for i in b_lst:
    print(i)
if map_lst[0][0] == '.':
    print(b_lst[-1][-1]//2)
else:
    print(b_lst[-1][-1]+1//2)


# supervised training
import argparse
import os
import numpy as np
import math
import itertools
import datetime
import time
import sys

import torchvision.transforms as transforms
import torchvision.models as models
from torchvision.utils import save_image

from torch.utils.data import DataLoader
from torchvision import datasets
from torch.autograd import Variable

from adaptive_conv_models import *
from discriminator import *

import torch.nn as nn
import torch.nn.functional as F
import torch

from h5topng.data import transforms as T
from h5topng.common import subsample

from Vtils.pytorch_msssim_master.pytorch_msssim import MS_SSIM, gaussian_filter

from adaptive_conv_models.vtils import Random_Rotate, Random_Flip, Random_Translate

class To_h_space:
    def __init__(self, mask=None, center_fractions=[0.04], accelerations=[8], seed=None):
        self.mask = mask
        self.seed = seed
        if mask == None:
            self.mask_func = subsample.MaskFunc(center_fractions, accelerations)

    def __call__(self, data):
        device = data.device
        # to complex data (B,1,H,W,2)
        data = data.unsqueeze(dim=-1).transpose(1,-1)
        # to fft domian
        data = T.fft2(data)

        # apply mask
        if self.mask == None:
            data, _ = T.apply_mask(data, self.mask_func, seed=self.seed)
        else:
            self.mask = self.mask.to(device)
            data = torch.where(self.mask == 0, torch.Tensor([0.]).to(device), data)

        # to image domain
        data = T.ifft2(data)
        return data.transpose(1,-1).squeeze(dim=-1)

class To_k_space:
    def __init__(self, mask=None, center_fractions=[0.04], accelerations=[8], seed=None):
        self.mask = mask
        self.seed = seed
        if mask == None:
            self.mask_func = subsample.MaskFunc(center_fractions, accelerations)

    def __call__(self, data):
        device = data.device
        # to complex data (B,1,H,W,2)
        data = data.unsqueeze(dim=-1).transpose(1,-1)
        # to fft domian
        data = T.fft2(data)

        # apply mask
        if self.mask == None:
            data, _ = T.apply_mask(data, self.mask_func, seed=self.seed)
        else:
            self.mask = self.mask.to(device)
            data = torch.where(self.mask == 0, torch.Tensor([0.]).to(device), data)

        # to (B,2,H,W)
        return data.transpose(1,-1).squeeze(dim=-1)

from utils import torch_fft, torch_ifft, sigtoimage, HLoss, normalize2d
class Soft_Data_Consistency(nn.Module):
    '''mask: (B=1, C=1, H, W)'''
    def __init__(self, mask):
        super().__init__()
        self.mask = mask
        self.mask_c = torch.ones_like(mask) - mask # complementary of support

    # def __call__(self, data, data_u):
    def forward(self, data, data_u):
        '''input: (B,2,H,W)'''
        device = data.device
        self.mask = self.mask.to(device)
        self.mask_c = self.mask_c.to(device)

        # # to complex data (B,1,H,W,2)
        # data = data.unsqueeze(dim=-1).transpose(1,-1)
        # data_u = data_u.unsqueeze(dim=-1).transpose(1,-1)

        # # to fft domian
        # data = T.fft2(data)
        # data_u = T.fft2(data_u)

        data = torch_fft(data)
        data_u = torch_fft(data_u)

        # DC operation
        data_dc = data*self.mask_c + data_u*self.mask

        # to image domain
        data_dc = torch_ifft(data_dc)
        # return data_dc.transpose(1,-1).squeeze(dim=-1)
        return data_dc

parser = argparse.ArgumentParser()
parser.add_argument("--epoch", type=int, default=0, help="epoch to start training from")
parser.add_argument("--n_epochs", type=int, default=200, help="number of epochs of training")
parser.add_argument("--dataset_name", type=str, default="NYU_MRI", help="name of the dataset")
parser.add_argument('--dataroot', required=True, help='path to dataset')
parser.add_argument('--mask', default=None, help='path to dataset')
parser.add_argument("--batch_size", type=int, default=8, help="size of the batches")
parser.add_argument("--lr", type=float, default=0.0002, help="adam: learning rate")
parser.add_argument("--b1", type=float, default=0.5, help="adam: decay of first order momentum of gradient")
parser.add_argument("--b2", type=float, default=0.999, help="adam: decay of first order momentum of gradient")
parser.add_argument("--n_cpu", type=int, default=4, help="number of cpu threads to use during batch generation")
parser.add_argument("--img_depth", type=int, default=1, help="size of image depth, e.g. coils")
parser.add_argument("--img_height", type=int, default=256, help="size of image height")
parser.add_argument("--img_width", type=int, default=256, help="size of image width")
parser.add_argument("--channels", type=int, default=2, help="number of image channels")
parser.add_argument("--repeat_dim", type=int, default=1, help="number of random samples in test")
parser.add_argument("--sample_interval", type=int, default=400, help="interval between saving generator samples")
parser.add_argument("--checkpoint_interval", type=int, default=-1, help="interval between model checkpoints")
parser.add_argument("--lambda_adv", type=float, default=1., help="pixelwise loss weight")
parser.add_argument("--lambda_pixel", type=float, default=10, help="pixelwise reconstruction loss weight")
parser.add_argument("--lambda_latent", type=float, default=0.5, help="latent loss weight")
parser.add_argument("--lambda_vgg", type=float, default=1., help="perceptual loss weight")
parser.add_argument("--lambda_grad", type=float, default=10., help="gradient penalty")

parser.add_argument("--mphn", default=False, action='store_true', help="mphn model")
parser.add_argument("--not_ML_dense", default=False, action='store_true', help="multi-level dense architecture")
parser.add_argument("--not_plus", default=False, action='store_true', help="no feature repeation to balance the model parameter size")
parser.add_argument("--dense", default=False, action='store_true', help="dense connections")
parser.add_argument("--stasm", default=False, action='store_true', help="add STASM modules")
parser.add_argument("--stasm_groups", type=int, default=1)

parser.add_argument("--data_consistency", default=False, action='store_true', help="interleaved data consistency")

opt = parser.parse_args()
# print(opt)

os.makedirs("images/%s" % opt.dataset_name, exist_ok=True)
os.makedirs("saved_models/%s" % opt.dataset_name, exist_ok=True)

cuda = True if torch.cuda.is_available() else False

input_shape = (opt.channels, opt.img_depth, opt.img_height, opt.img_width)

# mean square normalize
def mean_square_normalize(data, thresh=0.05, ratio=0.1, dilate=1.0):
    data[data.abs()<thresh] = 0.0 # threshold

    shape = data.shape
    mean_square = (data**2).sum(1).sqrt().mean((-2,-1))
    mean_square = mean_square.view((shape[0],1,1,1)).repeat((1,shape[1],shape[2],shape[3]))

    # normalize
    data = data/mean_square*ratio
    data = torch.tanh(data*dilate)
    return data

def sample_images(epoch, i):
    """Saves a generated sample rom the validation set"""
    generator.eval()
    # imgs = next(iter(val_dataloader))
    img_samples = None
    attention_samples = []

    for img_A, img_B in zip(to_cyc(val_dataset.type(Tensor)), val_dataset.type(Tensor)):
    # for img_A, img_B in zip(To_h_space(mask=None)(val_dataset.type(Tensor)), val_dataset.type(Tensor)):
        img_A = img_A.unsqueeze(dim=0) # (1, C, H W)
        img_B = img_B.unsqueeze(dim=0)
        # Repeat input image by number of desired columns
        repeat_dim = opt.repeat_dim
        real_A = img_A.repeat(repeat_dim, 1, 1, 1)
        real_A = Variable(real_A)

        # Generate samples
        with torch.no_grad():
            fake_B, _ = generator(real_A.contiguous().unsqueeze(dim=2), zero_filled=real_A.clone(), csm=None, dc_operator=multi_coil_dc)
            fake_B = fake_B.contiguous().squeeze(dim=2)

        '''compute magnitude maps'''
        # (B,2,H,W) to (B,2,H,W,1), B=1
        img_A = img_A.unsqueeze(-1)
        img_B = img_B.unsqueeze(-1)
        fake_B = fake_B.unsqueeze(-1)
        # to complex format (B,1,H,W,2)
        img_A = img_A.transpose(1,-1)
        img_B = img_B.transpose(1,-1)
        fake_B = fake_B.transpose(1,-1)
        # to magnitude in (B,1,H,W)
        img_A = T.complex_abs(img_A)
        img_B = T.complex_abs(img_B)
        fake_B = T.complex_abs(fake_B)

        # diff
        diff = (fake_B-img_B).abs()

        # Concatenate samples horisontally
        fake_B = torch.cat([x for x in fake_B], -1) # (C, H, 2*N*W)
        diff = torch.cat([x for x in diff], -1) # (C, H, 2*N*W)

        img_sample = torch.cat((img_A.squeeze(dim=0), fake_B, img_B.squeeze(dim=0), diff), -1) # (C, H, (N+2)*W)
        img_sample = img_sample.view(1, *img_sample.shape) # (1, C, H, (N+2)*W)
        # Concatenate with previous samples vertically
        img_samples = img_sample if img_samples is None else torch.cat([img_samples, img_sample], -2) # (1, C, M*H, (N+2)*W)
    # print(img_samples.shape, img_sample.shape)
    save_image(img_samples, "images/%s/Adap_GAN_epoch_%d_%d.png" % (opt.dataset_name, epoch, i), nrow=8, normalize=False)
    generator.train()

# measurement method to produce real_A from real_B: (1 ,1, 1, 256, 1)
if opt.mask == None:
    mask = opt.mask
else:
    mask = torch.load(opt.mask)

to_cyc = To_h_space(mask=mask)
to_k = To_k_space(mask=mask)
# to_cyc = To_h_space(mask=None, center_fractions=[0.04], accelerations=[8]) # sampling pattern diversity
# to_k = To_k_space(mask=None, center_fractions=[0.04], accelerations=[8])

soft_dc = Soft_Data_Consistency(mask=mask.squeeze(dim=-1)) # DC opeerator

def multi_coil_dc(inputs, zero_filled, CSM=None):
    outputs = soft_dc(inputs, zero_filled) # data consistency
    return outputs

# Loss functions
# mae_loss = torch.nn.MSELoss()
mae_loss = torch.nn.L1Loss()

eps = 1e-12
Smooth_L1 = lambda output, target: torch.sqrt((output - target)**2+eps).mean()

ms_ssim = MS_SSIM(data_range=1, channel=2, K=(0.01, 0.03)) # Try a larger K2 constant (e.g. 0.4)
win = ms_ssim.win

# Initialize generator, encoder and discriminators
# generator = AdapGenerator(input_shape)
# D_VAE = RA_MultiDiscriminator([input_shape[0], *input_shape[2:]]) # as we often distinguish among single-coil views

if opt.not_ML_dense:
    generator = Sequential_Dense_Network(img_shape=(2,256,256), out_channel=2, scaler_c=2, dense_dilation=False, stages=3, dense=opt.dense, no_plus = opt.not_plus)
else:
    generator = Multi_Level_Dense_Network(img_shape=(2,256,256), out_channel=2, scaler_c=2, dense_dilation=False, stages=3, stasm=opt.stasm, groups=opt.stasm_groups, data_consistency=opt.data_consistency)

D_VAE =  RA_MultiDiscriminator_CBAM([input_shape[0], *input_shape[2:]], p=0.1)

# D_VAE =  RA_MultiDiscriminator_Unet([input_shape[0], *input_shape[2:]])

# generator = Deep_Projection_Network(input_shape, mask=mask.squeeze(dim=-1))

vgg = models.vgg11_bn(pretrained=True).features[:19].cuda()
for param in vgg.parameters():
    param.requires_grad = False # no longer parameter(), but can receive and transmit gradients; it saves computational costs and memory

VGGList = nn.ModuleList()
VGGList.add_module('vgg_0', vgg[:9])
VGGList.add_module('vgg_1', vgg[9:12])
VGGList.add_module('vgg_2', vgg[12:16])
VGGList.add_module('vgg_3', vgg[16:])

from utils import Weight_init

if cuda:
    generator = generator.cuda()
    D_VAE = D_VAE.cuda()
    mae_loss.cuda()

optimizer_G = torch.optim.Adam(generator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2))
optimizer_D_VAE = torch.optim.Adam(D_VAE.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2))

if opt.epoch != 0:
    # Load pretrained models
    generator.load_state_dict(torch.load("saved_models/%s/generator_%d.pth" % (opt.dataset_name, opt.epoch), map_location='cpu'), strict=False)
    D_VAE.load_state_dict(torch.load("saved_models/%s/D_VAE_%d.pth" % (opt.dataset_name, opt.epoch), map_location='cpu'))
    optimizer_G.load_state_dict(torch.load("saved_models/%s/optimizer_G_%d.pth" % (opt.dataset_name, opt.epoch), map_location='cpu'))
    optimizer_D_VAE.load_state_dict(torch.load("saved_models/%s/optimizer_D_VAE_%d.pth" % (opt.dataset_name, opt.epoch), map_location='cpu'))

Tensor = torch.cuda.FloatTensor if cuda else torch.Tensor

# prepare dataset
dataset = torch.load(opt.dataroot) # complex MRI data (B,2,H,W)
start_ = 100
val_dataset = dataset[[10, 30, 35, 55, 75],:,start_:start_+256] # cropped validation samples, range(15,26,5)
# val_dataset = dataset[list(range(10,81,5)),:,start_:start_+256]
dataset = dataset[164:,:,list(range(start_, start_+256))] # cropped training samples

# create dataloaders for training and validation
dataloader = DataLoader(dataset, batch_size=opt.batch_size, shuffle=True, num_workers=opt.n_cpu)

# ----------
#  Training
# ----------
if __name__ == '__main__':
    # Adversarial loss
    valid = 1.
    fake = 0.

    prev_time = time.time()

    for epoch in range(opt.epoch+1, opt.n_epochs+opt.epoch+1):

        for i, batch in enumerate(dataloader):
            '''data augmentation'''
            # Runs the forward pass with autocasting.
            optimizer_G.zero_grad()

            # Runs the forward pass with autocasting.
            with torch.cuda.amp.autocast(enabled=False):
                # Set model input
                real_B = Variable(batch.type(Tensor))
                real_A = Variable(to_cyc(batch.type(Tensor)).detach())

                real_K = Variable(to_k(batch.type(Tensor)).detach())

                # Produce output using real_A
                fake_B, _ = generator(real_A, zero_filled=real_A.clone(), csm=None, dc_operator=multi_coil_dc)

                '''non-uniform mean'''

                # Pixelwise loss of translated image by VAE
                alpha = 0.64 # 0.84

                # L1_loss = torch.sqrt(nn.MSELoss()(fake_B, real_B))
                # L1_loss = (fake_B - real_B).abs()
                L1_loss = torch.sqrt((fake_B - real_B)**2 + eps)
                L1_loss = gaussian_filter(L1_loss, win.to(L1_loss.device)).mean() # Gaussian coefficients indicating the contribution

                # SSIM
                MS_SSIM_Loss = 1. - ms_ssim((fake_B+1.)/2, (real_B+1.)/2)

                # total pixel loss
                loss_pixel = (1-alpha)*L1_loss + alpha*MS_SSIM_Loss

                # Adversarial loss
                loss_VAE_GAN = D_VAE.compute_loss(real_B, fake_B, valid=fake, fake=valid, sg=False) # relativistic average
                # loss_VAE_GAN = D_VAE.compute_loss(fake_B, None, fake=valid, sg=False)

                # feature attention using a U-net-like D
                loss_FA = torch.Tensor(1).fill_(0.).type(Tensor)
                # loss_FA = torch.sqrt(((1.-relative_score.detach())*(fake_B - real_B))**2 + eps).mean()

                # Total Loss (Generator + Encoder)
                loss_GE = opt.lambda_adv*loss_VAE_GAN + opt.lambda_pixel * (loss_pixel + 0.5*loss_FA)

                # ---------
                # cLR-GAN
                # ---------

                loss_latent = opt.lambda_latent * Smooth_L1(to_k(fake_B), real_K)
                # loss_latent = loss_latent.detach()

                # VGG loss
                content_loss = []
                gram_loss = []
                lambda_gram = 0.005

                weight_list = [1., 1.5, 3., 4.5]

                # VGG loss via vgg11_bn
                real_content = sigtoimage(real_B).repeat(1,3,1,1)
                fake_content = sigtoimage(fake_B).repeat(1,3,1,1)

                for k, m in enumerate(VGGList):
                    real_content = m(real_content).detach()
                    fake_content = m(fake_content)

                    # real_vgg = norm(real_content) # instance normalize features
                    # fake_vgg = norm(fake_content)
                    real_vgg = real_content.clone()
                    fake_vgg = fake_content.clone()

                    # content_loss += [nn.L1Loss()(real_vgg, fake_vgg)]
                    content_loss += [Smooth_L1(real_vgg, fake_vgg)]
                    # content_loss += [5.*pdl_loss(real_vgg, fake_vgg, metric='charbonier', m=20)]

                    # gram matrices
                    gram_real = real_vgg.view(real_vgg.shape[0],real_vgg.shape[1],-1) @ real_vgg.view(real_vgg.shape[0],real_vgg.shape[1],-1).transpose(-2,-1)
                    gram_fake = fake_vgg.view(fake_vgg.shape[0],fake_vgg.shape[1],-1) @ fake_vgg.view(fake_vgg.shape[0],fake_vgg.shape[1],-1).transpose(-2,-1)

                    # gram_loss += [weight_list[k]*nn.L1Loss()(gram_real, gram_fake)]
                    gram_loss += [weight_list[k]*Smooth_L1(gram_real, gram_fake)]

                loss_VGG = sum(content_loss) + lambda_gram*sum(gram_loss)
                loss_VGG *= opt.lambda_vgg

                loss_G = loss_GE + loss_latent + loss_VGG
                # loss_G = loss_GE  + loss_VGG # DC has been applied

            loss_G.backward()
            optimizer_G.step()
            # optimizer_G_atasm.step()

            # scaler_G.scale_G(loss_G).backward()
            # scaler_G.step_G(optimizer_G)
            # scaler_G.update()

            # ----------------------------------
            #  Train Discriminator (cVAE-GAN)
            # ----------------------------------

            # if opt.epoch>0 and epoch == (opt.epoch+1) and i == 0:
            #         print('load optimizers here')
            #         print('load optimizers here')
            #         # Load pretrained models
            #         optimizer_D_VAE.load_state_dict(torch.load("saved_models/%s/optimizer_D_VAE_%d.pth" % (opt.dataset_name, opt.epoch)))
            #         print('load optimizers here')
            #         print('load optimizers here')

            optimizer_D_VAE.zero_grad()

            clone_B = torch.ones(fake_B.shape).cuda() # avoid issues caused by .detach()
            clone_B.copy_(fake_B)
            # clone_B = fake_B.new_tensor(fake_B)
            with torch.cuda.amp.autocast(enabled=False):
                loss_D_VAE = D_VAE.compute_loss(real_B, clone_B.detach(), valid=valid, fake=fake, sg=True) # relativistic average
                # loss_D_VAE = D_VAE.compute_loss(real_B, None, fake=valid, sg=False) + D_VAE.compute_loss(fake_B.detach(), None, fake=fake, sg=False)

                loss_D_VAE *= opt.lambda_adv

                # gradient penalty
                loss_grad_VAE = 0.
                loss_grad_VAE = 30.*D_VAE.compute_gradient_penalty(real_B, fake_B.detach()) # gradient penalty
                loss_grad_VAE *= opt.lambda_adv

                loss_D = loss_D_VAE + loss_grad_VAE

            loss_D.backward()
            optimizer_D_VAE.step()

            # scaler_D.scale(loss_D).backward()
            # scaler_D.step(optimizer_D_VAE)
            # scaler_D.update()

            # --------------
            #  Log Progress
            # --------------

            # Determine approximate time left
            batches_done = epoch * len(dataloader) + i
            batches_left = opt.n_epochs * len(dataloader) - batches_done
            time_left = datetime.timedelta(seconds=batches_left * (time.time() - prev_time))
            prev_time = time.time()

            sys.stdout.write(
                "\r[E %d/%d, %d/%d] [D: (%.3f, %.3f)] [G: (%.3f), pixel: (%.3f, %.3f, %.3f), LR: %.4f vgg: (%.3f, %.3f, %.3f), (%.3f, %.3f, %.3f)] ETA: %s"
                % (
                    epoch,
                    opt.n_epochs,
                    i,
                    len(dataloader),
                    loss_D_VAE.item(),
                    loss_grad_VAE,

                    loss_GE.item()-opt.lambda_pixel * loss_pixel.item(),

                    opt.lambda_pixel*(1-alpha)*L1_loss.item(),
                    opt.lambda_pixel*alpha*MS_SSIM_Loss.item(),
                    opt.lambda_pixel*0.5*loss_FA.item(),

                    loss_latent.item(),

                    opt.lambda_vgg*content_loss[0],
                    opt.lambda_vgg*content_loss[1],
                    opt.lambda_vgg*content_loss[2],

                    opt.lambda_vgg*lambda_gram*gram_loss[0],
                    opt.lambda_vgg*lambda_gram*gram_loss[1],
                    opt.lambda_vgg*lambda_gram*gram_loss[2],
                    time_left,
                )
            )

            if batches_done % opt.sample_interval == 0:
                sample_images(epoch, i)

        if opt.checkpoint_interval != -1 and epoch % opt.checkpoint_interval == 0:
            # Save model checkpoints
            torch.save(generator.state_dict(), "saved_models/%s/generator_%d.pth" % (opt.dataset_name, epoch))
            torch.save(D_VAE.state_dict(), "saved_models/%s/D_VAE_%d.pth" % (opt.dataset_name, epoch))
            torch.save(optimizer_G.state_dict(), "saved_models/%s/optimizer_G_%d.pth" % (opt.dataset_name, epoch))
            torch.save(optimizer_D_VAE.state_dict(), "saved_models/%s/optimizer_D_VAE_%d.pth" % (opt.dataset_name, epoch))

            # torch.save(optimizer_G_atasm.state_dict(), "saved_models/%s/optimizer_G_atasm_%d.pth" % (opt.dataset_name, epoch))


from collections import deque

vowels = deque(x for x in input().split())
consonants = [x for x in input().split()]

flowers = {
    "rose": [],
    "tulip": [],
    "lotus": [],
    "daffodil": []
}

def check_for_a_match():
    for word, found in flowers.items():
        if len(found) == len(word):
            return word

while vowels and consonants:
    current_vowel = vowels.popleft()
    current_consonant = consonants.pop()

    for flower in flowers.keys():
        if current_vowel in flower and current_vowel not in flowers[flower]:
            flowers[flower].extend(current_vowel * (flower.count(current_vowel)))
        if current_consonant in flower and current_consonant not in flowers[flower]:
            flowers[flower].extend(current_consonant * (flower.count(current_consonant)))

    result = check_for_a_match()
    if result:
        print(f"Word found: {result}")
        break

else:
    print("Cannot find any word!")

if vowels:
    print(f"Vowels left: {' '.join(vowels)}")
if consonants:
    print(f"Consonants left: {' '.join(consonants)}")


import torch
import torch.nn as nn

class ContentLoss(nn.Module):
    def __init__(self, target):
        super(ContentLoss, self).__init__()
        # 必须要用detach来分离出target，否则会计算目标值的梯度
        self.target = target.detach()
        self.criterion = nn.MSELoss()

    def forward(self, inputs):
        self.loss = self.criterion(inputs, self.target)
        return inputs

class StyleLoss(nn.Module):
    def __init__(self, target):
        super(StyleLoss, self).__init__()
        self.gram = GramMatrix()
        self.target = self.gram(target).detach()
        self.criterion = nn.MSELoss()

    def forward(self, inputs):
        self.G = self.gram(inputs)
        self.loss = self.criterion(self.G, self.target)
        return inputs

class GramMatrix(nn.Module):
    def forward(self, inputs):
        a, b, c, d = inputs.size()
        features = inputs.view(a * b, c * d)
        G = torch.mm(features, features.t())
        return G.div(a * b * c * d)


# s1 = '1234' when s2 = '1234', '2341', '3412' or '4123', return True, else return False

# 1. s = s1 + s1 ('12341234')
# 2. KMP s with s2

def kmp_get_next(p):
    p_len = len(p)
    next_arr = [0] * p_len
    next_arr[0] = -1
    k = -1
    i = 0
    while i < p_len-1:
        if k == -1 or p[k] == p[i]:
            k += 1
            i += 1
            next_arr[i] = k
        else:
            k = next_arr[k]
    return next_arr

def kmp(s, p):
    next_arr = kmp_get_next(p)
    i = 0
    j = 0
    while i < len(s):
        if j == -1 or s[i] == p[j]:
            i += 1
            j += 1
        else:
            j = next_arr[j]
        if j == len(p):
            return True
    return False

def is_rev_word(s1, s2):
    if len(s1) != len(s2):
        return False
    s = s1 + s1
    return kmp(s, s2)

print(is_rev_word('1234', '3241'))


"""
This question is asked by Amazon. Given a non-empty linked list,
return the middle node of the list. If the linked list contains
an even number of elements, return the node closer to the end.
Ex: Given the following linked lists...

1->2->3->null, return 2
1->2->3->4->null, return 3
1->null, return 1
"""

class ListNode:
  def __init__(self, value=None):
    self.data = value
    self.next = None

  def __str__(self) -> str:
    llString = ""
    currNode = self

    while currNode:
      llString += (str(currNode.data)+"->")
      currNode = currNode.next

    llString += "null"

    return llString

def findMiddleElement(head: ListNode) -> int:
  # Time: O(n)
  # Space: O(1)
  if not head: return -1

  slow = fast = head
  while fast and fast.next:
    slow = slow.next
    fast = fast.next.next

  return slow.data

l1 = ListNode(1)
l1.next = ListNode(2)
l1.next.next = ListNode(3)

assert findMiddleElement(l1) == 2

l2 = ListNode(1)
l2.next = ListNode(2)
l2.next.next = ListNode(3)
l2.next.next.next = ListNode(4)

assert findMiddleElement(l2) == 3

l3 = ListNode(1)

assert findMiddleElement(l3) == 1

print("Passed all tests!")


import time
import subprocess
import digitalio
import board
from PIL import Image, ImageDraw, ImageFont
import adafruit_rgb_display.st7789 as st7789
import pynmea2
import sys
from subprocess import Popen, PIPE
import serial
import io

# Configuration for CS and DC pins (these are FeatherWing defaults on M0/M4):
cs_pin = digitalio.DigitalInOut(board.CE0)
dc_pin = digitalio.DigitalInOut(board.D25)
reset_pin = None

# COLORS
ORGANGE = "#ffa600"
WHITE = "#FFFFFF"

# Config for display baudrate (default max is 24mhz):
BAUDRATE = 64000000

# Setup SPI bus using hardware SPI:
spi = board.SPI()

# Create the ST7789 display:
disp = st7789.ST7789(
    spi,
    cs=cs_pin,
    dc=dc_pin,
    rst=reset_pin,
    baudrate=BAUDRATE,
    width=135,
    height=240,
    x_offset=53,
    y_offset=40,
)

# Create blank image for drawing.
# Make sure to create image with mode 'RGB' for full color.
height = disp.width  # we swap height/width to rotate it to landscape!
width = disp.height
image = Image.new("RGB", (width, height))
rotation = 90

# Get drawing object to draw on image.
draw = ImageDraw.Draw(image)

# Draw a black filled box to clear the image.
draw.rectangle((0, 0, width, height), outline=0, fill=(0, 0, 0))
disp.image(image, rotation)
# Draw some shapes.
# First define some constants to allow easy resizing of shapes.
padding = -2
top = padding
bottom = height - padding
# Move left to right keeping track of the current x position for drawing shapes.
x = 0

# Alternatively load a TTF font.  Make sure the .ttf font file is in the
# same directory as the python script!
# Some other nice fonts to try: http://www.dafont.com/bitmap.php
font = ImageFont.truetype("/usr/share/fonts/truetype/noto/NotoMono-Regular.ttf", 24)

# Turn on the backlight
backlight = digitalio.DigitalInOut(board.D22)
backlight.switch_to_output()
backlight.value = True

while True:

    iterator = 0

    # Get output from std
    with Popen(["gpspipe", "/dev/ttyACM0", "-r"], stdout=PIPE, bufsize=1,
            universal_newlines=True) as p:
                for line in p.stdout:

                    iterator = iterator + 1

                    # counting up to 4 lines ignores the headers that would otherwise be unfit for parsing
                    if(iterator >= 4):

                        gpsmsg = pynmea2.parse(line)

                        # handling errors is critical - program will fail without this step
                        try:
                            latitude = gpsmsg.lat
                            longitude = gpsmsg.lon
                            #altitude = gpsmsg.alt

                            y = top

                            if(latitude != 0 and latitude != "null" and latitude != "NULL" and latitude != "" and latitude != " "):
                                #print(latitude)
                                draw.rectangle((0, 0, width, height), outline=0, fill=0)

                                #Write GPS data to screen
                                #y = top
                                draw.text((x, y), "LAT: " + latitude, font=font, fill=WHITE)
                                y += font.getsize("LAT")[1]

                            if(longitude != 0 and longitude != "null" and longitude != "NULL" and longitude != "" and longitude != " "):

                                draw.text((x, y), "LON: " + longitude, font=font, fill=WHITE)
                                y += font.getsize("LON")[1]

                            #if(altitude != 0 and altitude != "null" and altitude != "NULL" and altitude != "" and altitude != " "):

                                #draw.text((x, y), "ALT: " + altitude, font=font, fill=WHITE)
                                #y += font.getsize("ALT")[1]
                        except:
                            print("cannot parse that")
                            #pass

                        disp.image(image, rotation)

    time.sleep(0.1)


# Given an array of intervals, find the next interval of each interval.
# In a list of intervals, for an interval ‘i’ its next interval ‘j’ will have
# the smallest ‘start’ greater than or equal to the ‘end’ of ‘i’.

# Write a function to return an array containing indices of the next interval of each input interval.
# If there is no next interval of a given interval, return -1.
# It is given that none of the intervals have the same start point.

from heapq import *

class Interval:
	def __init__(self, start, end):
		self.start = start
		self.end = end

def find_next_interval(intervals):
	result = []

	minStartHeap = []

	for i in range(len(intervals)):
		heappush(minStartHeap, (intervals[i].start, i))

	for i in range(len(intervals)):
		if minStartHeap:
			while minStartHeap:
				start, index = heappop(minStartHeap)
				if intervals[i].end <= start and i < index:
					result.append(index)
		else:
			result.append(-1)

	return result

def main():

	result = find_next_interval(
		[Interval(2, 3), Interval(3, 4), Interval(5, 6)])
	print("Next interval indices are: " + str(result))

	result = find_next_interval(
		[Interval(3, 4), Interval(1, 5), Interval(4, 6)])
	print("Next interval indices are: " + str(result))

main()

9. Two Heaps/436. Find Right Interval.py


import random
import copy

# Чисто параметры для проверки алгоритма
seed_value = 60  # зерно рандомайзера
kolvo_prov = 10  # количество проверок
arr_legth = 20  # длинна проверяемых списков
random.seed(seed_value)  # установка зерна

# Сам алгоритм быстрой сортировки.
def quick_sort(array):
    if len(array) < 2:
        return array
    else:
        index = random.randrange(0, len(array))
        middle = array[index]
        del array[index]
        lower_arr = [i for i in array if i <= middle]
        upper_arr = [j for j in array if j > middle]
        return quick_sort(lower_arr) + [middle] + quick_sort(upper_arr)

# Цикл проверки алгоритма. Он создает два одинаковых списка с рандомными значениями и затем сортируется встроенным
# методом sort и алгоритмом быстрой сортировки. Если все норм, то он выведет истину, если где то ошибка то выведет не
# истину.
for _ in range(kolvo_prov):
    prov = True
    arr1 = [random.randrange(-100, 100) for _ in range(arr_legth)]
    arr2 = copy.deepcopy(arr1)
    print(f'\nМассив 1: {arr1}\nМассив 2: {arr2}')
    arr1.sort()
    arr2 = quick_sort(arr2)
    print(f"Разные ли объекты (списки):{arr1 is not arr2}")
    print(
        f'Массив отсортированный встроенной функцией (1 массив):\n{arr1}\n'
        f'Массив отсортированный быстрой сортировкой (2 массив):\n{arr2}')
    seed_value += 1
    for arr_index in range(arr_legth):
        if not arr1[arr_index] == arr2[arr_index]:
            prov = False
            break
    print(f"Одинаково ли отсортированы списки: {prov}")


import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
import scipy.optimize as optimize

# Opening image
img = cv.imread("red.png")

# Uncomment this and run the program to make sure the
# convex_hull_pointing_up algorithm works
# img = cv.rotate(img, cv.ROTATE_180)

# OpenCV stores images as BGR by default
# so the following two lines flip the color channels
# to RGB and HSV
img_rgb = cv.cvtColor(img, cv.COLOR_BGR2RGB)
img_hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV)

# Create the environment of the picture
plt.subplot(1, 1, 1)
plt.imshow(img_rgb)

# Defining thresholds to isolate the HSV pixels that
# have the desired color
img_thresh_low = cv.inRange(img_hsv, np.array([0, 135, 135]), np.array([15, 255, 255]))
img_thresh_high = cv.inRange(img_hsv, np.array([159, 135, 135]), np.array([179, 255, 255]))
# Add the two threshold maps together
img_thresh = cv.bitwise_or(img_thresh_low, img_thresh_high)

# Use erosion followed by dilation to remove noise
kernel = np.ones((5, 5))
img_thresh_opened = cv.morphologyEx(img_thresh, cv.MORPH_OPEN, kernel)

# Blur the image slightly
img_thresh_blurred = cv.medianBlur(img_thresh_opened, 5)

# Find edges with the Canny edge detection algorithm
img_edges = cv.Canny(img_thresh_blurred, 70, 255)

# Get contours
contours, _ = cv.findContours(np.array(img_edges), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

# Approximate contours using the Douglas-Peucker algorithm
approx_contours = []
for c in contours:
    approx = cv.approxPolyDP(c, 5, closed=True)
    approx_contours.append(approx)

# Find convex hulls of the contours
all_convex_hulls = []
for ac in approx_contours:
    all_convex_hulls.append(cv.convexHull(ac))

# Remove any hulls with more than 10 or less than 3 points
convex_hulls_3to10 = []
for ch in all_convex_hulls:
    if 3 <= len(ch) <= 10:
        convex_hulls_3to10.append(cv.convexHull(ch))

# Define a function to check if a hull is pointing up
def convex_hull_pointing_up(ch: np.ndarray) -> bool:
    points_above_center, points_below_center = [], []
    _, y, _, h = cv.boundingRect(ch)
    vertical_center = y + h / 2

    for point in ch:
        if point[0][1] < vertical_center:
            points_above_center.append(point)
        elif point[0][1] >= vertical_center:
            points_below_center.append(point)

    x_above, _, w_above, _ = cv.boundingRect(np.array(points_above_center))
    x_below, _, w_below, _ = cv.boundingRect(np.array(points_below_center))

    return x_above <= x_below + w_below and x_above + w_above <= x_below + w_below \
        and x_above >= x_below and x_above + w_above >= x_below

cones = []
bounding_rects = []

# Filter out the contours that aren't pointing up
for ch in convex_hulls_3to10:
    if convex_hull_pointing_up(ch):
        cones.append(ch)
        rect = cv.boundingRect(ch)
        bounding_rects.append(rect)

img_res = img_rgb.copy()

# Draw rectangles around the identified cones
for rect in bounding_rects:
    x, y, w, h = rect
    cv.rectangle(img_res, (x, y), (x + w, y + h), (0, 255, 0), 2)

# Fit best-fit lines to the left and right sides of the screen
cone_points_left = [(rect[0] + rect[2] / 2, rect[1] + rect[3] / 2) for rect in bounding_rects if rect[0] + rect[2] / 2 < img_res.shape[1] / 2]
cone_points_right = [(rect[0] + rect[2] / 2, rect[1] + rect[3] / 2) for rect in bounding_rects if rect[0] + rect[2] / 2 > img_res.shape[1] / 2]

def least_squares(x, y):
    # Create the least squares objective function.
    def func(x, a, b):
        return a * x + b

    popt, pcov = optimize.curve_fit(func, x, y)
    return popt

# Get best fit lines for these points
a1, b1 = least_squares(np.array([i[0] for i in cone_points_left]), np.array([i[1] for i in cone_points_left]))
a2, b2 = least_squares(np.array([i[0] for i in cone_points_right]), np.array([i[1] for i in cone_points_right]))

# Draw the best-fit lines on the image
cv.line(img_res, [0, int(b1)], [3000, int((3000 * a1) + b1)], (255, 1, 1), 5)
cv.line(img_res, [0, int(b2)], [3000, int((3000 * a2) + b2)], (255, 1, 1), 5)

# Display and save the final output image
plt.imshow(img_res)
plt.savefig("answer.png")
plt.show()


# -*- coding: utf-8 -*-
import scrapy

from collections import OrderedDict

class BriefingEarningsSpider(scrapy.Spider):
    name = 'briefing_earnings'
    allowed_domains = ['www.briefing.com']
    start_urls = ['https://www.briefing.com/Inv/content/Auth/Calendar/Earnings/week1.htm']  # Current week (week1)

    def parse(self, response):
        dates_lst = response.xpath('//*[@class="calDATE"]/text()').getall()    # Get list of days (dates)
        dates = {dates_lst[day]: day for day in range(len(dates_lst))}
        dates_sort = OrderedDict(sorted(dates.items(), key=lambda x: x[1]))     # Ordered dict to save que

        for i, day in enumerate(dates_sort):
            block = response.xpath('//*[@class="calDATE"]/following-sibling::ul')[i]    # Block for day
            events_lst = block.xpath('.//div[contains(@class,"calEVENT")]')             # Block for ticket

            tickets = OrderedDict()

            for event in events_lst:
                ticket = event.xpath('.//span/@data-ticker-search').get()
                name = event.xpath('.//strong/text()').get()
                surprise_value = event.xpath(
                    './/span[contains(text(), "Surprise:")]/following-sibling::span/text()').get()
                act_value = event.xpath('.//span[contains(text(), "Act:")]/following-sibling::span/text()').get()
                cons_value = event.xpath('.//span[contains(text(), "Cons:")]/following-sibling::span/text()').get()

                tickets.update({ticket: {'name': name,
                                         'surprise_value': surprise_value,
                                         'actual_value': act_value,
                                         'consensus_value': cons_value}})

            dates_sort.update({day: tickets})  # Add all tickets with values for day

        yield dates_sort


import streamlit as st
import pandas as pd
import plotly.express as px
import seaborn as sns

import ssl
ssl._create_default_https_context = ssl._create_unverified_context

st.set_option('deprecation.showPyplotGlobalUse', False)
# Loading dataset
df = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data',
                names=['sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'class'])

st.title('Exploratory Data Analysis of the Iris Dataset')
st.header('This app allows you to explore the Iris dataset and visualize the data using various plots.')

st.subheader("DataFrame")
st.dataframe(df)
selected_column = st.sidebar.selectbox('Select a column to visualize', df.columns)

st.write("Histogram Plots")
sns.histplot(df[selected_column])
st.pyplot()

st.write("Scatter plot")
x_axis = st.sidebar.selectbox('Select the x-axis', df.columns)
y_axis = st.sidebar.selectbox('Select the y-axis', df.columns)

fig = px.scatter(df, x=x_axis, y=y_axis)
st.plotly_chart(fig)

st.write("Pair Plot")
sns.pairplot(df, hue='class')
st.pyplot()
st.write("Description of the data")
st.table(df.describe())

st.header('Correlation Matrix')

corr = df.corr()
sns.heatmap(corr, annot=True)
st.pyplot()

st.header('Boxplot')

fig = px.box(df, y=selected_column)
st.plotly_chart(fig)

selected_class = st.sidebar.selectbox('Select a class to visualize', df['class'].unique())

if st.sidebar.button('Show Violin Plot'):
    fig = px.violin(df[df['class'] == selected_class], y=selected_column)
    st.plotly_chart(fig)


#!/usr/bin/python
# coding: utf-8

import numpy as np
import cv2
import csv
import os
import shutil
import shutil
import logging

def to_image_string(image_filepath):
    return open(image_filepath, "rb").read().encode("base64")

def from_base64(base64_data):
    nparr = np.fromstring(base64_data.decode("base64"), np.uint8)
    return cv2.imdecode(nparr, cv2.IMREAD_ANYCOLOR)

# clean all non-alphanumberic characters
def strip(string):
    words = string.split()
    words = [word for word in words if "#" not in word]
    string = " ".join(words)
    clean = ""
    for c in string:
        if str.isalnum(c) or (c in [" ", ".", ","]):
            clean += c
    return clean

# creating CSV header
def create_csv(filename):
    with open(filename, "w+", newline="", encoding="utf-8") as save_file:
        writer = csv.writer(save_file)
        writer.writerow(["Author", "uTime", "Text"])

def write_to_csv(filename, data):
    with open(filename, "a+", newline="", encoding="utf-8") as save_file:
        writer = csv.writer(save_file)
        writer.writerow(data)

def empty_folder(folder):
    for filename in os.listdir(folder):
        file_path = os.path.join(folder, filename)
        try:
            if os.path.isfile(file_path) or os.path.islink(file_path):
                os.unlink(file_path)
            elif os.path.isdir(file_path):
                empty_folder(file_path)
        except Exception as e:
            logging.info("Failed to delete %s. Reason: %s" % (file_path, e))

def move_file(source, dest):
    shutil.move(source, dest)


"""Tensorflow transformer layers definition in trident"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import numpy as np
import math

import tensorflow as tf
from tensorflow.python.ops import array_ops
from tensorflow.python.ops import math_ops

from trident import context
from trident.backend import dtype as Dtype
from trident.backend.tensorflow_backend import Layer, Sequential, get_device, ModuleList
from trident.backend.tensorflow_ops import *
from trident.layers.tensorflow_activations import Gelu
from trident.layers.tensorflow_blocks import FullConnect_Block
from trident.layers.tensorflow_layers import Embedding, Dropout, Dense
from trident.layers.tensorflow_normalizations import LayerNorm

ctx = context._context()
_float_dtype = Dtype.float32# if ctx.amp_available == True and ctx.is_autocast_enabled == True and get_device() == 'cuda' else Dtype.float32

__all__ = ['Mlp','BERT','BERTEmbedding','PositionalEmbedding','PositionwiseFeedForward','DropPath','Attention','MultiHeadedAttention','SublayerConnection','TransformerBlock']

def Mlp(hidden_features=None, out_features=None,dropout_rate=0):
    return Sequential(
        FullConnect_Block(num_filters=hidden_features,activation=Gelu(),dropout_rate=dropout_rate,normalization=None),
        FullConnect_Block(num_filters=out_features, activation=None, dropout_rate=dropout_rate,normalization=None),
    )

class PositionalEmbedding(Layer):

    def __init__(self, d_model, max_len=512):
        super().__init__()

        # Compute the positional encodings once in log space.
        pe = np.zeros((max_len, d_model))
        position = np.expand_dims(np.arange(0, max_len),1)
        div_term = (np.arange(0,d_model,2) * -np.exp(np.log(10000.0) / d_model))

        pe[:, 0::2] = np.sin(position * div_term)
        pe[:, 1::2] = np.cos(position * div_term)

        pe =to_tensor(np.expand_dims( pe,0))
        self.register_buffer('pe', pe)

    def forward(self, x, **kwargs):
        return self.pe[:, :int_shape(x)[1]]

class PositionwiseFeedForward(Layer):
    "Implements FFN equation."

    def __init__(self, d_model, d_ff, dropout_rate=0.1):
        super(PositionwiseFeedForward, self).__init__()
        self.w_1 = Dense(num_filters= d_ff,activation=Gelu())
        self.w_2 = Dense(num_filters= d_model)
        self.dropout = Dropout(dropout_rate)

    def forward(self, x):
        return self.w_2(self.dropout(self.w_1(x)))

#
# class PositionEmbeddingSine(Layer):
#     """
#     This is a more standard version of the position embedding, very similar to the one
#     used by the Attention is all you need paper, generalized to work on images.
#     """
#     def __init__(self, num_pos_feats=64, temperature=10000, normalize=False, scale=None):
#         super().__init__()
#         self.num_pos_feats = num_pos_feats
#         self.temperature = temperature
#         self.normalize = normalize
#         if scale is not None and normalize is False:
#             raise ValueError("normalize should be True if scale is passed")
#         if scale is None:
#             scale = 2 * math.pi
#         self.scale = scale
#
#     def forward(self, tensor_list):
#         x = tensor_list.tensors
#         mask = tensor_list.mask
#         assert mask is not None
#         not_mask = ~mask
#         y_embed = not_mask.cumsum(1, dtype=torch.float32)
#         x_embed = not_mask.cumsum(2, dtype=torch.float32)
#         if self.normalize:
#             eps = 1e-6
#             y_embed = y_embed / (y_embed[:, -1:, :] + eps) * self.scale
#             x_embed = x_embed / (x_embed[:, :, -1:] + eps) * self.scale
#
#         dim_t = torch.arange(self.num_pos_feats, dtype=torch.float32, device=x.device)
#         dim_t = self.temperature ** (2 * (dim_t // 2) / self.num_pos_feats)
#
#         pos_x = x_embed[:, :, :, None] / dim_t
#         pos_y = y_embed[:, :, :, None] / dim_t
#         pos_x = torch.stack((pos_x[:, :, :, 0::2].sin(), pos_x[:, :, :, 1::2].cos()), dim=4).flatten(3)
#         pos_y = torch.stack((pos_y[:, :, :, 0::2].sin(), pos_y[:, :, :, 1::2].cos()), dim=4).flatten(3)
#         pos = torch.cat((pos_y, pos_x), dim=3).permute(0, 3, 1, 2)
#         return pos
#
#
# class PositionEmbeddingLearned(Layer):
#     """
#     Absolute pos embedding, learned.
#     """
#     def __init__(self, num_pos_feats=256):
#         super().__init__()
#         self.row_embed = nn.Embedding(50, num_pos_feats)
#         self.col_embed = nn.Embedding(50, num_pos_feats)
#         self.reset_parameters()
#
#     def reset_parameters(self):
#         nn.init.uniform_(self.row_embed.weight)
#         nn.init.uniform_(self.col_embed.weight)
#
#     def forward(self, tensor_list):
#         x = tensor_list.tensors
#         h, w = x.shape[-2:]
#         i = torch.arange(w, device=x.device)
#         j = torch.arange(h, device=x.device)
#         x_emb = self.col_embed(i)
#         y_emb = self.row_embed(j)
#         pos = torch.cat([
#             x_emb.unsqueeze(0).repeat(h, 1, 1),
#             y_emb.unsqueeze(1).repeat(1, w, 1),
#         ], dim=-1).permute(2, 0, 1).unsqueeze(0).repeat(x.shape[0], 1, 1, 1)
#         return pos
#

class BERTEmbedding(Layer):
    """
    BERT Embedding which is consisted with under features
        1. TokenEmbedding : normal embedding matrix
        2. PositionalEmbedding : adding positional information using sin, cos
        2. SegmentEmbedding : adding sentence segment info, (sent_A:1, sent_B:2)
        sum of all these features are output of BERTEmbedding
    """

    def __init__(self, vocab_size, embedding_dim,cls_idx=1,sep_idx=2,unk_idx=3,pad_idx=0,mask_idx=4, dropout_rate=0.1, add_noise=False,noise_intensity=0.05):
        """
        :param vocab_size: total vocab size
        :param embed_size: embedding size of token embedding
        :param dropout: dropout rate
        """
        super().__init__()
        self.token = Embedding(num_embeddings=vocab_size,embedding_dim=embedding_dim,padding_idx=pad_idx,add_noise=add_noise,noise_intensity=noise_intensity)
        self.position = PositionalEmbedding(d_model=self.token.embedding_dim)
        self.segment = Embedding(num_embeddings=3,embedding_dim=self.token.embedding_dim,padding_idx=0)
        self.cls_idx=cls_idx
        self.sep_idx=sep_idx
        self.pad_idx=pad_idx
        self.unk_idx=unk_idx
        self.mask_idx=mask_idx
        self.dropout_rate=dropout_rate
        self.dropout = Dropout(dropout_rate)
        self.norm=LayerNorm()
        self.embedding_dim = embedding_dim

    def forward(self, x,segments_tensor=None):
        if segments_tensor is None:
            segments_tensor = zeros_like(x).to(x.device)

        x = self.token(x) + self.position(x) + self.segment(segments_tensor)
        x=self.norm(x)
        if self.dropout_rate>0 and self.training:
            x=self.dropout(x)
        return x

class DropPath(Layer):
    """Drop paths (Stochastic Depth) per sample  (when applied in main path of residual blocks).
    """
    def __init__(self, drop_prob=0):
        super(DropPath, self).__init__()
        self.drop_prob = drop_prob

    def forward(self, x):
        #return drop_path(x, self.drop_prob, self.training)

        if self.drop_prob == 0. or not self.get_root().training:
            return x
        keep_prob = 1 - self.drop_prob
        shape = (x.shape[0],) + (1,) * (x.ndim - 1)  # work with diff dim tensors, not just 2D ConvNets

        random_tensor =math_ops.floor( keep_prob +tf.random.uniform(shape, minval=0, maxval=1,dtype=x.dtype))
        output = tf.math.divide_no_nan(x,keep_prob) * random_tensor
        return output

class Attention(Layer):
    """
    Compute 'Scaled Dot Product Attention
    """
    def __init__(self, dropout_rate=0.1):
        super().__init__()
        self.dropout = Dropout(dropout_rate)

    def forward(self, query, key, value, mask=None):

        scores = math_ops.matmul(query, tf.transpose(key,perm = [0, 1, 3, 2])) / math.sqrt(int_shape(query)[-1])
        #scores = math_ops.matmul(tf.transpose(query,perm = [0, 2, 1, 3]), tf.transpose(key,perm = [0, 2, 1, 3])) / math.sqrt(int_shape(query)[-1])

        if mask is not None:
            if scores.dtype == tf.float32:
                scores=where(mask == 1,-1e9,scores)
            else:
                scores = where(mask == 1, -1e+4, scores)

        p_attn = softmax(scores,axis=-1)

        if self.dropout is not None:
            p_attn = self.dropout(p_attn)

        return math_ops.matmul(p_attn, value), p_attn

class MultiHeadedAttention(Layer):
    """
    Take in model size and number of heads.
    """

    def __init__(self, h, d_model, dropout_rate=0.1):
        super().__init__()
        assert d_model % h == 0

        # We assume d_v always equals d_k
        self.d_k = d_model // h
        self.h = h

        self.linear_layers = ModuleList([Dense(d_model) for _ in range(3)])
        self.output_linear = Dense(d_model)
        self.attention = Attention(dropout_rate=dropout_rate)

    def forward(self, x, mask=None):
        batch_size =int_shape(x)[0]
        # 1) Do all the linear projections in batch from d_model => h x d_k
        query=tf.transpose(tf.reshape(self.linear_layers[0](x),(batch_size, -1, self.h, self.d_k)),perm=[0,2,1,3])
        key = tf.transpose(tf.reshape(self.linear_layers[1](x),(batch_size, -1, self.h, self.d_k)),perm=[0,2,1,3])
        value = tf.transpose(tf.reshape(self.linear_layers[2](x),(batch_size, -1, self.h, self.d_k)),perm=[0,2,1,3])

        # 2) Apply attention on all the projected vectors in batch.
        x, attn = self.attention(query, key, value, mask=mask)

        # 3) "Concat" using a view and apply a final linear.
        x=tf.reshape(tf.transpose(x,perm=[0,2,1,3]),(batch_size, -1, self.h * self.d_k))
        return self.output_linear(x)

class SublayerConnection(Layer):
    """
    A residual connection followed by a layer norm.
    Note for code simplicity the norm is first as opposed to last.
    """

    def __init__(self, dropout_rate=0.0):
        super(SublayerConnection, self).__init__()
        self.norm = LayerNorm()
        self.dropout = DropPath(dropout_rate)

    def forward(self, x,sublayer):
        "Apply residual connection to any sublayer with the same size."
        return x + self.dropout(sublayer(self.norm(x)))

class TransformerBlock(Layer):
    """
    Bidirectional Encoder = Transformer (self-attention)
    Transformer = MultiHead_Attention + Feed_Forward with sublayer connection
    """

    def __init__(self, hidden, attn_heads, feed_forward_hidden=None, dropout_rate=0.1):
        """
        param hidden: hidden size of transformer
        :param attn_heads: head sizes of multi-head attention
        :param feed_forward_hidden: feed_forward_hidden, usually 4*hidden_size
        :param dropout: dropout rate
        """

        super().__init__()
        if feed_forward_hidden is None:
            feed_forward_hidden=4*hidden
        self.attention = MultiHeadedAttention(h=attn_heads, d_model=hidden)
        self.feed_forward = PositionwiseFeedForward(d_model=hidden, d_ff=feed_forward_hidden, dropout_rate=dropout_rate)
        self.input_sublayer = SublayerConnection( dropout_rate=dropout_rate)
        self.output_sublayer = SublayerConnection(dropout_rate=dropout_rate)
        self.dropout = Dropout(dropout_rate=dropout_rate)

    def forward(self, x, mask=None):
        x = self.input_sublayer(x, lambda _x: self.attention.forward(_x, mask=mask))
        x = self.output_sublayer(x, self.feed_forward)
        return self.dropout(x)

class BERT(Layer):
    """
    BERT model : Bidirectional Encoder Representations from Transformers.
    """

    def __init__(self, vocab_size, hidden=768, n_layers=12, attn_heads=12, dropout_rate=0.1,pad_idx=0):
        """
        param vocab_size: vocab_size of total words
        :param hidden: BERT model hidden size
        :param n_layers: numbers of Transformer blocks(layers)
        :param attn_heads: number of attention heads
        :param dropout: dropout rate
        """

        super().__init__()
        self.hidden = hidden
        self.n_layers = n_layers
        self.attn_heads = attn_heads
        self.pad_idx=pad_idx
        self.dropout_rate=dropout_rate

        # paper noted they used 4*hidden_size for ff_network_hidden_size
        self.feed_forward_hidden = hidden * 4

        # embedding for BERT, sum of positional, segment, token embeddings
        self.embedding = BERTEmbedding(vocab_size=vocab_size, embedding_dim=hidden,pad_idx=self.pad_idx)
        for i in range(n_layers):
            self.add_module('transformer_block{0}'.format(i),TransformerBlock(hidden, attn_heads, hidden * 4, dropout_rate) )

    def forward(self, x,segments_tensor=None):
        if int_shape(x)[1]==2:
            x,segments_tensor=split(x,num_splits=2,axis=1)
            x=x.squeeze(1)
            segments_tensor=segments_tensor.squeeze(1)
        elif segments_tensor is None:
            segments_tensor = zeros_like(x, dtype=x.dtype).to(get_device())
        # attention masking for padded token
        # torch.ByteTensor([batch_size, 1, seq_len, seq_len)
        mask =tf.expand_dims(tf.tile(tf.expand_dims(x == self.pad_idx,1),(1, int_shape(x)[1], 1)),1).to(x.dtype)

        # embedding the indexed sequence to sequence of vectors
        x = self.embedding(x, segments_tensor)

        # running over multiple transformer blocks
        for name,transformer in self.named_children():
            if 'transformer_block' in name:
                x = transformer.forward(x, mask)
        return x


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

import os
import pickle

#%%

def read_data_from_1810_09466():
    # elements in datalist:
    #    element[0] = R (kpc)
    #    element[1] = vc (km/s)
    #    element[2] = sigma- (km/s)
    #    element[3] = sigma+ (km/s)
    #    element[4] = syst (km/s) # saved later

    dir_path = os.path.dirname(os.path.realpath(__file__))
    data_file=dir_path+'/1810_09466.dat'

    with open(data_file, 'r') as f:
        content = f.readlines()

    data_lists = []
    for line in content:
        if not line.startswith('#') and line.strip():
            data_lists.append([float(a) for a in line.split()])

    systematics_file = dir_path+'/1810_09466-sys-data.dat'

    with open(systematics_file, 'r') as f:
        content = f.readlines()

    syst_list = []
    for line in content:
        if not line.startswith('#') and line.strip():
            syst_list.append([float(a) for a in line.split()])

    relative_syst_list = [data[1] for data in syst_list]

    data_values_list = [data[1] for data in data_lists]
    syst_list = []
    for i in range(len(relative_syst_list)):
        syst_list.append(relative_syst_list[i]*data_values_list[i])

    counter = 0
    for element in data_lists:
        element.append(syst_list[counter])
        counter += 1

    return data_lists

def pickle_results(Analysis, file_name):

    data_to_pickle = {
                'lnlikelihoods':Analysis.sampler.lnprobability,
                'chains':Analysis.sampler.chain,
                'acceptance_fractions':Analysis.sampler.acceptance_fraction,
                'variable_names':Analysis.variables_key_list,
    }

    with open(file_name, "wb") as f:
        pickle.dump(data_to_pickle,file=f)

def load_pickle_results(file_name):
    with open(file_name, "rb") as f:
        return pickle.load(f)

#%%
if __name__ == '__main__':
    pass


class exc(Exception):
	types = {}
	types["NV"] = "Not Enough or too many Values. Required at least 2."
	types["NB"] = "Non base 2 numbers. . ."
class calculate(exc):
	def __init__(self, instance_numbers=[0, 1], output_answer=True):
		for items in [(len(instance_numbers) != 2, "NV"), (len([bob for bob in instance_numbers if bob not in [1, 0]]) != 0, "NB")]:
			if items[0] != False:
				raise exc(exc.types[items[1]])
		self.orinst = instance_numbers[0] or instance_numbers[1]
		print("[DATA] Number value: %d. . .[DISJUNCTION]"%(self.orinst))
		self.andinst = instance_numbers[0] and instance_numbers[1]
		print("[DATA] Number value: %d . . .[CONJUCTION]"%(self.andinst))
	@property
	def calculateIt(self):
		cases = {1:0, 0:1}[self.andinst]
		print("[DATA] Negative: %d. . ."%(cases) + "\r\x0A" + "\x2D"*25)
		final_answer = self.orinst and cases
		print("\r\x0A\r\x0A[DATA] Final answer: %d"%(final_answer))


import random

class bcolors:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKCYAN = '\033[96m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    ENDC = '\033[0m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'

nums = []
for i in range(1, 10):
    num = random.randint(1, 100)
    nums.append(num)

print(f'{bcolors.OKGREEN}{nums}, size: {len(nums)}{bcolors.ENDC}')

def shellsort(nums):
    gap = len(nums)//2

    while gap > 0:
        for i in range(gap, len(nums)):
            temp = nums[i]
            j = i

            while j >= gap and nums[j - gap] > temp:
                nums[j] = nums[j - gap]
                j = j - gap
            nums[j] = temp
        gap = gap // 2

    return nums

print(shellsort(nums))


"""
Meta manager. Defines complex workflow in terms of lower level managers

For usage example see tests

"""
import re
from time import time
import logging

from collections import defaultdict, OrderedDict as odict
from copy import copy, deepcopy

import yaml

from shub_workflow.base import WorkFlowManager

from .utils import get_scheduled_jobs_specs

logger = logging.getLogger(__name__)

_STARTING_JOB_RE = re.compile("--starting-job(?:=(.+))?")

class GraphManager(WorkFlowManager):

    jobs_graph = {}
    base_failed_outcomes = ('failed', 'killed by oom', 'cancelled', 'cancel_timeout', 'memusage_exceeded',
                            'cancelled (stalled)')

    def __init__(self):
        self.__failed_outcomes = list(self.base_failed_outcomes)
        # Ensure jobs are traversed in the same order as they went pending.
        self.__pending_jobs = odict()
        self.__running_jobs = odict()
        self._available_resources = {}  # map resource : ammount
        self._acquired_resources = defaultdict(list)  # map resource : list of (job, ammount)
        self.__tasks = {}
        super(GraphManager, self).__init__()
        self.__start_time = defaultdict(time)
        for task in self.configure_workflow() or ():
            self._add_task(task)

    @property
    def description(self):
        return f"Workflow manager for {self.name!r}"

    def _add_task(self, task):
        assert task.task_id not in self.jobs_graph,\
            "Workflow inconsistency detected: task %s referenced twice." % task.task_id
        self.jobs_graph[task.task_id] = task.as_jobgraph_dict()
        self.__tasks[task.task_id] = task
        for ntask in task.get_next_tasks():
            self._add_task(ntask)

    def configure_workflow(self):
        raise NotImplementedError("configure_workflow() method need to be implemented.")

    def on_start(self):
        if not self.jobs_graph:
            self.argparser.error('Jobs graph configuration is empty.')
        if not self.args.starting_job and not self.args.resume_from_jobid:
            self.argparser.error('You must provide either --starting-job or --resume-from-jobid.')
        self._fill_available_resources()
        ran_tasks = self._maybe_setup_resume()
        self._setup_starting_jobs(ran_tasks)
        self.workflow_loop_enabled = True
        logger.info("Starting '%s' workflow", self.name)

    def _get_starting_jobs_from_resumed_job(self):
        starting_jobs = []
        job = self.get_project().jobs.get(self.args.resume_from_jobid)
        next_option_is_task = False
        for option in job.metadata.get('job_cmd'):
            if next_option_is_task:
                starting_jobs.append(option)
            else:
                m = _STARTING_JOB_RE.match(option)
                if m:
                    task = m.groups()[0]
                    if m:
                        starting_jobs.append(task)
                    else:
                        next_option_is_task = True
        return starting_jobs

    def _maybe_setup_resume(self):
        ran_tasks = []
        if self.args.resume_from_jobid:
            # fill tasks job ids
            logger.info("Will Resume from job (%s)", self.args.resume_from_jobid)
            for _, name, jobid in get_scheduled_jobs_specs(self, [self.args.resume_from_jobid]):
                mname, taskid = name.split('/')
                assert mname == self.name, "Resuming from wrong manager job: %s" % self.args.resume_from_jobid
                self.__tasks[taskid].append_jobid(jobid)
                ran_tasks.append(taskid)
        return ran_tasks

    def _setup_starting_jobs(self, ran_tasks, candidates=None):
        candidates = candidates or self.args.starting_job
        if not candidates:  # resuming
            candidates = self._get_starting_jobs_from_resumed_job()
        for taskid in candidates:
            if taskid in ran_tasks:
                logger.info("Task %s already done %s.", taskid, tuple(self.__tasks[taskid].get_scheduled_jobs()))
                next_tasks = [t.task_id for t in self.__tasks[taskid].get_next_tasks()]
                if next_tasks:
                    self._setup_starting_jobs(ran_tasks, next_tasks)
            else:
                self._add_initial_pending_job(taskid)
                logger.info("Resuming at task %s", taskid)

    def _fill_available_resources(self):
        """
        Ensure there are enough starting resources in order every job
        can run at some point
        """
        for job in self.jobs_graph.keys():
            for required_resources in self.__tasks[job].get_required_resources():
                for resource, req_amount in required_resources.items():
                    old_amount = self._available_resources.get(resource, 0)
                    if old_amount < req_amount:
                        logger.info("Increasing available resources count for %r"
                                    " from %r to %r.  Old value was not enough"
                                    " for job %r to run.",
                                    resource, old_amount, req_amount, job)
                        self._available_resources[resource] = req_amount

    def get_job(self, job, pop=False):
        if job not in self.jobs_graph:
            self.argparser.error('Invalid job: %s. Available jobs: %s' % (job, repr(self.jobs_graph.keys())))
        if pop:
            return self.jobs_graph.pop(job)
        return self.jobs_graph[job]

    def _add_initial_pending_job(self, job):
        wait_for = self.get_job(job).get('wait_for', [])
        self._add_pending_job(job, wait_for=tuple(wait_for))

    def _add_pending_job(self, job, wait_for=(), is_retry=False):
        if job in self.args.skip_job:
            return
        if job in self.__tasks:
            task = self.__tasks[job]
            parallelization = task.get_parallel_jobs()
        else:
            task_id = self.get_job(job).get('origin', job)
            task = self.__tasks[task_id]
            parallelization = 1
        if parallelization == 1:
            self.__pending_jobs[job] = {
                'wait_for': set(wait_for),
                'is_retry': is_retry,
                'wait_time': task.wait_time,
            }
        else:
            # Split parallelized task into N parallel jobs.
            basejobconf = self.get_job(job, pop=True)
            for i in range(parallelization):
                job_unit = "%s_%i" % (job, i)
                job_unit_conf = deepcopy(basejobconf)
                job_unit_conf['origin'] = job
                job_unit_conf['index'] = i

                for _, nextjobs in job_unit_conf.get('on_finish', {}).items():
                    if i != 0:  # only job 0 will conserve finish targets
                        for nextjob in copy(nextjobs):
                            if nextjob != 'retry':
                                if nextjob in self.jobs_graph:
                                    self.get_job(nextjob).setdefault('wait_for', []).append(job_unit)
                                    if nextjob in self.__pending_jobs:
                                        self.__pending_jobs[nextjob]['wait_for'].add(job_unit)
                                else:
                                    for i in range(parallelization):
                                        nextjobp = "%s_%i" % (job, i)
                                        self.get_job(nextjobp).get('wait_for', []).append(job_unit)
                                        if nextjobp in self.__pending_jobs:
                                            self.__pending_jobs[nextjobp]['wait_for'].add(job_unit)
                                nextjobs.remove(nextjob)
                self.jobs_graph[job_unit] = job_unit_conf
                self.__pending_jobs[job_unit] = {
                    'wait_for': set(wait_for),
                    'is_retry': is_retry,
                    'origin': job,
                    'wait_time': task.wait_time,
                }
            for other, oconf in self.jobs_graph.items():
                if job in oconf.get('wait_for', []):
                    oconf['wait_for'].remove(job)
                    if other in self.__pending_jobs:
                        self.__pending_jobs[other]['wait_for'].discard(job)
                    for i in range(parallelization):
                        job_unit = "%s_%i" % (job, i)
                        oconf['wait_for'].append(job_unit)
                        if other in self.__pending_jobs:
                            self.__pending_jobs[other]['wait_for'].add(job_unit)

    def add_argparser_options(self):
        super(GraphManager, self).add_argparser_options()
        self.argparser.add_argument('--jobs-graph', help='Define jobs graph_dict on command line', default='{}')
        self.argparser.add_argument('--starting-job', action='append', default=[],
                                    help='Set starting jobs. Can be given multiple times.')
        self.argparser.add_argument('--only-starting-jobs', action='store_true',
                                    help='If given, only run the starting jobs (don\'t follow on finish next jobs)')
        self.argparser.add_argument('--comment', help='Can be used for differentiate command line and avoid scheduling '
                                    'fail when a graph manager job is scheduled when another one with same option '
                                    'signature is running. Doesn\'t do anything else.')
        self.argparser.add_argument('--skip-job', default=[], action='append',
                                    help='Skip given job. Can be given multiple times. Also next jobs for the skipped'
                                         'one will be skipped.')
        self.argparser.add_argument('--resume-from-jobid', help='Resume from the given graph manager jobid')

    def parse_args(self):
        args = super(GraphManager, self).parse_args()
        self.jobs_graph = yaml.load(args.jobs_graph) or deepcopy(self.jobs_graph)

        if not self.name:
            self.argparser.error('Manager name not set.')
        return args

    def workflow_loop(self):
        logger.debug("Pending jobs: %r", self.__pending_jobs)
        logger.debug("Running jobs: %r", self.__running_jobs)
        logger.debug("Available resources: %r", self._available_resources)
        logger.debug("Acquired resources: %r", self._acquired_resources)
        self.check_running_jobs()
        if self.__pending_jobs:
            self.run_pending_jobs()
        elif not self.__running_jobs:
            return False
        return True

    def run_job(self, job, is_retry=False):
        task = self.__tasks.get(job)
        if task is not None:
            return task.run(self, is_retry)

        jobconf = self.get_job(job)
        task = self.__tasks.get(jobconf['origin'])
        if task is not None:
            idx = jobconf['index']
            return task.run(self, is_retry, index=idx)

    def _must_wait_time(self, job):
        status = self.__pending_jobs[job]
        if status['wait_time'] is not None:
            wait_time = status['wait_time'] - time() + self.__start_time[job]
            if wait_time > 0:
                logger.info("Job %s must wait %d seconds for running", job, wait_time)
                return True
        return False

    def run_pending_jobs(self):
        """Try running pending jobs.

        Normally, only jobs that have no outstanding dependencies are started.

        If all pending jobs have outstanding dependencies, try to start one job
        ignoring unknown tasks, i.e. those that are not currently pending.

        If none of the pending jobs cannot be started either way, it means
        there's a dependency cycle, in this case an error is raised.

        """

        # Normal mode: start jobs without dependencies.
        for job in sorted(self.__pending_jobs.keys()):
            if len(self.__running_jobs) >= self.max_running_jobs:
                break
            status = self.__pending_jobs[job]

            job_can_run = not status['wait_for'] and not self._must_wait_time(job) and self._try_acquire_resources(job)
            if job_can_run:
                try:
                    jobid = self.run_job(job, status['is_retry'])
                except:
                    self._release_resources(job)
                    raise
                self.__pending_jobs.pop(job)
                self.__running_jobs[job] = jobid

        if not self.__pending_jobs or self.__running_jobs or \
                any(status['wait_time'] is not None for status in self.__pending_jobs.values()):
            return

        # At this point, there are pending jobs, but none were started because
        # of dependencies, try "skip unknown deps" mode: start one job that
        # only has "unseen" dependencies to try to break the "stalemate."
        origin_job = None
        for job in sorted(self.__pending_jobs.keys()):
            if len(self.__running_jobs) >= self.max_running_jobs:
                break
            status = self.__pending_jobs[job]
            job_can_run = (
                all(w not in self.__pending_jobs for w in status['wait_for']) and
                (not origin_job or status.get('origin') == origin_job) and
                self._try_acquire_resources(job))
            origin_job = status.get('origin')
            if job_can_run:
                try:
                    jobid = self.run_job(job, status['is_retry'])
                except:
                    self._release_resources(job)
                    raise
                self.__pending_jobs.pop(job)
                self.__running_jobs[job] = jobid
            if not origin_job and self.__running_jobs:
                return

        if self.__running_jobs:
            return

        # Nothing helped, all pending jobs wait for each other somehow.
        raise RuntimeError("Job dependency cycle detected: %s" % ', '.join(
            '%s waits for %s' % (
                job, sorted(self.__pending_jobs[job]['wait_for']))
            for job in sorted(self.__pending_jobs.keys())))

    def check_running_jobs(self):
        for job, jobid in list(self.__running_jobs.items()):
            outcome = self.is_finished(jobid)
            if outcome is not None:
                logger.info('Job "%s/%s" (%s) finished', self.name, job, jobid)
                for st in self.__pending_jobs.values():
                    st['wait_for'].discard(job)
                for conf in self.jobs_graph.values():
                    if job in conf.get('wait_for', []):
                        conf['wait_for'].remove(job)
                for nextjob in self._get_next_jobs(job, outcome):
                    if nextjob == 'retry':
                        jobconf = self.get_job(job)
                        retries = jobconf.get('retries', 0)
                        if retries > 0:
                            self._add_pending_job(job, is_retry=True)
                            jobconf['retries'] -= 1
                            logger.warning('Will retry job %s (outcome: %s, number of retries left: %s)',
                                           job, outcome, jobconf['retries'])
                    elif nextjob in self.__pending_jobs:
                        logger.error('Job %s already pending', nextjob)
                    else:
                        wait_for = self.get_job(nextjob).get('wait_for', [])
                        self._add_pending_job(nextjob, wait_for)
                self._release_resources(job)
                self.__running_jobs.pop(job)
            else:
                logger.info("Job %s (%s) still running", job, jobid)

    def _try_acquire_resources(self, job):
        result = True
        task_id = self.get_job(job).get('origin', job)
        for required_resources in self.__tasks[task_id].get_required_resources(partial=True):
            for resource, req_amount in required_resources.items():
                if self._available_resources[resource] < req_amount:
                    result = False
                    break
            else:
                for resource, req_amount in required_resources.items():
                    self._available_resources[resource] -= req_amount
                    self._acquired_resources[resource].append((job, req_amount))
                return True
        return result

    def _release_resources(self, job):
        for res, acquired in self._acquired_resources.items():
            for rjob, res_amount in acquired:
                if rjob == job:
                    self._available_resources[res] += res_amount
                    self._acquired_resources[res].remove((rjob, res_amount))

    def _get_next_jobs(self, job, outcome):
        if self.args.only_starting_jobs:
            return []
        on_finish = self.get_job(job).get('on_finish', {})
        if outcome in on_finish:
            nextjobs = on_finish[outcome]
        elif outcome in self.__failed_outcomes:
            nextjobs = on_finish.get('failed', [])
        else:
            nextjobs = on_finish.get('default', [])
        return nextjobs

    @property
    def pending_jobs(self):
        return self.__pending_jobs


from __future__ import annotations

import os
import unittest
from collections import defaultdict, namedtuple
from math import ceil
from typing import Any, Iterator

import numpy as np

from rtree.index import Index, Property, RT_TPRTree

class Cartesian(
    namedtuple(
        "Cartesian",
        ("id", "time", "x", "y", "x_vel", "y_vel", "update_time", "out_of_bounds"),
    )
):
    __slots__ = ()

    def getX(self, t: float) -> float:
        return self.x + self.x_vel * (t - self.time)

    def getY(self, t: float) -> float:
        return self.y + self.y_vel * (t - self.time)

    def getXY(self, t: float) -> tuple[float, float]:
        return self.getX(t), self.getY(t)

    def get_coordinates(
        self, t_now: float | None = None
    ) -> tuple[
        tuple[float, float, float, float],
        tuple[float, float, float, float],
        float | tuple[float, float],
    ]:
        return (
            (self.x, self.y, self.x, self.y),
            (self.x_vel, self.y_vel, self.x_vel, self.y_vel),
            self.time if t_now is None else (self.time, t_now),
        )

class QueryCartesian(
    namedtuple("QueryCartesian", ("start_time", "end_time", "x", "y", "dx", "dy"))
):
    __slots__ = ()

    def get_coordinates(
        self,
    ) -> tuple[
        tuple[float, float, float, float],
        tuple[float, float, float, float],
        tuple[float, float],
    ]:
        return (
            (self.x - self.dx, self.y - self.dy, self.x + self.dx, self.y + self.dy),
            (0, 0, 0, 0),
            (self.start_time, self.end_time),
        )

def data_generator(
    dataset_size: int = 100,
    simulation_length: int = 10,
    max_update_interval: int = 20,
    queries_per_time_step: int = 5,
    min_query_extent: float = 0.05,
    max_query_extent: float = 0.1,
    horizon: int = 20,
    min_query_interval: int = 2,
    max_query_interval: int = 10,
    agility: float = 0.01,
    min_speed: float = 0.0025,
    max_speed: float = 0.0166,
    min_x: int = 0,
    min_y: int = 0,
    max_x: int = 1,
    max_y: int = 1,
) -> Iterator[tuple[str, int, Any]]:
    def create_object(
        id_: float, time: float, x: float | None = None, y: float | None = None
    ) -> Cartesian:
        # Create object with random or defined x, y and random velocity
        if x is None:
            x = np.random.uniform(min_x, max_x)
        if y is None:
            y = np.random.uniform(min_y, max_y)
        speed = np.random.uniform(min_speed, max_speed)
        angle = np.random.uniform(-np.pi, np.pi)
        x_vel, y_vel = speed * np.cos(angle), speed * np.sin(angle)

        # Set update time for when out of bounds, or max interval
        for dt in range(1, max_update_interval + 1):
            if not (0 < x + x_vel * dt < max_x and 0 < y + y_vel * dt < max_y):
                out_of_bounds = True
                update_time = time + dt
                break
        else:
            out_of_bounds = False
            update_time = time + max_update_interval

        return Cartesian(id_, time, x, y, x_vel, y_vel, update_time, out_of_bounds)

    objects = list()
    objects_to_update = defaultdict(set)
    for id_ in range(dataset_size):
        object_ = create_object(id_, 0)
        objects.append(object_)
        objects_to_update[object_.update_time].add(object_)
        yield "INSERT", 0, object_

    for t_now in range(1, simulation_length):
        need_to_update = ceil(dataset_size * agility)
        updated_ids = set()

        while need_to_update > 0 or objects_to_update[t_now]:
            kill = False
            if objects_to_update[t_now]:
                object_ = objects_to_update[t_now].pop()
                if object_ not in objects:
                    continue
                kill = object_.out_of_bounds
            else:
                id_ = np.random.randint(0, dataset_size)
                while id_ in updated_ids:
                    id_ = np.random.randint(0, dataset_size)
                object_ = objects[id_]

            updated_ids.add(object_.id)
            need_to_update -= 1

            yield "DELETE", t_now, object_

            if kill:
                x = y = None
            else:
                x, y = object_.getXY(t_now)
            object_ = create_object(object_.id, t_now, x, y)
            objects[object_.id] = object_
            objects_to_update[object_.update_time].add(object_)

            yield "INSERT", t_now, object_

        for _ in range(queries_per_time_step):
            x = np.random.uniform(min_x, max_x)
            y = np.random.uniform(min_y, max_y)
            dx = np.random.uniform(min_query_extent, max_query_extent)
            dy = np.random.uniform(min_query_extent, max_query_extent)
            dt = np.random.randint(min_query_interval, max_query_interval + 1)
            t = np.random.randint(t_now, t_now + horizon - dt)

            yield "QUERY", t_now, QueryCartesian(t, t + dt, x, y, dx, dy)

def intersects(
    x1: float, y1: float, x2: float, y2: float, x: float, y: float, dx: float, dy: float
) -> bool:
    # Checks if line from x1, y1 to x2, y2 intersects with rectangle with
    # bottom left at x-dx, y-dy and top right at x+dx, y+dy.
    # Implementation of https://stackoverflow.com/a/293052

    # Check if line points not both more/less than max/min for each axis
    if (
        (x1 > x + dx and x2 > x + dx)
        or (x1 < x - dx and x2 < x - dx)
        or (y1 > y + dy and y2 > y + dy)
        or (y1 < y - dy and y2 < y - dy)
    ):
        return False

    # Check on which side (+ve, -ve) of the line the rectangle corners are,
    # returning True if any corner is on a different side.
    calcs = (
        (y2 - y1) * rect_x + (x1 - x2) * rect_y + (x2 * y1 - x1 * y2)
        for rect_x, rect_y in (
            (x - dx, y - dy),
            (x + dx, y - dy),
            (x - dx, y + dy),
            (x + dx, y + dy),
        )
    )
    sign = np.sign(next(calcs))  # First corner (bottom left)
    return any(np.sign(calc) != sign for calc in calcs)  # Check remaining 3

class TPRTests(unittest.TestCase):
    def test_tpr(self) -> None:
        # TODO : this freezes forever on some windows cloud builds
        if os.name == "nt":
            return

        # Cartesians list for brute force
        objects = dict()
        tpr_tree = Index(properties=Property(type=RT_TPRTree))

        for operation, t_now, object_ in data_generator():
            if operation == "INSERT":
                tpr_tree.insert(object_.id, object_.get_coordinates())
                objects[object_.id] = object_
            elif operation == "DELETE":
                tpr_tree.delete(object_.id, object_.get_coordinates(t_now))
                del objects[object_.id]
            elif operation == "QUERY":
                tree_intersect = set(tpr_tree.intersection(object_.get_coordinates()))

                # Brute intersect
                brute_intersect = set()
                for tree_object in objects.values():
                    x_low, y_low = tree_object.getXY(object_.start_time)
                    x_high, y_high = tree_object.getXY(object_.end_time)

                    if intersects(
                        x_low,
                        y_low,
                        x_high,
                        y_high,  # Line
                        object_.x,
                        object_.y,
                        object_.dx,
                        object_.dy,
                    ):  # Rect
                        brute_intersect.add(tree_object.id)

                # Tree should match brute force approach
                assert tree_intersect == brute_intersect


from typing import *

import heapq

# TLE
# https://leetcode-cn.com/submissions/detail/292094052/testcase/
class Solution:
    def busiestServers(self, k: int, arrival: List[int], load: List[int]) -> List[int]:
        result = []
        server_load = [0] * k
        # 1 is available, 0 is busy
        available_servers = [1] * k
        task_end_heap = []
        for i, a in enumerate(arrival):
            # free the servers
            while len(task_end_heap) > 0:
                (end_time, server) = heapq.heappop(task_end_heap)
                if end_time <= a:
                    available_servers[server] = 1
                else:
                    heapq.heappush(task_end_heap, (end_time, server))
                    break
            # assign the new request
            server = i % k
            if available_servers[server]:
                available_servers[server] = 0
                heapq.heappush(task_end_heap, (a + load[i], server))
                server_load[server] += 1
            else:
                if sum(available_servers) == 0:
                    # all servers are busy
                    # drop the request
                    continue
                j = (server + 1) % k
                while j != server and not available_servers[j]:
                    j += 1
                    j %= k
                server = j
                if available_servers[server]:
                    available_servers[server] = 0
                    heapq.heappush(task_end_heap, (a + load[i], server))
                    server_load[server] += 1
                else:
                    # drop the request
                    continue
        max_load = max(server_load)
        result = [i for i, x in enumerate(server_load) if x == max_load]
        return result

if __name__ == "__main__":
    s = Solution()

    k = 3
    arrival = [1,2,3,4,5]
    load = [5,2,3,3,3]
    result = s.busiestServers(k, arrival, load)
    assert result == [1]

    k = 3
    arrival = [1,2,3,4]
    load = [1,2,1,2]
    result = s.busiestServers(k, arrival, load)
    assert result == [0]


from tkinter import ttk
import bitmap
from tkinter import Tk, mainloop, Canvas, PhotoImage, filedialog

def rgb2hex(r, g, b):
    """
    Convert an r,g,b colour to a hex code
    """
    return "#{:02x}{:02x}{:02x}".format(r, g, b)

class Root(Tk):
    """
    This is the root object, which inherits from TK

    The benefit of inheritance is we can write:
    self.button instead of self.root.button
    """

    def __init__(self):
        super(Root, self).__init__()
        self.title("BMP compression analyzer")
        self.minsize(640, 400)
        self.row = 3

        self.labelFrame = ttk.LabelFrame(self, text="Open File")
        self.labelFrame.grid(column=0, row=1, padx=20, pady=20)

        self.button()

    def get_row(self):
        self.row += 1
        return self.row

    def button(self):
        self.button = ttk.Button(
            self.labelFrame, text="Browse A File", command=self.file_dialog
        )
        self.button.grid(column=1, row=1)

    def file_dialog(self):
        """
        Opens a file dialog and has the user chose a file

        This then sets some labels afterwards
        """

        self.filename = filedialog.askopenfilename(
            initialdir="./", title="Select A File",
        )
        self.label = ttk.Label(self.labelFrame, text="")
        self.label.grid(column=1, row=2)
        self.label.configure(text=self.filename)
        if self.filename:
            self.get_bmp_info(self.filename)

    def get_bmp_info(self, filename):
        """
        Print some information about the bmp file

        Shows on the UI bmp
        """
        with open(filename, "rb") as bmp_file:
            bmp_data = bitmap.Image(bmp_file.read())

            self.show_image(
                bmp_data.getBitmapWidth(),
                bmp_data.getBitmapHeight(),
                bmp_data.getPixels(),
                self.get_row(),
                0,
            )

    def show_image(self, width, height, pixels, row, col):
        """
        Add an image to the gui
        """
        self.canvas = Canvas(self, width=width, height=height)
        self.canvas.grid(column=col, row=row)

        img = PhotoImage(width=width, height=height)
        self.canvas.create_image((width / 2, height / 2), image=img, state="normal")
        self.canvas.image = img

        for y_index, y in enumerate(pixels):
            for x_index, x in enumerate(y):
                blue, green, red = x
                hex_code = rgb2hex(r=red, g=green, b=blue)
                img.put(hex_code, (x_index, height - y_index))

if __name__ == "__main__":
    root = Root()
    root.mainloop()


import numpy as np
import torch

def ious(box, boxes, isMin = False):#定义iou函数
    box_area = (box[3] - box[1]) * (box[4] - box[2])#计算自信度最大框的面积
    area = (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 4] - boxes[:, 2])#计算其他所有框的面积
    xx1 = torch.max(box[1], boxes[:, 1])#计算交集左上角x的坐标其他同理
    yy1 = torch.max(box[2], boxes[:, 2])
    xx2 = torch.min(box[3], boxes[:, 3])
    yy2 = torch.min(box[4], boxes[:, 4])

    # w = torch.max(0, xx2 - xx1)
    # h = torch.max(0, yy2 - yy1)#获取最大值也可以用下面这种方法
    w = torch.clamp(xx2 - xx1, min=0)#获取最大值
    h = torch.clamp(yy2 - yy1, min=0)

    inter = w * h#计算交集面积

    # ovr1 = inter/torch.min(box_area, area)
    ovr2 = inter/ (box_area + area - inter)#交集面积/并集面积
    # ovr = torch.max(ovr2,ovr1)

    # if isMin:#用于判断是交集/并集，还是交集/最小面积（用于处理大框套小框的情况）
    #
    #     ovr = inter / torch.min(box_area, area)
    # else:
    #     ovr = inter / (box_area + area - inter)

    return ovr2

def nms(boxes, thresh=0.5, isMin = True):#定义nms函数并传3个参数，分别是框，自信度阀值，是否最小面积

    if boxes.shape[0] == 0:#获取框的个是看是否为0，为0没框就返回一个空的数组防止代码报错
        return torch.Tensor([])

    _boxes = boxes[(-boxes[:, 0]).argsort()]#对框进行排序按自信度从大到小的顺序
    r_boxes = []#定义一个空的列表用来装合格的框

    while _boxes.shape[0] > 1:#循环框的个数
        a_box = _boxes[0]#取出第一个（自信度最大的框）框最为目标框与 其他框做iou
        b_boxes = _boxes[1:]#取出剩下的所有框

        r_boxes.append(a_box)#将第一个框添加到列表

        # print(iou(a_box, b_boxes))

        index = torch.where(ious(a_box, b_boxes,isMin) < thresh)#对框做iou将满足iou阀值条件的框留下并反回其索引
        _boxes = b_boxes[index]#根据索引取框并赋值给_boxes，使其覆盖原来的_boxes

    if _boxes.shape[0] > 0:#判断是否剩下最后一个框
        r_boxes.append(_boxes[0])#将最后一个框，说明这是不同物体，并将其放进列表

    return torch.stack(r_boxes)

if __name__ == '__main__':
    # a = np.array([1,1,11,11])
    # bs = np.array([[1,1,10,10],[11,11,20,20]])
    # print(iou(a,bs))

    bs = torch.tensor([[1, 1, 10, 10, 40,8], [1, 1, 9, 9, 10,9], [9, 8, 13, 20, 15,3], [6, 11, 18, 17, 13,2]])
    # print(bs[:,3].argsort())
    print(nms(bs))


from datetime import datetime

class Greeter:
    def __init__(self, name):
        self.name = name

    def day():
        return datetime.now().strftime('%A')

    def part_of_day():  # Определяет часть, дня основываясь на текущем часе
        current_hour = datetime.now().hour

        if current_hour < 12:
            part_of_day = "утра"
        elif 12 <= current_hour < 17:
            part_of_day = 'дня'
        else:
            part_of_day = 'вечера'

        return part_of_day

    def greet(self, store): # Выводит приветствие, используя все расчетные составляющие
        print(f'Здраствуйте, меня зовут  {self.name}, и добро пожаловать'
              f'в {store}!')
        print(f'Желаем вам  приятного {day()} {part_of_day()}')
        print('Дарим вам купон на скидку 20%!')