import os
import typing

import numpy as np
import torch
import torchvision as tv
from PIL import Image
from torch.utils import data

import util
from config import Config
from dataset import PoseNetDataSet
from logger import Logger
from posenet import PoseNet

def getErrorVector ( output: np.ndarray, target: np.ndarray ) -> typing.Tuple[np.ndarray, np.ndarray]:
	"""
	Subtracts the output from the target elementwise then averages out the differences per dimension (X Y Z W P Q R).

	:param output: The output of the network.
	:param target: The labels of the data.
	:return: The average of the elementwise subtraction of the output and the target with position being [0] and orientation being [1].
	"""

	err: np.ndarray = np.subtract ( output, target )
	# Take the average of all the x y z w p q r values within the columns.
	err = np.mean ( err, axis = 0 )

	return err[:3], err[3:]

def ANEES ( error: np.ndarray, uncertainty: np.ndarray, numOfImages: int ) -> float:
	"""
	ANEES (Average Normalized Error Estimate Squared). It's the mean of the error * the inverse of the uncertainty *
	the transpose of the error.

	:param error: The error of the network between the output and the target.
	:param uncertainty: The covariance matrix of the network's output.
	:param numOfImages: How many images are in the dataset.
	:return: The average of all of that.
	"""
	anees: np.ndarray = np.zeros ( numOfImages )
	for j in range ( numOfImages ):
		anees[j] = error[j] @ np.linalg.inv ( uncertainty[j] ) @ error[j].transpose ()
	return anees.mean ( dtype = float )

def getUncertainty ( output: np.ndarray, returnMatrix: bool = False ) -> typing.Union[
	typing.Tuple[float, float], typing.Tuple[np.ndarray, np.ndarray, float, float]]:
	"""
	Gets the uncertainty of the output from the network. If return matrix is true, the function will also return
	the covariance matrix along with the uncertainty values.

	:param output: the output from the network.
	:param returnMatrix: whether to return the covariance matrix or not.
	:return: the uncertainty values and the covariance matrix if returnMatrix is true.
	"""
	outPos: np.ndarray = output[:, :3]
	outOri: np.ndarray = output[:, 3:]

	covPos: np.ndarray = np.cov ( outPos, rowvar = 0 )
	covOri: np.ndarray = np.cov ( outOri, rowvar = 0 )

	uncertaintyPos: float = covPos.diagonal ().sum ()
	uncertaintyOri: float = covOri.diagonal ().sum ()
	if returnMatrix:
		return covPos, covOri, uncertaintyPos, uncertaintyOri
	return uncertaintyPos, uncertaintyOri

def getDifference ( output: torch.Tensor, target: torch.Tensor ) -> typing.Tuple[np.ndarray, np.ndarray]:
	"""
	Return the difference between the expected output of the network and the actual output of the network.
	Basically a wrapper for getErrorVector to do torch.Tensor's.

	:param output: Given output from the network
	:param target: Expected output of the network
	:return: a dictionary of the position and orientation differences between the two parameters.
	"""
	return getErrorVector ( output = output.cpu ().detach ().numpy (),
	                        target = target.cpu ().detach ().numpy () )

# Loss function for posenet
# outputPosition and outputOrientation are both the output provided by the neural network
# target is the output that is expected from the neural network
# beta is a constant to keep errors from data collection from getting in the way
# The target Tensor is supposed to be in the form of [batch_size, 7]
# with the second dimension being [x, y, z, w, p, q, r]
# where the position vector is [x, y, z]
# and the orientation vector is [w, p, q, r]
def posenetLoss ( output: torch.Tensor, target: torch.Tensor, beta: int ) -> torch.Tensor:
	"""
	The loss function defined in the original paper of PoseNet.

	:param output: The given output from the network
	:param target: The expected output from the network
	:param beta: The error constant
	:return: The loss of the network
	"""

	Logger.log ( "Computing loss." )
	Logger.log (
			"Types of things: output {} target {} beta {}".format ( type ( output ), type ( target ), type ( beta ) ) )
	Logger.log ( "Data types of things: output {} target {}".format ( output.dtype, target.dtype ) )
	Logger.log ( "Is on Cuda? Output {} target {}".format ( output.device, target.device ) )
	# Normalize the difference of the two position vectors
	positionLoss: torch.Tensor = torch.norm ( output[:, :3] - target[:, :3] )
	# Normalize the difference of the two orientation vectors
	# and multiply by the error constant.
	# Normalizing is the same thing as finding the unit vector.
	orientationDifference: torch.Tensor = torch.norm ( output[:, 3:] ) - torch.norm ( target[:, 3:] )
	orientationLoss: torch.Tensor = torch.norm ( orientationDifference ) * beta
	# return their sum
	return positionLoss + orientationLoss

def trainNetwork ( network: torch.nn.Module, optimizer: torch.optim.Optimizer, dataloader: data.DataLoader, epoch: int,
                   beta: int, print_every: int ) -> typing.Tuple[float, typing.Union[float, np.ndarray], np.ndarray]:
	"""
	Trains the network with the given parameters.

	:param network: The network that is to be trained.
	:param optimizer: The optimizer to teach the network what to do.
	:param dataloader: The data that the network will train on.
	:param epoch: The current epoch of this training session
	:param beta: The error constant to be used in the loss function
	:param print_every: Print loss and difference every x batches.
	:return: the average loss and differences of this training session.
	"""
	Logger.log ( "Training!", logger = "min" )
	# get the training data from the dataloader with the current batch number
	past_losses: typing.List[torch.Tensor] = []
	# Previous differences
	pastPosDiff: typing.List[np.ndarray] = []
	pastOriDiff: typing.List[np.ndarray] = []

	Logger.log ( "Epoch {}".format ( epoch ) )
	for batchNum, (data, labels) in enumerate ( dataloader ):
		# Log current batch number
		Logger.log ( "Training Batch #{}".format ( batchNum ) )

		labels: torch.Tensor = labels.float ()

		# Set network to start training.
		network.train ()

		Logger.log ( "Getting data" )
		# get the current batch.

		util.logTensorInfo ( data, "data" )
		util.logTensorInfo ( labels, "labels" )

		# If we're working with GPUs, put them on there.
		data = util.putOnDevice ( data )
		labels = util.putOnDevice ( labels )

		util.logTensorInfo ( data, "data" )
		util.logTensorInfo ( labels, "labels" )

		Logger.log ( "Resetting optimizer." )
		# reset the optimizer (right?)
		optimizer.zero_grad ()

		Logger.log ( "Getting output from network." )
		# run the network based on the current batch
		output: torch.Tensor = network ( data )

		util.logTensorInfo ( output, "output" )

		# Put the output onto the GPU
		output = util.putOnDevice ( output )

		util.logTensorInfo ( output, "output" )

		Logger.log ( "Calculating loss." )

		# calculate the error between the output and the expected output
		loss: torch.Tensor = posenetLoss ( output = output, target = labels, beta = beta )

		# This is a 1 dimensional vector that is the average of the differences between the output and target.
		difference: typing.Tuple[np.ndarray, np.ndarray] = getDifference ( output = output, target = labels )
		pastPosDiff.append ( difference[0] )
		pastOriDiff.append ( difference[1] )
		past_losses.append ( loss.detach ().cpu ().numpy () )

		# Put the loss onto the GPU if we can use it.
		if Config.useCuda ():
			loss = loss.cuda ()

		Logger.log ( "Calculating gradient." )
		# Calculate the gradient necessary to fix the network
		loss.backward ()

		Logger.log ( "Optimizing network" )
		# Assign those changes from the loss function to the network to
		# find the local (and preferably absolute) minimum
		optimizer.step ()

		# Check the accuracy every nth batches.
		if batchNum % print_every == 0:
			Logger.log ( "At epoch %i, minibatch %i. Loss: %.4f." % (epoch, batchNum, past_losses[-1]), logger = "min" )
			Logger.log ( "Error of position and orientation: {} {}".format (
					pastPosDiff[-1], np.linalg.norm ( pastOriDiff[-1] ) ), logger = "min" )
			Logger.log ( "Progress: {:.2%}".format ( (batchNum / len ( dataloader )) ), logger = "main" )

	avgLoss: float = np.average ( past_losses )
	# Print average losses
	Logger.log ( "Average training losses for epoch {}: {}".format ( epoch, avgLoss ), logger = "min" )
	avgPositionDifference: np.ndarray = np.average ( pastPosDiff, axis = 0 )
	avgOrientationDifference: np.ndarray = np.linalg.norm ( np.average ( pastOriDiff, axis = 0 ) )

	Logger.log ( "Average training difference for epoch {}: Pos: {} Ori: {}".format ( epoch, avgPositionDifference,
	                                                                               avgOrientationDifference ),
	             logger = "min" )

	return avgLoss, np.linalg.norm ( avgPositionDifference ), avgOrientationDifference

def validate ( network: torch.nn.Module, dataloader: data.DataLoader, beta: int, print_every: int,
               epoch: int ) -> typing.Tuple[float, float, float]:
	"""
	Validates that the network trained effectively based on the given parameters.

	:param network: The network to be validated.
	:param dataloader: The data that will be used to validate
	:param beta: The data error constant that is to be used with the loss function
	:param print_every: For x batches, print the current loss and the differences of the network
	:param epoch: The current epoch
	:return: The average validation loss and difference of this validation session
	"""
	# Begin validation.
	Logger.log ( "Validating data!", logger = "min" )
	# Turn the network onto testing mode.
	network.eval ()

	# record past validation losses.
	validation_past_losses: typing.List[torch.Tensor] = []

	pastPosDiff: typing.List[np.ndarray] = []
	pastOriDiff: typing.List[np.ndarray] = []

	# Go through each thing in the testing data.
	for batchNum, (data, labels) in enumerate ( dataloader ):
		# Log current batch number
		Logger.log ( "Validation Batch #{}".format ( batchNum ) )

		labels: torch.Tensor = labels.float ()

		Logger.log ( "Getting data" )
		# If we want to use the GPU, use it.
		if Config.useCuda ():
			labels = labels.cuda ()
			data: torch.Tensor = data.cuda ()

		Logger.log ( "Getting output from network." )
		# Get the output of the network based on the given data.
		output: torch.Tensor = network ( data )
		# Put output onto the GPU.
		if Config.useCuda ():
			output = output.cuda ()

		Logger.log ( "Calculating loss" )

		# calculate the error between the output and the expected output
		loss: torch.Tensor = posenetLoss ( output = output, target = labels, beta = beta )
		differences: typing.Tuple[np.ndarray, np.ndarray] = getDifference ( output = output, target = labels )
		# These contain vectors.
		pastPosDiff.append ( differences[0] )
		pastOriDiff.append ( differences[1] )

		validation_past_losses.append ( loss.detach ().cpu ().numpy () )

		if batchNum % print_every == 0:
			Logger.log ( "Validation loss for epoch {} batch #{}: {}".format ( epoch, batchNum,
			                                                                   validation_past_losses[-1] ),
			             logger = "min" )
			Logger.log ( "Error of position and orientation: {} {}".format ( pastPosDiff[-1],
			                                                                 np.linalg.norm ( pastOriDiff[-1] ) ),
			             logger = "min" )
			Logger.log ( "Progress: {:.2%}".format ( (batchNum / len ( dataloader )) ), logger = "main" )
	avgLoss: float = np.average ( validation_past_losses )
	Logger.log ( "Total average validation loss: " + str ( avgLoss ), logger = "min" )

	# Compute average of position diff in the columns (per dimension like X Y Z)
	avgPositionDifference: float = np.average ( pastPosDiff, axis = 0 )
	# Get the average per column then get the magnitude of the average difference in orientation.
	avgOrientationDifference: float = np.linalg.norm ( np.average ( pastOriDiff, axis = 0 ) )

	Logger.log ( "Average validation difference for epoch {}: Pos: {} Ori: {}".format ( epoch, avgPositionDifference,
	                                                                               avgOrientationDifference ),
	             logger = "min" )
	return avgLoss, np.linalg.norm ( avgPositionDifference ), avgOrientationDifference

def testSingleImage ( network: torch.nn.Module, image: Image, transforms ) -> typing.Tuple[
	np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
	Logger.log ( "Testing single image!", logger = "main" )
	data: torch.Tensor = transforms ( image )

	data = util.putOnDevice(data)

	Logger.log ( "Resizing image." )
	data.resize_ ( 1, 3, 224, 224 )

	if Config.useCuda():
		network = network.cuda()
	else:
		network = network.cpu()

	Logger.log ( "Triggering dropout layers." )
	network.train ()
	outputs: typing.List[torch.Tensor] = []

	for i in range ( Config.getArgs ().num_of_tests ):
		outputs.append ( network ( data ) )

	outs: np.ndarray = np.zeros ( (len ( outputs ), 7) )
	for i in range ( len ( outputs ) ):
		outs[i] = outputs[i].cpu ().detach ().numpy ()

	Logger.log ( "Getting uncertainty." )
	certPosMat, certOriMat, _, _ = getUncertainty ( output = torch.from_numpy ( outs ), returnMatrix = True )

	Logger.log ( "Getting actual output.", logger = "main" )
	network.eval ()
	output: np.ndarray = network ( data ).detach ().cpu ().numpy ()
	return output[0], outs, certPosMat, certOriMat

def test ( network: torch.nn.Module, dataloader: torch.utils.data.DataLoader ) -> typing.Tuple[
	float, float, float, float, float, float]:
	"""
	Uses testSingleImage() to test the network. Goes through each image individually  and gets the uncertainty, the error,
	and ANEES.

	:param network: the network to be tested on.
	:param dataloader: The testing data
	:return: average uncertainty, average error, and ANEES. Each are tuples in the format of (position, orientation)
	"""

	Logger.log ( "Testing!", logger = "min" )
	uncertainties: typing.List[typing.Tuple[np.ndarray, np.ndarray]] = []
	errors: typing.List[typing.Tuple[np.ndarray, np.ndarray]] = []

	# Trigger the dropout layers.
	network.train ()

	print_every = Config.getArgs ().print_every

	if not Config.getArgs ().test_print_lots:
		print_every *= Config.getArgs ().batch_size

	# The batch size is 1
	for batchNum, (data, labels) in enumerate ( dataloader ):
		if Config.useCuda ():
			data = data.cuda ()
			labels = labels.cuda ()
		outputs: typing.List[np.ndarray] = []
		for i in range ( Config.getArgs ().num_of_tests ):
			# Get 1 output from the network.
			output: torch.Tensor = network ( data )
			outputs.append ( output.detach ().cpu ().numpy () )
		# Concat output into a single np.ndarray
		outputNP: np.ndarray = np.zeros ( (len ( outputs ), outputs[0].shape[1]) )
		for i in range ( len ( outputs ) ):
			outputNP[i] = outputs[i]
		error: typing.Tuple[np.ndarray, np.ndarray] = getErrorVector ( outputNP,
		                                                               target = labels.cpu ().detach ().numpy () )
		uncertainty: typing.Tuple[np.ndarray, np.ndarray, float, float] = getUncertainty ( outputNP,
		                                                                              returnMatrix = True )

		errors.append ( error )
		# A list of the uncertainty matrices
		uncertainties.append ( uncertainty[:2] )
		if batchNum % print_every == 0:
			Logger.log ( "Last Error: Pos {} Ori {}".format ( errors[-1][0], np.linalg.norm ( errors[-1][1] ) ),
			             logger = "min" )
			Logger.log ( "Last uncertainty: Pos {} Ori {}".format ( np.sqrt ( uncertainty[0].diagonal () ),
			                                                        np.sqrt ( uncertainty[3] ) ), logger = "min" )
			Logger.log ( "Progress: {:4}%".format ( 100.0 * (float ( batchNum ) / float ( len ( dataloader ) )) ),
			             logger = "min" )

	errorsNP: np.ndarray = np.ndarray ( (len ( errors ), 7) )
	for i in range ( len ( errors ) ):
		errorsNP[i] = np.concatenate ( errors[i], axis = 0 )
	posErrors: np.ndarray = errorsNP[:, :3]
	oriErrors: np.ndarray = errorsNP[:, 3:]

	averagePosErr: float = np.average ( posErrors, axis = 0 )
	averageOriErr: float = np.linalg.norm ( np.average ( oriErrors, axis = 0 ) )

	averageError: typing.Tuple[float, float] = (np.linalg.norm ( averagePosErr ), averageOriErr)

	Logger.log (
			"Average Error during test: Pos: {} Ori: {}".format ( averagePosErr, averageError[1] ),
			logger = "min" )

	certaintyNP: typing.Tuple[np.ndarray, np.ndarray] = (
		np.ndarray ( (len ( uncertainties ), 3, 3) ),
		np.ndarray ( (len ( uncertainties ), 4, 4) )
	)
	for i in range ( len ( uncertainties ) ):
		certaintyNP[0][i] = uncertainties[i][0]
		certaintyNP[1][i] = uncertainties[i][1]
	posCerts: np.ndarray = certaintyNP[0]
	oriCerts: np.ndarray = certaintyNP[1]

	avgPosCert: np.ndarray = np.ndarray ( (len ( posCerts ), 3) )
	for i in range ( len ( posCerts ) ):
		avgPosCert[i] = posCerts[i].diagonal ()
	avgPosCert = np.average ( avgPosCert, axis = 0 )

	avgOriCert: np.ndarray = np.ndarray ( (len ( oriCerts ), 4) )
	for i in range ( len ( oriCerts ) ):
		avgOriCert[i] = oriCerts[i].diagonal ()
	avgOriCert = np.average ( avgOriCert, axis = 0 )
	avgOriCert = avgOriCert.sum ()

	averageUncertainty: typing.Tuple[float, float] = (np.sqrt ( avgPosCert.sum () ), np.sqrt ( avgOriCert ))

	Logger.log ( "Average uncertainty: Pos {} Ori {}".format ( np.sqrt ( avgPosCert ),
	                                                           averageUncertainty[1] ) )

	aneesPos: float = ANEES ( posErrors, posCerts, len ( dataloader ) )
	aneesOri: float = ANEES ( oriErrors, oriCerts, len ( dataloader ) )

	Logger.log ( "Average Normalized Error Estimate Squared: Pos {} Ori {}".format ( aneesPos, aneesOri ),
	             logger = "min" )

	return averageUncertainty[0], averageUncertainty[1], averageError[0], averageError[1], aneesPos, aneesOri

def loadModel () -> typing.Dict[str, typing.Union[torch.nn.Module, torch.optim.Optimizer,
                                                  typing.List, float, float, int, typing.Tuple[float, float],
                                                  typing.Tuple[float, float], typing.Tuple[float, float], typing.Tuple[
	                                                  float, float], typing.Tuple[float, float]]]:
	"""
	Loads the model from file. If any keys mismatch, it'll wrap the network in a nn.DataParallel. If it gets any other errors
	it will initiate the network from the default GoogLeNet model found in pretrained-models. Also loads epochs, training
	and validation differences, and a plethora of other stuff. See util.saveModel for more information on what is loaded.

	:return: Everything that was in the file.
	"""
	# Create the network.
	network: torch.nn.Module = PoseNet ( input_nc = 3 )

	# Default network should be placed on the GPU so that the other default things
	# can expect that to be the case.
	if Config.useCuda ():
		network = network.cuda ()

	Logger.log ( "Creating learning objects.", logger = "main" )

	optimizer: torch.optim.Optimizer = torch.optim.Adam ( network.parameters (), lr = Config.getArgs ().learning_rate )

	scheduler1: torch.optim.lr_scheduler.ReduceLROnPlateau = torch.optim.lr_scheduler.ReduceLROnPlateau (
			optimizer = optimizer, threshold = Config.getArgs ().beta,
			verbose = Logger.shouldLog (), threshold_mode = "abs",
			factor = Config.getArgs ().factor )

	scheduler2: torch.optim.lr_scheduler.StepLR = torch.optim.lr_scheduler.StepLR ( optimizer = optimizer,
	                                                                               step_size = 80,
	                                                                               gamma = Config.getArgs ().factor )
	trainingLoss: typing.List[float] = []
	validationLoss: typing.List[float] = []
	trainingDiff: typing.List[float] = []
	validationDiff: typing.List[float] = []
	testingDiff: typing.List[float] = []
	uncertainty: typing.List[float] = []
	anees: typing.List[float] = []

	starting_epoch: int = 0

	hasParallelilized: bool = False

	defaultPretrainedModel: str = "pretrained-models/places-googlenet.pickle"

	Logger.log ( "Loading from pretrained model {}".format ( Config.getArgs ().pretrained_model ), logger = "main" )
	# Load from pretrained model.
	path: str = Config.getArgs ().pretrained_model
	if path is not None or Config.getArgs ().resume:
		try:
			# Load checkpoint from file
			checkpoint: typing.Dict[str, typing.Any] = util.getPretrainedModel ( path = path )
			# If we have version in the data of checkpoint
			if "version" in checkpoint:
				# But it's not the current version...
				if checkpoint["version"] != Config.version:
					# Load in GoogLeNet
					Logger.warn ( "User wants to load outdated model file!" )
				# If the version matches, load in the posenet model

				try:
					# We can't load in from googlenet here because googlenet doesn't have a version key
					network.load_state_dict ( checkpoint["model"] )
				except RuntimeError:
					# If we get a RuntimeError it's probably because we're trying to load something
					# that was wrapped in the nn.DataParallel layer.
					# We could prewrap it all beforehand, but that would mean we would need to
					# circumnavigate GoogLeNet and its keys.
					network = torch.nn.DataParallel ( network )
					hasParallelilized = True
					try:
						network.load_state_dict ( checkpoint["model"] )
					except RuntimeError:
						# if we still get an error message, that means we changed the architecture.
						Logger.warn (
								"Trying to load from version that has different architecture than current version." )
						Logger.log ( "Loading from default model.", logger = "min" )
						network = torch.nn.DataParallel (
								PoseNet ( input_nc = 3, weights = util.getPretrainedModel ( defaultPretrainedModel ) ) )
				if checkpoint["version"] == Config.version:
					# We wouldn't want to load in these things from a different version.
					optimizer.load_state_dict ( checkpoint["optimizer"] )
					scheduler1 = checkpoint["schedulers"][0]
					scheduler2.load_state_dict ( checkpoint["schedulers"][1] )
					trainingLoss = checkpoint["trainingLoss"]
					validationLoss = checkpoint["validationLoss"]
					trainingDiff = checkpoint["trainingDifference"]
					validationDiff = checkpoint["validationDifference"]
					starting_epoch = checkpoint["epoch"] + 1
					testingDiff = checkpoint["testingDifference"]
					uncertainty = checkpoint["uncertainty"]
					anees = checkpoint["anees"]
			else:  # If we don't have a version in the model file, we'll load GoogLeNet.
				Logger.log ( "Loading network from default pretrained model." )
				network = PoseNet ( input_nc = 3, weights = util.getPretrainedModel ( defaultPretrainedModel ) )
		except FileNotFoundError:
			Logger.error ( "Cannot find pretrained model file!" )
			Logger.log ( "Loading from default pretrained model." )
			# Load from googleNet
			network = PoseNet ( input_nc = 3, weights = util.getPretrainedModel ( defaultPretrainedModel ) )
	else:
		Logger.log ( "Loading from default pretrained model." )
		# Load from googleNet
		network = PoseNet ( input_nc = 3, weights = util.getPretrainedModel ( defaultPretrainedModel ) )

	# This will be the same on GPU or CPU so don't you worry baby.
	# Don't you worry OHHHH-OHOH
	if not hasParallelilized:
		network = torch.nn.DataParallel ( network )

	# If we have access to GPUs, put PoseNet on them.
	if Config.useCuda ():
		network = network.cuda ()

	return {
		"network":              network,
		"optimizer":            optimizer,
		"schedulers":           [scheduler1, scheduler2],
		"trainingLoss":         trainingLoss,
		"validationLoss":       validationLoss,
		"startingEpoch":        starting_epoch,
		"validationDifference": validationDiff,
		"trainingDifference":   trainingDiff,
		"testingDifference":    testingDiff,
		"uncertainty":          uncertainty,
		"anees":                anees
	}

def main ():
	"""
	The main training script of the program. Runs through the whole shebang!

	"""
	args = Config.getArgs ()
	if args.threads is 7:
		Logger.warn ( "Number of threads has been limited to 7 for PyTorch reasons." )
	if args.force_threads and args.threads >= 8:
		Logger.warn ( "Remember PyTorch can be a little wonky with 8+ threads!" )
	Logger.log ( "Use Cuda? {}".format ( Config.useCuda () ) )
	if Config.useCuda ():
		Logger.log ( "CUDA Properties is: {}".format ( torch.cuda.get_device_properties ( 0 ) ) )

	Logger.log ( "Parsed args", logger = "main" )
	Logger.log ( str ( args ) )

	# Create validation data by stealing some from training data.
	util.createValidationDataFile ( filenameTrain = os.path.join ( args.database_root, "dataset_train.txt" ),
	                                filenameValidate = os.path.join ( args.database_root, "dataset_validate.txt" ) )

	Logger.log ( "Creating PoseNet.", logger = "main" )

	# Get the mean and std of the database that we'll be using.
	# Btw this takes a while.
	Logger.log ( message = "Getting mean and std of dataset", logger = "main" )
	Logger.log ( message = "This can take a while...", logger = "main" )
	if not args.skip_training:
		normalizeDataset: torch.utils.data.Dataset = PoseNetDataSet ( dataroot = args.database_root,
		                                                              transform = tv.transforms.ToTensor () )
	else:
		normalizeDataset: torch.utils.data.Dataset = PoseNetDataSet ( dataroot = args.database_root,
		                                                              transform = tv.transforms.ToTensor (),
		                                                              phase = "test" )
	mean, std = util.getMeanAndStd ( normalizeDataset )

	Logger.log ( "Mean and std is {} {}".format ( mean, std ) )

	# Create the transformation functions we'll use on each of our images.
	transformImg: tv.transforms.Compose = tv.transforms.Compose ( [  # Resize the image to 256x256
		tv.transforms.Resize ( (256, 256) ),  # Crop the image to 224 x 224
		tv.transforms.RandomCrop ( (224, 224) ),  # Make the image a tensor with dimensions 3x256x256
		# (3 because of rgb values within the image)
		tv.transforms.ToTensor (),  # Normalize the images
		tv.transforms.Normalize ( mean = mean, std = std )] )

	Logger.log ( "Loading dataset.", logger = "main" )
	# Create the dataset based on the KingsCollege database that should be in
	# the working directory of the program.
	datasetTrain: PoseNetDataSet = PoseNetDataSet ( dataroot = args.database_root, transform = transformImg )
	datasetValid: PoseNetDataSet = PoseNetDataSet ( dataroot = args.database_root, transform = transformImg,
	                                                phase = "validate" )
	datasetTest: PoseNetDataSet = PoseNetDataSet ( dataroot = args.database_root, transform = transformImg,
	                                               phase = "test" )

	# Create the dataloader which takes in the KingsCollege dataset and
	# allows us to use it in our training.
	dataloaderTrain: data.DataLoader = data.DataLoader ( dataset = datasetTrain, batch_size = args.batch_size,
	                                                     shuffle = True,
	                                                     num_workers = Config.getArgs ().threads )
	dataloaderValidate: data.DataLoader = data.DataLoader ( dataset = datasetValid, batch_size = args.batch_size,
	                                                        shuffle = True,
	                                                        num_workers = Config.getArgs ().threads )
	# Same as above but with testing.
	dataloaderTest: data.DataLoader = data.DataLoader ( dataset = datasetTest, batch_size = 1,
	                                                    num_workers = Config.getArgs ().threads )

	# The typing for loadModel is already horrible. We won't do it here.
	bigDictionary = loadModel ()
	network = bigDictionary["network"]
	optimizer = bigDictionary["optimizer"]

	schedulers: typing.List = bigDictionary["schedulers"]
	schedulerPlateau: torch.optim.lr_scheduler.ReduceLROnPlateau = schedulers[0]
	schedulerStep: torch.optim.lr_scheduler.StepLR = schedulers[1]

	trainingLoss: typing.List[float] = bigDictionary["trainingLoss"]
	validationLoss: typing.List[float] = bigDictionary["validationLoss"]
	trainingDiff: typing.List[typing.Tuple[float, float]] = bigDictionary["trainingDifference"]
	validationDiff: typing.List[typing.Tuple[float, float]] = bigDictionary["validationDifference"]
	starting_epoch: int = bigDictionary["startingEpoch"]
	testUncertainties: typing.List[typing.Tuple[float, float]] = bigDictionary["uncertainty"]
	testDifferences: typing.List[typing.Tuple[float, float]] = bigDictionary["testingDifference"]
	anees: typing.List[typing.Tuple[float, float]] = bigDictionary["anees"]

	ending_epoch: int = starting_epoch + args.epochs

	Logger.log ( "Optimizer state: {}".format ( optimizer.state ) )

	if Config.useCuda ():
		network = network.cuda ()
	else:
		network = network.cpu ()

	# for each epoch that we want to do...
	for epoch in range ( starting_epoch, ending_epoch ):
		if not args.skip_training:
			# If the current epoch is divisible by 80, decrease it by 90%
			schedulerStep.step ()
			# train network
			trainLoss, trainPosDiff, trainOriDiff = trainNetwork ( network = network, optimizer = optimizer,
			                                                       dataloader = dataloaderTrain,
			                                                       epoch = epoch,
			                                                       beta = args.beta,
			                                                       print_every = args.print_every )
			trainingLoss.append ( trainLoss )
			trainingDiff.append ( (trainPosDiff, trainOriDiff) )

			# validate network
			validLoss, validPosDiff, validOriDiff = validate ( network = network, dataloader = dataloaderValidate,
			                                                   beta = args.beta,
			                                                   print_every = args.print_every, epoch = epoch )

			validationLoss.append ( validLoss )
			validationDiff.append ( (validPosDiff, validOriDiff) )

			# Decrease threshold of scheduler when our loss is less than the current threshold
			# times a certain factor.
			if validationLoss[-1] < schedulerPlateau.threshold * args.threshold_factor:
				schedulerPlateau.threshold /= 2

			schedulerPlateau.step ( epoch = epoch, metrics = validationLoss[-1] )

			# Save the network
			util.saveModel ( model_filename = args.model_file,
			                 schedulers = [schedulerPlateau, schedulerStep.state_dict ()],
			                 epoch = epoch, network = network, optimizer = optimizer,
			                 trainingLoss = trainingLoss, validationLoss = validationLoss,
			                 trainingDifference = trainingDiff, validationDifference = validationDiff,
			                 testingDifference = testDifferences, uncertainty = testUncertainties, anees = anees )

		if not args.skip_testing and (epoch % args.test_every == 0 or epoch + 1 == ending_epoch):
			# Test the network
			posUncert, oriUncert, posDiff, oriDiff, aneesPos, aneesOri = test ( network = network,
			                                                                    dataloader = dataloaderTest )
			testUncertainties.append ( (posUncert, oriUncert) )
			testDifferences.append ( (posDiff, oriDiff) )
			anees.append ( (aneesPos, aneesOri) )
			# Save the network
			util.saveModel ( model_filename = args.model_file,
			                 schedulers = [schedulerPlateau, schedulerStep.state_dict ()],
			                 epoch = epoch, network = network, optimizer = optimizer,
			                 trainingLoss = trainingLoss, validationLoss = validationLoss,
			                 trainingDifference = trainingDiff, validationDifference = validationDiff,
			                 testingDifference = testDifferences, uncertainty = testUncertainties, anees = anees )


from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.throttling import ScopedRateThrottle
from rest_framework.permissions import IsAuthenticated
from rest_framework.authtoken.models import Token
from django.contrib.auth import get_user_model
from rest_framework.response import Response
from rest_framework.reverse import reverse
from rest_framework.views import APIView
from rest_framework import status
from django.http import Http404
from .serializers import *
from .permissions import *
from .models import *

User = get_user_model()

class ApiRoot(APIView):

    def get(self, request, *args, **kwargs):

        data = {

            'api-token': reverse('api-token', request=request),
            'users': reverse('users-list', request=request),
            'profiles': reverse('profiles-list', request=request),
            'profiles-posts': reverse('posts-list', request=request),
            'posts-comments': reverse('comments-list', request=request),
            'profiles-detail': reverse('profiles-detail-posts-comments', request=request),
        }

        return Response(data, status=status.HTTP_200_OK)

class UserList(APIView):

    permission_classes = [IsUserOrReadOnly]

    def get(self, request, format=None):
        user = User.objects.all()
        self.check_object_permissions(request, User)
        user_serializer = UserSerializer(user, many=True)
        return Response(user_serializer.data, status=status.HTTP_200_OK)

class ProfileList(APIView):

    permission_classes = [IsProfileOrReadOnly]

    def get(self, request, format=None):
        profiles = Profile.objects.all()
        self.check_object_permissions(request, Profile)
        profile_serializer = ProfileSerializer(profiles, many=True)
        return Response(profile_serializer.data, status=status.HTTP_200_OK)

class ProfileDetail(APIView):

    permission_classes = [IsProfileOrReadOnly]

    def get_object(self, pk):
        try:
            return Profile.objects.get(pk=pk)
        except Profile.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        profile = self.get_object(pk)
        profile_serializer = ProfileSerializer(profile)
        return Response(profile_serializer.data, status=status.HTTP_200_OK)

    def put(self, request, pk, format=None):
        profile = self.get_object(pk)
        profile_serializer = ProfileSerializer(profile, data=request.data)
        if profile_serializer.is_valid():
            profile_serializer.save()
            return Response(profile_serializer.data, status=status.HTTP_200_OK)
        return Response(profile_serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk, format=None):
        profile = self.get_object(pk)
        profile.delete()
        return Response(status=status.HTTP_200_OK)

class PostList(APIView):

    permission_classes = [PostIsOwnerOrReadOnly]

    def get(self, request, format=None):
        profiles = Profile.objects.all()
        profile_serializer = ProfileListPostSerializer(profiles, many=True)
        return Response(profile_serializer.data, status=status.HTTP_200_OK)

class PostDetail(APIView):

    permission_classes = [PostIsOwnerOrReadOnly]

    def get_object(self, obj, pk):
        try:
            return obj.objects.get(pk=pk)
        except obj.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        profile = self.get_object(Profile, pk)
        profile_serializer = ProfileListPostSerializer(profile, many=False)
        return Response(profile_serializer.data, status=status.HTTP_200_OK)

    def post(self, request, pk, format=None):
        self.get_object(Profile, pk)
        request.data['userId'] = pk
        profile_serializer = PostSerializer(data=request.data)
        if profile_serializer.is_valid():
            profile_serializer.save()
            return Response(profile_serializer.data, status=status.HTTP_201_CREATED)
        return Response(profile_serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def put(self, request, pk, format=None):
        post = self.get_object(Post, pk)
        self.check_object_permissions(request, post)
        request.data['userId'] = post.userId_id
        request.data['pk'] = pk
        profile_serializer = PostSerializer(post, data=request.data)
        if profile_serializer.is_valid():
            profile_serializer.save()
            return Response(profile_serializer.data, status=status.HTTP_200_OK)
        return Response(profile_serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk, format=None):
        post = self.get_object(Post, pk)
        self.check_object_permissions(request, post)
        post.delete()
        return Response(status=status.HTTP_200_OK)

class CommentList(APIView):

    permission_classes = [CommentIsOwnerOrReadOnly]

    def get(self, request, format=None):
        post = Post.objects.all()
        post_serializer = PostListCommentSerializer(post, many=True)
        return Response(post_serializer.data, status=status.HTTP_200_OK)

class PostListWithCommentDetail(APIView):

    permission_classes = [CommentIsOwnerOrReadOnly]

    def get_object(self, pk):
        try:
            return Post.objects.get(pk=pk)
        except Post.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        post = self.get_object(pk)
        post_serializer = PostListCommentSerializer(post, many=False)
        return Response(post_serializer.data, status=status.HTTP_200_OK)

class CommentCreateOrList(APIView):

    permission_classes = [CommentIsOwnerOrReadOnly]

    def get_object(self, pk):
        try:
            return Comment.objects.filter(postId=pk)
        except Comment.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        comment = self.get_object(pk)
        comment_serializer = CommentSerializer(comment, many=True)
        return Response(comment_serializer.data, status=status.HTTP_200_OK)

    def post(self, request, pk, format=None):
        request.data['postId'] = pk
        comment_serializer = CommentSerializer(data=request.data)
        if comment_serializer.is_valid():
            comment_serializer.save()
            return Response(comment_serializer.data, status=status.HTTP_201_CREATED)
        return Response(comment_serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class CommentDetail(APIView):

    permission_classes = [CommentIsOwnerOrReadOnly]

    def get_comment(self, pk_post, pk_comment):
        try:
            post = Comment.objects.filter(postId=pk_post)
            try:
                return post.get(pk=pk_comment)
            except Comment.DoesNotExist:
                raise Http404
        except Post.DoesNotExist:
            raise Http404

    def get(self, request, pk_post, pk_comment, format=None):
        comment = self.get_comment(pk_post, pk_comment)
        comment_serializer = CommentSerializer(comment, many=False)
        return Response(comment_serializer.data, status=status.HTTP_200_OK)

    def put(self, request, pk_post, pk_comment, format=None):
        comment = self.get_comment(pk_post, pk_comment)
        request.data['postId'] = pk_post
        comment_serializer = CommentSerializer(comment, data=request.data)
        if comment_serializer.is_valid():
            comment_serializer.save()
            return Response(comment_serializer.data, status=status.HTTP_200_OK)
        return Response(comment_serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk_post, pk_comment, format=None):
        comment = self.get_comment(pk_post, pk_comment)
        self.check_object_permissions(request, comment)
        comment.delete()
        return Response(status=status.HTTP_200_OK)

class AmountPostAndCommentFromProfile(APIView):

    def get(self, request, format=None):
        profiles = Profile.objects.all()

        profiles_detail = []

        for profile in profiles:
            info = {}
            amount_post = Post.objects.filter(userId=profile.pk)
            info['pk'] = profile.pk
            info['name'] = profile.name
            info['amount_posts'] = len(amount_post)
            info['amount_comments'] = 0
            for post in amount_post:
                amount_comment = Comment.objects.filter(postId=post.pk)
                info['amount_comments'] += len(amount_comment)
            profiles_detail.append(info)

        return Response(profiles_detail, status=status.HTTP_200_OK)

class CustomAuthToken(ObtainAuthToken):

    throttle_scope = 'api-token'
    throttle_classes = [ScopedRateThrottle]

    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data, context={'request': request})
        self.check_throttles(request)
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data['user']
        token, created = Token.objects.get_or_create(user=user)
        return Response({
            'token': token.key,
            'user_id': user.pk,
            'name': user.username,
            'email': user.email},
            status=status.HTTP_200_OK)


"""Clock generation
"""

import numpy as np

_rng = np.random.default_rng()

def edges(t_sym: float = 8e-10,
          t_rj: float = 0,
          t_uj: float = 0,
          t_sj: float = 0,
          f_sj: float = 0,
          dcd: float = 0.0,
          n: int = 1e6) -> np.ndarray:
  """Generate edges of a clock

  Args:
    t_sym: Duration of a symbol
    t_rj: Amplitude of random jitter, gaussian standard deviation
    t_uj: Amplitude of uniform jitter, uniform distribution width
    t_sj: Amplitude of sinusoidal jitter
    f_sj: Frequency of sinusoidal jitter
    dcd: Duty-cycle-distortion [-1, 1]
    n: Number of edges to generate

  Returns:
    numpy array of edges times
  """
  n = int(n)
  e = np.linspace(0, t_sym * (n - 1), n)
  e += np.sin(2 * np.pi * f_sj * e + _rng.uniform(0, 2 * np.pi)) * t_sj
  e[::2] += dcd * t_sym
  e += _rng.normal(0, t_rj, n)
  e += _rng.uniform(-t_uj / 2, t_uj / 2, n)
  return e


with open('data/09.txt', 'r') as file:
    garbage, escaped, depth, score, removed = False, False, 0, 0, 0
    for char in file.readline():
        if escaped:
            escaped = False
        elif garbage:
            if char == '!':
                escaped = True
            elif char == '>':
                garbage = False
            else:
                removed += 1
        elif char == '<':
            garbage = True
        elif char == '{':
            depth += 1
            score += depth
        elif char == '}':
            depth -= 1

print(f'Part one: {score}')
print(f'Part two: {removed}')


N = 10

def get(num, l, r):
    res = 0
    for i in range(l, r-1, -1): res = res * 10 + num[i]
    return res

def power10(x):
    res = 1
    while x:
        res *= 10
        x -= 1
    return res

def count(n, x):
    if not n: return 0
    num = []
    while n:
        num.append(n % 10)
        n //= 10
    n = len(num)

    res = 0
    for i in range(n - 1 - (not x), -1, -1):
        if i < n - 1:
            res += get(num, n-1, i+1) * power10(i)
            if not x: res -= power10(i)

        if num[i] == x: res += get(num, i-1, 0) + 1
        elif num[i] > x: res += power10(i)

    return res

while True:
    a, b = map(int, input().split())
    if a == 0 and b == 0:
        break

    if a > b: a, b = b, a
    for i in range(0, 10):
        print(count(b, i) - count(a-1, i), end=' ')
    print()


class Solution:
    def isPalindrome(self, x):
        """
        :type x: int
        :rtype: bool
        """
        if x<0 or ((x != 0) and (x%10 == 0)):
            return False

        half = 0
        while half < x:
            half = x%10 +half*10
            x = (x/10).__int__()

        return (half == x) or ((half/10).__int__() == x)

if __name__ == '__main__':
    S = Solution()
    x = -121
    print(S.isPalindrome(x))


# _*_ coding:utf-8 _*_
# 开发人员：Lee
# 开发时间：2021-04-26 10:52
# 文件名称：gamma_aug
# 开发工具：PyCharm
import cv2
import numpy as np
import math
import SimpleITK as sitk
from matplotlib.pyplot import plot as plt
from pylab import *

def gamma_trans(img, gamma):  # gamma函数处理
    """
    gamma correction
    Args:
        img: H, W, C pic
        gamma: gamma corr

    """
    gamma_table = [np.power(x / 255.0, gamma) * 255.0 for x in range(256)]  # 建立映射表
    gamma_table = np.round(np.array(gamma_table)).astype(np.uint8)  # 颜色值为整数

    return cv2.LUT(img, gamma_table)  # 图片颜色查表。另外可以根据光强（颜色）均匀化原则设计自适应算法。

def main(exp_flag, nii_flag, nii_in_path, gamma1):
    if exp_flag:
        file_path = "/Now_state/code_in_test/aug/mapel.png"
        img_gray = cv2.imread(file_path, 0)  # 灰度图读取，用于计算gamma值
        img = cv2.imread(file_path)  # 原图读取

        mean = np.mean(img_gray)
        gamma_val = math.log10(0.5) / math.log10(mean / 255)  # 公式计算gamma
        # gamma_val = 2

        image_gamma_correct = gamma_trans(img[:, :, 1], gamma_val)  # gamma变换
        image_gamma_correct1 = gamma_trans(img_gray, gamma1)  # gamma变换
        # image_gamma_correct2 = gamma_trans(img_gray, 1 / gamma1)  # gamma变换

        fig = plt.figure()
        subplot(131)
        imshow(image_gamma_correct1, cmap='gray')
        title('gamma=' + str(gamma1))
        axis('off')
        subplot(132)
        imshow(img_gray, cmap='gray')
        title('ori')
        axis('off')
        subplot(133)
        imshow(image_gamma_correct, cmap='gray')
        title('gamma=' + str(gamma_val))
        axis('off')
        plt.savefig('gamma_corr.jpg')
        plt.show()

        hist, bins = np.histogram(img_gray, 256, [0, 255])
        # 使用 plt.fill 函数 填充多边形
        plt.fill(hist)
        #  标记x轴的名称
        plt.xlabel('pixel value')
        # 显示直方图
        plt.show()
        plt.savefig('ori hist.png')

        hist, bins = np.histogram(image_gamma_correct1, 256, [0, 255])
        # 使用 plt.fill 函数 填充多边形
        plt.fill(hist)
        #  标记x轴的名称
        plt.xlabel('pixel value')
        # 显示直方图
        plt.show()
        plt.savefig('hist at gamma=' + str(gamma1) + '.png')

        hist, bins = np.histogram(image_gamma_correct, 256, [0, 255])
        # 使用 plt.fill 函数 填充多边形
        plt.fill(hist)
        #  标记x轴的名称
        plt.xlabel('pixel value')
        # 显示直方图
        plt.show()
        plt.savefig('hist at gamma=' + str(gamma_val) + '.png')

        # cv2.namedWindow('image_raw', 0)   # 解决显示不全的问题
        # cv2.imshow('image_raw', img_gray)
        #
        # cv2.namedWindow('image_gamma', 0)
        # cv2.imshow('image_gamma', image_gamma_correct)
        #
        # cv2.waitKey(0)

    if nii_flag:
        img = sitk.GetArrayFromImage(nii_in_path)

if __name__ == '__main__':
    exp_flag = True
    nii_flag = False

    gamma1 = 0.8

    nii_in_path = 'D:/Dataset/1/train/case_00000/imaging.nii.gz'
    main(exp_flag, nii_flag, nii_in_path, gamma1)


'''
    신라대학교 202395016 컴퓨터공학부 박수연

    -- bubble sort 설명 (버블 정렬) --
        : 현재 인덱스의 값보다 다음 인덱스의 값이 작을 경우 서로 값을 변경하는 정렬 알고리즘
        : 현재 위치보다 다음 위치의 값이 더 작을 때 둘의 위치를 바꿈 (오름차순 정렬)
        : 파이썬에서는 2개의 변수만으로 값을 서로 바꿀 수 있음

        arr = [64, 34, 25, 12, 57, 93, 1, 123]          # arr 변수에 이와 같은 리스트 값을 선언되었을 때

        if arr[j] > arr[j + 1]:                         # 현재 인덱스 값이 바로 뒤에 있는 인덱스 값보다 크다면
	        arr[j], arr[j + 1] = arr[j + 1], arr[j]     # 서로의 위치를 바꿈
'''
# list 변수에 리스트 선언
list = [64, 34, 25, 12, 57, 93, 1, 123]

# 버블 정렬의 범용성을 높이기 위해 함수로 만듬
def bubbleSort(list):
    n = len(list)        # len을 리스트에 쓰면 요소를 셈, arr 변수에 있는 요소는 8개

    # 배열의 크기만큼 반복, 8번 반복
    for i in range(n):

        # 배열의 총 크기에서 i의 값과 1을 뺀 만큼 반복
        for j in range(0, n - i - 1):

            # 현재 인덱스의 값이 다음 인덱스의 값보다 크다면
            if list[j] > list[j + 1]:
                list[j], list[j + 1] = list[j + 1], list[j] # 서로 위치를 변환

print(":: 버블 정렬 전 ::\n", list)
print()
bubbleSort(list)        # 함수 호출 전엔 list 변수에 있는 리스트 요소들이 그대로 출력, 함수 호출 후엔 리스트 요소들이 오름차순으로 정렬됨

print(":: 버블 정렬 후::\n", list)


import string
import tkinter.ttk
import tkinter as tk
from string import *

alphabetlist = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
plugboard = ["Z", "P", "H", "N","M", "S", "W", "C", "I", "Y", "T", "Q", "E", "D", "O", "B", "L", "R", "F", "K", "U", "V", "G", "X", "J","A"]

rotorI = ["E", "K", "M", "F", "L", "G", "D", "Q", "V", "Z", "N", "T", "O", "W", "Y", "H", "X", "U", "S", "P", "A", "I", "B", "R", "C", "J"]
rotorII = ["A", "J", "D", "K", "S", "I", "R", "U", "X", "B", "L", "H", "W", "T", "M", "C", "Q", "G", "Z", "N", "P", "Y", "F", "V", "O", "E"]
rotorIII = ["B", "D", "F", "H", "J", "L", "C", "P", "R", "T", "X", "V", "Z", "N", "Y", "E", "I", "W", "G", "A", "K", "M", "U", "S", "Q", "O"]
rotorIV = ["E", "S", "O", "V", "P", "Z", "J", "A", "Y", "Q", "U", "I", "R", "H", "X", "L", "N", "F", "T", "G", "K", "D", "C", "M", "W", "B"]
rotorV = ["V", "Z", "B", "R", "G", "I", "T", "Y", "U", "P", "S", "D", "N", "H", "L", "X", "A", "W", "M", "J", "Q", "O", "F", "E", "C", "K"]

#This is so that the GUI would recognise rotorI as "RotorI" rather than "E,K,M...." for example
rotor_dictionary = {"RotorI":rotorI,"RotorII":rotorII,"RotorIII":rotorIII,"RotorIV":rotorIV,"RotorV":rotorV}

reflectorA = ["E","J","M","Z","A","L","Y","X","V","B","W","F","C","R","Q","U","O","N","T","S","P","I","K","H","G","D"]
reflectorB = ["Y","R","U","H","Q","S","L","D","P","X","N","G","O","K","M","I","E","B","F","Z","C","W","V","J","A","T"]
reflector_dictionary = {"ReflectorA":reflectorA,"ReflectorB":reflectorB}

#make root and main page
root = tk.Tk()
canvas = tk.Canvas(root, width=1720, height=900)

#main GUI is made here
user_input = tk.Text(root, font='Arial 10')
user_input.place(x = 350, y = 400, width=400, height=200)
input_label = tk.Label(root, text="Input plaintext here:")
input_label.place(x = 350, y = 375)

user_output = tk.Text(root, font='Arial 10')
user_output.place(x = 950, y = 400, width=400, height=200)
output_label = tk.Label(root, text="Ciphertext will be output here:")
output_label.place(x = 950, y = 375)

slow_select = tk.ttk.Combobox(root, value=list(rotor_dictionary))
slow_select.place(x = 480, y = 100)

slow_label = tk.Label(root,text="Please set the slow rotor:")
slow_label.place(x = 480, y =75)

slow_position = tk.ttk.Combobox(root, value=list(alphabetlist))
slow_position.place(x = 480, y = 200)

pos1_label = tk.Label(root,text="Set the position of the slow rotor:")
pos1_label.place(x = 475, y =175)

middle_select = tk.ttk.Combobox(root, value=list(rotor_dictionary))
middle_select.place(x = 780, y = 100)

middle_label = tk.Label(root,text="Please set the middle rotor:")
middle_label.place(x = 780, y =75)

middle_position = tk.ttk.Combobox(root, value=list(alphabetlist))
middle_position.place(x = 780, y = 200)

pos2_label = tk.Label(root,text="Set the position of the middle rotor:")
pos2_label.place(x = 775, y =175)

fast_select = tk.ttk.Combobox(root, value=list(rotor_dictionary))
fast_select.place(x = 1080, y = 100)

fast_label = tk.Label(root,text="Please set the fast rotor:")
fast_label.place(x = 1080, y =75)

fast_position = tk.ttk.Combobox(root, value=list(alphabetlist))
fast_position.place(x = 1080, y = 200)

pos3_label = tk.Label(root,text="Set the position of the fast rotor:")
pos3_label.place(x = 1075, y =175)

reflector_select = tk.ttk.Combobox(root, value=list(reflector_dictionary))
reflector_select.place(x = 635, y = 300)

reflector_label = tk.Label(root, text="Please select a reflector:")
reflector_label.place(x = 635, y = 275)

#The main method that handles the encryption/decryption processs
def encrypt_or_decrypt():
    encrypt_list = []
    #set the index to what the user assigns
    index_rotor1 = alphabetlist.index(fast_position.get())
    index_rotor2 = alphabetlist.index(middle_position.get())
    index_rotor3 = alphabetlist.index(slow_position.get())

    #This is to pick up the input
    to_encrypt = list(user_input.get("1.0","end-1c"))

    #set our rotors and reflector to what the user chose
    fast_rotor = rotor_dictionary.get(fast_select.get())
    middle_rotor = rotor_dictionary.get(middle_select.get())
    slow_rotor = rotor_dictionary.get(slow_select.get())

    reflector = reflector_dictionary.get(reflector_select.get())

    for char in to_encrypt:

        if char in alphabetlist:

            #This is to facilitate the rotor movement after each cycle is done
            if index_rotor1 % 25 == 0 and index_rotor1 > 0:
                index_rotor1 = 0
                index_rotor2 += 1
                middle_position.set(alphabetlist[index_rotor2 % 26]) #make sure to do modulo 26 so it doesn't overflow
            else: #rotor1/fast rotor should usually go up by one
                index_rotor1 += 1

            if index_rotor2 % 26 == 0 and index_rotor2 > 0:
                index_rotor2 = 0
                index_rotor3 += 1
                slow_position.set(alphabetlist[index_rotor3 % 26])

            if index_rotor3 % 26 == 0:
                index_rotor3 = 0
                slow_position.set(alphabetlist[index_rotor3 % 26])
            #Example with encrypting the letter A with our fast as RotorI,middle as RotorII,slow as RotorIII all in their base positions:

            char = plugboard[alphabetlist.index(char) % 26] #start with plugboard encryption e.g A -> Z
            plugboard_encryption = char

            fast_position.set(alphabetlist[index_rotor1 % 26] ) #Updates position in GUI
            current_pos1 = (alphabetlist.index(char) + index_rotor1) % 26 #makes the current position of the rotor in this case to B
            char = fast_rotor[current_pos1] # A is encrypted to E
            char = alphabetlist[((alphabetlist.index(char) - index_rotor1) + index_rotor2) % 26] # This changes E to D for the next rotor

            current_pos2 = (alphabetlist.index(char))
            char = middle_rotor[current_pos2] #D is encrypted to K
            char = alphabetlist[((alphabetlist.index(char) - index_rotor2) + index_rotor3 )% 26] #K is set to K as both rotors haven't moved

            current_pos3 = (alphabetlist.index(char))
            char = slow_rotor[current_pos3] #K encrypts to X

            char = reflector[(alphabetlist.index(char) - index_rotor3) % 26] #Reflector substitutes X to J

            char = alphabetlist[(alphabetlist.index(char) + index_rotor3) % 26]
            char = alphabetlist[slow_rotor.index(char)] #We work backwards so J is now E

            char = alphabetlist[((alphabetlist.index(char) + index_rotor2) - index_rotor3) % 26]
            char = alphabetlist[middle_rotor.index(char)] #Now E is encrypted to Z

            char = alphabetlist[((alphabetlist.index(char) + index_rotor1) - index_rotor2) % 26] #Changed back to A as fast rotor has moved
            char = alphabetlist[fast_rotor.index(char)] # A changes to U

            char = alphabetlist[(alphabetlist.index(char) - index_rotor1) % 26] #U changes to T

            char = alphabetlist[plugboard.index(char) % 26] #Plugboard encrypts T to K

            encrypt_list.append(char) # Append encrypted characters in a list
            print( "current rotor1 pos: " + alphabetlist[index_rotor1% 26] )
            print( "current rotor2 pos: " + alphabetlist[index_rotor2% 26])
            print("current rotor3 pos: " + alphabetlist[index_rotor3% 26])
            print(encrypt_list)

    ciphertext= "".join(encrypt_list) #Join the elements in the list and make them one string
    user_output.delete(1.0,"end") #Delete the old items in the text field
    user_output.insert(1.0,ciphertext) #Insert the new ciphertext in the text field

run_txt = tk.StringVar()
run_btn = tk.Button(root, textvariable=run_txt, font='Arial', command=encrypt_or_decrypt) #Button that runs the method
run_txt.set("Encrypt/Decrypt")
run_btn.grid(column=1, row=2)

canvas.grid(columnspan=3, rowspan=3)

root.mainloop()

Cyber Security Assignment/EnigmaMachine .py


for _ in range(int(input())):
    N, X = map(int, input().split())
    L = list(input())
    visited = [X]
    for i in L:
        if i == 'R':
            X += 1
        else:
            X -= 1
        if X not in visited:
            visited.append(X)
    print(len(visited))


from fastsklearnfeature.transformations.NumericUnaryTransformation import NumericUnaryTransformation
from sklearn.base import BaseEstimator, TransformerMixin
import pandas as pd
import numpy as np
from fastsklearnfeature.candidates.CandidateFeature import CandidateFeature
from typing import List
import sympy

class discretize(sympy.Function):
    @classmethod
    def eval(cls, x):
        if isinstance(x, discretize): #idempotent
            return x

class PandasDiscretizerTransformation(BaseEstimator, TransformerMixin, NumericUnaryTransformation):
    def __init__(self, number_bins, qbucket=False):
        self.number_bins = number_bins
        self.qbucket = qbucket
        name = 'discretize'
        NumericUnaryTransformation.__init__(self, name)

    def fit(self, X, y=None):
        if not self.qbucket:
            _, self.bins = pd.cut(X[:,0], bins=self.number_bins, retbins=True, labels=range(self.number_bins))
        else:
            _, self.bins = pd.qcut(X[:,0], q=self.number_bins, retbins=True, labels=range(self.number_bins))
        return self

    def transform(self, X):
        bucket_labels = pd.cut(X[:,0], bins=self.bins, labels=range(self.number_bins),
                               include_lowest=True).__array__()
        bucket_labels[np.isnan(bucket_labels)] = -1
        return np.reshape(bucket_labels, (len(X), 1))

    def is_applicable(self, feature_combination: List[CandidateFeature]):
        if not super(PandasDiscretizerTransformation, self).is_applicable(feature_combination):
            return False
        if isinstance(feature_combination[0].transformation, PandasDiscretizerTransformation):
            return False
        if 'number_distinct_values' in feature_combination[0].properties and feature_combination[0].properties['number_distinct_values'] <= self.number_bins:
            return False

        return True

    def get_sympy_representation(self, input_attributes):
        return discretize(input_attributes[0])

    def derive_properties(self, training_data, parents: List[CandidateFeature]):
        properties = {}
        # type properties
        properties['type'] = training_data.dtype

        try:
            # missing values properties
            properties['missing_values'] = False #nan -> -1

            # range properties
            properties['has_zero'] = True

            if 'missing_values' in parents[0].properties:
                if parents[0].properties['missing_values'] == True:
                    properties['min'] = -1
                else:
                    properties['min'] = 0
            else:
                properties['min'] = np.nanmin(training_data)

            properties['max'] = self.number_bins - 1
        except:
            # was nonnumeric data
            pass

        if 'missing_values' in parents[0].properties:
            if parents[0].properties['missing_values'] == True:
                properties['number_distinct_values'] = self.number_bins + 1
            else:
                properties['number_distinct_values'] = self.number_bins
        else:
            properties['number_distinct_values'] = self.number_bins #estimate

        return properties


from collections import Counter

class Solution:
    def secFrequent(self, arr, n):
        a = Counter(arr).most_common()
        m = a[0][1]
        for i in range(len(a)):
            if a[i][1] != m:
                return a[i][0]
        return -1

# Test
arr = ['aaa', 'bbb', 'ccc', 'bbb', 'aaa', 'aaa']
print(Solution().secFrequent(arr, len(arr)))


from torchvision import transforms
from torchvision.transforms.transforms import RandomCrop
from Model.FaceNet import FaceNet
import torch
import pandas as pd
from PIL import Image
from torchvision.transforms import ToTensor, Resize
from torchvision.datasets import ImageFolder
from torch.utils.data import DataLoader
import csv
import numpy as np

model=FaceNet(last_lyr=False,width_mult=0.75)
#model.load_state_dict(torch.load('Fine_tuned_params_256x171.pt',map_location='cpu'),strict=False)
model.load_state_dict(torch.load('Fine_tuned_params_256x171_v2.pt',map_location='cpu'),strict=False)
model.eval()

def create_matrix(persons_in_database,csv_file):

    transform=transforms.Compose([ToTensor(),Resize(size=(256,171))])
    matrix=torch.zeros(size=(persons_in_database,1280))
    indexer=csv_file.index
    for e in range(persons_in_database):
        output=torch.zeros(size=(1,1280))
        condition_1=csv_file['subject']==e
        condition=condition_1
        indices=indexer[condition].to_list()
        for index in indices:
            img=Image.open(csv_file.iloc[index,0])
            img=transform(img)
            output+=model(img.unsqueeze(0))

        output=output/len(indices)
        print(e)
        matrix[e,:]=output
    print('matrix_created')
    return matrix

def create_matrix_fa(persons_in_database,csv_file):
    transform=transform=transforms.Compose([ToTensor(),Resize(size=(256,171))])
    matrix=torch.zeros(size=(persons_in_database,1280))
    indexer=csv_file.index
    for e in range(persons_in_database):
        output=torch.zeros(size=(1,1280))
        condition_1=csv_file['subject']==e
        condition_2=csv_file['pose']=='fa'
        condition=condition_1 & condition_2
        indices=indexer[condition].to_list()
        for index in indices:
            img=Image.open(csv_file.iloc[index,0])
            img=transform(img)
            output+=model(img.unsqueeze(0))

        output=output/len(indices)
        print(e)
        matrix[e,:]=output
    return matrix

def distance(img,matrix,dist_num,model=model):
    pred=model(img)
    x=torch.cdist(pred,matrix)
    value,indices=torch.min(x,dim=1)
    if value>dist_num:
        indices='unknown'
    return value,indices

def evaluate(persons_in_database, valid_dl,csv_file,dist_num,matrix=None):

    if matrix==None:
        matrix=create_matrix(persons_in_database,csv_file)
    max_dist=0
    x=0
    false_negatives=0
    false_positives=0
    error=0
    cheers=0

    for i,(xb,yb) in enumerate(valid_dl):
        dist,indices=distance(xb,matrix,dist_num)
        if dist>max_dist:
            max_dist=dist
        if yb >(persons_in_database-1):
            yb='unknown'

        if indices==yb:
            x+=1
            if indices!='unknown':
                cheers+=1
        elif yb!='unknown':
            if indices=='unknown':
                false_negatives+=1
            else:
                error+=1
        elif yb=='unknown':
            false_positives+=1

        print(i,x,error, false_positives, false_negatives,cheers)
        if i%1000==0:
            print(i,max_dist)
    return [i,x,error,false_positives,false_negatives,cheers]

def evaluate_params(params_doc_list,model,persons_in_database,csv_file,dist_num,iterations=10):
    header=['params_doc','persons_in_db','distance_threshold','images_evaluated','total_success','errors_both_db','false_positives','false_negatives','pairing_success']
    with open('Test_results.csv','w')as f:
        writer=csv.writer(f)
        writer.writerow(header)

        for doc in params_doc_list:
            row=[]
            model.load_state_dict(torch.load(str(doc),map_location='cpu'),strict=False)
            model.eval()
            iterations_value=np.zeros(shape=(iterations, len(header)-3 ))
            for iteration in range(iterations):
                iterations_value[iteration,:]=evaluate(persons_in_database,valid_dl,csv_file,dist_num)
                mean=np.mean(iterations_value,axis=0)
            row=[doc,persons_in_database,dist_num]+list(mean)
            writer.writerow(row)
            print(1)

params_doc_list=['Fine_tuned_params_256x171.pt','Model_state_dict_256x171.pt','Model_state_dict_256x171_v2.pt']
persons_in_database=50
csv_file=pd.read_csv('Dataset_dvd2.csv')
transform=transforms.Compose([ToTensor(),Resize(size=(256,171)),])#RandomCrop(size=(256,171),padding=(40,26),padding_mode='reflect')])
dataset=ImageFolder('colorferet/dvd2/data/images',transform=transform)
valid_dl=DataLoader(dataset,batch_size=1,shuffle=True)
dist_num=19
evaluate_params(params_doc_list,model,persons_in_database,csv_file,dist_num,iterations=1)

matrix=create_matrix_fa(persons_in_database,csv_file)
evaluate(persons_in_database,valid_dl,csv_file,dist_num,matrix)

matrix=create_matrix(268,csv_file)
triplets_dict={}
a=torch.cdist(matrix,matrix)
for e in range(len(a)):
    a[e,e]=1000

values, indices=torch.min(a,dim=1)
for i,e in enumerate(indices):
    triplets_dict[str(i)]=e

for a,b in triplets_dict.items():
    print(a,b)

triplets_dict['202']

triplets_dict['239']

triplets_dict['130']

values.sort()

triplets_dict['62']

Carpeta Github Face Algorithm/Test/Testing_256x171.py


import sys
import pandas as pd
import matplotlib.pyplot as plt

from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.metrics import classification_report, confusion_matrix

def plot_df(df, subsets):
    """ preferably 2 dimensional subset vector for visualization, 1 for class
    [x, y, class]
    """
    x_data = df[subsets[0]]
    y_data = df[subsets[1]]
    c_data = df[subsets[2]]

    plt.scatter(x_data, y_data, c=c_data)
    plt.xlabel(f'{subsets[0]}')
    plt.ylabel(f'{subsets[1]}')
    plt.show()

def dropna(df, axis=0, inplace=True, subset=None):
    df.dropna(axis=axis, inplace=inplace, subset=subset)

def solve_titanic(input_file, output_file):
    df = pd.read_csv(f'../data/{input_file}.csv')

    subset = ["Survived", "Pclass", "Sex", "Age"]

    # tailor the data to remove NaN values and consider only subset solumns
    # CHANGES FOR ALL COLUMNS
    dropna(df, axis=0, inplace=True, subset=subset)
    df = df[subset]
    df.replace({"male": 0, "female": 1}, inplace=True)

    # plot_df(df, ['Pclass', 'Age', 'Survived'])

    X = df.drop('Survived', axis=1)
    y = df['Survived']
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20)

    svc_classifier = SVC(kernel='rbf', degree=3)
    svc_classifier.fit(X_train, y_train)

    y_pred = svc_classifier.predict(X_test)

    print(confusion_matrix(y_test, y_pred))
    print(classification_report(y_test, y_pred))

if __name__ == '__main__':
    """ Titanic Kaggle task

    Author: Abhishek Joshi
    """

    input_file = sys.argv[1]
    output_file = sys.argv[2]

    solve_titanic(input_file=input_file,
                  output_file=output_file)


from __future__ import annotations

import sys
from typing import List, Tuple

from sumtype import sumtype

from compiler.lexing.util import FileTextSpan

def eprint(*args, **kwargs):
    print(*args, file=sys.stderr, end=None, **kwargs)

def eprintln(*args, **kwargs):
    print(*args, file=sys.stderr, **kwargs)

class CompilerError(sumtype):
    def Message(message: str, span: FileTextSpan): ...
    def MessageWithHint(message: str, span: FileTextSpan, hint: str, hint_span: FileTextSpan): ...

class MessageSeverity(sumtype):
    def Hint(): ...  # -> MessageSeverity
    def Error(): ...  # -> MessageSeverity

    def color_code(self):
        if self.variant == 'Hint':
            return 94  # Bright Blue
        if self.variant == 'Error':
            return 31  # Red

def print_error_json(file_name: str, error: CompilerError):
    if error.variant == 'Message':
        display_message_with_span_json(MessageSeverity.Error(), file_name, error.message, error.span)
    elif error.variant == 'MessageWithHint':
        display_message_with_span_json(MessageSeverity.Error(), file_name, error.message, error.span)
        display_message_with_span_json(MessageSeverity.Hint(), file_name, error.hint, error.hint_span)

def print_error(file_name: str, file_contents: str, error: CompilerError):
    if error.variant == 'Message':
        display_message_with_span(MessageSeverity.Error(), file_name, file_contents, error.message, error.span)
    elif error.variant == 'MessageWithHint':
        display_message_with_span(MessageSeverity.Error(), file_name, file_contents, error.message, error.span)
        display_message_with_span(MessageSeverity.Hint(), file_name, file_contents, error.hint, error.hint_span)

def display_message_with_span_json(severity: MessageSeverity, file_name: str, message: str, span: FileTextSpan):
    print(f"{{\"type\":\"diagnostic\",\"message\":\"{message}\","
            f"\"severity\":\"{severity.variant}\","
            f"\"file_id\":{span.file_id},"
            f"\"span\":{{\"start\":{span.start},\"end\":{span.end}}}}}")

def display_message_with_span(severity: MessageSeverity, file_name: str, contents: str | None,
                              message: str, span: FileTextSpan):
    eprintln(f'{severity.variant}: {message}')

    if not contents:
        return

    line_spans = gather_line_spans(contents)
    line_index = 1
    largest_line_number = len(line_spans)
    width = len(str(largest_line_number))

    while line_index < largest_line_number:
        if line_spans[line_index][0] <= span.start <= line_spans[line_index][1]:
            column_index = span.start - line_spans[line_index][0]
            eprintln(f'----- \x1b[33m{file_name}:{line_index + 1}:{column_index + 1}\x1b0m')
            if line_index > 0:
                print_source_line(severity, contents, line_spans[line_index - 1], span, line_index, largest_line_number)
            print_source_line(severity, contents, line_spans[line_index], span, line_index, largest_line_number)

            for _ in range(span.start - line_spans[line_index][0] + width + 4):
                eprint(' ')

            eprintln(f'\x1b[{severity.color_code()}m^- {message}\x1b[0m')

            while line_index < len(line_spans) and span.end > line_spans[line_index][0]:
                line_index += 1
                if line_index >= len(line_spans):
                    break
                print_source_line(severity, contents, line_spans[line_index], span, line_index + 1, largest_line_number)
                break
        else:
            line_index += 1

def print_source_line(severity: MessageSeverity, file_contents: str,
                      file_span: Tuple[int, int], error_span: FileTextSpan,
                      line_number: int, largest_line_number: int):
    index = file_span[0]

    eprint(f' {line_number} | ')

    while index <= file_span[1]:
        char = ' '
        if index < file_span[1]:
            char = file_contents[index]
        elif error_span.start == error_span.end and index == error_span.start:
            char = '_'

        if index == error_span.start:
            eprint(f'\x1b[{severity.color_code()}m')
        if index == error_span.end:
            eprint('\x1b[0m')
        eprint(char)

        index += 1
    eprintln('')

def gather_line_spans(file_contents: str) -> [(int, int)]:
    idx = 0
    output: List[Tuple[int, int]] = []

    start = idx
    while idx < len(file_contents):
        if file_contents[idx] == '\n':
            output.append((start, idx))
            start = idx + 1
        idx += 1
    if start < idx:
        output.append((start, idx))
    return output


#What is the index of the first term in the Fibonacci sequence to contain 1000 digits?

def thousandfib(a,b):
    result = 2
    while(len(str(b)) < 1000):
     a , b = b , a + b
     result = result + 1
    return result
print(thousandfib(1,1))


import sys
import subprocess

"""
To make it even easier to use - just type alias
find a row where -> HOME="workspaces/YOUR_CODESPACE_NUMBER",
select and rightclick to copy. Now create your own alias:
alias cs50get='python workspaces/YOUR_CODESPACE_NUMBER/cs50get.py'
or if you dont have it in your main directory:
alias cs50get='python workspaces/YOUR_CODESPACE_NUMBER/YOUR_PATH/cs50get.py'
be free and use this programm in every directory you want.
Remember that the directory made by the zip file,
is gonna be placed in your current console path
"""

def command(string):

    p = subprocess.Popen(string, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    for line in p.stdout.readlines():
        print(line[:-1])
    p.wait()

def main():

    if len(sys.argv) != 2: return

    commands = {
        'wget': f"wget {sys.argv[1]}",
        'unzip': f"unzip {sys.argv[1].split('/')[-1]}",
        'remove': f"rm {sys.argv[1].split('/')[-1]}"
    }

    for key in commands:
        command(commands[key])

if __name__ == "__main__":
    main()


## Grant Gasser
## 9.3 File Encryption & Decryption, Caesar's Cipher
## 3/25

#Should be able to encode all ASCII characters (values 0-252), 255-3=252
MAX_ASCII_VAL = 252

#NOTE: ord() function returns ASCII value of character
# chr() function returns corresponding character of int by ASCII (opposite of
# ord())
def create_codex():
    '''
    Inputs: None
    Description: creates dictionary of codes based on Ceasar Cipher shift. So
        each character key has a value that is the character shifted 3 to right
    Returns: dictionary called codes
    '''
    codes = {}

    char = chr(0) #start at ASCII value 0 (NUL)
    ascii = 0

    while ascii <= MAX_ASCII_VAL:
        codes[char] = chr(ascii + 3)
        ascii += 1
        char = chr(ascii)

    return codes

def encrypt(infile, encrypted, codes):
    '''
    Inputs: input file, output file (encrypted input file), dictionary of codes
    Description: encrypts file using 3 char shift (Caesar Cipher), going forward
        3 chars
    Returns:
    '''

    #read each line in file
    for line in infile:
        #read and encrypt each character for each line
        for char in line:
            if char in codes:
                encrypted.write(codes[char])
            else:
                #cant encrypt or decrypt so keep this char the same
                encrypted.write(char)

def decrypt(encrypted, decrypted, codes):
    '''
    Inputs: in file (previously encrypted), out file (decrypted file), dictionary of codes
    Description: decrypts file using 3 char shift (Caesar Cipher), going back 3
        this time
    Returns:
    '''

    for line in encrypted:
        for char in line:
            if char in codes.values():
                for key, val in codes.items():
                    if char == val:
                        decrypted.write(key)

            else:
                decrypted.write(char)

def main():

    codes = create_codex()

    print('This is the code for encrypting files:\n', codes)

    #read in file and encrypt
    infile = open('python.txt', 'r')
    encrypted = open('encrypted.txt', 'w')

    #encrypt infile
    encrypt(infile, encrypted, codes)
    infile.close()
    encrypted.close()

    #re-open 'encrypted' file to read from and decrypt
    encrypted = open('encrypted.txt', 'r')

    #will be decrypted file, should have same contents as 'test.txt' after
    #decrypt() is called
    decrypted = open('decrypted.txt', 'w')

    #decrypt file called 'encrypted'
    decrypt(encrypted, decrypted, codes)

    encrypted.close()
    decrypted.close()

main()


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

from setuptools import setup, find_packages

long_desc = '''
This package contains the autorunrecord Sphinx extension.

Inspired by and based on the 'autorun' sphinx extension
by Vadim Gubergrits.
'''

requires = ['Sphinx']

setup(
    name='autorunrecord',
    version='0.4',
    url='http://github.com/mih/autorunrecord',
    license='BSD',
    author='Michael Hanke',
    author_email='michael.hanke@gmail.com',
    description='Sphinx extension autorunrecord',
    long_description=long_desc,
    zip_safe=False,
    classifiers=[
        'Development Status :: 4 - Beta',
        'Environment :: Console',
        'Environment :: Web Environment',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: BSD License',
        'Operating System :: OS Independent',
        'Programming Language :: Python',
        'Topic :: Documentation',
        'Topic :: Utilities',
    ],
    platforms='any',
    packages=find_packages(),
    include_package_data=True,
    install_requires=requires,
    namespace_packages=['sphinxcontrib'],
)


from sklearn import cross_validation, datasets, linear_model
import numpy as np
diabetes = datasets.load_diabetes()
X = diabetes.data[:150]
y = diabetes.target[:150]
lasso = linear_model.Lasso()
alphas = np.logspace(-4, -.5, 30)
lasso.alphas=alphas
from sklearn.grid_search import GridSearchCV
parameters = {'alpha': alphas}
clf = GridSearchCV(lasso, parameters,n_jobs=-1)
clf.fit(diabetes.data[150:], diabetes.target[150:])
print(clf.best_estimator_.alpha)
print(clf.best_score_)

crossvalidation optimal regularization pararmeter calculation example.py


'''Merge Linked Lists

Write a function that takes in the heads of two singly linked lists that are in sorted order. The function should merge the lists in place.
'''

# This is an input class. Do not edit.
class LinkedList:
    def __init__(self, value):
        self.value = value
        self.next = None

def mergeLinkedLists(headOne, headTwo):
    # Write your code here.

    # 6 head1 -> 7 -> 8 -> 9 -> 10
    # 1 head2 -> 3 -> 4 -> 5

    # 1 prev -> 6 head1 -> 7 -> 8 -> 9 -> 10
    # 3 head2-> 4 -> 5
    head1 = headOne
    head2 = headTwo
    if head1.value <= head2.value:
        ans = headOne
    else:
        ans = headTwo
    prev = None
    while head1 and head2:
        if head2.value < head1.value:
            temp2 = head2.next
            head2.next = head1
            if not prev:
                prev = head2
            else:
                prev.next = head2
                prev = head2
            head2 = temp2
        elif head2.value >= head1.value:
            prev = head1
            head1 = head1.next

    if not prev.next:
        prev.next = head2

    return ans

Algoexpert/Linked Lists/Merge Linked List.py


#===============================================================================
# Display Query Data in a Table
#--------------------------------------------------------------------------
# (2018-04-05) - sklyon
#===============================================================================

import getpass
import cx_Oracle
from tkinter import *
from tkinter import ttk

########################################
# Some Global variables
#=======================================
vHeader, vCell = [], []
vRows, vCols   = 0, 0

########################################
# Build the Oracle Connect String
#=======================================
import getpass
#-----
vUsr = input( ">>> Enter UserName : " )
vPwd = getpass.getpass( prompt = ">>> Enter Password : " )
vDbs = input( ">>> Enter Database : " )
#=======================================
vCnctStr = vUsr + "/" + vPwd + "@" + vDbs

########################################
# Define functions for buttons
#=======================================
def vClick_Left():                          # Shift Data in Cells: Left
  global vRows, vCols, vCell, vHeader
  for v1 in range( vRows ):
    vTmp = vCell[v1][0].get()
    vP = [ vTmp, "" ]
    for v2 in range( vCols-1, -1, -1 ):
      vP[1] = vP[0]
      vP[0] = vCell[v1][v2].get()
      vCell[v1][v2].delete(0, 'end')
      vCell[v1][v2].insert(0, vP[1])
  vTmp = vHeader[0].get()
  vP = [ vTmp, "" ]
  for v2 in range( vCols-1, -1, -1 ):
    vP[1] = vP[0]
    vP[0] = vHeader[v2].get()
    vHeader[v2].delete(0, 'end')
    vHeader[v2].insert(0, vP[1])
#------------
def vClick_Right():                         # Shift Data in Cells: Right
  global vRows, vCols, vCell, vHeader
  for v1 in range( vRows ):
    vTmp = vCell[v1][vCols-1].get()
    vP = [ vTmp, "" ]
    for v2 in range( vCols ):
      vP[1] = vP[0]
      vP[0] = vCell[v1][v2].get()
      vCell[v1][v2].delete(0, 'end')
      vCell[v1][v2].insert(0, vP[1])
  vTmp = vHeader[vCols-1].get()
  vP = [ vTmp, "" ]
  for v2 in range( vCols ):
    vP[1] = vP[0]
    vP[0] = vHeader[v2].get()
    vHeader[v2].delete(0, 'end')
    vHeader[v2].insert(0, vP[1])
#------------
def vClick_Up():                            # Shift Data in Cells: Up
  global vRows, vCols, vCell, vHeader
  for v2 in range( vCols ):
    vTmp = vCell[0][v2].get()
    vP = [ vTmp, "" ]
    for v1 in range( vRows-1, -1, -1 ):
      vP[1] = vP[0]
      vP[0] = vCell[v1][v2].get()
      vCell[v1][v2].delete(0, 'end')
      vCell[v1][v2].insert(0, vP[1])
#------------
def vClick_Down():                          # Shift Data in Cells: Down
  global vRows, vCols, vCell, vHeader
  for v2 in range( vCols ):
    vTmp = vCell[vRows-1][v2].get()
    vP = [ vTmp, "" ]
    for v1 in range( vRows ):
      vP[1] = vP[0]
      vP[0] = vCell[v1][v2].get()
      vCell[v1][v2].delete(0, 'end')
      vCell[v1][v2].insert(0, vP[1])
#------------

########################################
# Connect to Database and run query.
#=======================================
vOraSession = cx_Oracle.connect( vCnctStr )
###
vQry = """\
------
select  case
          when  Empno = 7902  then '@@ 7902 @@'
          else  to_char( Empno )
        end  as "ID"
     ,  case
          when  initcap(ename) = 'Ford'  then '@@ Ford @@'
          else  initcap(ename)
        end  as "Who"
     ,  lower(job)  as "What"
     ,  mgr  as mgr_id
     ,  to_char(hiredate,'YYYY-Mon-DD') as "Hired-On"
     ,  sal
     ,  deptno
     ,  to_char(sysdate, 'Mon-DD HH24:MI:SS') as "TimeStamp"
  from  train.emp
 where  1=1
   and  job in ( 'ANALYST', 'SALESMAN', 'CLERK' )
   and  rownum < 50
 order  by ename
------
"""
###
vQryRslt = vOraSession.cursor().execute( vQry )
#########

#=======================================
#  Store the query-results in lists
#---------------------------------------
vQryHdr, vQryData = [], []
###
v_col_cnt = len(vQryRslt.description)
for v2 in range( v_col_cnt ):
   vTmp = vQryRslt.description[v2][0]
   vQryHdr.append( vTmp )
###
v1 = 0
for v_row in vQryRslt:
   vQryData.append([])
   v_col_cnt = len( v_row )
   for v2 in range( v_col_cnt ):
      vTmp = str(v_row[v2])
      vQryData[v1].append(vTmp)
   v1 += 1

vCols = len( vQryData[0] )
vRows = len( vQryData )

#=======================================
#  Build the Frames
#---------------------------------------
vWndo = Tk()
vWndo.title( "Query Results" )
vWndo.geometry( str(100*vCols + 24) + "x" + str(20*vRows + 100) )

# Make a frame to put the buttons in:
vFrm1 = ttk.Frame(vWndo, padding="3 3 3 3")
vFrm1.grid(column=0, row=0)
vFrm1.columnconfigure(0, weight=1)
vFrm1.rowconfigure(0, weight=1)

# Make a frame to put the column-names in:
vFrm2 = ttk.Frame(vWndo, padding="12 12 12 12")
vFrm2.grid(column=0, row=1, sticky=(N, W, E, S))
vFrm2.columnconfigure(0, weight=1)
vFrm2.rowconfigure(0, weight=1)

# Make a frame to put the data-grid in:
vFrm3 = ttk.Frame(vWndo, padding="12 12 12 12")
vFrm3.grid(column=0, row=2, sticky=(N, W, E, S))
vFrm3.columnconfigure(0, weight=1)
vFrm3.rowconfigure(0, weight=1)

#=======================================
#  Create the Buttons
#---------------------------------------
vBtn1 = Button( vFrm1, text = "Left", command = vClick_Left )
vBtn1.grid( column = 0, row = 0 )
###
vBtn2 = Button( vFrm1, text = "Right", command = vClick_Right )
vBtn2.grid( column = 1, row = 0 )
###
vBtn3 = Button( vFrm1, text = "Up", command = vClick_Up )
vBtn3.grid( column = 2, row = 0 )
###
vBtn4 = Button( vFrm1, text = "Down", command = vClick_Down )
vBtn4.grid( column = 3, row = 0 )

#=======================================
#  Put data into the column-name grid
#  and into the data-grid:
#---------------------------------------
for v2 in range( vCols ):
  vTmp = Entry( vFrm2, width = 16 )
  vHeader.append( vTmp )
  vHeader[v2].grid( row = 0, column = v2 )
  vHeader[v2].config( {"background": "Grey"} )
  vHeader[v2].insert( 0, vQryHdr[v2] )
###
for v1 in range( vRows ):
  vCell.append( [] )
  for v2 in range( vCols ):
    vTmp = Entry( vFrm3, width = 16 )
    vCell[v1].append( vTmp )
    vCell[v1][v2].grid( row = v1, column = v2 )
    vCell[v1][v2].insert( 0, vQryData[v1][v2] )

#=======================================
# Display the whole thing and
# wait for input
#---------------------------------------
vWndo.mainloop()

vNull = input( ">>> Enter to continue : " )
#===============================================================================
# Eof
#===============================================================================


import torch
from torch.nn import Module
import string

VALID_CHARS = "\r" + string.digits + string.ascii_uppercase + string.punctuation + " \n"

class ROIFinder(Module):
    def __init__(self):
        super().__init__()
        self.network = torch.nn.Sequential(
            # 1 x 256 x 256
            Conv(1, 2, 3, padding=1),
            torch.nn.MaxPool2d(2),
            # 2 x 128 x 128
            Conv(2, 4, 3, padding=1),
            torch.nn.MaxPool2d(2),
            # 4 x 64 x 64
            Conv(4, 8, 3, padding=1),
            torch.nn.MaxPool2d(2),
            # 8 x 32 x 32
            Conv(8, 16, 3, padding=1),
            torch.nn.MaxPool2d(2),
            # 16 x 16 x 16
            Conv(16, 32, (1, 4), padding=0, stride=(1, 4), groups=4),
            # 32 x 16 x 4
            Conv(32, 64, (4, 1), padding=0, stride=(4, 1), groups=4),
            # 64 x 4 x 4
            torch.nn.Conv2d(64, 64, 4, groups=4),
            # 64 x 1 x 1
            torch.nn.Conv2d(64, 4, 1, groups=4),
        )

    def forward(self, inpt):
        oupt = self.network(inpt).squeeze()
        oupt = torch.cat((torch.tanh(oupt[:, 0:2]).mul(0.5), torch.sigmoid(oupt[:, 2:4])), dim=1)
        return oupt

class LineEncoder(Module):
    def __init__(self):
        super().__init__()
        self.feature_extractor = torch.nn.Sequential(
            # 3 x 768 x 384
            Conv(3, 12, 5, padding=2),
            # 12 x 768 x 384
            Residual(12),
            ResidualReduce(12, 24),
            # 24 x 384 x 192
            Residual(24),
            ResidualReduce(24, 48),
            # 48 x 192 x 96
            Residual(48),
            ResidualReduce(48, 96),
            # 96 x 96 x 48
            Residual(96),
            ResidualReduce(96, 192),
            # 192 x 48 x 24
        )
        self.line_detector = torch.nn.Sequential(
            # 192 x 48 x 24
            Conv(192, 216, (1, 3), padding=0, groups=3),
            # 240 x 48 x 22
            Conv(216, 240, (1, 3), padding=0, groups=3),
            # 240 x 48 x 20
            torch.nn.Conv2d(240, 240, (1, RESO_H // 32 - 4), groups=3),
            # 240 x 48 x 1
            torch.nn.Conv2d(240, 3, 1, groups=3),
            # 3 x 48 x 1
        )

class LineDecoder(Module):
    def __init__(self):
        super().__init__()

class Residual(torch.nn.Module):
    def __init__(self, channels):
        super().__init__()
        self.conv = torch.nn.Sequential(
            Conv(channels, channels, 3, padding=1), Conv(channels, channels, 1, padding=0)
        )

    def forward(self, inpt):
        oupt = self.conv(inpt)
        return oupt + inpt

class ResidualReduce(torch.nn.Module):
    def __init__(self, in_chan, out_chan):
        super().__init__()
        self.branch_0 = torch.nn.Sequential(
            Conv(in_chan, out_chan, 3, padding=1, stride=2),
            #
            Conv(out_chan, out_chan, 1, padding=0),
        )
        self.branch_1 = torch.nn.Sequential(
            torch.nn.MaxPool2d(2), Conv(in_chan, out_chan, 1, padding=0)
        )

    def forward(self, inpt):
        oupt_0 = self.branch_0(inpt)
        oupt_1 = self.branch_1(inpt)
        return oupt_0 + oupt_1

class Conv(torch.nn.Module):
    def __init__(self, in_chan, out_chan, kernel_size, padding, stride=1, groups=1):
        super().__init__()
        self.conv = torch.nn.Sequential(
            torch.nn.Conv2d(in_chan, out_chan, kernel_size, stride, padding, groups=groups),
            torch.nn.BatchNorm2d(out_chan),
            torch.nn.LeakyReLU(inplace=True),
        )

    def forward(self, inpt):
        return self.conv(inpt)

if __name__ == "__main__":
    inpt = torch.rand(16, 1, 256, 256)
    model = ROIFinder()
    oupt = model(inpt)
    print(oupt)


# -*- encoding: utf-8 -*-
'''
@project :   LeetCode
@File    :   angrams.py
@Contact :   9824373@qq.com
@Desc    :
            编写一种方法，对字符串数组进行排序，将所有变位词组合在一起。变位词是指字母相同，但排列不同的字符串。

            注意：本题相对原题稍作修改

            示例:

            输入: ["eat", "tea", "tan", "ate", "nat", "bat"],
            输出:
            [
              ["ate","eat","tea"],
              ["nat","tan"],
              ["bat"]
            ]
            说明：

            所有输入均为小写字母。
            不考虑答案输出的顺序。

            来源：力扣（LeetCode）
            链接：https://leetcode-cn.com/problems/group-anagrams-lcci

@Modify Time                @Author     @Version    @Desciption
------------                -------     --------    -----------
2020-03-13     zhan        1.0         None
'''

from collections import defaultdict

class Solution(object):
    def groupAnagrams(self, strs):
        """
        以排序后的字符串为key键hash表。
        :type strs: List[str]
        :rtype: List[List[str]]
        """

        sort_strs = defaultdict(list)

        for s in strs:
            tmps = ''.join(sorted(s))
            sort_strs[tmps].append(s)

        return list(sort_strs.values())

if __name__ == '__main__':

    a = ["eat","tea","tan","ate","nat","bat"]
    rst = Solution().groupAnagrams(a)
    print(rst)


import pygame
import os
import time
import random
pygame.font.init()

WIDTH, HEIGHT = 720, 720
WIN = pygame.display.set_mode((WIDTH,HEIGHT))
pygame.display.set_caption("Chess - A2")

LIGHT_SQUARE = pygame.image.load(os.path.join("PicsA2", "light square.png"))
DARK_SQUARE = pygame.image.load(os.path.join("PicsA2", "dark square.png"))
HIGHLIGHTED_SQUARE = pygame.image.load(os.path.join("PicsA2", "highlighted square.png"))

LIGHT_PAWN = pygame.image.load(os.path.join("PicsA2", "light pawn.png"))
LIGHT_CASTLE = pygame.image.load(os.path.join("PicsA2", "light castle.png"))
LIGHT_KNIGHT = pygame.image.load(os.path.join("PicsA2", "light knight.png"))
LIGHT_BISHOP = pygame.image.load(os.path.join("PicsA2", "light bishop.png"))
LIGHT_QUEEN = pygame.image.load(os.path.join("PicsA2", "light queen.png"))
LIGHT_KING = pygame.image.load(os.path.join("PicsA2", "light king.png"))

DARK_PAWN = pygame.image.load(os.path.join("PicsA2", "dark pawn.png"))
DARK_CASTLE = pygame.image.load(os.path.join("PicsA2", "dark castle.png"))
DARK_KNIGHT = pygame.image.load(os.path.join("PicsA2", "dark knight.png"))
DARK_BISHOP = pygame.image.load(os.path.join("PicsA2", "dark bishop.png"))
DARK_QUEEN = pygame.image.load(os.path.join("PicsA2", "dark queen.png"))
DARK_KING = pygame.image.load(os.path.join("PicsA2", "dark king.png"))

class Button():
    def __init__(self, color, x,y,width,height, text=''):
        self.color = color
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.text = text

    def draw(self,win,outline=None):
        #Call this method to draw the button on the screen

        pygame.draw.rect(win, self.color, (self.x,self.y,self.width,self.height),0)

    def isOver(self, pos):
        #Pos is the mouse position or a tuple of (x,y) coordinates
        if pos[0] > self.x and pos[0] < self.x + self.width:
            if pos[1] > self.y and pos[1] < self.y + self.height:
                return True

        return False

class Index():
    def__init__(self,x,y,button,piece)

class Piece:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.piece_img = None
    def draw(self, window):
        window.blit(self.piece_img, (self.x, self.y))

class Pawn(Piece):
    COLOUR_MAP = {
        "light": (LIGHT_PAWN),
        "dark": (DARK_PAWN)
        }
    def __init__(self, x, y, colour):
        super().__init__(x,y)
        self.piece_img = self.COLOUR_MAP[colour]

class Castle(Piece):
    COLOUR_MAP = {
        "light": (LIGHT_CASTLE),
        "dark": (DARK_CASTLE)
        }
    def __init__(self, x, y, colour):
        super().__init__(x,y)
        self.piece_img = self.COLOUR_MAP[colour]

class Knight(Piece):
    COLOUR_MAP = {
        "light": (LIGHT_KNIGHT),
        "dark": (DARK_KNIGHT)
        }
    def __init__(self, x, y, colour):
        super().__init__(x,y)
        self.piece_img = self.COLOUR_MAP[colour]

class Bishop(Piece):
    COLOUR_MAP = {
        "light": (LIGHT_BISHOP),
        "dark": (DARK_BISHOP)
        }
    def __init__(self, x, y, colour):
        super().__init__(x,y)
        self.piece_img = self.COLOUR_MAP[colour]

class Queen(Piece):
    COLOUR_MAP = {
        "light": (LIGHT_QUEEN),
        "dark": (DARK_QUEEN)
        }
    def __init__(self, x, y, colour):
        super().__init__(x,y)
        self.piece_img = self.COLOUR_MAP[colour]

class King(Piece):
    COLOUR_MAP = {
        "light": (LIGHT_KING),
        "dark": (DARK_KING)
        }
    def __init__(self, x, y, colour):
        super().__init__(x,y)
        self.piece_img = self.COLOUR_MAP[colour]

def background():
    scale = 90
    for x in range(0,4):
        for y in range (0,4):
            WIN.blit(LIGHT_SQUARE,(2*x*scale,2*y*scale))
    for x in range(1,5):
        for y in range (1,5):
            WIN.blit(LIGHT_SQUARE,(((2*x)-1)*scale,((2*y)-1)*scale))
    for x in range(1,5):
        for y in range (0,4):
            WIN.blit(DARK_SQUARE,((2*x-1)*scale,2*y*scale))
    for x in range(0,4):
        for y in range (1,5):
            WIN.blit(DARK_SQUARE,(2*x*scale,(2*y-1)*scale))
    pygame.display.update()

def set_up():
    home_pieces = []
    away_pieces = []

    COLOUR_MAP = {
        "light": (LIGHT_PAWN, LIGHT_CASTLE, LIGHT_KNIGHT, LIGHT_BISHOP, LIGHT_QUEEN, LIGHT_KING),
        "dark": (DARK_PAWN, DARK_CASTLE, DARK_KNIGHT, DARK_BISHOP, DARK_QUEEN, DARK_KING)
        }

    #randomsing player colour
    home_colour = random.choice(["light", "dark"])
    if home_colour == "light":
        away_colour = "dark"
    else:
        away_colour = "light"

#pawns
    for i in range (0,8):
        piece = Pawn(i*90, 6*90, home_colour)
        home_pieces.append(piece)
    for i in range (0,8):
        piece = Pawn(i*90, 1*90, away_colour)
        away_pieces.append(piece)
#backrow
    #Castles
    piece = Castle(0*90, 7*90, home_colour)
    home_pieces.append(piece)
    piece = Castle(7*90, 7*90, home_colour)
    home_pieces.append(piece)
    piece = Castle(0*90, 0*90, away_colour)
    away_pieces.append(piece)
    piece = Castle(7*90, 0*90, away_colour)
    away_pieces.append(piece)
    #Knights
    piece = Knight(1*90, 7*90, home_colour)
    home_pieces.append(piece)
    piece = Knight(6*90, 7*90, home_colour)
    home_pieces.append(piece)
    piece = Knight(1*90, 0*90, away_colour)
    away_pieces.append(piece)
    piece = Knight(6*90, 0*90, away_colour)
    away_pieces.append(piece)
    #Bishops
    piece = Bishop(2*90, 7*90, home_colour)
    home_pieces.append(piece)
    piece = Bishop(5*90, 7*90, home_colour)
    home_pieces.append(piece)
    piece = Bishop(2*90, 0*90, away_colour)
    away_pieces.append(piece)
    piece = Bishop(5*90, 0*90, away_colour)
    away_pieces.append(piece)
    #Queens
    piece = Queen(3*90, 7*90, home_colour)
    home_pieces.append(piece)
    piece = Queen(3*90, 0*90, away_colour)
    away_pieces.append(piece)
    #Kings
    piece = King(4*90, 7*90, home_colour)
    home_pieces.append(piece)
    piece = King(4*90, 0*90, away_colour)
    away_pieces.append(piece)

    for piece in home_pieces:
         piece.draw(WIN)
    for piece in away_pieces:
         piece.draw(WIN)

    pygame.display.update()
    print(away_pieces)

def main():

    background()
    set_up()

main()


#viewentry
#view a spendings entry

from . import classes
from . import globalvar
import sys

def viewentry(args):
    src = 0
    cate = 0

    #Deciding whether the entry the user wants to look up is under a source or cate
    while True:
        inp = input('Source or category (src/cate/q) ')
        if inp == 'src':
            src = 1
            break
        elif inp == 'cate':
            cate = 1
            break
        elif inp == 'q':
            print('Cancelling operation...')
            sys.exit(1)
        else:
            print('Invalid input.')

    if src == 1:
        #Picking a source to look under
        #Is copied straight from newentry.py
        print('Sources: {0}'.format(globalvar.listStrSource))
        while True:
            source = input('Enter a source, or type \'q\' to quit: ')
            if source == 'q':
                print('Cancelling operation...')
                sys.exit(1)
            try:
                globalvar.masterSource[source]
                break
            except KeyError:
                print('Source not found. Please try again.')
        #Picking an entry to display
        globalvar.masterSource[source].display()
        while True:
            num = input('Enter the ID of the entry, or type \'q\' to quit: ')
            if num == 'q':
                print('Cancelling operation...')
                sys.exit(1)
            try:
                globalvar.masterSource[source].spendEntryList[int(num) - 1].display()
                break
            except IndexError:
                print('Invalid ID number. Please try again.')

    if cate == 1:
        #Picking a source to look under
        #Is copied straight from newentry.py
        print('Categories: {0}'.format(globalvar.listStrCate))
        while True:
            cate = input('Enter a category, or type \'q\' to quit: ')
            if cate == 'q':
                print('Cancelling operation...')
                sys.exit(1)
            try:
                globalvar.masterCate[cate]
                break
            except KeyError:
                print('Source not found. Please try again.')
        #Picking an entry to display
        globalvar.masterCate[cate].display()
        while True:
            num = int(input('Enter the ID of the entry, or type \'q\' to quit: '))
            if num == 'q':
                print('Cancelling operation...')
                sys.exit(1)
            try:
                globalvar.masterCate[cate].spendEntryList[num - 1].display()
                break
            except IndexError:
                print('Invalid ID number. Please try again.')


## Read input as specified in the question.
## Print output as specified in the question.
#  *
# ***
#*****
# ***
#  *

n=int(input())
n1=(n+1)/2
n2=(n-1)/2
i=1
while i <= n1:
    spaces=1
    while spaces<= n1-i:
        print(' ',end='')
        spaces=spaces+1
    num=1
    while num<=i:
        print('*',end='')
        num=num+1
    p=i-1
    while p>=1:
        print('*',end='')
        p=p-1
    print()
    i=i+1

i=n2

while i>=1:
    spaces=n2-i+1
    while spaces>=1:
        print(' ',end='')
        spaces=spaces-1
    num= 2*i-1
    while num>=1:
        print('*',end='')
        num=num-1
    print()
    i=i-1