diff --git a/algorithms/cryptography/railfence_cipher.py b/algorithms/cryptography/railfence_cipher.py new file mode 100644 index 0000000..0cdf24a --- /dev/null +++ b/algorithms/cryptography/railfence_cipher.py @@ -0,0 +1,78 @@ +def railencrypt(st,k): + c = 0 + x = 0 + m =[[0] * (len(st)) for i in range(k)] + for r in range(len(st)): + m[c][r] = st[r] + if x == 0: + if c == (k-1): + x = 1 + c -= 1 + else: + c += 1 + else: + if c == 0: + x = 0 + c += 1 + else: + c -= 1 + + result = [] + for i in range(k): + for j in range(len(st)): + if m[i][j] != 0: + result.append(m[i][j]) + print("CipherText:","" . join(result)) + +def raildecrypt(st,k): + c , x = 0 , 0 + m =[[0] * (len(st)) for i in range(k)] + for r in range(len(st)): + m[c][r] = 1 + if x == 0: + if c == (k-1): + x = 1 + c -= 1 + else: + c += 1 + else: + if c == 0: + x = 0 + c += 1 + else: + c -= 1 + result = [] + c , x = 0 , 0 + for i in range(k): + for j in range(len(st)): + if m[i][j] == 1: + m[i][j] = st[x] + x += 1 + for r in range(len(st)): + if m[c][r] != 0: + result.append(m[c][r]) + if x == 0: + if c == (k-1): + x = 1 + c -= 1 + else: + c += 1 + else: + if c == 0: + x = 0 + c += 1 + else: + c -= 1 + print("PlainText:","" . join(result)) + +if __name__ == "__main__": + string = input("Enter the Message:") + string = string.upper() + key = int(input("Enter the Key:")) + n = int(input("1.Encryption\n2.Decryption\nInput Your choice:")) + if(n == 1): + railencrypt(string,key) + elif(n == 2): + raildecrypt(string,key) + else: + print("Error") diff --git a/algorithms/sorting/tim_sort.py b/algorithms/sorting/tim_sort.py new file mode 100644 index 0000000..993c07e --- /dev/null +++ b/algorithms/sorting/tim_sort.py @@ -0,0 +1,90 @@ +from random import randint + + +class TimSort: + """ A class to demonstrate Tim Sort """ + + def __init__(self, array): + self.array = array + self.arrayLength = len(array) + self.__RUN = 32 + + def insertionSort(self, arr): + """ Sorts the given array from given starting index to ending index """ + + for i in range(1, len(arr)): + currentElement = arr[i] + j = i - 1 + while j >= 0 and arr[j] > currentElement: + arr[j + 1] = arr[j] + j -= 1 + arr[j + 1] = currentElement + + return arr + + def mergeRuns(self, arr1, arr2): + """ Merges the given two arrays: arr1 and arr2 """ + + newArray = list() + lengthOfArr1 = len(arr1) + lengthOfArr2 = len(arr2) + + # The variable i is used to keep track of the indices of the first array + # The variable j is used to keep track of the indices of the second array + # The variable k is used to keep track of the indices of the newArray array which is to be returned + i, j, k = 0, 0, 0 + + while i < lengthOfArr1 and j < lengthOfArr2: + if arr1[i] <= arr2[j]: + newArray[k] = arr1[i] + k += 1 + i += 1 + elif arr1[i] >= arr2[j]: + newArray[k] = arr2[j] + k += 1 + j += 1 + + # The below two loops will append any remaining elements left in any of the two arrays. + while i < lengthOfArr1: + newArray.append(arr1[i]) + i += 1 + + while j < lengthOfArr2: + newArray.append(arr2[j]) + j += 1 + + return newArray + + def changeRun(self, newRun): + self.__RUN = newRun + + def algorithm(self): + """ This function will perfom Tim Sort on the given array """ + + # Breaking the array into chunks of subarray(RUNS) of size RUN and perfomring insertionSort on them. + for i in range(0, self.arrayLength, self.__RUN): + currentRunElements = self.array[i: i + self.__RUN] + + self.array[i: i + + self.__RUN] = self.insertionSort(currentRunElements) + + temp_runner = self.__RUN + while temp_runner < self.arrayLength: + for idx in range(0, self.arrayLength, temp_runner * 2): + firstArray = self.array[idx: idx + temp_runner] + secondArray = self.array[idx + + temp_runner: idx + temp_runner * 2] + self.array[idx: idx + temp_runner * + 2] = self.mergeRuns(firstArray, secondArray) + temp_runner = self.__RUN * 2 + + print(f"The sorted array is : {self.array}") + + def __repr__(self): + return f"Array: {self.array}\nRUN: {self.__RUN}" + + +myArray = [randint(1, 100) for i in range(15)] +demo = TimSort(myArray) +print(demo) +demo.algorithm() diff --git a/classification/fcm.py b/classification/fcm.py new file mode 100644 index 0000000..79a3ee9 --- /dev/null +++ b/classification/fcm.py @@ -0,0 +1,57 @@ +from tools import * + +# https://en.wikipedia.org/wiki/Fuzzy_clustering + + +class FuzzyCMeans: + def __init__(self, n_clusters, initial_centers, data, max_iter=250, m=2, error=1e-5): + assert m > 1 + #assert initial_centers.shape[0] == n_clusters + self.U = None + self.centers = initial_centers + self.max_iter = max_iter + self.m = m + self.error = error + self.data = data + + def membership(self, data, centers): + U_temp = cdist(data, centers, 'euclidean') + U_temp = numpy.power(U_temp, 2/(self.m - 1)) + denominator_ = U_temp.reshape( + (data.shape[0], 1, -1)).repeat(U_temp.shape[-1], axis=1) + denominator_ = U_temp[:, :, numpy.newaxis] / denominator_ + return 1 / denominator_.sum(2) + + def Centers(self, data, U): + um = U ** self.m + return (data.T @ um / numpy.sum(um, axis=0)).T + + def newImage(self, U, centers, im): + best = numpy.argmax(self.U, axis=-1) + # print(best) + # numpy.round() + image = im.astype(int) + for i in range(256): + image = numpy.where(image == float(i), centers[best[i]][0], image) + return image + + def compute(self): + self.U = self.membership(self.data, self.centers) + + past_U = numpy.copy(self.U) + begin_time = datetime.datetime.now() + for i in range(self.max_iter): + + self.centers = self.Centers(self.data, self.U) + self.U = self.membership(self.data, self.centers) + + if norm(self.U - past_U) < self.error: + break + past_U = numpy.copy(self.U) + x = datetime.datetime.now() - begin_time + return self.centers, self.U, x + +# that's how you run it, data being your data, and the other parameters being the basic FCM parameters such as numbe rof cluseters, degree of fuzziness and so on +# f = FuzzyCMeans(n_clusters=C, initial_centers=Initial_centers, +# data=data m=2, max_iter=1000, error=1e-5) +# centers, U, time = f.compute() diff --git a/classification/tools.py b/classification/tools.py new file mode 100644 index 0000000..682268a --- /dev/null +++ b/classification/tools.py @@ -0,0 +1,20 @@ +from matplotlib.image import imread +import matplotlib.pyplot as plt +from math import sqrt +import math +import random +import numpy +import operator +from scipy.spatial.distance import cdist +from scipy.linalg import norm +import datetime + + +def Histogram(path): + image = imread(path) + if len(image.shape) != 2: + def gray(rgb): return numpy.dot(rgb[..., :3], [0.2989, 0.5870, 0.1140]) + gray = gray(image) + image = gray + hist, bins = numpy.histogram(image.ravel(), 256, [0, 256]) + return adapt(hist) diff --git a/data-structures/zigzagtraversal_iterative.py b/data-structures/zigzagtraversal_iterative.py new file mode 100644 index 0000000..fa485b3 --- /dev/null +++ b/data-structures/zigzagtraversal_iterative.py @@ -0,0 +1,75 @@ +class Node: + """ + A Node has data variable and pointers to its left and right nodes. + """ + + def __init__(self, data): + self.left = None + self.right = None + self.data = data + +def make_tree() -> Node: + root = Node(1) + root.left = Node(2) + root.right = Node(3) + root.left.left = Node(4) + root.left.right = Node(5) + return root + +def zigzag_iterative(root: Node): + """ + ZigZag traverse by iterative method: Print node left to right and right to left, alternatively. + """ + if root == None: + return + + # two stacks to store alternate levels + s1 = [] # For levels to be printed from right to left + s2 = [] # For levels to be printed from left to right + + # append first level to first stack 's1' + s1.append(root) + + # Keep printing while any of the stacks has some nodes + while not len(s1) == 0 or not len(s2) == 0: + + # Print nodes of current level from s1 and append nodes of next level to s2 + while not len(s1) == 0: + temp = s1[-1] + s1.pop() + print(temp.data, end = " ") + + # Note that is left is appended before right + if temp.left: + s2.append(temp.left) + if temp.right: + s2.append(temp.right) + + # Print nodes of current level from s2 and append nodes of next level to s1 + while not len(s2) == 0: + temp = s2[-1] + s2.pop() + print(temp.data, end = " ") + + # Note that is rightt is appended before left + if temp.right: + s1.append(temp.right) + if temp.left: + s1.append(temp.left) + +def main(): # Main function for testing. + """ + Create binary tree. + """ + root = make_tree() + print("\nZigzag order traversal(iterative) is: ") + zigzag_iterative(root) + print() + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + main() +