# Lesson 26 my code
from pyspark.sql import SparkSession #import spark sql with session and row
from pyspark.sql import Row #both of these thigns we use to itneract with SparkSQL and dataFrames

spark = SparkSession.builder.appName("SparkSQL").getOrCreate() #the get or create again, creating a new spark session or connect to one from a previous one

def mapper(line):
    fields = line.split(',')
    return Row(ID = int(fields[0]), #going in order to create the rows. First field or 0th element is ID, etc.
                name = str(fields[1].encode("utf-8")), \
                age = int(fields[2]),
                numFriends = int(fields[3]))

lines = spark.sparkContext.textFile("../CSV/fakefriends.csv") #note that this csv does NOT ahve headers so it may make it difficult to structure the data. We still have SparkCOntext availabel under spark session. Creates RDD named lines.
# Also quick note, original code said textFile("fakefriends.csv") this still has the path problem so I had to update it to go to the director with the csv files
people = lines.map(mapper) #map every row from the incoming lines. Need rows first before creating a DataFrame.

schemaPeople = spark.createDataFrame(people).cache() #we first infer the schema. Passing in people RDD and converting into dataframe. Keep this in memory thats why we cache it
schemaPeople.createOrReplaceTempView("people") #register the DataFrame as a table. Existing view then it would be replaced. Can use this like a database table

teenagers = spark.sql("SELECT * FROM people WHERE age >= 13 AND age <= 19")
#SQL can be run over DataFrames that have been registered as a table ^^^. Teenagers is a dataFrame!! Also the names map back to the names we gave them when we constructed the Row object.

for teen in teenagers.collect(): #results of SQL queries are RDDs and supprot all the normal RDD operations
    print(teen) #this is a simple collect and print

schemaPeople.groupBy("age").count().orderBy("age").show() #can also use fcns rather than SQL queries. We can do either fcns or SQL commands!

spark.stop() #kinda like opening and closing a database. good practice to close if we do not use. Stop when done.


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

"""
test_django-private-chat
------------

Tests for `django-private-chat` models module.
"""

from test_plus.test import TestCase
from django_private_chat.models import *

class DialogMethodTest(TestCase):

    def setUp(self):
        self.dialog = Dialog()
        self.dialog.owner = self.make_user(username="owuser")
        self.dialog.opponent = self.make_user(username="opuser")

    def test_str_method(self):
        self.assertEqual(str(self.dialog), "Chat with opuser")

class MessageMethodTest(TestCase):

    def setUp(self):
        self.dialog = Dialog()
        self.dialog.owner = self.make_user(username="owuser")
        self.dialog.opponent = self.make_user(username="opuser")
        self.dialog.save()
        self.message = Message()
        self.message.dialog = self.dialog
        self.message.sender = self.dialog.owner
        self.message.text = "text about something interesting"
        self.message.save()

    def test_str_method(self):
        """
        Makes sure message text and something relating to the date
        is in the string function output
        """
        mes = str(self.message)
        text = self.message.text
        min = self.message.modified.strftime('%M')
        day = self.message.modified.strftime('%d')
        hour = self.message.modified.strftime('%H')
        tfhour = self.message.modified.strftime('%I')  # 24-hour clock
        month = self.message.modified.strftime('%m')
        lmon = self.message.modified.strftime('%b')  # month abbreviation
        # remove 0 padding
        min = min.lstrip("0").replace(" 0", " ")
        day = day.lstrip("0").replace(" 0", " ")
        hour = hour.lstrip("0").replace(" 0", " ")
        tfhour = tfhour.lstrip("0").replace(" 0", " ")
        month = month.lstrip("0").replace(" 0", " ")

        self.assertIn(text, mes)
        self.assertIn(min, mes)
        self.assertIn(day, mes)
        self.assertTrue(hour in mes or tfhour in mes)
        self.assertTrue(month in mes or lmon in mes)

    def test_soft_delete(self):
        msg = self.message
        self.message.delete()
        self.assertNotIn(msg, Message.objects.all())
        self.assertIn(msg, Message.all_objects.filter(is_removed=True))


#Loops

#python program to find the sum of all elements of a list.

#list of number.
list=[2,4,5,6,78,89,56,7,2]

#sum variable to the numbers.
sum=0

for val in list:
 sum=sum+val

#print sum of all elements.
print("The sum of all elements in list",sum)

#python  program which will find all such numbers which are divisible by 7 but are not a multiple of 5,between 2000 and 3200 (both included).

list=[]
for i in range(2000,3200):
 if i%7==0 and i%5!=0:
    list.append(str(i))
print(','.join(list))


import datacube
import sys
import xarray as xr
import numpy as np
import geopandas as gpd
from datacube.virtual import construct_from_yaml
from datacube.storage.masking import mask_invalid_data
from osgeo import gdal, osr

site = sys.argv[1]

grid = gpd.read_file('/scratch/a.klh5/mangrove_data/shapefiles/{}.shp'.format(site))

bounds = grid.total_bounds

xmin = bounds[0]
xmax = bounds[2]
ymin = bounds[3]
ymax = bounds[1]
crs = int(grid.crs['init'].split(':')[1])

srs = osr.SpatialReference()
srs.ImportFromEPSG(crs)

combined_ls_sref = construct_from_yaml("""
    collate:
        - product: ls4_arcsi_sref_global_mangroves
          measurements: [green, NIR, red]
        - product: ls5_arcsi_sref_global_mangroves
          measurements: [green, NIR, red]
        - product: ls7_arcsi_sref_global_mangroves
          measurements: [green, NIR, red]
        - product: ls8_arcsi_sref_global_mangroves
          measurements: [green, NIR, red]
    """)

def getDataset(crs, xmin, xmax, ymin, ymax):

    "Fetch all data for the given area."

    print("Fetching data...")

    fetch_ds = combined_ls_sref.query(dc, x=(xmin, xmax), y=(ymin, ymax), crs='EPSG:{}'.format(crs), time=('2009-01-01', '2011-12-31'))

    grouped_ds = combined_ls_sref.group(fetch_ds, resolution=(-30, 30), output_crs='EPSG:{}'.format(crs))

    ds = combined_ls_sref.fetch(grouped_ds)

    ds = mask_invalid_data(ds)

    print("Done.")

    return(ds)

def getNDWI(ds):

    print("Generating NDWI...")

    ds['NDWI'] = (ds.green - ds.NIR) / (ds.green + ds.NIR)

    avg = ds.NDWI.mean('time', skipna=True)

    print("Producing mask...")

    wm = xr.where(avg >= -0.3, 1, 0)

    wm = wm.fillna(255)

    wm = wm.astype('uint8')

    wm = wm.sortby("y", ascending=False)

    print("Done.")

    return(wm)

def outputToFile(output):

    outfile = '{}.kea'.format(site)

    # Output to KEA file
    x_size = len(output.x.values)
    y_size = len(output.y.values)
    x_min = np.amin(output.x.values)
    y_max = np.amax(output.y.values)

    geo_transform = (x_min, 30, 0.0, y_max, 0.0, -30)

    driver = gdal.GetDriverByName('KEA')
    output_raster = driver.Create(outfile, x_size, y_size, 1, 1) # Only one band, byte data type since there are only 2 values

    output_raster.SetProjection(srs.ExportToWkt())
    output_raster.SetGeoTransform(geo_transform)

    raster_band = output_raster.GetRasterBand(1)
    raster_band.SetNoDataValue(255)
    raster_band.SetDescription("mask")

    raster_band.WriteArray(output.values)

    output_raster = None

dc = datacube.Datacube()

ds = getDataset(crs, xmin, xmax, ymin, ymax)

wm = getNDWI(ds)

outputToFile(wm)


num_list = [0.136, 0.082, 2.691, 1.175, 4.737, 0.083, 0.082, 1.161, 2.41, 0.0, 7.421, 6.496, 5.012, 1.145, 6.512, 4.547, 4.245, 2.093, 3.511, 3.059, 1.247, 1.882, 7.155, 8.881, 5.095]

num_avg = 0.0
rolling_avg = []

for i,flt in enumerate(num_list, 1):
    num_avg += flt
    rolling_avg.append(num_avg/i)
num_avg = num_avg/len(num_list)

print(num_list)
print(rolling_avg)
print(num_avg)

#given solution

# Initialize a sum accumulator
num_sum = 0.0

# Initialize an empty list to track the rolling average
rolling_avg = []

# Initialize a counter (for use in rolling average)
i = 0

for num in num_list:
    # Accumulate as usual
    num_sum += num

    # Increment counter
    i += 1
    rolling_avg.append(num_sum / i)

# Make sure to divide the sum by the total number of values to get the final average:
num_avg = num_sum / i

# OR: num_avg = num_sum / len(num_list)
# OR: num_avg = rolling_avg[-1]


import torch
import torch.nn as nn
from torch import cat, exp
import torch.nn.functional as F
from torch.nn.functional import pad
from torch.nn.modules.batchnorm import _BatchNorm

class my_AFF(nn.Module):
    '''
    Point-wise Convolution based Attention module (PWAtt)
    '''

    def __init__(self, channels=64, r=2):
        super(my_AFF, self).__init__()
        inter_channels = int(channels // r)

        self.local_att = nn.Sequential(
            nn.Conv1d(in_channels=channels, out_channels=inter_channels, kernel_size=1, stride=1, padding=0),
            nn.BatchNorm1d(inter_channels),
            nn.ReLU(inplace=True),
            nn.Conv1d(in_channels=inter_channels, out_channels=channels, kernel_size=1, stride=1, padding=0),
            nn.BatchNorm1d(channels),
        )

        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        xa = self.local_att(x)
        wei = self.sigmoid(xa)

        xo = 2 * x * wei
        return xo, wei

# Root Mean Squared Logarithmic Error (RMSLE) loss
class RMSLELoss(nn.Module):
    def __init__(self, eps=1e-6):
        super(RMSLELoss, self).__init__()
        self.squared_error = nn.MSELoss(reduction='none')
        self.eps = eps

    def forward(self, y_hat, y, mask, seq_length, sum_losses=False):
        # the log(predictions) corresponding to no data should be set to 0
        # log_y_hat = y_hat.log().where(mask, torch.zeros_like(y))
        log_y_hat = torch.log(y_hat + 1).where(mask, torch.zeros_like(y))
        # the we set the log(labels) that correspond to no data to be 0 as well
        # log_y = y.log().where(mask, torch.zeros_like(y))
        log_y = torch.log(y + 1).where(mask, torch.zeros_like(y))
        # where there is no data log_y_hat = log_y = 0, so the squared error will be 0 in these places
        loss = self.squared_error(log_y_hat, log_y)
        rmsle_loss = torch.sqrt(loss + self.eps)
        loss = torch.sum(rmsle_loss, dim=1)
        if not sum_losses:
            loss = loss / seq_length.clamp(min=1)
        return loss.mean()

# Root Mean Squared Error (MSE) loss
class RMSELoss(nn.Module):
    def __init__(self, eps=1e-6):
        super(RMSELoss, self).__init__()
        self.squared_error = nn.MSELoss(reduction='none')
        self.eps = eps

    def forward(self, y_hat, y, mask, seq_length, sum_losses=False):
        # the predictions corresponding to no data should be set to 0
        y_hat = y_hat.where(mask, torch.zeros_like(y))
        # the we set the labels that correspond to no data to be 0 as well
        y = y.where(mask, torch.zeros_like(y))
        # where there is no data log_y_hat = log_y = 0, so the squared error will be 0 in these places
        loss = self.squared_error(y_hat, y)
        rmse_loss = torch.sqrt(loss + self.eps)
        loss = torch.sum(rmse_loss, dim=1)
        if not sum_losses:
            loss = loss / seq_length.clamp(min=1)
        return loss.mean()

# Mean Squared Logarithmic Error (MSLE) loss
class MSLELoss(nn.Module):
    def __init__(self):
        super(MSLELoss, self).__init__()
        self.squared_error = nn.MSELoss(reduction='none')

    def forward(self, y_hat, y, mask, seq_length, sum_losses=False):
        # the log(predictions) corresponding to no data should be set to 0
        log_y_hat = y_hat.log().where(mask, torch.zeros_like(y))
        # the we set the log(labels) that correspond to no data to be 0 as well
        log_y = y.log().where(mask, torch.zeros_like(y))
        # where there is no data log_y_hat = log_y = 0, so the squared error will be 0 in these places
        loss = self.squared_error(log_y_hat, log_y)
        loss = torch.sum(loss, dim=1)
        if not sum_losses:
            loss = loss / seq_length.clamp(min=1)
        return loss.mean()

# Mean Squared Error (MSE) loss
class MSELoss(nn.Module):
    def __init__(self):
        super(MSELoss, self).__init__()
        self.squared_error = nn.MSELoss(reduction='none')

    def forward(self, y_hat, y, mask, seq_length, sum_losses=False):
        # the predictions corresponding to no data should be set to 0
        y_hat = y_hat.where(mask, torch.zeros_like(y))
        # the we set the labels that correspond to no data to be 0 as well
        y = y.where(mask, torch.zeros_like(y))
        # where there is no data log_y_hat = log_y = 0, so the squared error will be 0 in these places
        loss = self.squared_error(y_hat, y)
        loss = torch.sum(loss, dim=1)
        if not sum_losses:
            loss = loss / seq_length.clamp(min=1)
        return loss.mean()

class MyBatchNorm(_BatchNorm):
    def __init__(self, num_features, eps=1e-5, momentum=0.1, affine=True,
                 track_running_stats=True):
        super(MyBatchNorm, self).__init__(
            num_features, eps, momentum, affine, track_running_stats)

    def forward(self, input):
        self._check_input_dim(input)

        # hack to work around model.eval() issue
        if not self.training:
            self.eval_momentum = 0  # set the momentum to zero when the model is validating

        if self.momentum is None:
            exponential_average_factor = 0.0
        else:
            exponential_average_factor = self.momentum if self.training else self.eval_momentum

        if self.track_running_stats:
            if self.num_batches_tracked is not None:
                self.num_batches_tracked = self.num_batches_tracked + 1
                if self.momentum is None:  # use cumulative moving average
                    exponential_average_factor = 1.0 / float(self.num_batches_tracked)
                else:  # use exponential moving average
                    exponential_average_factor = self.momentum if self.training else self.eval_momentum

        return F.batch_norm(
            input, self.running_mean, self.running_var, self.weight, self.bias,
            training=True, momentum=exponential_average_factor, eps=self.eps)  # set training to True so it calculates the norm of the batch

class MyBatchNorm1d(MyBatchNorm):
    def _check_input_dim(self, input):
        if input.dim() != 2 and input.dim() != 3:
            raise ValueError('expected 2D or 3D input (got {}D input)'.format(input.dim()))

class EmptyModule(nn.Module):
    def forward(self, X):
        return X

class TempSepConv_CAFF(nn.Module):
    def __init__(self, config, no_ts_features=None, no_daig_features=None, no_flat_features=None):

        super(TempSepConv_CAFF, self).__init__()
        self.task = config['task']
        self.n_layers = config['n_layers']
        self.diagnosis_size = config['diagnosis_size']
        self.main_dropout_rate = config['main_dropout_rate']
        self.temp_dropout_rate = config['temp_dropout_rate']
        self.kernel_size = config['kernel_size']
        self.temp_kernels = config['temp_kernels']
        self.last_linear_size = config['last_linear_size']
        self.no_ts_features = no_ts_features
        self.no_daig_features = no_daig_features
        self.no_flat_features = no_flat_features

        self.no_diag = config['no_diag']

        self.alpha = 100

        self.keep_prob = 1-config['main_dropout_rate'] #0.5

        self.relu = nn.ReLU()
        self.sigmoid = nn.Sigmoid()
        self.hardtanh = nn.Hardtanh(min_val=1/48, max_val=100)  # keep the end predictions between half an hour and 100 days
        self.rmsle_loss = RMSLELoss()
        self.msle_loss = MSLELoss()
        self.mse_loss = MSELoss()
        self.bce_loss = nn.BCELoss()

        self.main_dropout = nn.Dropout(p=self.main_dropout_rate)
        self.temp_dropout = nn.Dropout(p=self.temp_dropout_rate)

        self.remove_none = lambda x: tuple(xi for xi in x if xi is not None)  # removes None items from a tuple
        self.empty_module = EmptyModule()

        self.batchnormclass = MyBatchNorm1d
        # self.batchnormclass = nn.BatchNorm1d

        self.diagnosis_encoder = nn.Linear(in_features=self.no_daig_features, out_features=self.diagnosis_size)

        self.diagnosis_encoder1 = nn.Linear(in_features=self.no_daig_features, out_features=self.temp_kernels[0]+1)
        self.flat_encoder = nn.Linear(in_features=self.no_flat_features, out_features=self.temp_kernels[0]+1)

        self.bn_diagnosis_encoder = self.batchnormclass(num_features=self.diagnosis_size, momentum=0.1)  # input shape: B * diagnosis_size
        self.bn_point_last_los = self.batchnormclass(num_features=self.last_linear_size, momentum=0.1)  # input shape: (B * T) * last_linear_size
        self.bn_point_last_mort = self.batchnormclass(num_features=self.last_linear_size, momentum=0.1)  # input shape: (B * T) * last_linear_size

        # self.bn_diagnosis_encoder = self.empty_module
        # self.bn_point_last_los = self.empty_module
        # self.bn_point_last_mort = self.empty_module

        # input shape: (B * T) * last_linear_size
        # output shape: (B * T) * 1
        self.final_los = nn.Linear(in_features=self.last_linear_size, out_features=1)
        self.final_mort = nn.Linear(in_features=self.last_linear_size, out_features=1)

        # TDSC layers settings
        self.layers = []
        for i in range(self.n_layers):
            dilation = i * (self.kernel_size - 1) if i > 0 else 1  # dilation = 1 for the first layer, after that it captures all the information gathered by previous layers
            temp_k = self.temp_kernels[i]

            self.layers.append({})
            if temp_k is not None:
                padding = [(self.kernel_size - 1) * dilation, 0]  # [padding_left, padding_right]
                self.layers[i]['temp_kernels'] = temp_k
                self.layers[i]['dilation'] = dilation
                self.layers[i]['padding'] = padding
                self.layers[i]['stride'] = 1

        self.layer_modules = nn.ModuleDict()

        self.Y = 0  # Y is the number of channels in the previous temporal layer (could be 0 if this is the first layer)
        self.n = 0  # n is the layer number

        for i in range(self.n_layers):

            temp_in_channels = (self.no_ts_features + self.n) * (1 + self.Y) if i > 0 else 2 * self.no_ts_features  # (F + n) * (Y + 1)
            temp_out_channels = (self.no_ts_features + self.n) * self.layers[i]['temp_kernels']  # (F + n) * temp_kernels
            out_channels_caff = (self.no_ts_features+self.n+1)*(self.layers[i]['temp_kernels']+1)
            if self.n == 0:
                linear_input_dim = (self.no_ts_features + self.n - 1) * self.Y + 2 * self.no_ts_features + 2 + self.no_flat_features
            else:
                linear_input_dim = (self.no_ts_features + self.n - 1) * self.Y + (self.layers[i]['temp_kernels']+1) + 2 * self.no_ts_features + 2 + self.no_flat_features  # (F + n-1) * Y + Z + 2F + 2 + no_flat_features
            linear_output_dim = (self.layers[i]['temp_kernels']+1)

            temp = nn.Conv1d(in_channels=temp_in_channels,  # (F + n) * (Y + 1)
                             out_channels=temp_out_channels,  # (F + n) * Y
                             kernel_size=self.kernel_size,
                             stride=self.layers[i]['stride'],
                             dilation=self.layers[i]['dilation'],
                             groups=self.no_ts_features + self.n)

            caff_fc = nn.Linear(in_features=linear_input_dim, out_features=linear_output_dim)

            bn_temp = self.batchnormclass(num_features=temp_out_channels, momentum=0.1)
            bn_caff = self.batchnormclass(num_features=linear_output_dim, momentum=0.1)

            # bn_temp = bn_point = self.empty_module  # linear module; does nothing

            A_layer = my_AFF(out_channels_caff)
            FFA_layer = my_AFF(linear_input_dim)

            self.layer_modules[str(i)] = nn.ModuleDict({
                'temp': temp,
                'bn_temp': bn_temp,
                'caff_fc': caff_fc,
                'bn_caff': bn_caff,
                'A_layer': A_layer,
                'FFA_layer': FFA_layer})

            self.Y = self.layers[i]['temp_kernels']
            self.n += 1

        # input shape: (B * T) * ((F + n) * (1 + Y) + diagnosis_size + no_flat_features)
        # output shape: (B * T) * last_linear_size
        # input_size = (self.no_ts_features + self.n) * (1 + self.Y) + self.diagnosis_size + self.no_flat_features
        #input_size = (self.no_ts_features + self.n) * (1 + self.Y) + self.diagnosis_size + self.no_flat_features

        input_size = (self.no_ts_features + self.n) * (1 + self.Y) + (self.n_layers * (1 + self.Y)) + self.diagnosis_size + self.no_flat_features
        if self.no_diag:
            # input_size = input_size - self.diagnosis_size
            input_size = input_size - self.diagnosis_size #input_size - self.diagnosis_size

        self.last_los_fc = nn.Linear(in_features=input_size, out_features=self.last_linear_size)
        self.last_mort_fc = nn.Linear(in_features=input_size, out_features=self.last_linear_size)

        return

    def tdsc_caff(self, B=None, T=None, X=None, repeat_flat=None, X_orig=None, temp=None, bn_temp=None, caff_fc=None,
                       bn_caff=None, A_layer=None, FFA_layer=None, temp_kernels=None, padding=None, prev_temp=None, prev_caff=None, m_scale_output=None,
                       caff_skip=None):

        X_padded = pad(X, padding, 'constant', 0)  # B * ((F + n) * (Y + 1)) * (T + padding)
        X_temp = self.temp_dropout(bn_temp(temp(X_padded)))  # B * ((F + n) * temp_kernels) * T

        #### Context Aware Attentive Feature Fusion (CAFF) #####
        if prev_caff is None:
            X_concat = cat(self.remove_none((prev_temp,  # (B * T) * ((F + n-1) * Y)
                                            prev_caff,  # (B * T) * 1
                                            X_orig,  # (B * T) * (2F + 2)
                                            repeat_flat)),  # (B * T) * no_flat_features
                        dim=1)  # (B * T) * (((F + n-1) * Y) + 1 + 2F + 2 + no_flat_features)
        else:
            X_concat = cat(self.remove_none((prev_temp.view(B*T,-1),  # (B * T) * ((F + n-1) * Y)
                                            prev_caff.permute(0,3,1,2).view(B*T,-1),  # (B * T) * 1
                                            X_orig,  # (B * T) * (2F + 2)
                                            repeat_flat)),  # (B * T) * no_flat_features
                        dim=1)  # (B * T) * (((F + n-1) * Y) + 1 + 2F + 2 + no_flat_features)

        X_concat, wei_1 = FFA_layer(X_concat.view(B,T,-1).permute(0,2,1)) # Step 2 Attention
        X_concat = X_concat.permute(0,2,1).view(B*T,-1)
        caff_output = self.main_dropout(bn_caff(caff_fc(X_concat)))  # (B * T) * 1
        caff_output = caff_output.view(B, T, -1).unsqueeze(2).permute(0,2,3,1)

        # Accumulate multi-scale features
        m_scale_output = cat((m_scale_output,caff_output), dim=1) if m_scale_output is not None else caff_output

        caff_skip = cat((caff_skip, prev_caff[:,:,-1,:].unsqueeze(2)), dim=1) if prev_caff is not None else caff_skip

        temp_skip = cat((caff_skip,  # B * (F + n) * 1 * T
                         X_temp.view(B, caff_skip.shape[1], temp_kernels, T)),  # B * (F + n) * temp_kernels * T
                        dim=2)  # B * (F + n) * (1 + temp_kernels) * T

        X_combined = self.relu(cat((temp_skip, caff_output), dim=1))  # B * (F + n) * (1 + temp_kernels) * T
        next_X = X_combined.view(B, (caff_skip.shape[1] + 1) * (1 + temp_kernels), T)  # B * ((F + n + 1) * (1 + temp_kernels)) * T

        next_X, wei_2 = A_layer(next_X.view(B,-1,T)) # step 4 attention
        next_X =  next_X.view(B, (caff_skip.shape[1] + 1) * (1 + temp_kernels), T)

        temp_output = X_temp.permute(0, 2, 1).contiguous().view(B * T, caff_skip.shape[1] * temp_kernels)  # (B * T) * ((F + n) * temp_kernels)

        return (temp_output,  # (B * T) * ((F + n) * temp_kernels)
                caff_output,  # (B * T) * 1
                next_X,  # B * ((F + n) * (1 + temp_kernels)) * T
                caff_skip, # caff features of the prevous layer
                m_scale_output, #  keeping track of the caff multi scale features from all layers; B * (F + n) * T
                wei_1, wei_2)  #  PWatt Attention weights

    def forward(self, X, diagnoses, flat, time_before_pred=5):

        # flat is B * no_flat_features
        # diagnoses is B * no_daig_features
        # X is B * no_daig_features * T

        # split into features and indicator variables
        X_separated = torch.split(X[:, 1:-1, :], self.no_ts_features, dim=1)  # tuple ((B * F * T), (B * F * T))

        # prepare repeat arguments and initialise layer loop
        B, _, T = X_separated[0].shape

        repeat_flat = flat.repeat_interleave(T, dim=0)  # (B * T) * no_flat_features
        X_orig = X.permute(0, 2, 1).contiguous().view(B * T, 2 * self.no_ts_features + 2)  # (B * T) * (2F + 2)
        repeat_args = {'repeat_flat': repeat_flat,
                        'X_orig': X_orig,
                        'B': B,
                        'T': T}

        next_X = torch.stack(X_separated, dim=2).reshape(B, 2 * self.no_ts_features, T)
        caff_skip = X_separated[0].unsqueeze(2)  # ts features without indicators, keeps track of caff skip connections generated from caff module;
        temp_output = None
        caff_output = None
        m_scale_output = None
        wei_step2 = []
        wei_step4 = []
        for i in range(self.n_layers):
            kwargs = dict(self.layer_modules[str(i)], **repeat_args)

            temp_output, caff_output, next_X, caff_skip, m_scale_output, wei_1, wei_2 = self.tdsc_caff(X=next_X, caff_skip=caff_skip,
                                                                prev_temp=temp_output, prev_caff=caff_output,
                                                                temp_kernels=self.layers[i]['temp_kernels'],
                                                                padding=self.layers[i]['padding'],
                                                                m_scale_output= m_scale_output,
                                                                **kwargs)

            wei_step2.append(wei_1.detach().cpu())
            wei_step4.append(wei_2.detach().cpu())

        m_scale_output = m_scale_output.view(B,-1,T)
        if self.no_diag:
            combined_features = cat((flat.repeat_interleave(T - time_before_pred, dim=0),  # (B * (T - time_before_pred)) * no_flat_features
                                     next_X[:, :, time_before_pred:].permute(0, 2, 1).contiguous().view(B * (T - time_before_pred), -1),
                                     m_scale_output[:, :, time_before_pred:].permute(0, 2, 1).contiguous().view(B * (T - time_before_pred), -1)), dim=1)  # (B * (T - time_before_pred)) * (((F + n) * (1 + Y)) + no_flat_features) for tpc
        else:
            diagnoses_enc = self.relu(self.main_dropout(self.bn_diagnosis_encoder(self.diagnosis_encoder(diagnoses))))  # B * diagnosis_size
            combined_features = cat((flat.repeat_interleave(T - time_before_pred, dim=0),  # (B * (T - time_before_pred)) * no_flat_features
                                     diagnoses_enc.repeat_interleave(T - time_before_pred, dim=0),  # (B * (T - time_before_pred)) * diagnosis_size
                                     next_X[:, :, time_before_pred:].permute(0, 2, 1).contiguous().view(B * (T - time_before_pred), -1),
                                     m_scale_output[:, :, time_before_pred:].permute(0, 2, 1).contiguous().view(B * (T - time_before_pred), -1)), dim=1)  # (B * (T - time_before_pred)) * (((F + n) * (1 + Y)) + diagnosis_size + no_flat_features) for tpc

        last_los = self.relu(self.main_dropout(self.bn_point_last_los(self.last_los_fc(combined_features))))
        last_mort = self.relu(self.main_dropout(self.bn_point_last_mort(self.last_mort_fc(combined_features))))

        los_predictions = self.hardtanh(exp(self.final_los(last_los).view(B, T - time_before_pred)))  # B * (T - time_before_pred)
        mort_predictions = self.sigmoid(self.final_mort(last_mort).view(B, T - time_before_pred))  # B * (T - time_before_pred)

        return los_predictions, mort_predictions, wei_step2, wei_step4

    def loss(self, y_hat_los, y_hat_mort, y_los, y_mort, mask, seq_lengths, device, sum_losses, loss_type):
        # mortality loss
        if self.task == 'mortality':
            loss = self.bce_loss(y_hat_mort, y_mort) * self.alpha
        # LoS loss
        else:
            bool_type = torch.cuda.BoolTensor if device == torch.device('cuda:3') else torch.BoolTensor
            if loss_type == 'rmsle':
                los_loss = self.rmsle_loss(y_hat_los, y_los, mask.type(bool_type), seq_lengths, sum_losses)
            if loss_type == 'msle':
                los_loss = self.msle_loss(y_hat_los, y_los, mask.type(bool_type), seq_lengths, sum_losses)
            elif loss_type == 'mse':
                los_loss = self.mse_loss(y_hat_los, y_los, mask.type(bool_type), seq_lengths, sum_losses)

            loss = los_loss
        return loss


from __future__ import annotations

import sys
from typing import TYPE_CHECKING

from ansiblelint.rules import AnsibleLintRule

if TYPE_CHECKING:
    from ansiblelint.file_utils import Lintable
    from ansiblelint.utils import Task

def _changed_in_when(item: str) -> bool:
    if not isinstance(item, str):
        return False
    item_list = item.split()

    if {"and", "or", "not"} & set(item_list):
        return False
    return any(
        changed in item
        for changed in [
            ".changed",
            "|changed",
            '["changed"]',
            "['changed']",
            "is changed",
        ]
    )

class UseHandlerRatherThanWhenChangedRule(AnsibleLintRule):
    """Tasks that run when changed should likely be handlers."""

    id = "no-handler"
    description = (
        "If a task has a ``when: result.changed`` setting, it is effectively "
        "acting as a handler. You could use ``notify`` and move that task to "
        "``handlers``."
    )
    link = "https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_handlers.html#handlers"
    severity = "MEDIUM"
    tags = ["idiom"]
    version_added = "historic"

    def matchtask(
        self,
        task: Task,
        file: Lintable | None = None,
    ) -> bool | str:
        if task["__ansible_action_type__"] != "task" or task.is_handler():
            return False

        when = task.get("when")
        result = False

        if isinstance(when, list):
            if len(when) <= 1:
                result = _changed_in_when(when[0])
        elif isinstance(when, str):
            result = _changed_in_when(when)
        return result

if "pytest" in sys.modules:
    import pytest

    # pylint: disable=ungrouped-imports
    from ansiblelint.rules import RulesCollection
    from ansiblelint.runner import Runner
    from ansiblelint.testing import run_ansible_lint

    @pytest.mark.parametrize(
        ("test_file", "failures"),
        (
            pytest.param("examples/playbooks/no_handler_fail.yml", 5, id="fail"),
            pytest.param("examples/playbooks/no_handler_pass.yml", 0, id="pass"),
        ),
    )
    def test_no_handler(
        default_rules_collection: RulesCollection,
        test_file: str,
        failures: int,
    ) -> None:
        """Test rule matches."""
        results = Runner(test_file, rules=default_rules_collection).run()
        assert len(results) == failures
        for result in results:
            assert result.tag == "no-handler"

    def test_role_with_handler() -> None:
        """Test role with handler."""
        role_path = "examples/roles/role_with_handler"

        results = run_ansible_lint("-v", role_path)
        assert "no-handler" not in results.stdout


import typing as t
import collections

import flask_restx
import flask_restx.fields as frf
import marshmallow.fields as mf
from marshmallow_pynamodb import ModelSchema

from model.base_model import Model
from common.util import create_table

class Serializer(ModelSchema):
    _api_model = None

    def __init__(self, *args, **kwargs):
        super(Serializer, self).__init__(*args, **kwargs)
        create_table(self.model())

    @property
    def api_model(self):
        if self._api_model is None:
            self._api_model = self._get_api_model()
        return self._api_model

    def loads_required(self, json_data: str, many: bool = False):
        data = self.loads(json_data=json_data, many=many).attribute_values
        if many:
            return [self._remove_additional_fields(data_entry) for data_entry in data]
        return self._remove_additional_fields(data)

    def serialize(self, obj, *, many: bool = False):
        return super(Serializer, self)._serialize(obj, many=many)

    def _remove_additional_fields(self, data: dict):
        """ Remove fields that aren't provided by user in request """
        return {k: v for k, v in data.items() if k in self.declared_fields}

    def _get_api_model(self):
        """ Map marshmallow schema into flask_restx api model """
        model_name = self.model().__name__.replace("Model", "")
        rest_attributes = collections.OrderedDict()
        for key, value in self.declared_fields.items():
            rest_attributes[key] = self.map_marshmallow_field_to_api_field(value)
        return flask_restx.Model(model_name, rest_attributes)

    @classmethod
    def model(cls) -> t.Type[Model]:
        """ Expose PynamoDB Model """
        return cls.Meta.model

    @classmethod
    def map_marshmallow_field_to_api_field(cls, marshmallow_field: mf.Field):
        if isinstance(marshmallow_field, mf.String):
            return frf.String()
        if isinstance(marshmallow_field, (mf.Raw, mf.Mapping, mf.Dict)):
            return frf.Raw()
        if isinstance(marshmallow_field, (mf.List, mf.Tuple)):
            return frf.List(cls.map_marshmallow_field_to_api_field(marshmallow_field.inner))
        if isinstance(marshmallow_field, (mf.Number, mf.Integer, mf.Decimal, mf.Int)):
            return frf.Integer()
        if isinstance(marshmallow_field, (mf.Boolean, mf.Bool)):
            return frf.Boolean()
        if isinstance(marshmallow_field, mf.Float):
            return frf.Float()
        if isinstance(marshmallow_field, mf.Date):
            return frf.Date()
        if isinstance(marshmallow_field, mf.DateTime):
            return frf.DateTime()
        if isinstance(marshmallow_field, (mf.Url, mf.URL)):
            return frf.Url()
        raise Exception(f"Cannot map {marshmallow_field} to API model field")

def serializer_factory(model_class: t.Type[Model]):
    class _Serializer(Serializer):
        is_removed = mf.Boolean(default=False)
        created_at = mf.Float(allow_none=True)

        class Meta:
            model = model_class

    return _Serializer


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

from InterpolatePoints import *

class InterpolatePoints(object):
    def __init__(self):
        self.label = "Interpolate points"
        self.description = ""
        self.canRunInBackground = True

    def getParameterInfo(self):

        param_points_table = arcpy.Parameter(
            displayName="Data points (table)",
            name="points_table",
            datatype="GPTableView",
            parameterType="Required",
            direction="Input")
        param_pts_id_field = arcpy.Parameter(
            displayName="ID field in the data points table",
            name="pts_id_field",
            datatype="Field",
            parameterType="Required",
            direction="Input")
        param_pts_rid_field = arcpy.Parameter(
            displayName="Route ID field in the data points table",
            name="pts_rid_field",
            datatype="Field",
            parameterType="Required",
            direction="Input")
        param_pts_distfield = arcpy.Parameter(
            displayName="Distance field in the data points on network layer",
            name="pts_distfield",
            datatype="Field",
            parameterType="Required",
            direction="Input")
        param_list_fields = arcpy.Parameter(
            displayName="Choose the fields with values to interpolate",
            name="list_fields_to_keep",
            datatype="Field",
            parameterType="Required",
            direction="Input",
            multiValue=True)
        param_targets = arcpy.Parameter(
            displayName="Target points to interpolate on (table)",
            name="targets",
            datatype="GPTableView",
            parameterType="Required",
            direction="Input")
        param_targets_id_field = arcpy.Parameter(
            displayName="ID field in the target points table",
            name="targets_id_field",
            datatype="Field",
            parameterType="Required",
            direction="Input")
        param_targets_rid_field = arcpy.Parameter(
            displayName="Route ID field in the target points table",
            name="targets_rid_field",
            datatype="Field",
            parameterType="Required",
            direction="Input")
        param_targets_distfield = arcpy.Parameter(
            displayName="Distance field in the target points on network layer",
            name="targets_distfield",
            datatype="Field",
            parameterType="Required",
            direction="Input")
        param_routes = arcpy.Parameter(
            displayName="Input route feature class (lines)",
            name="routes",
            datatype="GPFeatureLayer",
            parameterType="Required",
            direction="Input")
        param_RID_field = arcpy.Parameter(
            displayName="RID field in routes feature class",
            name="RID_field",
            datatype="Field",
            parameterType="Required",
            direction="Input")
        param_order_field = arcpy.Parameter(
            displayName="Ordering field in routes feature class",
            name="order_field",
            datatype="Field",
            parameterType="Required",
            direction="Input")
        param_links = arcpy.Parameter(
            displayName="Routes links",
            name="links",
            datatype="GPTableView",
            parameterType="Required",
            direction="Input")
        param_output_points = arcpy.Parameter(
            displayName="Points Output table",
            name="output_points",
            datatype="GPTableView",
            parameterType="Required",
            direction="Output")

        param_pts_id_field.parameterDependencies = [param_points_table.name]
        param_pts_rid_field.parameterDependencies = [param_points_table.name]
        param_pts_distfield.parameterDependencies = [param_points_table.name]
        param_list_fields.parameterDependencies = [param_points_table.name]
        param_targets_id_field.parameterDependencies = [param_targets.name]
        param_targets_rid_field.parameterDependencies = [param_targets.name]
        param_targets_distfield.parameterDependencies = [param_targets.name]
        param_RID_field.parameterDependencies = [param_routes.name]
        param_order_field.parameterDependencies = [param_routes.name]

        params = [param_points_table, param_pts_id_field, param_pts_rid_field, param_pts_distfield, param_list_fields,
                  param_targets, param_targets_id_field, param_targets_rid_field, param_targets_distfield, param_routes,
                  param_RID_field, param_order_field, param_links, param_output_points]

        return params

    def isLicensed(self):
        return True

    def updateParameters(self, parameters):
        return

    def updateMessages(self, parameters):
        return

    def execute(self, parameters, messages):

        points_table = parameters[0].valueAsText
        id_field_pts = parameters[1].valueAsText
        RID_field_pts = parameters[2].valueAsText
        Distance_field_pts = parameters[3].valueAsText
        list_fields = (parameters[4].valueAsText).split(';')
        data_fields = [str(item) for item in list_fields]
        targetpoints = parameters[5].valueAsText
        id_field_target = parameters[6].valueAsText
        RID_field_target = parameters[7].valueAsText
        Distance_field_target = parameters[8].valueAsText
        network_shp = parameters[9].valueAsText
        network_RID_field = parameters[10].valueAsText
        order_field = parameters[11].valueAsText
        links_table= parameters[12].valueAsText
        ouput_table = parameters[13].valueAsText

        execute_InterpolatePoints(points_table, id_field_pts, RID_field_pts, Distance_field_pts, data_fields,
                                  targetpoints, id_field_target, RID_field_target, Distance_field_target, network_shp,
                                  links_table, network_RID_field, order_field, ouput_table)

        return


n = input()
n = list(n)
lst = []
for i in range(0,len(n)-1):
    count = 1
    for j in range(i+1,len(n)):
        if n[i] == n[j]:
            count += 1
        else:
            break
    lst.append(count)
print(max(lst))


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

# In[5]:

# Conventions are the same as Bourbaki, for example,
# Type E convention 1 3 4 5 6 7 8
#                       2

# Input under above convention if type E
J1=[1,2,3,4];
J2=[5,6,7,8];
Type="E";n=6;
D=DynkinDiagram([Type, n]);

# main program.
from sage.combinat.root_system.dynkin_diagram import DynkinDiagram_class

# weight algorithm

def weight(globalType, globaln, D): # return the weigtht of a chunk(type of original dynkin diagram, rank of original dynkin diagram, current chunk)
    n=D.rank();
    Type=D.cartan_matrix().cartan_type().type(); # the intrisic type of current dynkin subdiagram.
    if globalType=="A":
        return (n,0,"A");
    if globalType=="D":
        if Type=="A": # type A chunk.
            if Set(D.index_set())==Set([globaln-2,globaln-1,globaln]): # type D3 case. Note that here we rely on the index set.
                return (2*n-2,0,"D");
            return (n,0,"A");
        else: # type D chunk.
            return (2*n-2,0,"D");
    if globalType=="E":
        if Type=="A": # type A chunk.
            if Set([2,4]).issubset(Set(D.index_set())): # Note that here we rely on the index set.
                if n>=3:
                    return (n,1,"A")  # A^# case;
                elif n==2:
                    return (n,-1,"A"); # A^b case;
            return (n,0,"A");
        if Type=="D":
            return (2*n-2,0,"D")
        if Type=="E":
            return (100,0,"E") # weight is infinity for type E chunks.

def disjointChunks(dynkin,E,i,C,P,maxLen,D): # return all maximal selection P of disjoint chunks P(current selection, the union of all chunk-index of D,current position in C, all dominant chunks, maximal selections,length of maximal selections)
    if i>=len(C):
        if len(dynkin)>=maxLen:
            if len(dynkin)>maxLen:
                maxLen=len(dynkin);
                P=[];
            P.append(copy(dynkin));
        return P,maxLen;
    x=C[i];
    if Set(x[0]).intersection(E).is_empty()==True:
        f=True;
        for j in dynkin:
            if D.subtype(Set(j[0]).union(Set(x[0]))).is_connected()==True: # the new connected chunk is not disjoint to dynkin.
                f=False;
                break;
        if f: # if disjoint, we can add the new chunk x.
            dynkin.append(x);
            P,maxLen=disjointChunks(dynkin,E.union(Set(x[0])),i+1,C,P,maxLen,D);
            dynkin.pop();
    P,maxLen=disjointChunks(dynkin,E,i+1,C,P,maxLen,D); # we ignore the new chunk x.
    return P,maxLen;

def weightAlg(Type, D,n , J1, J2,J): # the weight algorithm on labeled dynkin diagram D,J1,J2(type of dynkin diagram, dynkin diagram, rank, label J1, label J2, union of all labels/support)
    if Set(J)==Set(J1) or Set(J)==Set(J2):  # the whole diagram is uniformly labeled.
        return [[]];
    L1=D.subtype(J1);
    L2=D.subtype(J2);
    index1=DynkinDiagram_class(L1).strongly_connected_components();
    index2=DynkinDiagram_class(L2).strongly_connected_components();

    if len(index1)==1:
        index1=[J1];
    if len(index2)==1:
        index2=[J2];
    weight1=[];
    weight2=[];
    maxWeight=0;
    for i in index1:
        w=weight(Type,n, D.subtype(i))
        weight1.append(w);
        if w[0]>maxWeight:
            maxWeight=w[0];
    for i in index2:
        w=weight(Type,n, D.subtype(i))
        weight2.append(w);
        if w[0]>maxWeight:
            maxWeight=w[0];

    # Step 1: finding all dominant chunks.
    C=[];# format: (root_index, label, (weight, type))
    for i in range(len(weight1)):
        if weight1[i][0]==maxWeight:
            C.append((index1[i],1,weight1[i]));
    for i in range(len(weight2)):
        if weight2[i][0]==maxWeight:
            C.append((index2[i],2,weight2[i]));
    # Step 2: finding all selections P of dominant chunks.
    P,temp=disjointChunks([],Set([]),0,C,[],0,D); # get the list of maximal selections.
    dominant_collection=[];
    if len(P)==1:
        dominant_collection.append(P[0]);
    else: # Step 3: tie breaking.
        # 1. choose as many type A as possible.
        P1=copy(P);
        for d in P:
            for l in d:
                if l[2][2]!="A": # the type of chunks
                    P1.remove(d);
        if len(P1)>0:
            P=P1;
        if len(P)==1:
            dominant_collection.append(P[0]);
        else:
            # 2. choose those not adjacent to extra root.
            extraRoots=[];
            if Type=="D":
                extraRoots=[n,n-1];
            if Type=="E":
                extraRoots=[2];
            if extraRoots!=[]:
                P1=copy(P);
                for j in extraRoots:
                    for d in P:
                        f=False;
                        for l in d:
                            if (j in l[0])==True:
                                break;
                            if D.subtype(Set(l[0]).union(Set([j]))).is_connected()==True: # this selection of chunks is adjacent to extra root.
                                f=True;
                        if f:
                            if d in P1:
                                P1.remove(d);

                if len(P1)>0:
                    P=P1;
                if len(P)==1:
                    dominant_collection.append(P[0]);
                else:
                    # 3. A^# and A^b cases.
                    if Type=="E":
                        f=False;
                        for d in P:
                            for l in d:
                                if l[2][1]==1:    # A^# case.
                                    f=True;
                                    dominant_collection.append(d);
                                    break;
                        if not f:
                            P1=copy(P);
                            for d in P:
                                for l in d:
                                    if l[2][1]==-1:       # A^b case
                                        P1.remove(d);
                            if len(P1)>0:
                                P=P1;

    if dominant_collection==[]:    # 4. the rest choices are all ok.
        dominant_collection+=P;

    totalKillList=[];
    D_copy=copy(D);
    J1_copy=copy(J1);
    J2_copy=copy(J2);
    J_copy=copy(J);
    for dominant_selection in dominant_collection:
        D=copy(D_copy);
        J1=copy(J1_copy);
        J2=copy(J2_copy);
        J=copy(J_copy);
        dominants=Set({});
        for d in dominant_selection:
            dominants=dominants.union(Set(d[0]));
        dominants=list(dominants);
        # kill the roots adjacents to the dominant selection.
        kill_list=[];
        for i in D.index_set():
            if not (i in dominants):
                f=False;
                for j in dominants:
                    if D.subtype(Set([i]).union(Set([j]))).is_connected():
                        f=True;
                if f:
                    kill_list.append(i);
                    if i in J1:
                        J1.remove(i);
                    if i in J2:
                        J2.remove(i);
                    if i in J:
                        J.remove(i);
        # induction with the subdiagram.
        kill_list=list(Set(kill_list));
        D=D.subtype(J);
        subdiagram=False;
        kill_list=[kill_list];
        for c in DynkinDiagram_class(D).strongly_connected_components():
            if len(c)==1:
                continue;
            D1=D.subtype(c);
            I1=list(Set(J1).intersection(Set(c)));
            I2=list(Set(J2).intersection(Set(c)));
            I=c;
            if "type_relabel" in D1.cartan_matrix().cartan_type().__module__: # need relabeling
                label_inv=D1.cartan_matrix().cartan_type()._relabelling;
            else:
                label_inv={v:v for v in range(1,len(c)+1)}; # trivial relabeling
            label = {v: w for w, v in label_inv.items()}
            D1_relabel=D1.relabel(label)
            I1_relabel=[label[w] for w in I1];
            I2_relabel=[label[w] for w in I2];
            I=list(Set(I1_relabel).union(Set(I2_relabel)));
            totalTemp=weightAlg(D1_relabel.cartan_matrix().cartan_type().type(),D1_relabel,D1_relabel.rank(),I1_relabel,I2_relabel,I);
            newKillList=[];
            for temp in totalTemp:
                if temp!=[]:
                    temp_1=[label_inv[w] for w in temp];
                    subdiagram=True;
                    for j in kill_list:
                        newKillList.append(copy(list(Set(j).union(Set(temp_1)))));
            if newKillList!=[]:
                kill_list=newKillList;

        for j in kill_list:
            if not(j in totalKillList):
                totalKillList.append(j);
    return copy(totalKillList);

# pattern algorithm

def branch(x,last_root,I1,I2,J,D,m,result):
    # Find m number of I1 vertices starting from x protected by I2(starting point, last step, main branch label, protection label, all labeled roots, dynkin diagram, steps to remain, record history root): return successful or not.
    nbhd=[]; # the neighbour roots of x except x itself and last root.
    next_root=[];
    for k in J:
        if k!=x and (not(k in last_root)) and D.subtype(Set([k,x])).is_connected()==True: # k is the neighbour of x.
            if k in I1:
                next_root.append(k);
            nbhd.append(k);
    if m<=1: # final step.
        flag=True;
        for k in nbhd:
            if (not(k in I2)): # protection check.
                flag=False;
        if flag:
            return True,result;
        else:
            return False,[];

    # not final step.
    for y in next_root:
        flag=True;
        for k in nbhd:
            if (not(k in I2)) and (k!=y): # protection check except next root.
                flag=False;
        if flag:
            result.append(y);
            temp,temp1=branch(y,[x],I1,I2,J,D,m-1,result);
            if temp:
                return True,temp1;
            result.pop();
    return False,[]; # return false if no next roots are successful.
def pattern1(x,y,J1,J2,J,D,m): # root x has label J1 and y has J2, we want to find m number of J1 dominant m number of J2 pattern with J1 protection: return vertices to be killed.
    flag1,negative_branch=branch(y,[x],J2,J1,J,D,m,[y])
    flag2,positive_branch=branch(x,[y],J1,J1,J,D,m,[x]);
    if flag1 and flag2:
        for i in positive_branch:
            for j in negative_branch:
                if D.subtype(Set([i,j])).is_connected()==True:
                    return True,[j];
    return False,[];

def pattern2(x,y,J1,J2,J,D): # root x has label J1 and y has J2, we want to find m number of J1 dominant m number of J2 pattern with J1 protection: return vertices to be killed.
    flag1,negative_branch=branch(y,[x],J2,J1,J,D,2,[2,y]);
    flag2,positive_branch=branch(x,[2,y],J1,J1,J,D,3,[x]);
    if flag1 and flag2:
        for i in positive_branch:
            for j in negative_branch:
                if D.subtype(Set([i,j])).is_connected()==True and j!=2:
                    return True,[2,j];
    return False,[];

def pattern_alg(Type, D, n,J1,J2,J):
    if Set(J)==Set(J1) or Set(J)==Set(J2):  # the whole diagram is uniformly labeled.
        return [];
    kill_list=[];
    if Type=="E" and n==8: # pattern 5 for type E8.
        if Set(J1)==Set([1,2,3,4]) and Set(J2)==Set([5,6,7,8]):
            kill_list.append(5);
            return kill_list;
        if Set(J2)==Set([1,2,3,4]) and Set(J1)==Set([5,6,7,8]):
            kill_list.append(5);
            return kill_list;
    quit=False;
    for i in J:
        if quit: break;
        count1=0;
        count2=0;
        nbhd=[]
        for j in J:
            if j!=i and D.subtype(Set([i,j])).is_connected()==True: # j is the neighbour of i.
                nbhd.append(j);
        for j in nbhd:
            if quit: break;
            if (i in J1) and (j in J2): # j is the neighbour of i with opposite sign.
                for m in [1,2,3]:
                    flag,result=pattern1(i,j,J1,J2,J,D,m); # use J1 dominant J2 pattern 1-3.
                    if flag:
                        kill_list=kill_list+copy(result);
                        quit=True;
                if (Type=="E") and (4 in J1) and (2 in J2): # pattern 4.
                    flag,result=pattern2(i,j,J1,J2,J,D);
                    if flag:
                        kill_list=kill_list+copy(result);
                        quit=True;
            if (i in J2) and (j in J1): # switching labels J1 and J2.
                for m in [1,2,3]:
                    flag,result=pattern1(i,j,J2,J1,J,D,m); # use J2 dominant J1 pattern.
                    if flag:
                        kill_list=kill_list+copy(result);
                        quit=True;
                if (Type=="E") and (4 in J2) and (2 in J1): # pattern 4.
                    flag,result=pattern2(i,j,J2,J1,J,D);
                    if flag:
                        kill_list=kill_list+copy(result);
                        quit=True;

    J1=list(Set(J1).difference(Set(kill_list)));
    J2=list(Set(J2).difference(Set(kill_list)));
    J=list(Set(J).difference(Set(kill_list)));
    # induction with the subdiagram.
    D=D.subtype(J);
    for c in DynkinDiagram_class(D).strongly_connected_components():
        if len(c)==1:
            continue;
        D1=D.subtype(c);
        I1=list(Set(J1).intersection(Set(c)));
        I2=list(Set(J2).intersection(Set(c)));
        I=c;
        if "type_relabel" in D1.cartan_matrix().cartan_type().__module__: # need relabeling
            label_inv=D1.cartan_matrix().cartan_type()._relabelling;
        else:
            label_inv={v:v for v in range(1,len(c)+1)}; # trivial relabeling
        label = {v: w for w, v in label_inv.items()}
        D1_relabel=D1.relabel(label)
        I1_relabel=[label[w] for w in I1];
        I2_relabel=[label[w] for w in I2];
        I=list(Set(I1_relabel).union(Set(I2_relabel)));
        if D1_relabel.cartan_matrix().cartan_type().type()=="E": # if the remaining subdiagram is of Type E, we do pattern algorithm again.
            temp=pattern_alg(D1_relabel.cartan_matrix().cartan_type().type(),D1_relabel,D1_relabel.rank(),I1_relabel,I2_relabel,I);
        else: # if of classical types, we do weight algorithm.
            temp=weightAlg(D1_relabel.cartan_matrix().cartan_type().type(),D1_relabel,D1_relabel.rank(),I1_relabel,I2_relabel,I);
            temp=temp[0];
        if temp!=[]:
            temp_1=[label_inv[w] for w in temp];
            kill_list=list(Set(kill_list).union(Set(temp_1)));
    return copy(kill_list);

# # test pattern algorithm individually.
# J=list(Set(J1).union(Set(J2)));
# print("One possible J is",sorted(list(Set(list(Set(J1).union(Set(J2)))).difference(Set(pattern_alg(Type,D,n,copy(J1),copy(J2),copy(J)))))));

# Lusztig_Spaltenstein algorithm

def Lusztig_Spaltenstein(i,conjugate,W,I,X,M,J,K):
    # return J and K are conjugated or not (current position in I, conjugated or not, weyl group, I:I_i with I_0=J  I_n=K satisfying given conditions, record element used for conjugation, collection of all conjugates of J, # The elements used for conjugation, J,K): boolean whether J and K are conjugated.
    if Set(J)==Set(K):
        return True;
    for j in range(n):
        if (not ((j+1) in I[i])):

            L=copy(I[i]);
            L.append(j+1);
            x=W.long_element(index_set=I[i])*W.long_element(index_set=L); #longest coset representative.
            X.append(x);
            L.pop();

            # calculate x^-1*L*x and see if it is again standard parabolic.
            flag=False;
            for k in range(len(L)):
                y=x^-1*W.simple_reflection(L[k])*x;
                if y.length()!=1: #x^-1*L*x is not simple reflection
                    flag=True;
                    break;
                L[k]=int(str(y)[1:]);
            if flag:
                continue;
            if Set(L)==Set(K):
                conjugate=True;
                I.append(L);
#                 Uncomment following code if want detailed conjugation procedure.
#                 print("The two parabolic subgroups are conjugate, with conjugation sequence as follows:");
#                 for l in range(len(I)-1):
#                     print(Set(I[l]),"--", X[l],"-> ",end="");
#                 print(Set(I[len(I)-1]));
                return conjugate;

            # detect if L is already inside the conjuation class of J, cutting redundant search.
            selfloop=False;
            for l in range(len(M)):
                if (Set(L)==Set(M[l])):
                    selfloop=True;
            if selfloop:
                continue;
            I.append(L);
            M.append(L); # memorize all conjugates of J.
            conjugate=Lusztig_Spaltenstein(i+1,conjugate,W,I,X,M,J,K);
            if conjugate:
                return conjugate;
            I.pop();
            X.pop();
    return conjugate;

# below are testing code for all cases in type=A/D/E,n=6-8.
def testing(J1,J2,i,Type,D,n):
    if i>n:
        print("J1=",J1,"J2=",J2)
        result_pattern=sorted(list(Set(list(Set(J1).union(Set(J2)))).difference(Set(pattern_alg(Type,D,n,copy(J1),copy(J2),copy(list(Set(J1).union(Set(J2)))))))));
        totalKillList=weightAlg(Type,D,n,copy(J1),copy(J2),list(Set(J1).union(Set(J2))));
        for kill_list in totalKillList:
            result_weight=sorted(list(Set(list(Set(J1).union(Set(J2)))).difference(Set(kill_list))));
            temp=Lusztig_Spaltenstein(0,False,WeylGroup(D.cartan_matrix().cartan_type(),prefix="s",implementation="permutation"),[result_weight],[],[result_weight],result_weight,result_pattern);
            if temp:
                result_LS="conjugated";
            else:
                result_LS="not conjugated";
#                 print(J1,J2,"weight:",result_weight,"pattern:",result_pattern) #uncomment if only want not conjugated output.
            print("weight:",result_weight,"pattern:",result_pattern,"\n\t\t\t\t\t\t\t\t\t\t\t They are",result_LS);
        return;
    J1.append(i);
    testing(J1,J2,i+1,Type,D,n)
    J1.pop();
    J2.append(i);
    testing(J1,J2,i+1,Type,D,n)
    J2.pop();
#     testing(J1,J2,i+1,Type,D,n) # uncomment if want cases where J1 union J2 is not all vertices.
for Type in ['A','D','E']: # input all test types you want in the list here.
    for n in [6,7,8]: # input all test ranks you want in the list here.
        print("\n\n testing type",Type, n)
        testing([1],[],2,Type,DynkinDiagram([Type, n]),n)

Regularity of Unipotent Elements in Total Positivity.py


class Solution:
    def maxProfit(self, prices: List[int]) -> int:

        min = float('inf')
        maxProfit = 0

        for i in prices:
            if i < min:
                min = i
            elif i -min > maxProfit:
                maxProfit = i - min
        return maxProfit


#Problem link:https://practice.geeksforgeeks.org/problems/bst-to-max-heap/1

#Time Complexity: O(N)
#Space Complexity: O(N)
class Solution:

    def convertToMaxHeapUtil(self, root):
        arr = []
        i = 0

        #inOrder traversal
        #to get the values sorted
        def ino(node):
            if not node:
                return

            ino(node.left)
            arr.append(node.data)
            ino(node.right)

        ino(root)#call the inorder traversal

        #preOrder traversal
        #to put the list values
        #inplace of tree values
        def dfs(node):
            nonlocal i
            if not node:
                return

            dfs(node.left)
            dfs(node.right)
            node.data=arr[i]
            i+=1

        dfs(root)#call the preorder traversal


from tkinter import *
import first_task
import second_task
import third_task

class Lab1:
    def __init__(self):
        self.root = Tk()

        # Create Gui  for first task
        self.file_frame = Frame(self.root)
        self.fr1 = LabelFrame(self.file_frame, text="First task", font="Times 16")
        self.fr2 = LabelFrame(self.file_frame, text="Results", font="Times 14")

        self.generated_frame = Frame(self.root)
        self.gfr1 = LabelFrame(self.generated_frame, text="First task", font="Times 14")
        self.gfr2 = LabelFrame(self.generated_frame, text="Results", font="Times 14")

        self.from_fl = Frame(self.root)
        self.flfr1 = LabelFrame(self.from_fl, text="Results", font="Times 14")

        self.lbb1 = Label(self.fr2, text="y1 = ", font="Times 14")
        self.lbb2 = Label(self.gfr2, text="y1= ", font="Times 14")
        self.lbb3 = Label(self.flfr1, text="y1= ", font="Times 14")

        # Create Gui for second task
        self.ffile_frame = Frame(self.root)
        self.ffr1 = LabelFrame(self.ffile_frame, text="First task", font="Times 16")
        self.ffr2 = LabelFrame(self.ffile_frame, text="Results", font="Times 14")

        self.ggenerated_frame = Frame(self.root)
        self.ggfr1 = LabelFrame(self.ggenerated_frame, text="First task", font="Times 14")
        self.ggfr2 = LabelFrame(self.ggenerated_frame, text="Results", font="Times 14")

        self.ffrom_fl = Frame(self.root)
        self.fflfr1 = LabelFrame(self.ffrom_fl, text="Results", font="Times 14")

        self.llbb1 = Label(self.ffr2, text="res= ", font="Times 14")
        self.llbb2 = Label(self.ggfr2, text="res= ", font="Times 14")
        self.llbb3 = Label(self.fflfr1, text="res= ", font="Times 14")

        # Create GUI for last (third) task
        self.fffile_frame = Frame(self.root)
        self.fffr1 = LabelFrame(self.fffile_frame, text="First task", font="Times 16")
        self.fffr2 = LabelFrame(self.fffile_frame, text="Results", font="Times 14")

        self.gggenerated_frame = Frame(self.root)
        self.gggfr1 = LabelFrame(self.gggenerated_frame, text="First task", font="Times 14")
        self.gggfr2 = LabelFrame(self.gggenerated_frame, text="Results", font="Times 14")

        self.fffrom_fl = Frame(self.root)
        self.ffflfr1 = LabelFrame(self.fffrom_fl, text="Results", font="Times 14")

        self.lllbb1 = Label(self.fffr2, text="res= ", font="Times 14")
        self.lllbb2 = Label(self.gggfr2, text="res= ", font="Times 14")
        self.lllbb3 = Label(self.ffflfr1, text="res= ", font="Times 14")

    def main_window(self):
        win = first_task
        self.root.title("lab1")
        self.root.geometry('630x400+400+200')

        var = IntVar()
        var.set(0)

        def change_window(wind):
            nonlocal win
            win = wind
            win.size_and_title(self)
            nonlocal var
            var.set(0)
            rad()
            return win

        mainmenu = Menu(self.root)
        self.root.config(menu=mainmenu)

        filemenu = Menu(mainmenu, tearoff=0)
        filemenu.add_command(label="First Task", font="Times 14", command=lambda wind=first_task: change_window(wind))
        filemenu.add_command(label="Second Task", font="Times 14", command=lambda wind=second_task: change_window(wind))
        filemenu.add_command(label="Third Task", font="Times 14", command=lambda wind=third_task: change_window(wind))
        mainmenu.add_cascade(label="Tasks", font="Times 14", menu=filemenu)

        def rad():
            if win == first_task:
                self.ffile_frame.pack_forget()
                self.ffr1.grid_forget()
                self.ffr2.grid_forget()
                self.ggenerated_frame.pack_forget()
                self.ggfr1.grid_forget()
                self.ggfr2.grid_forget()
                self.ffrom_fl.pack_forget()
                self.fflfr1.grid_forget()

                self.fffile_frame.pack_forget()
                self.fffr1.grid_forget()
                self.fffr2.grid_forget()
                self.gggenerated_frame.pack_forget()
                self.gggfr1.grid_forget()
                self.gggfr2.grid_forget()
                self.fffrom_fl.pack_forget()
                self.ffflfr1.grid_forget()

                if var.get() == 0:
                    win.file(self)
                    self.generated_frame.pack_forget()
                    self.gfr1.grid_forget()
                    self.gfr2.grid_forget()
                    self.from_fl.pack_forget()
                    self.flfr1.grid_forget()

                    self.lbb1.configure(text="y1= ")
                    self.lbb2.configure(text="y1= ")
                    self.lbb3.configure(text='y1= ')

                elif var.get() == 2:
                    win.from_file(self)
                    self.file_frame.pack_forget()
                    self.fr1.grid_forget()
                    self.fr2.grid_forget()
                    self.generated_frame.pack_forget()
                    self.gfr1.grid_forget()
                    self.gfr2.grid_forget()

                    self.lbb1.configure(text="y1= ")
                    self.lbb2.configure(text="y1= ")
                    self.lbb3.configure(text='y1= ')

                else:
                    win.generated(self)
                    self.file_frame.pack_forget()
                    self.fr1.grid_forget()
                    self.fr2.grid_forget()
                    self.from_fl.pack_forget()
                    self.flfr1.grid_forget()

                    self.lbb1.configure(text="y1= ")
                    self.lbb2.configure(text="y1= ")
                    self.lbb3.configure(text='y1= ')
            elif win == second_task:
                self.file_frame.pack_forget()
                self.fr1.grid_forget()
                self.fr2.grid_forget()
                self.generated_frame.pack_forget()
                self.gfr1.grid_forget()
                self.gfr2.grid_forget()
                self.from_fl.pack_forget()
                self.flfr1.grid_forget()

                self.fffile_frame.pack_forget()
                self.fffr1.grid_forget()
                self.fffr2.grid_forget()
                self.gggenerated_frame.pack_forget()
                self.gggfr1.grid_forget()
                self.gggfr2.grid_forget()
                self.fffrom_fl.pack_forget()
                self.ffflfr1.grid_forget()

                if var.get() == 0:
                    win.file(self)
                    self.ggenerated_frame.pack_forget()
                    self.ggfr1.grid_forget()
                    self.ggfr2.grid_forget()
                    self.ffrom_fl.pack_forget()
                    self.fflfr1.grid_forget()

                    self.lllbb1.configure(text="f= ")
                    self.lllbb2.configure(text="f= ")
                    self.lllbb3.configure(text='f= ')

                elif var.get() == 2:
                    win.from_file(self)
                    self.ffile_frame.pack_forget()
                    self.ffr1.grid_forget()
                    self.ffr2.grid_forget()
                    self.ggenerated_frame.pack_forget()
                    self.ggfr1.grid_forget()
                    self.ggfr2.grid_forget()

                    self.llbb1.configure(text="res= ")
                    self.llbb2.configure(text="res= ")
                    self.llbb3.configure(text='res= ')

                else:
                    win.generated(self)
                    self.ffile_frame.pack_forget()
                    self.ffr1.grid_forget()
                    self.ffr2.grid_forget()
                    self.ffrom_fl.pack_forget()
                    self.fflfr1.grid_forget()

                    self.llbb1.configure(text="res= ")
                    self.llbb2.configure(text="res= ")
                    self.llbb3.configure(text='res= ')
            else:
                self.file_frame.pack_forget()
                self.fr1.grid_forget()
                self.fr2.grid_forget()
                self.generated_frame.pack_forget()
                self.gfr1.grid_forget()
                self.gfr2.grid_forget()
                self.from_fl.pack_forget()
                self.flfr1.grid_forget()

                self.ffile_frame.pack_forget()
                self.ffr1.grid_forget()
                self.ffr2.grid_forget()
                self.ggenerated_frame.pack_forget()
                self.ggfr1.grid_forget()
                self.ggfr2.grid_forget()
                self.ffrom_fl.pack_forget()
                self.fflfr1.grid_forget()

                if var.get() == 0:
                    win.file(self)
                    self.gggenerated_frame.pack_forget()
                    self.gggfr1.grid_forget()
                    self.gggfr2.grid_forget()
                    self.fffrom_fl.pack_forget()
                    self.ffflfr1.grid_forget()

                    self.lllbb1.configure(text="f= ")
                    self.lllbb2.configure(text="f= ")
                    self.lllbb3.configure(text='f= ')

                elif var.get() == 2:
                    win.from_file(self)
                    self.fffile_frame.pack_forget()
                    self.fffr1.grid_forget()
                    self.fffr2.grid_forget()
                    self.gggenerated_frame.pack_forget()
                    self.gggfr1.grid_forget()
                    self.gggfr2.grid_forget()

                    self.lllbb1.configure(text="f= ")
                    self.lllbb2.configure(text="f= ")
                    self.lllbb3.configure(text='f= ')

                else:
                    win.generated(self)
                    self.fffile_frame.pack_forget()
                    self.fffr1.grid_forget()
                    self.fffr2.grid_forget()
                    self.fffrom_fl.pack_forget()
                    self.ffflfr1.grid_forget()

                    self.lllbb1.configure(text="f= ")
                    self.lllbb2.configure(text="f= ")
                    self.lllbb3.configure(text='f= ')

        r1 = Radiobutton(text="By hands", variable=var, value=0, command=rad, font="Times 14")
        r2 = Radiobutton(text="Generated", variable=var, value=1, font="Times 14", command=rad)
        r3 = Radiobutton(text="From File", variable=var, value=2, font="Times 14", command=rad)

        r1.pack(anchor=W)
        r2.pack(anchor=W)
        r3.pack(anchor=W)

        win.file(self)
        self.root.mainloop()

window = Lab1()
window.main_window()


import epyk as pk

# Create a basic report object
page = pk.Page()
page.headers.dev()

tb1 = page.ui.layouts.table()
tb1.style.css.border_collapse = "separate"
tb1.style.css.border_spacing = 10

# Add a header (first row is by default the header)
tb1 += [1, 2, 3]

# Change the CSS style of a cell in the header
tb1.get_header()[1].style.color = 'red'
tb1.get_header()[1].style.background = 'grey'

# Change all header cells style
for c in tb1.get_header():
  # This will add CSS attribute to the CSS inline section
  c.style.padding = 5
  c.style.border = "1px solid black"

# Create bespoke HTML component to be added to the table
span1 = page.ui.texts.span("Text 1").tooltip("Click to hide header last line")
span2 = page.ui.texts.span("Text 2")
span3 = page.ui.texts.span("Text 3").tooltip("Click to change table values")

# Add the row to the table (to the body)
tb1 += [span1, span2, span3]

span3.click([
  page.js.log(span3.dom.content),
  span2.build("New text"),

  # Change the cell properties
  #tb1[1].cell(1).dom.css({"background": page.theme.warning[0]})
  tb1[0][1].dom.css({"background": page.theme.warning[0]}),

  # Change the component in the cell
  tb1[0][1].val[0].dom.css({'text-decoration': 'underline'}),
])

# Add an extra row to the header
tb1.header += [4, 5]
tb1.get_header(1)[1].colspan(2)
tb1.get_header(1)[1].style.border = "1px solid black"

span1.click([
  # The display value must be table-row for a row
  tb1.get_header(1).dom.toggle()
])

# Add a text caption to this table
text = tb1.add_caption("This is a text attached to the table")
text.style.css.text_align = 'left'

# CSS class
# Create a bespoke CSS class for this report
from epyk.core.css.styles.classes import CssStyle

class MyCssBody(CssStyle.Style):
  _attrs = {'background': 'inherit'}
  _hover = {'background': page.theme.success[0]}

  _selectors = {'child': 'tbody td'}

# Attach the class to the component
tb1.style.add_classes.custom(MyCssBody)

# delete row
page.ui.button("Remove").click([
  tb1[0].dom.remove()
])


import collections

class Rectangle():
    def __init__(self, w, h, placed=None, free_wh=None):
        self.wh = w, h
        self.placed = placed or []
        self.free_wh = free_wh or (0,0)

    @property
    def w(self):
        return self.wh[0]

    @property
    def h(self):
        return self.wh[1]

    def transposed(self):
        return Rectangle(self.h, self.w,
                         [r.transposed() for r in self.placed],
                        (self.free_wh[1], self.free_wh[0]),
                        )

    @staticmethod
    def placed_build(W, H, rect):
        # build rectangle of size (W, H) with placed rectangle rect
        if not W or not H:
            return

        w, h = rect.wh

        if (W, H) == (w, h):
            return Rectangle(W, H, [rect])

        elif (W, H) == (h, w):
            return Rectangle(W, H, [rect.transposed()])

        H_h = H - h, W >= w
        W_w = W - w, H >= h
        H_w = H - w, W >= h
        W_h = W - h, H >= w
        cases = [H_h, W_w, H_w, W_h]
        residue = [c[0] for c in cases if c[1] and c[0] >= 0]
        if not residue:
            return None

        min_size = min(residue)

        if H_h[0] == min_size and H_h[1]:
            placed_r = Rectangle(w, H,
                                [rect],
                                (w, H - h))
            free_wh = (W - w, H)
        elif W_w[0] == min_size and W_w[1]:
            placed_r = Rectangle(W, h,
                                [rect],
                                (W - w, h))
            free_wh = (W, H - h)
        elif H_w[0] == min_size and H_w[1]:
            placed_r = Rectangle(h, H,
                                 [rect.transposed()],
                                (h, H - w))
            free_wh = (W - h, H)
        elif W_h[0] == min_size and W_h[1]:
            placed_r = Rectangle(W, w,
                                [rect.transposed()],
                                (W - h, w))
            free_wh = (W, H - w)
        else:
            assert False, 'impossible'

        out = Rectangle(W, H, [placed_r], free_wh)
        return out

    def place(self, rect):
        W, H = self.free_wh
        r = Rectangle.placed_build(W, H, rect)
        if not r:
            return False
        self.placed.append(r.placed[0])
        self.free_wh = r.free_wh
        #print(f'place {rect.wh}: free {W,H} -> {self.free_wh}')
        return True

    @staticmethod
    def concat(rects, by='w'):
        w = list(map(lambda r : r.w, rects))
        h = list(map(lambda r : r.h, rects))

        if 'w' == by:
            max_w = max(w)
            placed_r = [
                Rectangle.placed_build(max_w, r.h, r)
                for r in rects
            ]
            out = Rectangle(max_w, sum(h), placed_r)
        else:
            max_h = max(h)
            placed_r = [
                Rectangle.placed_build(r.w, max_h, r)
                for r in rects
            ]
            out = Rectangle(sum(w), max_h, placed_r)

        return out

    @staticmethod
    def min_concat(W, H, rect1, rect2):
        rect2T = Rectangle(rect2.h, rect2.w, rect2.placed, rect2.free_wh)
        concat_cases = [
            Rectangle.concat([rect1, rect2], by='w'),
            Rectangle.concat([rect1, rect2], by='h'),
            Rectangle.concat([rect1, rect2T], by='w'),
            Rectangle.concat([rect1, rect2T], by='h'),
        ]
        if W < H:
            W, H = H, W
        concat_cases = [r for r in concat_cases if max(r.wh) <= W and min(r.wh) <= H]
        if not concat_cases:
            return
        return min(concat_cases, key=lambda r : r.free_square)

    @property
    def square(self):
        return self.w * self.h

    @property
    def free_square(self):
        out = self.free_wh[0] * self.free_wh[1]
        for r in self.placed:
            out += r.free_square
        return out

    def free_print(self):
        if self.free_wh[0] and self.free_wh[1]:
            print(self.free_wh)
        for r in self.placed:
            r.free_print()

    @property
    def fullness(self):
        return (1 - self.free_square / self.square) * 100

    def __repr__(self):
        return f'Rectangle(w={self.w}, h={self.h}, childs={len(self.placed)}, free_wh={self.free_wh}, fullness={self.fullness}%)'

def equal_side_concat_step(rects, W, H, order='descending'):
    w = list(map(lambda r : r.w, rects))
    h = list(map(lambda r : r.h, rects))
    side_cnt = collections.Counter([s for s in w + h if s <= max(W, H)])
    side_repeats = [ side
                     for side, cnt in side_cnt.most_common()
                     if cnt > 1
                    ]
    side_repeats.sort(reverse=('descending' == order))

    single_rects = list(rects)
    side_to_rects = {}
    for side in side_repeats:
        side_to_rects[side] = [r for r in single_rects
                               if side in r.wh]
        single_rects = [r for r in single_rects
                        if side not in r.wh]

    # TODO: Если прямоугольник совпадает каждой стороной с другими -> варианты по какой стороне объединять
    concat_rects = []
    for side, side_rects in side_to_rects.items():
        if 1 == len(side_rects):
            single_rects.append(side_rects[0])
            continue
        for r in side_rects:
            if side != r.w:
                r.wh = r.h, r.w
        # TODO: 1d упаковка вдоль H или W
        # далее идет упаковка вдоль максимальной возможной стороны
        side_rects.sort(key=lambda r : r.h, reverse=True)
        concat_side = max(H, W) if side <= min(H, W) else min(H, W)
        while side_rects:
            rects_for_concat = []
            rest_rects = []
            sum_h = 0
            for r in side_rects:
                if sum_h + r.h <= concat_side:
                    rects_for_concat.append(r)
                    sum_h += r.h
                else:
                    rest_rects.append(r)
            if len(rects_for_concat) == 1:
                single_rects.append(rects_for_concat[0])
            elif len(rects_for_concat) > 1:
                concat_rects.append(Rectangle.concat(rects_for_concat, by='w'))
            else:
                single_rects.extend(rest_rects)
                break
                #assert False, f'side_rects={side_rects}, rest_rects={rest_rects}, max_h={max_h}'
            side_rects = rest_rects

    return single_rects, concat_rects

def exact_concat(rects, W, H):
    merge_rects = list(rects)
    while True:
        single_rects, concat_rects = equal_side_concat_step(merge_rects, W, H, order='descending')
        #print(f'single_rects={single_rects} \n concat_rects={concat_rects} \n')
        merge_rects = single_rects + concat_rects
        if not concat_rects:
            break

    while True:
        single_rects, concat_rects = equal_side_concat_step(merge_rects, W, H, order='ascending')
        merge_rects = single_rects + concat_rects
        if not concat_rects:
            break
    return merge_rects

def pallet_exact_side_placement(rects, pallet, side='max'):
    W, H = pallet.free_wh
    side = max(W, H) if 'max' == side else min (W, H)

    rest_rects = []
    for r in rects:
        if side in r.wh:
            if pallet.place(r):
                continue
        rest_rects.append(r)
    return rest_rects

def exact_placement(rects, pallet):
    rest_rects = list(rects)
    while rest_rects:
        rest_rects1 = pallet_exact_side_placement(rest_rects, pallet, side='max')
        rest_rects2 = pallet_exact_side_placement(rest_rects1, pallet, side='min')
        if len(rest_rects) == len(rest_rects2):
            break
        rest_rects = rest_rects2
    return rest_rects

def rects_flatten(rects):
    out = []
    for r in rects:
        if r.placed:
            out.extend(rects_flatten(r.placed))
        else:
            out.append(r)
    return out

def min_residue(WH, rects):
    W, H = WH
    min_r = None
    min_residue_wh = WH
    for r in rects:
        placed_r = Rectangle.placed_build(W, H, r)
        if placed_r:
            residue_wh = placed_r.placed[0].free_wh
            if residue_wh[0] * residue_wh[1] < min_residue_wh[0] * min_residue_wh[1]:
                min_residue_wh = residue_wh
                min_r = r
    return min_r, min_residue_wh

def min_residue_placement(pallet, rects):
    max_r, min_residue_wh = min_residue(pallet.free_wh, rects)
    if not max_r or min_residue_wh[0] * min_residue_wh[1] > max_r.square:
        return rects

    rest_rects = [r for r in rects if r is not max_r]

    r, _ = min_residue(min_residue_wh, rest_rects)
    if not r:
        pallet.place(max_r)
        return rest_rects

    return rects

def find_concat_pair(W, H, rects):
    min_loss = 1
    min_values = None
    for i in range(len(rects)):
        for j in range(i + 1, len(rects)):
            cur_concat = Rectangle.min_concat(W, H, rects[i], rects[j])
            if not cur_concat:
                continue
            cur_loss = cur_concat.free_square / min(rects[i].square, rects[j].square)
            if cur_loss < min_loss:
                min_loss = cur_loss
                min_values = (i, j, cur_concat)
    return min_values

def free_placement(pallet, rects):
    rest_rects = list(rects)
    while rest_rects:
        W, H = pallet.free_wh
        if not W * H:
            break
        concat_rects = exact_concat(rest_rects, W, H)
        #print(f'concat_rects={concat_rects}')
        rest_rects = exact_placement(concat_rects, pallet)
        #print(f'exact_placement: rest_rects={rest_rects}, concat_rects={concat_rects}, pallet={pallet}')
        if len(rest_rects) == len(concat_rects):
            rest_rects2 = min_residue_placement(pallet, rest_rects)
            if len(rest_rects2) == len(rest_rects):
                find_values = find_concat_pair(W, H, rest_rects)
                if not find_values:
                    #print(f'not find_concat_pair for rest_rects={rest_rects}')
                    break
                i, j, concat_r = find_values
                assert pallet.place(concat_r)
                del rest_rects[j]
                del rest_rects[i]
            else:
                rest_rects = rest_rects2
        rest_rects = rects_flatten(rest_rects)

    return rest_rects

def pallet_placement(pallet, rects):
    rest_rects = free_placement(pallet, rects)

#     placed = len(rects) - len(rest_rects)
#     if placed:
#         print(f'pallet: {pallet}, placed: {placed} \n')

    for r in pallet.placed:
        rest_rects = pallet_placement(r, rest_rects)

    return rest_rects

def assign_coordinates(x, y, W, H, rects):
    out_xywh = []
    for r in rects:
        if W == r.h or H == r.w:
            r = r.transposed()
        if not r.placed:
            out_xywh.append((x, y, r.w, r.h))
            #print(f'append {x,y,r.w,r.h}')
        else:
            out_xywh.extend(assign_coordinates(x, y, r.w, r.h, r.placed))
        if W == r.w:
            y += r.h
            H -= r.h
        elif H == r.h:
            x += r.w
            W -= r.w
        else:
            assert False, f'WH={W,H}, r={r}'

    return out_xywh


from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive

gauth = GoogleAuth()
gauth.LoadCredentialsFile("mycreds.txt")

if gauth.credentials is None:
  gauth.LocalWebserverAuth()
elif gauth.access_token_expired:
  gauth.Refresh()
else:
  gauth.Authorize()

gauth.SaveCredentialsFile("mycreds.txt")

drive = GoogleDrive(gauth)

file1 = drive.CreateFile({'title': 'Automata.txt'})  # Create GoogleDriveFile instance with title 'Hello.txt'.
file1.SetContentString('Automataaa') # Set content of the file from given string.
file1.Upload()
print(drive)


import numpy as np
import pandas as pd
import scipy
from sklearn.linear_model import LinearRegression as linreg
from sklearn.linear_model import LogisticRegression as logreg
from sklearn.cross_validation import KFold
from sklearn.cross_validation import *
from sklearn import  cross_validation

titanic=pd.read_csv("train.csv")

#print(titanic.describe())
#print(titanic.head(5))

# ------------------- DATA CORRECTION --------------------------------

# 1) Fill missing Age data with median
titanic["Age"]=titanic["Age"].fillna(titanic["Age"].median())

# 2) Convert Sex string with 0 or 1
titanic.loc[titanic["Sex"] == "male", "Sex"] = 0 #convert 0 for men
titanic.loc[titanic["Sex"] =="female", "Sex"]=1 #convert 1 for women

# 3) Fill missing Embarked data with most common char
print(pd.value_counts(titanic["Embarked"].values, sort=False))
     # "S" is most common char -> chosen as default for missing values
titanic["Embarked"]=titanic["Embarked"].fillna("S")

#4) Replace Embarked char with numeric code
#titanic.loc[titanic["Embarked"]=="S", "Embarked"]=0 # 'S' -> 0
#titanic.loc[titanic["Embarked"]=="C", "Embarked"]=1 # 'C' -> 1
titanic.loc[titanic["Embarked"]=="S", "Embarked"]=0
titanic.loc[titanic["Embarked"]=="C", "Embarked"]=1
titanic.loc[titanic["Embarked"]=="Q", "Embarked"]=2 # 'Q' -> 2

# input column used for predictions :
predictors=["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked"]

# Initialize the algorithm
algo_linreg = linreg()

# Generate cross-validation folds with random splits
# return rows indices for corresponding train and set
kf =KFold(titanic.shape[0], n_folds=3, random_state=1)

# Make the predictions
predictions =[]
for train, test in kf:
    # Which predictors used on train fold
    train_predictors = (titanic[predictors].iloc[train,:])
    # Target/goal used to train the algo
    train_target= titanic["Survived"].iloc[train]

    # Train the algo with the predictors and target
    # .fit(x input, y output)
    algo_linreg.fit(train_predictors, train_target)
    # Make predictions with the trained algo on test fold
    test_predictions = algo_linreg.predict(titanic[predictors].iloc[test,:])
    predictions.append(test_predictions)

# The predictions are in 3 Numpy arrays
# So we concatenate the arrays on axis 0 (bc only 1 axis)
predictions=np.concatenate(predictions, axis=0)

predictions[predictions> .5]=1
predictions[predictions<= .5]=0

print(predictions)

print(sum(predictions==titanic["Survived"]))
accuracy= sum(predictions==titanic["Survived"])/len(predictions)
print(accuracy) # = 0.783

#------------------- Logistic Regression method ---------------------

# Initialize the algo
algo_logreg = logreg(random_state=1)

# Compute accuracy score for all cross-V folds;
# cross_val_score(algo, predictors, target, cross-validation fold)
scores = cross_validation.cross_val_score(algo_logreg, titanic[predictors], titanic["Survived"], cv=3)
# Mean of the scores for each folds (3 folds)
print(scores.mean())

#----------------------------------- Log Reg. with test set ---------------------

titanic_test = pd.read_csv("test.csv")

# I) Clean data
titanic_test["Age"] = titanic_test["Age"].fillna(titanic["Age"].median())
titanic_test["Fare"] = titanic_test["Fare"].fillna(titanic_test["Fare"].median())
titanic_test.loc[titanic_test["Sex"] == "male", "Sex"] = 0
titanic_test.loc[titanic_test["Sex"] == "female", "Sex"] = 1
titanic_test["Embarked"] = titanic_test["Embarked"].fillna("S")

titanic_test.loc[titanic_test["Embarked"] == "S", "Embarked"] = 0
titanic_test.loc[titanic_test["Embarked"] == "C", "Embarked"] = 1
titanic_test.loc[titanic_test["Embarked"] == "Q", "Embarked"] = 2

# II) Test algo on data

# Initialize the algo
algo_logreg_test=logreg(random_state=1)

# Train algo on using all training data
algo_logreg_test.fit(titanic[predictors], titanic["Survived"])

# Make predictions with algo on data
predictions=algo_logreg_test.predict(titanic_test[predictors])

# Generate new dataset for kaggle submission
submission= pd.DataFrame({
    "PassengerId" : titanic_test["PassengerId"],
    "Survived": predictions
})

submission.to_csv("kaggle.csv", index=False)