diff --git a/.github/code-of-conduct.md b/.github/code-of-conduct.md
new file mode 100644
index 0000000..f809c8b
--- /dev/null
+++ b/.github/code-of-conduct.md
@@ -0,0 +1,40 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
+
+[homepage]: http://contributor-covenant.org
+[version]: http://contributor-covenant.org/version/1/4/
diff --git a/.github/contributing.md b/.github/contributing.md
new file mode 100644
index 0000000..01f6600
--- /dev/null
+++ b/.github/contributing.md
@@ -0,0 +1,3 @@
+## Contributing
+
+> Please note that this project is released with a [Contributor Code of Conduct](code-of-conduct.md). By participating in this project you agree to abide by its terms.
\ No newline at end of file
diff --git a/.github/issue-template.md b/.github/issue-template.md
new file mode 100644
index 0000000..99764fe
--- /dev/null
+++ b/.github/issue-template.md
@@ -0,0 +1 @@
+I am creating an issue because...
diff --git a/.github/pull-request-template.md b/.github/pull-request-template.md
new file mode 100644
index 0000000..3bc0935
--- /dev/null
+++ b/.github/pull-request-template.md
@@ -0,0 +1,6 @@
+I am creating a pull request for...
+
+- [ ] New algorithm
+- [ ] Update to an algorithm
+- [ ] Fix an error
+- [ ] Other - *Describe below*
\ No newline at end of file
diff --git a/README.md b/README.md
deleted file mode 100644
index b6eb0d5..0000000
--- a/README.md
+++ /dev/null
@@ -1,42 +0,0 @@
-
-
-
-## Contents
-
-- [Arithmetic Analysis](arithmetic-analysis)
-- [Graphs](graphs)
-- [Math](math)
-- [Ciphers](ciphers)
-- [Data Structures](data-structures)
-- [Dynamic Programming](dynamic-programming)
-- [Hashes](hashes)
-- [Searches](searches)
-- [Sorting](sorting)
-- [Strings](strings)
-- [Traversals](traversals)
-
-## License
-
-This work is licensed under a [MIT License](https://github.com/abranhe/algorithms/blob/master/LICENSE)
-
-[![MIT IMG][mit-license]]((https://github.com/abranhe/algorithms/blob/master/LICENSE))
-
-To the extent possible under law, [Carlos Abraham](https://go.abranhe.com/github) has waived all copyright and related or neighboring rights to this work.
-
-
-[mit-license]: https://cdn.abraham.gq/projects/algorithms/mit-license.png
diff --git a/algorithms/artificial-intelligence/dbscan.py b/algorithms/artificial-intelligence/dbscan.py
new file mode 100644
index 0000000..299fd99
--- /dev/null
+++ b/algorithms/artificial-intelligence/dbscan.py
@@ -0,0 +1,84 @@
+import numpy as np
+import math
+
+UNCLASSIFIED = False
+NOISE = None
+
+def _dist(p,q):
+ return math.sqrt(np.power(p-q,2).sum())
+
+def _eps_neighborhood(p,q,eps):
+ return _dist(p,q) < eps
+
+def _region_query(m, point_id, eps):
+ n_points = m.shape[1]
+ seeds = []
+ for i in range(0, n_points):
+ if _eps_neighborhood(m[:,point_id], m[:,i], eps):
+ seeds.append(i)
+ return seeds
+
+def _expand_cluster(m, classifications, point_id, cluster_id, eps, min_points):
+ seeds = _region_query(m, point_id, eps)
+ if len(seeds) < min_points:
+ classifications[point_id] = NOISE
+ return False
+ else:
+ classifications[point_id] = cluster_id
+ for seed_id in seeds:
+ classifications[seed_id] = cluster_id
+
+ while len(seeds) > 0:
+ current_point = seeds[0]
+ results = _region_query(m, current_point, eps)
+ if len(results) >= min_points:
+ for i in range(0, len(results)):
+ result_point = results[i]
+ if classifications[result_point] == UNCLASSIFIED or \
+ classifications[result_point] == NOISE:
+ if classifications[result_point] == UNCLASSIFIED:
+ seeds.append(result_point)
+ classifications[result_point] = cluster_id
+ seeds = seeds[1:]
+ return True
+
+def dbscan(m, eps, min_points):
+ """Implementation of Density Based Spatial Clustering of Applications with Noise
+ See https://en.wikipedia.org/wiki/DBSCAN
+
+ scikit-learn probably has a better implementation
+
+ Uses Euclidean Distance as the measure
+
+ Inputs:
+ m - A matrix whose columns are feature vectors
+ eps - Maximum distance two points can be to be regionally related
+ min_points - The minimum number of points to make a cluster
+
+ Outputs:
+ An array with either a cluster id number or dbscan.NOISE (None) for each
+ column vector in m.
+ """
+ cluster_id = 1
+ n_points = m.shape[1]
+ classifications = [UNCLASSIFIED] * n_points
+ for point_id in range(0, n_points):
+ point = m[:,point_id]
+ if classifications[point_id] == UNCLASSIFIED:
+ if _expand_cluster(m, classifications, point_id, cluster_id, eps, min_points):
+ cluster_id = cluster_id + 1
+ return classifications
+
+# def test_dbscan():
+# m = np.matrix('1 1.2 0.8 3.7 3.9 3.6 10; 1.1 0.8 1 4 3.9 4.1 10')
+# eps = 0.5
+# min_points = 2
+# assert dbscan(m, eps, min_points) == [1, 1, 1, 2, 2, 2, None]
+
+def main():
+ m = np.matrix('-0.99 -0.98 -0.97 -0.96 -0.95 0.95 0.96 0.97 0.98 0.99; 1.1 1.09 1.08 1.07 1.06 1.06 1.07 1.08 1.09 1.1')
+ eps = 1
+ min_points = 3
+ print(dbscan(m, eps, min_points))
+
+main()
diff --git a/algorithms/cellular-automaton/conways_game_of_life.py b/algorithms/cellular-automaton/conways_game_of_life.py
new file mode 100644
index 0000000..bf66999
--- /dev/null
+++ b/algorithms/cellular-automaton/conways_game_of_life.py
@@ -0,0 +1,185 @@
+"""
+Conway's Game of Life
+"""
+import itertools
+
+class GameOfLife:
+ @classmethod
+ def dead_grid(cls, *, height=None, width=None):
+ return [
+ [Dead() for _cols in range(width)]
+ for _rows in range(height)
+ ]
+
+ @classmethod
+ def from_str(cls, string):
+ non_empty_lines = (
+ line for line in string.splitlines()
+ if len(line) > 0
+ )
+ parsed_grid = [
+ [Cell.from_str(char) for char in line]
+ for line in non_empty_lines
+ ]
+ return cls(grid=parsed_grid)
+
+ def __init__(self, grid=None):
+ self.grid = grid
+ self.height = len(grid)
+ self.width = len(grid[0])
+
+
+ def __str__(self):
+ return '\n'.join(
+ ''.join(str(cell) for cell in row)
+ for row in self.grid
+ )
+
+ def next_generation(self):
+ next_grid = [
+ [
+ cell.next_state(neighbor_count)
+ for cell, neighbor_count in row
+ ]
+ for row in self.grid_with_live_neighbor_counts()
+ ]
+ return GameOfLife(grid=next_grid)
+
+ def grid_with_live_neighbor_counts(self):
+ '''
+ Returns an iterator of grid rows in which each element
+ is a tuple containing the cell and the count of living neighbors
+ adjacent to that cell.
+ E.g. [[(Live, 0), (Dead, 3), ...], ...]
+ '''
+ return (
+ (
+ (cell, self.count_live_neighbors(row, col))
+ for (row, col), cell in coordinated_row
+ )
+ for coordinated_row in self.coordinate()
+ )
+
+ def coordinate(self):
+ '''
+ Returns an iterator of grid rows in which each element
+ is a tuple containg the coordinates and the content of the grid
+ at those coordinates.
+ E.g. [[((0, 0), Live), ((0, 1), Dead), ...], ...]
+ '''
+ return (
+ (
+ ((row_index, col_index), cell)
+ for col_index, cell in enumerate(row)
+ )
+ for row_index, row in enumerate(self.grid)
+ )
+
+ def count_live_neighbors(self, row, col):
+ directions_1D = (-1, 0, 1)
+ directions_2D = itertools.product(directions_1D, directions_1D)
+ neighbor_coords = (
+ (row + d_row, col + d_col)
+ for (d_row, d_col) in directions_2D
+ if (d_row, d_col) != (0, 0)
+ )
+
+ def is_coord_alive(coord):
+ cell = self.get(*coord, default=Dead())
+ return int(cell.is_alive)
+
+ return sum(map(is_coord_alive, neighbor_coords))
+
+ def get(self, row, col, default=None):
+ is_within_rows = (0 <= row < self.height)
+ is_within_cols = (0 <= col < self.width)
+ if is_within_rows and is_within_cols:
+ return self.grid[row][col]
+ return default
+
+
+class Cell:
+ @classmethod
+ def from_str(cls, string):
+ if string == Live.string_form:
+ return Live()
+ return Dead()
+
+ def __str__(self):
+ return self.string_form
+
+class Dead(Cell):
+ string_form = '·'
+ is_alive = False
+
+ def next_state(self, neighbor_count):
+ if neighbor_count == 3:
+ return Live()
+ return Dead()
+
+class Live(Cell):
+ string_form = '0'
+ is_alive = True
+
+ def next_state(self, neighbor_count):
+ if neighbor_count in [2, 3]:
+ return Live()
+ return Dead()
+
+
+from textwrap import dedent
+
+def run_string_example(
+ *,
+ seed_string=None,
+ seed_name=None,
+ num_gens=10
+):
+ seed_game = GameOfLife.from_str(seed_string)
+ if seed_name is None:
+ seed_name = f'A {seed_game.height}x{seed_game.width} grid'
+ print(dedent(f'''
+ =========================
+ | Conway's Game of Life |
+ {'':=^50}
+ | {f'Starting with seed: "{seed_name:.10}"': <46.46} |
+ | {f'Running for {str(num_gens):1.3} generations.': <46.46} |
+ {'':=^50}
+ '''))
+ latest_generation = seed_game
+ for gen_num in range(1, num_gens + 1):
+ print(f'Generation {gen_num}:')
+ print(str(latest_generation))
+ latest_generation = latest_generation.next_generation()
+ print('Done')
+
+def glider_example():
+ glider_string = dedent('''
+ ··0····
+ 0·0····
+ ·00····
+ ·······
+ ·······
+ ·······
+ ''')
+ run_string_example(
+ seed_string=glider_string,
+ seed_name='Glider',
+ num_gens=15
+ )
+
+def question_example():
+ from textwrap import dedent
+
+ game_string = dedent('''
+ ·0·
+ 0·0
+ ''')
+ run_string_example(
+ seed_string=game_string,
+ num_gens=4
+ )
+
+if __name__ == '__main__':
+ glider_example()
+ question_example()
diff --git a/algorithms/ciphers/bkdr.py b/algorithms/ciphers/bkdr.py
new file mode 100644
index 0000000..bbb89d2
--- /dev/null
+++ b/algorithms/ciphers/bkdr.py
@@ -0,0 +1,20 @@
+#!/usr/bin/python
+
+
+
+
+def BKDRHash(s):
+ '''BKDR Hash is an algorithm invented by Brian Kernighan, Dennis Ritchie.
+ The algorithm was presented in/on "The C Programming Language".
+ The digest (hash generated by this algorithm) is 32 bits (4 Bytes) in length.
+ refer to: http://www.partow.net/programming/hashfunctions/
+ '''
+ seed = 131 # can be any combination of 31, like 31 131 1313 13131 131313
+ hash = 0
+ for i in range(len(s)):
+ hash = (hash * seed) + ord(s[i])
+ return hash
+
+if __name__ == '__main__':
+ cleartext = "This is a test string for use with the BKDRHash"
+ print BKDRHash(cleartext)
\ No newline at end of file
diff --git a/algorithms/computational-geometry/graham_scan.py b/algorithms/computational-geometry/graham_scan.py
new file mode 100644
index 0000000..f968159
--- /dev/null
+++ b/algorithms/computational-geometry/graham_scan.py
@@ -0,0 +1,68 @@
+'''
+Layout: algorithms
+Title : Graham Scan Algorithm
+Author: RadientBrain
+'''
+
+
+from random import randint
+import matplotlib.pyplot as plt
+
+
+def orientation(m, n, o):
+ val = ((n[1]-m[1])*(o[0]-n[0])) - ((o[1]-n[1])*(n[0]-m[0]))
+ if val > 0:
+ return 1
+ elif val < 0:
+ return -1
+ else:
+ return 0
+
+def distance(m, n):
+ return (n[0]-m[0])**2 + (n[1]-m[1])**2
+
+def Sorting_with_bubble(coordinates, b):
+ for coord_ith in range(len(coordinates)):
+ for j in range(len(coordinates)-coord_ith-1):
+ if (orientation(b, coordinates[j], coordinates[j+1]) > 0) or (orientation(b, coordinates[j], coordinates[j+1])==0 and (distance(b, coordinates[j]) > distance(b, coordinates[j+1]))):
+ temp = coordinates[j+1]
+ coordinates[j+1] = coordinates[j]
+ coordinates[j] = temp
+
+ return coordinates
+
+
+def Convex_hull_through_graham(coordinates):
+ b = min(coordinates, key= lambda coord: (coord[1], coord[0]))
+ coord_ith = coordinates.index(b)
+ coordinates[coord_ith]=coordinates[0]
+ coordinates[0] = b
+ coordinates = [b] + Sorting_with_bubble(coordinates[1:], b)
+ size_triplet = [coordinates[0], coordinates[1], coordinates[2]]
+ for coord_ith in range(3, len(coordinates)):
+ while len(size_triplet)>=3 and orientation(size_triplet[-2], size_triplet[-1], coordinates[coord_ith]) >= 0:
+ size_triplet.pop()
+ size_triplet.append(coordinates[coord_ith])
+ return size_triplet+[size_triplet[0]]
+
+
+def random_points(n=30):
+ coordinates = [(randint(0, n), randint(0, n)) for _ in range(n)]
+ print (coordinates)
+ return coordinates
+
+
+if __name__ == "__main__":
+ coordinates = random_points(120)
+
+ X = [coord[0] for coord in coordinates]
+ Y = [coord[1] for coord in coordinates]
+ plt.plot(X, Y, '.b')
+
+ boundary_poly = Convex_hull_through_graham(coordinates)
+
+ X = [coord[0] for coord in boundary_poly]
+ Y = [coord[1] for coord in boundary_poly]
+ plt.plot(X, Y, '-og')
+
+ plt.show()
\ No newline at end of file
diff --git a/algorithms/cryptography/Hill_cipher.py b/algorithms/cryptography/Hill_cipher.py
new file mode 100644
index 0000000..943c463
--- /dev/null
+++ b/algorithms/cryptography/Hill_cipher.py
@@ -0,0 +1,42 @@
+import numpy as np
+s=list(input("Enter a string"))
+c=[]
+for i in range(len(s)):
+ c.append(ord(s[i])-65)
+
+arr= np.array(c)
+
+a1=np.transpose(arr)
+print(a1)
+a1= a1.reshape(3,1)
+print(a1.shape)
+
+
+#key input
+print("Enter the key for the encryption")
+R = int(input("rows:"))
+C = int(input("columns:"))
+matrix = []
+print("Enter the key:")
+
+for i in range(R):
+ a =[]
+ for j in range(C):
+ a.append(int(input()))
+ matrix.append(a)
+
+for i in range(R):
+ for j in range(C):
+ print(matrix[i][j], end = " ")
+matrix = np.array(matrix)
+print(matrix.shape)
+print(matrix[1][1])
+
+mul=np.matmul(matrix,a1)
+mul = np.array(mul)
+print(mul.shape)
+print(mul)
+for i in range(R):
+ mul[i]=mul[i]%26
+
+print(mul)
diff --git a/algorithms/cryptography/aes.py b/algorithms/cryptography/aes.py
new file mode 100644
index 0000000..02275ea
--- /dev/null
+++ b/algorithms/cryptography/aes.py
@@ -0,0 +1,669 @@
+#!/usr/bin/python
+import os
+import sys
+import math
+
+class AES(object):
+ '''AES funtions for a single block
+ '''
+ # Very annoying code: all is for an object, but no state is kept!
+ # Should just be plain functions in a AES modlule.
+
+ # valid key sizes
+ keySize = dict(SIZE_128=16, SIZE_192=24, SIZE_256=32)
+
+ # Rijndael S-box
+ sbox = [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67,
+ 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59,
+ 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7,
+ 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1,
+ 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05,
+ 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83,
+ 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29,
+ 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
+ 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa,
+ 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c,
+ 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc,
+ 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,
+ 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19,
+ 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee,
+ 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49,
+ 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
+ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4,
+ 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6,
+ 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70,
+ 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9,
+ 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e,
+ 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1,
+ 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0,
+ 0x54, 0xbb, 0x16]
+
+ # Rijndael Inverted S-box
+ rsbox = [0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3,
+ 0x9e, 0x81, 0xf3, 0xd7, 0xfb , 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f,
+ 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb , 0x54,
+ 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b,
+ 0x42, 0xfa, 0xc3, 0x4e , 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24,
+ 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 , 0x72, 0xf8,
+ 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d,
+ 0x65, 0xb6, 0x92 , 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
+ 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 , 0x90, 0xd8, 0xab,
+ 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3,
+ 0x45, 0x06 , 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1,
+ 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b , 0x3a, 0x91, 0x11, 0x41,
+ 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6,
+ 0x73 , 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9,
+ 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e , 0x47, 0xf1, 0x1a, 0x71, 0x1d,
+ 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b ,
+ 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0,
+ 0xfe, 0x78, 0xcd, 0x5a, 0xf4 , 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07,
+ 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f , 0x60,
+ 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f,
+ 0x93, 0xc9, 0x9c, 0xef , 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5,
+ 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 , 0x17, 0x2b,
+ 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55,
+ 0x21, 0x0c, 0x7d]
+
+ def getSBoxValue(self,num):
+ """Retrieves a given S-Box Value"""
+ return self.sbox[num]
+
+ def getSBoxInvert(self,num):
+ """Retrieves a given Inverted S-Box Value"""
+ return self.rsbox[num]
+
+ def rotate(self, word):
+ """ Rijndael's key schedule rotate operation.
+
+ Rotate a word eight bits to the left: eg, rotate(1d2c3a4f) == 2c3a4f1d
+ Word is an char list of size 4 (32 bits overall).
+ """
+ return word[1:] + word[:1]
+
+ # Rijndael Rcon
+ Rcon = [0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36,
+ 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97,
+ 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72,
+ 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66,
+ 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,
+ 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d,
+ 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,
+ 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61,
+ 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
+ 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
+ 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc,
+ 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5,
+ 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a,
+ 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d,
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c,
+ 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
+ 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4,
+ 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
+ 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08,
+ 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
+ 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d,
+ 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2,
+ 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74,
+ 0xe8, 0xcb ]
+
+ def getRconValue(self, num):
+ """Retrieves a given Rcon Value"""
+ return self.Rcon[num]
+
+ def core(self, word, iteration):
+ """Key schedule core."""
+ # rotate the 32-bit word 8 bits to the left
+ word = self.rotate(word)
+ # apply S-Box substitution on all 4 parts of the 32-bit word
+ for i in range(4):
+ word[i] = self.getSBoxValue(word[i])
+ # XOR the output of the rcon operation with i to the first part
+ # (leftmost) only
+ word[0] = word[0] ^ self.getRconValue(iteration)
+ return word
+
+ def expandKey(self, key, size, expandedKeySize):
+ """Rijndael's key expansion.
+
+ Expands an 128,192,256 key into an 176,208,240 bytes key
+
+ expandedKey is a char list of large enough size,
+ key is the non-expanded key.
+ """
+ # current expanded keySize, in bytes
+ currentSize = 0
+ rconIteration = 1
+ expandedKey = [0] * expandedKeySize
+
+ # set the 16, 24, 32 bytes of the expanded key to the input key
+ for j in range(size):
+ expandedKey[j] = key[j]
+ currentSize += size
+
+ while currentSize < expandedKeySize:
+ # assign the previous 4 bytes to the temporary value t
+ t = expandedKey[currentSize-4:currentSize]
+
+ # every 16,24,32 bytes we apply the core schedule to t
+ # and increment rconIteration afterwards
+ if currentSize % size == 0:
+ t = self.core(t, rconIteration)
+ rconIteration += 1
+ # For 256-bit keys, we add an extra sbox to the calculation
+ if size == self.keySize["SIZE_256"] and ((currentSize % size) == 16):
+ for l in range(4): t[l] = self.getSBoxValue(t[l])
+
+ # We XOR t with the four-byte block 16,24,32 bytes before the new
+ # expanded key. This becomes the next four bytes in the expanded
+ # key.
+ for m in range(4):
+ expandedKey[currentSize] = expandedKey[currentSize - size] ^ \
+ t[m]
+ currentSize += 1
+
+ return expandedKey
+
+ def addRoundKey(self, state, roundKey):
+ """Adds (XORs) the round key to the state."""
+ for i in range(16):
+ state[i] ^= roundKey[i]
+ return state
+
+ def createRoundKey(self, expandedKey, roundKeyPointer):
+ """Create a round key.
+ Creates a round key from the given expanded key and the
+ position within the expanded key.
+ """
+ roundKey = [0] * 16
+ for i in range(4):
+ for j in range(4):
+ roundKey[j*4+i] = expandedKey[roundKeyPointer + i*4 + j]
+ return roundKey
+
+ def galois_multiplication(self, a, b):
+ """Galois multiplication of 8 bit characters a and b."""
+ p = 0
+ for counter in range(8):
+ if b & 1: p ^= a
+ hi_bit_set = a & 0x80
+ a <<= 1
+ # keep a 8 bit
+ a &= 0xFF
+ if hi_bit_set:
+ a ^= 0x1b
+ b >>= 1
+ return p
+
+ #
+ # substitute all the values from the state with the value in the SBox
+ # using the state value as index for the SBox
+ #
+ def subBytes(self, state, isInv):
+ if isInv: getter = self.getSBoxInvert
+ else: getter = self.getSBoxValue
+ for i in range(16): state[i] = getter(state[i])
+ return state
+
+ # iterate over the 4 rows and call shiftRow() with that row
+ def shiftRows(self, state, isInv):
+ for i in range(4):
+ state = self.shiftRow(state, i*4, i, isInv)
+ return state
+
+ # each iteration shifts the row to the left by 1
+ def shiftRow(self, state, statePointer, nbr, isInv):
+ for i in range(nbr):
+ if isInv:
+ state[statePointer:statePointer+4] = \
+ state[statePointer+3:statePointer+4] + \
+ state[statePointer:statePointer+3]
+ else:
+ state[statePointer:statePointer+4] = \
+ state[statePointer+1:statePointer+4] + \
+ state[statePointer:statePointer+1]
+ return state
+
+ # galois multiplication of the 4x4 matrix
+ def mixColumns(self, state, isInv):
+ # iterate over the 4 columns
+ for i in range(4):
+ # construct one column by slicing over the 4 rows
+ column = state[i:i+16:4]
+ # apply the mixColumn on one column
+ column = self.mixColumn(column, isInv)
+ # put the values back into the state
+ state[i:i+16:4] = column
+
+ return state
+
+ # galois multiplication of 1 column of the 4x4 matrix
+ def mixColumn(self, column, isInv):
+ if isInv: mult = [14, 9, 13, 11]
+ else: mult = [2, 1, 1, 3]
+ cpy = list(column)
+ g = self.galois_multiplication
+
+ column[0] = g(cpy[0], mult[0]) ^ g(cpy[3], mult[1]) ^ \
+ g(cpy[2], mult[2]) ^ g(cpy[1], mult[3])
+ column[1] = g(cpy[1], mult[0]) ^ g(cpy[0], mult[1]) ^ \
+ g(cpy[3], mult[2]) ^ g(cpy[2], mult[3])
+ column[2] = g(cpy[2], mult[0]) ^ g(cpy[1], mult[1]) ^ \
+ g(cpy[0], mult[2]) ^ g(cpy[3], mult[3])
+ column[3] = g(cpy[3], mult[0]) ^ g(cpy[2], mult[1]) ^ \
+ g(cpy[1], mult[2]) ^ g(cpy[0], mult[3])
+ return column
+
+ # applies the 4 operations of the forward round in sequence
+ def aes_round(self, state, roundKey):
+ state = self.subBytes(state, False)
+ state = self.shiftRows(state, False)
+ state = self.mixColumns(state, False)
+ state = self.addRoundKey(state, roundKey)
+ return state
+
+ # applies the 4 operations of the inverse round in sequence
+ def aes_invRound(self, state, roundKey):
+ state = self.shiftRows(state, True)
+ state = self.subBytes(state, True)
+ state = self.addRoundKey(state, roundKey)
+ state = self.mixColumns(state, True)
+ return state
+
+ # Perform the initial operations, the standard round, and the final
+ # operations of the forward aes, creating a round key for each round
+ def aes_main(self, state, expandedKey, nbrRounds):
+ state = self.addRoundKey(state, self.createRoundKey(expandedKey, 0))
+ i = 1
+ while i < nbrRounds:
+ state = self.aes_round(state,
+ self.createRoundKey(expandedKey, 16*i))
+ i += 1
+ state = self.subBytes(state, False)
+ state = self.shiftRows(state, False)
+ state = self.addRoundKey(state,
+ self.createRoundKey(expandedKey, 16*nbrRounds))
+ return state
+
+ # Perform the initial operations, the standard round, and the final
+ # operations of the inverse aes, creating a round key for each round
+ def aes_invMain(self, state, expandedKey, nbrRounds):
+ state = self.addRoundKey(state,
+ self.createRoundKey(expandedKey, 16*nbrRounds))
+ i = nbrRounds - 1
+ while i > 0:
+ state = self.aes_invRound(state,
+ self.createRoundKey(expandedKey, 16*i))
+ i -= 1
+ state = self.shiftRows(state, True)
+ state = self.subBytes(state, True)
+ state = self.addRoundKey(state, self.createRoundKey(expandedKey, 0))
+ return state
+
+ # encrypts a 128 bit input block against the given key of size specified
+ def encrypt(self, iput, key, size):
+ output = [0] * 16
+ # the number of rounds
+ nbrRounds = 0
+ # the 128 bit block to encode
+ block = [0] * 16
+ # set the number of rounds
+ if size == self.keySize["SIZE_128"]: nbrRounds = 10
+ elif size == self.keySize["SIZE_192"]: nbrRounds = 12
+ elif size == self.keySize["SIZE_256"]: nbrRounds = 14
+ else: return None
+
+ # the expanded keySize
+ expandedKeySize = 16*(nbrRounds+1)
+
+ # Set the block values, for the block:
+ # a0,0 a0,1 a0,2 a0,3
+ # a1,0 a1,1 a1,2 a1,3
+ # a2,0 a2,1 a2,2 a2,3
+ # a3,0 a3,1 a3,2 a3,3
+ # the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3
+ #
+ # iterate over the columns
+ for i in range(4):
+ # iterate over the rows
+ for j in range(4):
+ block[(i+(j*4))] = iput[(i*4)+j]
+
+ # expand the key into an 176, 208, 240 bytes key
+ # the expanded key
+ expandedKey = self.expandKey(key, size, expandedKeySize)
+
+ # encrypt the block using the expandedKey
+ block = self.aes_main(block, expandedKey, nbrRounds)
+
+ # unmap the block again into the output
+ for k in range(4):
+ # iterate over the rows
+ for l in range(4):
+ output[(k*4)+l] = block[(k+(l*4))]
+ return output
+
+ # decrypts a 128 bit input block against the given key of size specified
+ def decrypt(self, iput, key, size):
+ output = [0] * 16
+ # the number of rounds
+ nbrRounds = 0
+ # the 128 bit block to decode
+ block = [0] * 16
+ # set the number of rounds
+ if size == self.keySize["SIZE_128"]: nbrRounds = 10
+ elif size == self.keySize["SIZE_192"]: nbrRounds = 12
+ elif size == self.keySize["SIZE_256"]: nbrRounds = 14
+ else: return None
+
+ # the expanded keySize
+ expandedKeySize = 16*(nbrRounds+1)
+
+ # Set the block values, for the block:
+ # a0,0 a0,1 a0,2 a0,3
+ # a1,0 a1,1 a1,2 a1,3
+ # a2,0 a2,1 a2,2 a2,3
+ # a3,0 a3,1 a3,2 a3,3
+ # the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3
+
+ # iterate over the columns
+ for i in range(4):
+ # iterate over the rows
+ for j in range(4):
+ block[(i+(j*4))] = iput[(i*4)+j]
+ # expand the key into an 176, 208, 240 bytes key
+ expandedKey = self.expandKey(key, size, expandedKeySize)
+ # decrypt the block using the expandedKey
+ block = self.aes_invMain(block, expandedKey, nbrRounds)
+ # unmap the block again into the output
+ for k in range(4):
+ # iterate over the rows
+ for l in range(4):
+ output[(k*4)+l] = block[(k+(l*4))]
+ return output
+
+
+class AESModeOfOperation(object):
+ '''Handles AES with plaintext consistingof multiple blocks.
+ Choice of block encoding modes: OFT, CFB, CBC
+ '''
+ # Very annoying code: all is for an object, but no state is kept!
+ # Should just be plain functions in an AES_BlockMode module.
+ aes = AES()
+
+ # structure of supported modes of operation
+ modeOfOperation = dict(OFB=0, CFB=1, CBC=2)
+
+ # converts a 16 character string into a number array
+ def convertString(self, string, start, end, mode):
+ if end - start > 16: end = start + 16
+ if mode == self.modeOfOperation["CBC"]: ar = [0] * 16
+ else: ar = []
+
+ i = start
+ j = 0
+ while len(ar) < end - start:
+ ar.append(0)
+ while i < end:
+ ar[j] = ord(string[i])
+ j += 1
+ i += 1
+ return ar
+
+ # Mode of Operation Encryption
+ # stringIn - Input String
+ # mode - mode of type modeOfOperation
+ # hexKey - a hex key of the bit length size
+ # size - the bit length of the key
+ # hexIV - the 128 bit hex Initilization Vector
+ def encrypt(self, stringIn, mode, key, size, IV):
+ if len(key) % size:
+ return None
+ if len(IV) % 16:
+ return None
+ # the AES input/output
+ plaintext = []
+ iput = [0] * 16
+ output = []
+ ciphertext = [0] * 16
+ # the output cipher string
+ cipherOut = []
+ # char firstRound
+ firstRound = True
+ if stringIn != None:
+ for j in range(int(math.ceil(float(len(stringIn))/16))):
+ start = j*16
+ end = j*16+16
+ if end > len(stringIn):
+ end = len(stringIn)
+ plaintext = self.convertString(stringIn, start, end, mode)
+ # print 'PT@%s:%s' % (j, plaintext)
+ if mode == self.modeOfOperation["CFB"]:
+ if firstRound:
+ output = self.aes.encrypt(IV, key, size)
+ firstRound = False
+ else:
+ output = self.aes.encrypt(iput, key, size)
+ for i in range(16):
+ if len(plaintext)-1 < i:
+ ciphertext[i] = 0 ^ output[i]
+ elif len(output)-1 < i:
+ ciphertext[i] = plaintext[i] ^ 0
+ elif len(plaintext)-1 < i and len(output) < i:
+ ciphertext[i] = 0 ^ 0
+ else:
+ ciphertext[i] = plaintext[i] ^ output[i]
+ for k in range(end-start):
+ cipherOut.append(ciphertext[k])
+ iput = ciphertext
+ elif mode == self.modeOfOperation["OFB"]:
+ if firstRound:
+ output = self.aes.encrypt(IV, key, size)
+ firstRound = False
+ else:
+ output = self.aes.encrypt(iput, key, size)
+ for i in range(16):
+ if len(plaintext)-1 < i:
+ ciphertext[i] = 0 ^ output[i]
+ elif len(output)-1 < i:
+ ciphertext[i] = plaintext[i] ^ 0
+ elif len(plaintext)-1 < i and len(output) < i:
+ ciphertext[i] = 0 ^ 0
+ else:
+ ciphertext[i] = plaintext[i] ^ output[i]
+ for k in range(end-start):
+ cipherOut.append(ciphertext[k])
+ iput = output
+ elif mode == self.modeOfOperation["CBC"]:
+ for i in range(16):
+ if firstRound:
+ iput[i] = plaintext[i] ^ IV[i]
+ else:
+ iput[i] = plaintext[i] ^ ciphertext[i]
+ # print 'IP@%s:%s' % (j, iput)
+ firstRound = False
+ ciphertext = self.aes.encrypt(iput, key, size)
+ # always 16 bytes because of the padding for CBC
+ for k in range(16):
+ cipherOut.append(ciphertext[k])
+ return mode, len(stringIn), cipherOut
+
+ # Mode of Operation Decryption
+ # cipherIn - Encrypted String
+ # originalsize - The unencrypted string length - required for CBC
+ # mode - mode of type modeOfOperation
+ # key - a number array of the bit length size
+ # size - the bit length of the key
+ # IV - the 128 bit number array Initilization Vector
+ def decrypt(self, cipherIn, originalsize, mode, key, size, IV):
+ # cipherIn = unescCtrlChars(cipherIn)
+ if len(key) % size:
+ return None
+ if len(IV) % 16:
+ return None
+ # the AES input/output
+ ciphertext = []
+ iput = []
+ output = []
+ plaintext = [0] * 16
+ # the output plain text character list
+ chrOut = []
+ # char firstRound
+ firstRound = True
+ if cipherIn != None:
+ for j in range(int(math.ceil(float(len(cipherIn))/16))):
+ start = j*16
+ end = j*16+16
+ if j*16+16 > len(cipherIn):
+ end = len(cipherIn)
+ ciphertext = cipherIn[start:end]
+ if mode == self.modeOfOperation["CFB"]:
+ if firstRound:
+ output = self.aes.encrypt(IV, key, size)
+ firstRound = False
+ else:
+ output = self.aes.encrypt(iput, key, size)
+ for i in range(16):
+ if len(output)-1 < i:
+ plaintext[i] = 0 ^ ciphertext[i]
+ elif len(ciphertext)-1 < i:
+ plaintext[i] = output[i] ^ 0
+ elif len(output)-1 < i and len(ciphertext) < i:
+ plaintext[i] = 0 ^ 0
+ else:
+ plaintext[i] = output[i] ^ ciphertext[i]
+ for k in range(end-start):
+ chrOut.append(chr(plaintext[k]))
+ iput = ciphertext
+ elif mode == self.modeOfOperation["OFB"]:
+ if firstRound:
+ output = self.aes.encrypt(IV, key, size)
+ firstRound = False
+ else:
+ output = self.aes.encrypt(iput, key, size)
+ for i in range(16):
+ if len(output)-1 < i:
+ plaintext[i] = 0 ^ ciphertext[i]
+ elif len(ciphertext)-1 < i:
+ plaintext[i] = output[i] ^ 0
+ elif len(output)-1 < i and len(ciphertext) < i:
+ plaintext[i] = 0 ^ 0
+ else:
+ plaintext[i] = output[i] ^ ciphertext[i]
+ for k in range(end-start):
+ chrOut.append(chr(plaintext[k]))
+ iput = output
+ elif mode == self.modeOfOperation["CBC"]:
+ output = self.aes.decrypt(ciphertext, key, size)
+ for i in range(16):
+ if firstRound:
+ plaintext[i] = IV[i] ^ output[i]
+ else:
+ plaintext[i] = iput[i] ^ output[i]
+ firstRound = False
+ if originalsize is not None and originalsize < end:
+ for k in range(originalsize-start):
+ chrOut.append(chr(plaintext[k]))
+ else:
+ for k in range(end-start):
+ chrOut.append(chr(plaintext[k]))
+ iput = ciphertext
+ return "".join(chrOut)
+
+
+def append_PKCS7_padding(s):
+ """return s padded to a multiple of 16-bytes by PKCS7 padding"""
+ numpads = 16 - (len(s)%16)
+ return s + numpads*chr(numpads)
+
+def strip_PKCS7_padding(s):
+ """return s stripped of PKCS7 padding"""
+ if len(s)%16 or not s:
+ raise ValueError("String of len %d can't be PCKS7-padded" % len(s))
+ numpads = ord(s[-1])
+ if numpads > 16:
+ raise ValueError("String ending with %r can't be PCKS7-padded" % s[-1])
+ return s[:-numpads]
+
+def encryptData(key, data, mode=AESModeOfOperation.modeOfOperation["CBC"]):
+ """encrypt `data` using `key`
+
+ `key` should be a string of bytes.
+
+ returned cipher is a string of bytes prepended with the initialization
+ vector.
+
+ """
+ key = map(ord, key)
+ if mode == AESModeOfOperation.modeOfOperation["CBC"]:
+ data = append_PKCS7_padding(data)
+ keysize = len(key)
+ assert keysize in AES.keySize.values(), 'invalid key size: %s' % keysize
+ # create a new iv using random data
+ iv = [ord(i) for i in os.urandom(16)]
+ moo = AESModeOfOperation()
+ (mode, length, ciph) = moo.encrypt(data, mode, key, keysize, iv)
+ # With padding, the original length does not need to be known. It's a bad
+ # idea to store the original message length.
+ # prepend the iv.
+ return ''.join(map(chr, iv)) + ''.join(map(chr, ciph))
+
+def decryptData(key, data, mode=AESModeOfOperation.modeOfOperation["CBC"]):
+ """decrypt `data` using `key`
+
+ `key` should be a string of bytes.
+
+ `data` should have the initialization vector prepended as a string of
+ ordinal values.
+ """
+
+ key = map(ord, key)
+ keysize = len(key)
+ assert keysize in AES.keySize.values(), 'invalid key size: %s' % keysize
+ # iv is first 16 bytes
+ iv = map(ord, data[:16])
+ data = map(ord, data[16:])
+ moo = AESModeOfOperation()
+ decr = moo.decrypt(data, None, mode, key, keysize, iv)
+ if mode == AESModeOfOperation.modeOfOperation["CBC"]:
+ decr = strip_PKCS7_padding(decr)
+ return decr
+
+def generateRandomKey(keysize):
+ """Generates a key from random data of length `keysize`.
+ The returned key is a string of bytes.
+ """
+ if keysize not in (16, 24, 32):
+ emsg = 'Invalid keysize, %s. Should be one of (16, 24, 32).'
+ raise ValueError, emsg % keysize
+ return os.urandom(keysize)
+
+def testStr(cleartext, keysize=16, modeName = "CBC"):
+ '''Test with random key, choice of mode.'''
+ print 'Random key test', 'Mode:', modeName
+ print 'cleartext:', cleartext
+ key = generateRandomKey(keysize)
+ print 'Key:', [ord(x) for x in key]
+ mode = AESModeOfOperation.modeOfOperation[modeName]
+ cipher = encryptData(key, cleartext, mode)
+ print 'Cipher:', [ord(x) for x in cipher]
+ decr = decryptData(key, cipher, mode)
+ print 'Decrypted:', decr
+
+
+if __name__ == "__main__":
+ moo = AESModeOfOperation()
+ cleartext = "This is a test with several blocks!"
+ cypherkey = [143,194,34,208,145,203,230,143,177,246,97,206,145,92,255,84]
+ iv = [103,35,148,239,76,213,47,118,255,222,123,176,106,134,98,92]
+ mode, orig_len, ciph = moo.encrypt(cleartext, moo.modeOfOperation["CBC"],
+ cypherkey, moo.aes.keySize["SIZE_128"], iv)
+ print 'm=%s, ol=%s (%s), ciph=%s' % (mode, orig_len, len(cleartext), ciph)
+ decr = moo.decrypt(ciph, orig_len, mode, cypherkey,
+ moo.aes.keySize["SIZE_128"], iv)
+ print decr
+ testStr(cleartext, 16, "CBC")
+
+
+
+
+
diff --git a/algorithms/cryptography/caesar_cipher.py b/algorithms/cryptography/caesar_cipher.py
new file mode 100644
index 0000000..6cd35e7
--- /dev/null
+++ b/algorithms/cryptography/caesar_cipher.py
@@ -0,0 +1,68 @@
+import sys
+def encrypt(strng, key):
+ encrypted = ''
+ for x in strng:
+ indx = (ord(x) + key) % 256
+ if indx > 126:
+ indx = indx - 95
+ encrypted = encrypted + chr(indx)
+ return encrypted
+
+
+def decrypt(strng, key):
+ decrypted = ''
+ for x in strng:
+ indx = (ord(x) - key) % 256
+ if indx < 32:
+ indx = indx + 95
+ decrypted = decrypted + chr(indx)
+ return decrypted
+
+def brute_force(strng):
+ key = 1
+ decrypted = ''
+ while key <= 94:
+ for x in strng:
+ indx = (ord(x) - key) % 256
+ if indx < 32:
+ indx = indx + 95
+ decrypted = decrypted + chr(indx)
+ print("Key: {}\t| Message: {}".format(key, decrypted))
+ decrypted = ''
+ key += 1
+ return None
+
+
+def main():
+ print('-' * 10 + "\n**Menu**\n" + '-' * 10)
+ print("1.Encrpyt")
+ print("2.Decrypt")
+ print("3.BruteForce")
+ print("4.Quit")
+ while True:
+ choice = input("What would you like to do?: ")
+ if choice not in ['1', '2', '3', '4']:
+ print ("Invalid choice")
+ elif choice == '1':
+ strng = input("Please enter the string to be ecrypted: ")
+ while True:
+ key = int(input("Please enter off-set between 1-94: "))
+ if key in range(1, 95):
+ print (encrypt(strng, key))
+ main()
+ elif choice == '2':
+ strng = input("Please enter the string to be decrypted: ")
+ while True:
+ key = int(input("Please enter off-set between 1-94: "))
+ if key > 0 and key <= 94:
+ print(decrypt(strng, key))
+ main()
+ elif choice == '3':
+ strng = input("Please enter the string to be decrypted: ")
+ brute_force(strng)
+ main()
+ elif choice == '4':
+ print ("Goodbye.")
+ sys.exit()
+
+main()
diff --git a/algorithms/cryptography/playfair.py b/algorithms/cryptography/playfair.py
new file mode 100644
index 0000000..7396cf9
--- /dev/null
+++ b/algorithms/cryptography/playfair.py
@@ -0,0 +1,146 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import sys
+
+# @Author: Gleydson Rodrigues
+
+# ./playfair.py [encrypt/decrypt] key message
+
+
+alphabet = "abcdefghijlmnopqrstuvwxyz".upper()
+
+def vetorize(text):
+ listText = []
+ for letter in text:
+ listText.append(letter)
+ return listText
+
+def normalizeMessage(text):
+ newText = []
+ text = text.upper()
+ text = text.replace(" ", "")
+ text = text.replace(".", "")
+ text = text.replace(",", "")
+ pos = 0
+ while pos < len(text) - 1:
+ firstLetter = text[pos]
+ secondLetter = text[pos + 1]
+ if firstLetter == secondLetter:
+ if firstLetter == "X":
+ newText.append(firstLetter)
+ newText.append("Z")
+ pos += 1
+ else:
+ newText.append(firstLetter)
+ newText.append("X")
+ pos += 1
+ else:
+ newText.append(firstLetter)
+ newText.append(secondLetter)
+ pos += 2
+ if pos < len(text):
+ if text[-1] == "X":
+ newText.append(text[pos])
+ newText.append("Z")
+ else:
+ newText.append(text[pos])
+ newText.append("X")
+ return newText
+
+def createMatrix():
+ matrix = []
+ for i in range(5):
+ matrix.append([])
+ for j in range(5):
+ matrix[i].append("")
+ return matrix
+
+def mountGrid(matrix, key, alphabet):
+ alphabet = vetorize(alphabet)
+ line, column, pos = 0, 0, 0
+ for letter in key:
+ line = pos / 5
+ column = pos % 5
+ if letter in alphabet:
+ alphabet.remove(letter)
+ matrix[line][column] = letter
+ pos += 1
+ while len(alphabet) > 0:
+ line = pos / 5
+ column = pos % 5
+ matrix[line][column] = alphabet.pop(0)
+ pos += 1
+ return matrix
+
+def getIndex(letter, matrix):
+ for i in range(5):
+ for j in range(5):
+ if matrix[i][j] == letter:
+ return [i, j]
+
+def encrypt(message, key):
+ matrix = mountGrid(createMatrix(), key, alphabet)
+ message = normalizeMessage(message)
+ messageEncrypted = ""
+ pos, line, column = 0, 0, 1
+ while pos < len(message) - 1:
+ firstLetter = message[pos]
+ secondLetter = message[pos + 1]
+ indexFirstLetter = getIndex(firstLetter, matrix)
+ indexSecondLetter = getIndex(secondLetter, matrix)
+ if indexFirstLetter[line] == indexSecondLetter[line]:
+ messageEncrypted += matrix[indexFirstLetter[line]][(indexFirstLetter[column] + 1) % 5]
+ messageEncrypted += matrix[indexSecondLetter[line]][(indexSecondLetter[column] + 1) % 5]
+ elif indexFirstLetter[column] == indexSecondLetter[column]:
+ messageEncrypted += matrix[(indexFirstLetter[line] + 1) % 5][indexFirstLetter[column]]
+ messageEncrypted += matrix[(indexSecondLetter[line] + 1) % 5][indexSecondLetter[column]]
+ else:
+ messageEncrypted += matrix[indexFirstLetter[line]][indexSecondLetter[column]]
+ messageEncrypted += matrix[indexSecondLetter[line]][indexFirstLetter[column]]
+ pos += 2
+ return messageEncrypted
+
+def decrypt(messageEncrypted, key):
+ matrix = mountGrid(createMatrix(), key, alphabet)
+ messageDecrypted = ""
+ pos, line, column = 0, 0, 1
+ while pos < len(messageEncrypted):
+ firstLetter = messageEncrypted[pos]
+ secondLetter = messageEncrypted[pos + 1]
+ indexFirstLetter = getIndex(firstLetter, matrix)
+ indexSecondLetter = getIndex(secondLetter, matrix)
+ if indexFirstLetter[line] == indexSecondLetter[line]:
+ messageDecrypted += matrix[indexFirstLetter[line]][(indexFirstLetter[column] - 1) % 5]
+ messageDecrypted += matrix[indexSecondLetter[line]][(indexSecondLetter[column] - 1) % 5]
+ elif indexFirstLetter[column] == indexSecondLetter[column]:
+ messageDecrypted += matrix[(indexFirstLetter[line] - 1) % 5][indexFirstLetter[column]]
+ messageDecrypted += matrix[(indexSecondLetter[line] - 1) % 5][indexSecondLetter[column]]
+ else:
+ messageDecrypted += matrix[indexFirstLetter[line]][indexSecondLetter[column]]
+ messageDecrypted += matrix[indexSecondLetter[line]][indexFirstLetter[column]]
+ pos += 2
+ return messageDecrypted
+
+def help():
+ print(
+ "./playfair.py [encrypt/decrypt] key message"
+ )
+
+def main():
+ params = sys.argv[1:]
+ if len(params) == 0:
+ help()
+ elif params[0] == "encrypt":
+ key = params[1].upper()
+ message = params[2:]
+ print(encrypt("".join(x for x in message).upper(), key))
+ elif params[0] == "decrypt":
+ key = params[1].upper()
+ message = params[2:]
+ print(decrypt("".join(x for x in message).upper(), key))
+ else:
+ help()
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file
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/data-structures/binarySerach.py b/algorithms/data-structures/binarySerach.py
new file mode 100644
index 0000000..4169aee
--- /dev/null
+++ b/algorithms/data-structures/binarySerach.py
@@ -0,0 +1,25 @@
+def binSearch(a, x, low, high):
+ #Return True if target is found in indicated portion of a Python list.
+ #The search only considers the portion from data[low] to data[high] inclusive.
+
+ if low > high:
+ return False # interval is empty; no match
+ else:
+ mid = (low + high) // 2
+ if x == a[mid]: # found a match
+ return True
+ elif x < a[mid]:
+ # recur on the portion left of the middle
+ return binSearch(a, x, low, mid - 1)
+ else:
+ # recur on the portion right of the middle
+ return binSearch(a, x, mid + 1, high)
+a = [5, 10, 15, 20, 25, 30, 40]
+x = 20
+low = 0
+high = 6
+result = binSearch(a, x, low, high)
+if result:
+ print("The value ", x, " Found")
+else:
+ print("The value ", x, " Not found")
diff --git a/algorithms/data-structures/hashs/hash_table.py b/algorithms/data-structures/hashs/hash_table.py
new file mode 100644
index 0000000..daa12d9
--- /dev/null
+++ b/algorithms/data-structures/hashs/hash_table.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python3
+from number_theory.prime_numbers import next_prime
+
+class HashTable:
+
+ def __init__(self, size_table, charge_factor=None, lim_charge=None):
+ self.size_table = size_table
+ self.values = [None] * self.size_table
+ self.lim_charge = 0.75 if lim_charge is None else lim_charge
+ self.charge_factor = 1 if charge_factor is None else charge_factor
+ self.__aux_list = []
+ self._keys = {}
+
+ def keys(self):
+ return self._keys
+
+ def balanced_factor(self):
+ return sum([1 for slot in self.values
+ if slot is not None]) / (self.size_table * self.charge_factor)
+
+ def hash_function(self, key):
+ return key % self.size_table
+
+ def _step_by_step(self, step_ord):
+
+ print("step {0}".format(step_ord))
+ print([i for i in range(len(self.values))])
+ print(self.values)
+
+ def bulk_insert(self, values):
+ i = 1
+ self.__aux_list = values
+ for value in values:
+ self.insert_data(value)
+ self._step_by_step(i)
+ i += 1
+
+ def _set_value(self, key, data):
+ self.values[key] = data
+ self._keys[key] = data
+
+ def _colision_resolution(self, key, data=None):
+ new_key = self.hash_function(key + 1)
+
+ while self.values[new_key] is not None \
+ and self.values[new_key] != key:
+
+ if self.values.count(None) > 0:
+ new_key = self.hash_function(new_key + 1)
+ else:
+ new_key = None
+ break
+
+ return new_key
+
+ def rehashing(self):
+ survivor_values = [value for value in self.values if value is not None]
+ self.size_table = next_prime(self.size_table, factor=2)
+ self._keys.clear()
+ self.values = [None] * self.size_table #hell's pointers D: don't DRY ;/
+ map(self.insert_data, survivor_values)
+
+ def insert_data(self, data):
+ key = self.hash_function(data)
+
+ if self.values[key] is None:
+ self._set_value(key, data)
+
+ elif self.values[key] == data:
+ pass
+
+ else:
+ colision_resolution = self._colision_resolution(key, data)
+ if colision_resolution is not None:
+ self._set_value(colision_resolution, data)
+ else:
+ self.rehashing()
+ self.insert_data(data)
+
+
diff --git a/algorithms/data-structures/linked-lists/linked_list.py b/algorithms/data-structures/linked-lists/linked_list.py
new file mode 100644
index 0000000..f311c36
--- /dev/null
+++ b/algorithms/data-structures/linked-lists/linked_list.py
@@ -0,0 +1,25 @@
+# Python Implementation of a Linked List
+
+class Node(object):
+ def __init__(self, value):
+ super(Node, self).__init__()
+
+ self._value = value
+ self._next = None
+
+ def traverse(self):
+ node = self
+ while node:
+ print(node._value)
+ node = node._next
+
+### Test ###
+
+node_1 = Node(123)
+node_2 = Node('abc')
+node_3 = Node('Linked List')
+
+node_1._next = node_2
+node_2._next = node_3
+
+node_1.traverse()
diff --git a/algorithms/data-structures/stack/stack.py b/algorithms/data-structures/stack/stack.py
new file mode 100644
index 0000000..6865245
--- /dev/null
+++ b/algorithms/data-structures/stack/stack.py
@@ -0,0 +1,30 @@
+'''
+ Created by Luiz Guerra
+ My github github.com/LuizGuerra
+'''
+
+class Stack:
+
+ def __init__ (.self):
+ head = null
+ count = 0
+
+ def append(.self, e):
+ n = Node(e)
+ if count == 0:
+ head = n
+ count += 1
+ else:
+ n.next = head.next
+ head = n
+
+ def pop(.self):
+ n = head
+ head = head.next
+ return n.element
+
+
+class Node (e):
+ __init__ (.self, e):
+ next = null
+ element = e
diff --git a/algorithms/data-structures/stacks/node.py b/algorithms/data-structures/stacks/node.py
new file mode 100644
index 0000000..757368c
--- /dev/null
+++ b/algorithms/data-structures/stacks/node.py
@@ -0,0 +1,30 @@
+class Node:
+
+ def __init__(self,item,next=None):
+ self.item = item
+ self.next = next
+
+ def __str__(self):
+ string = '[' + str(self.item) + ']'
+ next = self.next
+
+ while next:
+ if next:
+ string += ' -> ' + str(next)
+ next = next.get_next()
+
+ return string
+
+
+ def get_item(self):
+ return self.item
+
+ def get_next(self):
+ return self.next
+
+ def set_item(self,item):
+ self.item = item
+
+ def set_next(self,next):
+ self.next = next
+
diff --git a/algorithms/data-structures/stacks/stack.py b/algorithms/data-structures/stacks/stack.py
new file mode 100644
index 0000000..085e7b6
--- /dev/null
+++ b/algorithms/data-structures/stacks/stack.py
@@ -0,0 +1,56 @@
+from node import Node
+
+class Stack:
+
+ def __init__(self):
+ self.head = None
+
+ def __str__(self):
+ node = self.head
+ list = []
+ while node:
+ list.append(node.get_item())
+ node = node.get_next()
+ return str(list)
+
+ def is_empty(self):
+ return not self.head
+
+ def push(self, item):
+ if not self.head:
+ self.head = Node(item)
+ else:
+ self.head = Node(item,self.head)
+
+ def pop(self):
+ if not self.head:
+ raise EmptyStackException('Cannot pop from a empty stack')
+ else:
+ item = self.head.get_item()
+
+ if self.head.get_next():
+ self.head = self.head.get_next()
+
+ else:
+ self.head = None
+
+ return item
+
+
+ def peek(self):
+ if not self.head:
+ raise EmptyStackException('Cannot peek from an empty stack')
+ else:
+ return self.head.get_item()
+
+ def size(self):
+ count = 0
+ node = self.head
+ while node:
+ count += 1
+ node = node.get_next()
+ return count
+
+
+class EmptyStackException(Exception):
+ pass
\ No newline at end of file
diff --git a/algorithms/data-structures/stacks/stacks.py b/algorithms/data-structures/stacks/stacks.py
new file mode 100644
index 0000000..22d90bd
--- /dev/null
+++ b/algorithms/data-structures/stacks/stacks.py
@@ -0,0 +1,17 @@
+myStack = []
+
+myStack.append('a')
+myStack.append('b')
+myStack.append('c')
+
+myStack
+
+
+myStack.pop()
+
+myStack.pop()
+
+myStack.pop()
+
+
+myStack.pop()
\ No newline at end of file
diff --git a/algorithms/data-structures/stacks/test_node.py b/algorithms/data-structures/stacks/test_node.py
new file mode 100644
index 0000000..7f57f83
--- /dev/null
+++ b/algorithms/data-structures/stacks/test_node.py
@@ -0,0 +1,29 @@
+import unittest
+from node import Node
+
+class TestNode(unittest.TestCase):
+
+ def setUp(self):
+ self.next_node = Node('item 2')
+ self.node = Node('item 1',self.next_node)
+
+ def test_str(self):
+ self.assertEqual(str(self.node),'[item 1] -> [item 2]')
+
+ def test_get_item(self):
+ self.assertEqual(self.node.get_item(),'item 1')
+
+ def test_get_next(self):
+ self.assertIs(self.node.get_next(),self.next_node)
+
+ def test_set_item(self):
+ self.node.set_item('another item')
+ self.assertEqual(self.node.get_item(),'another item')
+
+ def test_set_next(self):
+ another_node = Node('another item')
+ self.node.set_next(another_node)
+ self.assertIs(self.node.get_next(),another_node)
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/algorithms/data-structures/stacks/test_stack.py b/algorithms/data-structures/stacks/test_stack.py
new file mode 100644
index 0000000..bcadbae
--- /dev/null
+++ b/algorithms/data-structures/stacks/test_stack.py
@@ -0,0 +1,53 @@
+import unittest
+from stack import Stack, EmptyStackException
+
+class TestStack(unittest.TestCase):
+
+ def setUp(self):
+ self.stack = Stack()
+
+ def test_is_empty(self):
+ self.assertTrue(self.stack.is_empty())
+
+ def test_str_and_push(self):
+ self.stack.push(6)
+ self.assertEqual(str(self.stack),"[6]")
+
+ def test_push_three_elements(self):
+ self.stack.push(3)
+ self.stack.push(2)
+ self.stack.push(1)
+ self.assertEqual(str(self.stack),"[1, 2, 3]")
+
+ def test_pop_exception(self):
+ with self.assertRaises(EmptyStackException):
+ self.stack.pop()
+
+ def test_pop_with_one_element(self):
+ self.stack.push("Item")
+ self.assertEqual(self.stack.pop(),"Item")
+ self.assertTrue(self.stack.is_empty())
+
+ def test_pop_with_two_elements(self):
+ self.stack.push(2)
+ self.stack.push(1)
+ self.assertEqual(self.stack.pop(),1)
+ self.assertEqual(str(self.stack),'[2]')
+
+ def test_peek_exception(self):
+ with self.assertRaises(EmptyStackException):
+ self.stack.peek()
+
+ def test_peek(self):
+ self.stack.push(1)
+ self.assertEqual(self.stack.peek(),1)
+
+ def test_size(self):
+ self.assertEqual(self.stack.size(),0)
+ self.stack.push(1)
+ self.stack.push(2)
+ self.stack.push(3)
+ self.assertEqual(self.stack.size(),3)
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/algorithms/data-structures/trees/avl.py b/algorithms/data-structures/trees/avl.py
new file mode 100644
index 0000000..d77692b
--- /dev/null
+++ b/algorithms/data-structures/trees/avl.py
@@ -0,0 +1,178 @@
+from __future__ import print_function
+
+
+class Node:
+
+ def __init__(self, label):
+ self.label = label
+ self._parent = None
+ self._left = None
+ self._right = None
+ self.height = 0
+
+ @property
+ def right(self):
+ return self._right
+
+ @right.setter
+ def right(self, node):
+ if node is not None:
+ node._parent = self
+ self._right = node
+
+ @property
+ def left(self):
+ return self._left
+
+ @left.setter
+ def left(self, node):
+ if node is not None:
+ node._parent = self
+ self._left = node
+
+ @property
+ def parent(self):
+ return self._parent
+
+ @parent.setter
+ def parent(self, node):
+ if node is not None:
+ self._parent = node
+ self.height = self.parent.height + 1
+ else:
+ self.height = 0
+
+
+class AVL:
+
+ def __init__(self):
+ self.root = None
+ self.size = 0
+
+ def insert(self, value):
+ node = Node(value)
+
+ if self.root is None:
+ self.root = node
+ self.root.height = 0
+ self.size = 1
+ else:
+ # Same as Binary Tree
+ dad_node = None
+ curr_node = self.root
+
+ while True:
+ if curr_node is not None:
+
+ dad_node = curr_node
+
+ if node.label < curr_node.label:
+ curr_node = curr_node.left
+ else:
+ curr_node = curr_node.right
+ else:
+ node.height = dad_node.height
+ dad_node.height += 1
+ if node.label < dad_node.label:
+ dad_node.left = node
+ else:
+ dad_node.right = node
+ self.rebalance(node)
+ self.size += 1
+ break
+
+ def rebalance(self, node):
+ n = node
+
+ while n is not None:
+ height_right = n.height
+ height_left = n.height
+
+ if n.right is not None:
+ height_right = n.right.height
+
+ if n.left is not None:
+ height_left = n.left.height
+
+ if abs(height_left - height_right) > 1:
+ if height_left > height_right:
+ left_child = n.left
+ if left_child is not None:
+ h_right = (left_child.right.height
+ if (left_child.right is not None) else 0)
+ h_left = (left_child.left.height
+ if (left_child.left is not None) else 0)
+ if (h_left > h_right):
+ self.rotate_left(n)
+ break
+ else:
+ self.double_rotate_right(n)
+ break
+ else:
+ right_child = n.right
+ if right_child is not None:
+ h_right = (right_child.right.height
+ if (right_child.right is not None) else 0)
+ h_left = (right_child.left.height
+ if (right_child.left is not None) else 0)
+ if (h_left > h_right):
+ self.double_rotate_left(n)
+ break
+ else:
+ self.rotate_right(n)
+ break
+ n = n.parent
+
+ def rotate_left(self, node):
+ aux = node.parent.label
+ node.parent.label = node.label
+ node.parent.right = Node(aux)
+ node.parent.right.height = node.parent.height + 1
+ node.parent.left = node.right
+
+
+ def rotate_right(self, node):
+ aux = node.parent.label
+ node.parent.label = node.label
+ node.parent.left = Node(aux)
+ node.parent.left.height = node.parent.height + 1
+ node.parent.right = node.right
+
+ def double_rotate_left(self, node):
+ self.rotate_right(node.getRight().getRight())
+ self.rotate_left(node)
+
+ def double_rotate_right(self, node):
+ self.rotate_left(node.getLeft().getLeft())
+ self.rotate_right(node)
+
+ def empty(self):
+ if self.root is None:
+ return True
+ return False
+
+ def preShow(self, curr_node):
+ if curr_node is not None:
+ self.preShow(curr_node.left)
+ print(curr_node.label, end=" ")
+ self.preShow(curr_node.right)
+
+ def preorder(self, curr_node):
+ if curr_node is not None:
+ self.preShow(curr_node.left)
+ self.preShow(curr_node.right)
+ print(curr_node.label, end=" ")
+
+ def getRoot(self):
+ return self.root
+
+t = AVL()
+t.insert(1)
+t.insert(2)
+t.insert(3)
+# t.preShow(t.root)
+# print("\n")
+# t.insert(4)
+# t.insert(5)
+# t.preShow(t.root)
+# t.preorden(t.root)
diff --git a/algorithms/data-structures/trees/binary_search_tree.py b/algorithms/data-structures/trees/binary_search_tree.py
new file mode 100644
index 0000000..1ceb107
--- /dev/null
+++ b/algorithms/data-structures/trees/binary_search_tree.py
@@ -0,0 +1,237 @@
+from __future__ import print_function
+class Node:
+
+ def __init__(self, label, parent):
+ self.label = label
+ self.left = None
+ self.right = None
+ #Added in order to delete a node easier
+ self.parent = parent
+
+ def getLabel(self):
+ return self.label
+
+ def setLabel(self, label):
+ self.label = label
+
+ def getLeft(self):
+ return self.left
+
+ def setLeft(self, left):
+ self.left = left
+
+ def getRight(self):
+ return self.right
+
+ def setRight(self, right):
+ self.right = right
+
+ def getParent(self):
+ return self.parent
+
+ def setParent(self, parent):
+ self.parent = parent
+
+class BinarySearchTree:
+
+ def __init__(self):
+ self.root = None
+
+ def insert(self, label):
+ # Create a new Node
+ new_node = Node(label, None)
+ # If Tree is empty
+ if self.empty():
+ self.root = new_node
+ else:
+ #If Tree is not empty
+ curr_node = self.root
+ #While we don't get to a leaf
+ while curr_node is not None:
+ #We keep reference of the parent node
+ parent_node = curr_node
+ #If node label is less than current node
+ if new_node.getLabel() < curr_node.getLabel():
+ #We go left
+ curr_node = curr_node.getLeft()
+ else:
+ #Else we go right
+ curr_node = curr_node.getRight()
+ #We insert the new node in a leaf
+ if new_node.getLabel() < parent_node.getLabel():
+ parent_node.setLeft(new_node)
+ else:
+ parent_node.setRight(new_node)
+ #Set parent to the new node
+ new_node.setParent(parent_node)
+
+ def delete(self, label):
+ if (not self.empty()):
+ #Look for the node with that label
+ node = self.getNode(label)
+ #If the node exists
+ if(node is not None):
+ #If it has no children
+ if(node.getLeft() is None and node.getRight() is None):
+ self.__reassignNodes(node, None)
+ node = None
+ #Has only right children
+ elif(node.getLeft() is None and node.getRight() is not None):
+ self.__reassignNodes(node, node.getRight())
+ #Has only left children
+ elif(node.getLeft() is not None and node.getRight() is None):
+ self.__reassignNodes(node, node.getLeft())
+ #Has two children
+ else:
+ #Gets the max value of the left branch
+ tmpNode = self.getMax(node.getLeft())
+ #Deletes the tmpNode
+ self.delete(tmpNode.getLabel())
+ #Assigns the value to the node to delete and keesp tree structure
+ node.setLabel(tmpNode.getLabel())
+
+ def getNode(self, label):
+ curr_node = None
+ #If the tree is not empty
+ if(not self.empty()):
+ #Get tree root
+ curr_node = self.getRoot()
+ #While we don't find the node we look for
+ #I am using lazy evaluation here to avoid NoneType Attribute error
+ while curr_node is not None and curr_node.getLabel() is not label:
+ #If node label is less than current node
+ if label < curr_node.getLabel():
+ #We go left
+ curr_node = curr_node.getLeft()
+ else:
+ #Else we go right
+ curr_node = curr_node.getRight()
+ return curr_node
+
+ def getMax(self, root = None):
+ if(root is not None):
+ curr_node = root
+ else:
+ #We go deep on the right branch
+ curr_node = self.getRoot()
+ if(not self.empty()):
+ while(curr_node.getRight() is not None):
+ curr_node = curr_node.getRight()
+ return curr_node
+
+ def getMin(self, root = None):
+ if(root is not None):
+ curr_node = root
+ else:
+ #We go deep on the left branch
+ curr_node = self.getRoot()
+ if(not self.empty()):
+ curr_node = self.getRoot()
+ while(curr_node.getLeft() is not None):
+ curr_node = curr_node.getLeft()
+ return curr_node
+
+ def empty(self):
+ if self.root is None:
+ return True
+ return False
+
+ def __InOrderTraversal(self, curr_node):
+ nodeList = []
+ if curr_node is not None:
+ nodeList.insert(0, curr_node)
+ nodeList = nodeList + self.__InOrderTraversal(curr_node.getLeft())
+ nodeList = nodeList + self.__InOrderTraversal(curr_node.getRight())
+ return nodeList
+
+ def getRoot(self):
+ return self.root
+
+ def __isRightChildren(self, node):
+ if(node == node.getParent().getRight()):
+ return True
+ return False
+
+ def __reassignNodes(self, node, newChildren):
+ if(newChildren is not None):
+ newChildren.setParent(node.getParent())
+ if(node.getParent() is not None):
+ #If it is the Right Children
+ if(self.__isRightChildren(node)):
+ node.getParent().setRight(newChildren)
+ else:
+ #Else it is the left children
+ node.getParent().setLeft(newChildren)
+
+ #This function traversal the tree. By default it returns an
+ #In order traversal list. You can pass a function to traversal
+ #The tree as needed by client code
+ def traversalTree(self, traversalFunction = None, root = None):
+ if(traversalFunction is None):
+ #Returns a list of nodes in preOrder by default
+ return self.__InOrderTraversal(self.root)
+ else:
+ #Returns a list of nodes in the order that the users wants to
+ return traversalFunction(self.root)
+
+ #Returns an string of all the nodes labels in the list
+ #In Order Traversal
+ def __str__(self):
+ list = self.__InOrderTraversal(self.root)
+ str = ""
+ for x in list:
+ str = str + " " + x.getLabel().__str__()
+ return str
+
+def InPreOrder(curr_node):
+ nodeList = []
+ if curr_node is not None:
+ nodeList = nodeList + InPreOrder(curr_node.getLeft())
+ nodeList.insert(0, curr_node.getLabel())
+ nodeList = nodeList + InPreOrder(curr_node.getRight())
+ return nodeList
+
+def testBinarySearchTree():
+ t = BinarySearchTree()
+ t.insert(8)
+ t.insert(3)
+ t.insert(6)
+ t.insert(1)
+ t.insert(10)
+ t.insert(14)
+ t.insert(13)
+ t.insert(4)
+ t.insert(7)
+
+ #Prints all the elements of the list in order traversal
+ print(t.__str__())
+
+ if(t.getNode(6) is not None):
+ print("The label 6 exists")
+ else:
+ print("The label 6 doesn't exist")
+
+ if(t.getNode(-1) is not None):
+ print("The label -1 exists")
+ else:
+ print("The label -1 doesn't exist")
+
+ if(not t.empty()):
+ print(("Max Value: ", t.getMax().getLabel()))
+ print(("Min Value: ", t.getMin().getLabel()))
+
+ t.delete(13)
+ t.delete(10)
+ t.delete(8)
+ t.delete(3)
+ t.delete(6)
+ t.delete(14)
+
+ #Gets all the elements of the tree In pre order
+ #And it prints them
+ list = t.traversalTree(InPreOrder, t.root)
+ for x in list:
+ print(x)
+
+if __name__ == "__main__":
+ testBinarySearchTree()
diff --git a/algorithms/data-structures/trees/heap.py b/algorithms/data-structures/trees/heap.py
new file mode 100644
index 0000000..e66d02b
--- /dev/null
+++ b/algorithms/data-structures/trees/heap.py
@@ -0,0 +1,90 @@
+#!/usr/bin/python
+
+from __future__ import print_function
+
+try:
+ raw_input # Python 2
+except NameError:
+ raw_input = input # Python 3
+
+class Heap:
+ def __init__(self):
+ self.h = []
+ self.currsize = 0
+
+ def leftChild(self,i):
+ if 2*i+1 < self.currsize:
+ return 2*i+1
+ return None
+
+ def rightChild(self,i):
+ if 2*i+2 < self.currsize:
+ return 2*i+2
+ return None
+
+ def maxHeapify(self,node):
+ if node < self.currsize:
+ m = node
+ lc = self.leftChild(node)
+ rc = self.rightChild(node)
+ if lc is not None and self.h[lc] > self.h[m]:
+ m = lc
+ if rc is not None and self.h[rc] > self.h[m]:
+ m = rc
+ if m!=node:
+ temp = self.h[node]
+ self.h[node] = self.h[m]
+ self.h[m] = temp
+ self.maxHeapify(m)
+
+ def buildHeap(self,a):
+ self.currsize = len(a)
+ self.h = list(a)
+ for i in range(self.currsize/2,-1,-1):
+ self.maxHeapify(i)
+
+ def getMax(self):
+ if self.currsize >= 1:
+ me = self.h[0]
+ temp = self.h[0]
+ self.h[0] = self.h[self.currsize-1]
+ self.h[self.currsize-1] = temp
+ self.currsize -= 1
+ self.maxHeapify(0)
+ return me
+ return None
+
+ def heapSort(self):
+ size = self.currsize
+ while self.currsize-1 >= 0:
+ temp = self.h[0]
+ self.h[0] = self.h[self.currsize-1]
+ self.h[self.currsize-1] = temp
+ self.currsize -= 1
+ self.maxHeapify(0)
+ self.currsize = size
+
+ def insert(self,data):
+ self.h.append(data)
+ curr = self.currsize
+ self.currsize+=1
+ while self.h[curr] > self.h[curr/2]:
+ temp = self.h[curr/2]
+ self.h[curr/2] = self.h[curr]
+ self.h[curr] = temp
+ curr = curr/2
+
+ def display(self):
+ print(self.h)
+
+def main():
+ l = list(map(int, raw_input().split()))
+ h = Heap()
+ h.buildHeap(l)
+ h.heapSort()
+ h.display()
+
+if __name__=='__main__':
+ main()
+
+
diff --git a/algorithms/data-structures/trees/lowest_common_ancestor.py b/algorithms/data-structures/trees/lowest_common_ancestor.py
new file mode 100644
index 0000000..0b60686
--- /dev/null
+++ b/algorithms/data-structures/trees/lowest_common_ancestor.py
@@ -0,0 +1,112 @@
+# -*- coding: UTF-8 -*-
+#
+# Lowest Common Ancestor
+# The All ▲lgorithms library for python
+#
+# Contributed by: Anish Narkhede
+# Github: @anish03
+#
+class Node:
+ def __init__(self,data):
+ self.data = data
+ self.left = None
+ self.right = None
+
+class BST:
+ def __init__(self):
+ self.root = None
+
+ def getRoot(self):
+ return self.root
+
+ def add(self,data):
+ if not self.root:
+ self.root = Node(data)
+ else:
+ self._add(data,self.root)
+
+ def _add(self,data,node):
+ if data <= node.data:
+ if node.left:
+ self._add(data,node.left)
+ else:
+ node.left = Node(data)
+ else:
+ if node.right:
+ self._add(data,node.right)
+ else:
+ node.right = Node(data)
+
+ def find(self,data):
+ if self.root:
+ self._find(data,self.root)
+ else:
+ return None
+
+ def _find(data,node):
+ if data == node.data:
+ return node
+ elif node.left and data <= node.data:
+ return self._find(data,node.left)
+ elif node.right and data > node.data:
+ return self._find(data,node.right)
+
+ def inorder(self,node):
+ if node:
+ self.inorder(node.left)
+ print node.data
+ self.inorder(node.right)
+
+ def get_height(self,node):
+ if not node:
+ return 0
+ else:
+ i = max(self.get_height(node.left),self.get_height(node.right)) + 1
+ return i
+
+ def find_path(self,root,path,k):
+ if not root:
+ return False
+
+ path.append(root.data)
+
+ if root.data == k:
+ return True
+
+ if (root.left and self.find_path(root.left,path,k) or root.right and self.find_path(root.right,path,k)):
+ return True
+
+ path.pop()
+ return False
+
+ def Driver(self,root,n1,n2):
+ path1,path2 = [],[]
+
+ if (not self.find_path(root,path1,n1) or not self.find_path(root,path2,n2)):
+ return -1
+
+ i = 0
+ while i < len(path1) and i < len(path2):
+ if path1[i] != path2[i]:
+ break
+ i += 1
+ return path1[i-1]
+
+def main():
+
+ B = BST()
+
+ B.add(8)
+ B.add(3)
+ B.add(10)
+ B.add(1)
+ B.add(6)
+ B.add(14)
+ B.add(4)
+ B.add(7)
+ B.add(13)
+
+ print B.Driver(B.root,1,6)
+
+if __name__ == '__main__':
+ main()
diff --git a/algorithms/data-structures/trees/min_height_bst.py b/algorithms/data-structures/trees/min_height_bst.py
new file mode 100644
index 0000000..ad4e6fc
--- /dev/null
+++ b/algorithms/data-structures/trees/min_height_bst.py
@@ -0,0 +1,84 @@
+class Node:
+ def __init__(self,data):
+ self.data = data
+ self.left = None
+ self.right = None
+
+class BST:
+ def __init__(self):
+ self.root = None
+
+ def getRoot(self):
+ return self.root
+
+ def add(self,data):
+ if not self.root:
+ self.root = Node(data)
+ else:
+ self._add(data,self.root)
+
+ def _add(self,data,node):
+ if data <= node.data:
+ if node.left:
+ self._add(data,node.left)
+ else:
+ node.left = Node(data)
+ else:
+ if node.right:
+ self._add(data,node.right)
+ else:
+ node.right = Node(data)
+
+ def find(self,data):
+ if self.root:
+ self._find(data,self.root)
+ else:
+ return None
+
+ def _find(data,node):
+ if data == node.data:
+ return node
+ elif node.left and data <= node.data:
+ return self._find(data,node.left)
+ elif node.right and data > node.data:
+ return self._find(data,node.right)
+
+ def inorder(self,node):
+ if node:
+ self.inorder(node.left)
+ print node.data
+ self.inorder(node.right)
+
+
+ def create_min_bst(self,arr,start,end):
+ if end < start:
+ return
+ mid = (start+end) / 2
+ node = Node(arr[mid])
+ self.add(node.data)
+ print 'adding node: ',node.data
+ node.left = self.create_min_bst(arr,start,mid-1)
+ node.right = self.create_min_bst(arr,mid+1,end)
+
+ def get_height(self,node):
+ if not node:
+ return 0
+ else:
+ i = max(self.get_height(node.left),self.get_height(node.right)) + 1
+ return i
+
+ def validate_bst(self):
+ root = self.root
+ diff = abs(self.get_height(root.left) - self.get_height(root.right))
+ return diff
+
+def main():
+ B = BST()
+ nodes = [1,2,3,4,5,6,7]
+ B.create_min_bst(nodes,0,len(nodes)-1)
+ B.inorder(B.root)
+
+ print B.validate_bst()
+
+if __name__ == '__main__':
+ main()
diff --git a/algorithms/data-structures/trees/size_of_subtree.py b/algorithms/data-structures/trees/size_of_subtree.py
new file mode 100644
index 0000000..eb594f0
--- /dev/null
+++ b/algorithms/data-structures/trees/size_of_subtree.py
@@ -0,0 +1,28 @@
+"""
+ This is an efficient algorithm to find the size of a subtree from every node in O(n) time.
+ The idea is to use one dfs and first calculate the size of subtree of children of a node recursively.
+ Then add the size of each subtree of its children to get the size of its subtree.
+"""
+from collections import defaultdict as dd
+
+
+def dfs(source, parent):
+ # Initial size of root is 1
+ size[source] = 1
+ for child in graph[source]:
+ if child != parent:
+ # Recursively calculate size of subtree of children nodes
+ dfs(child, source)
+ # Adding size of each child's subtree.
+ size[source] += size[child]
+
+
+size = dd(int)
+graph = dd(set)
+n = int(input())
+for i in range(n-1):
+ u, v = map(int, input().split())
+ graph[u].add(v)
+ graph[v].add(u)
+dfs(1, 0)
+print(size)
diff --git a/algorithms/data-structures/trie/trie.py b/algorithms/data-structures/trie/trie.py
new file mode 100644
index 0000000..13f5568
--- /dev/null
+++ b/algorithms/data-structures/trie/trie.py
@@ -0,0 +1,40 @@
+class trienode:
+ def __init__(self,character):
+ self.character = character
+ self.nextnodes = {}
+ self.isEnd = False
+ self.dataNode = None
+
+class trie: # use case: username/password
+ def __init__(self):
+ self.start = trienode('')
+ def insert(self,id,value): # returns true on successful insertion (value == password)
+ temp = self.start
+ for nextChar in id:
+ temp.nextnodes[nextChar] = temp.nextnodes.get(nextChar,trienode(nextChar))
+ temp = temp.nextnodes[nextChar]
+ if temp.isEnd == True:
+ print("ID already Exists!!")
+ return False
+ temp.isEnd =True
+ temp.dataNode = value
+ return True
+ def findNode(self,id): # returns false if node doesn't exist and true, node if it does
+ temp = self.start
+ for nextChar in id:
+ next = temp.nextnodes.get(nextChar,None)
+ if next is None:
+ return False,None
+ temp = next
+ if temp.isEnd == True:
+ return True,temp
+ else:
+ return False,None
+
+if __name__ == '__main__':
+ t = trie()
+ t.insert('test1',"dummy1")
+ t.insert('test2',"dummy2")
+ print(t.findNode('test')) # (false,None)
+ a,b = t.findNode('test1')
+ print(a,b.dataNode) # true,dummy1
\ No newline at end of file
diff --git a/algorithms/divide-and-conquer/mergesort.py b/algorithms/divide-and-conquer/mergesort.py
new file mode 100644
index 0000000..05e5a0b
--- /dev/null
+++ b/algorithms/divide-and-conquer/mergesort.py
@@ -0,0 +1,26 @@
+def merge(left_subarray,right_subarray):
+ i,j = 0,0
+ result = []
+
+ while i= 0 else 0
+
+ # Count of solutions excluding S[j]
+ y = table[i][j-1] if j >= 1 else 0
+
+ # total count
+ table[i][j] = x + y
+
+ return table[n][m-1]
+
+# Driver program to test above function
+arr = [1, 2, 3]
+m = len(arr)
+n = 4
+print(count(arr, m, n))
\ No newline at end of file
diff --git a/algorithms/dynamic-programming/edit_distance.py b/algorithms/dynamic-programming/edit_distance.py
new file mode 100644
index 0000000..15130a7
--- /dev/null
+++ b/algorithms/dynamic-programming/edit_distance.py
@@ -0,0 +1,39 @@
+from __future__ import print_function
+
+
+class EditDistance:
+
+ def __init__(self):
+ self.__prepare__()
+
+ def __prepare__(self, N = 0, M = 0):
+ self.dp = [[-1 for y in range(0,M)] for x in range(0,N)]
+
+ def __solveDP(self, x, y):
+ if (x==-1):
+ return y+1
+ elif (y==-1):
+ return x+1
+ elif (self.dp[x][y]>-1):
+ return self.dp[x][y]
+ else:
+ if (self.A[x]==self.B[y]):
+ self.dp[x][y] = self.__solveDP(x-1,y-1)
+ else:
+ self.dp[x][y] = 1+min(self.__solveDP(x,y-1), self.__solveDP(x-1,y), self.__solveDP(x-1,y-1))
+
+ return self.dp[x][y]
+
+ def solve(self, A, B):
+ if isinstance(A,bytes):
+ A = A.decode('ascii')
+
+ if isinstance(B,bytes):
+ B = B.decode('ascii')
+
+ self.A = str(A)
+ self.B = str(B)
+
+ self.__prepare__(len(A), len(B))
+
+ return self.__solveDP(len(A)-1, len(B)-1)
diff --git a/algorithms/dynamic-programming/kadanes_algorithm.py b/algorithms/dynamic-programming/kadanes_algorithm.py
new file mode 100644
index 0000000..04cf630
--- /dev/null
+++ b/algorithms/dynamic-programming/kadanes_algorithm.py
@@ -0,0 +1,27 @@
+def Kadane(array):
+ partialSum = bestSum = array[0]
+ fromIndex = toIndex = 0
+
+ for i in range(1, len(array)):
+ if array[i] > partialSum + array[i]:
+ partialSum = array[i]
+ fromIndex = i
+ else:
+ partialSum += array[i]
+
+ if partialSum >= bestSum:
+ bestSum = partialSum
+ toIndex = i
+
+ return {
+ "fromIndex" : fromIndex,
+ "toIndex" : toIndex,
+ "bestSum" : bestSum
+ }
+
+n = int(input("Enter the size of the array: "))
+print("Input the array")
+array = map(int,raw_input().split())
+
+kadane = Kadane(array)
+print("Sum: %d From: %d To: %d" % (kadane['bestSum'], kadane['fromIndex'], kadane['toIndex']))
\ No newline at end of file
diff --git a/algorithms/dynamic-programming/knapsack.py b/algorithms/dynamic-programming/knapsack.py
new file mode 100644
index 0000000..1c4b329
--- /dev/null
+++ b/algorithms/dynamic-programming/knapsack.py
@@ -0,0 +1,23 @@
+# A Dynamic Programming based Python Program for 0-1 Knapsack problem
+# Returns the maximum value that can be put in a knapsack of capacity W
+def knapSack(W, wt, val, n):
+ K = [[0 for x in range(W+1)] for x in range(n+1)]
+
+ # Build table K[][] in bottom up manner
+ for i in range(n+1):
+ for w in range(W+1):
+ if i==0 or w==0:
+ K[i][w] = 0
+ elif wt[i-1] <= w:
+ K[i][w] = max(val[i-1] + K[i-1][w-wt[i-1]], K[i-1][w])
+ else:
+ K[i][w] = K[i-1][w]
+
+ return K[n][W]
+
+# Driver program to test above function
+val = [60, 100, 120]
+wt = [10, 20, 30]
+W = 50
+n = len(val)
+print(knapSack(W, wt, val, n))
\ No newline at end of file
diff --git a/algorithms/dynamic-programming/lcs.py b/algorithms/dynamic-programming/lcs.py
new file mode 100644
index 0000000..8b24b92
--- /dev/null
+++ b/algorithms/dynamic-programming/lcs.py
@@ -0,0 +1,28 @@
+# Dynamic Programming implementation of LCS problem
+
+def lcs(X , Y):
+ # find the length of the strings
+ m = len(X)
+ n = len(Y)
+
+ # declaring the array for storing the dp values
+ L = [[None]*(n+1) for i in xrange(m+1)]
+
+ for i in range(m+1):
+ for j in range(n+1):
+ if i == 0 or j == 0 :
+ L[i][j] = 0
+ elif X[i-1] == Y[j-1]:
+ L[i][j] = L[i-1][j-1]+1
+ else:
+ L[i][j] = max(L[i-1][j] , L[i][j-1])
+
+ # L[m][n] contains the length of LCS of X[0..n-1] & Y[0..m-1]
+ return L[m][n]
+#end of function lcs
+
+
+# Driver program to test the above function
+X = "AGGTAB"
+Y = "GXTXAYB"
+print "Length of LCS is ", lcs(X, Y)
\ No newline at end of file
diff --git a/algorithms/dynamic-programming/longest_increasing_subsequence.py b/algorithms/dynamic-programming/longest_increasing_subsequence.py
new file mode 100644
index 0000000..ad1fd42
--- /dev/null
+++ b/algorithms/dynamic-programming/longest_increasing_subsequence.py
@@ -0,0 +1,31 @@
+# Dynamic programming Python implementation of LIS problem
+
+# lis returns length of the longest increasing subsequence
+# in arr of size n
+def lis(arr):
+ n = len(arr)
+
+ # Declare the list (array) for LIS and initialize LIS
+ # values for all indexes
+ lis = [1]*n
+
+ # Compute optimized LIS values in bottom up manner
+ for i in range (1 , n):
+ for j in range(0 , i):
+ if arr[i] > arr[j] and lis[i]< lis[j] + 1 :
+ lis[i] = lis[j]+1
+
+ # Initialize maximum to 0 to get the maximum of all
+ # LIS
+ maximum = 0
+
+ # Pick maximum of all LIS values
+ for i in range(n):
+ maximum = max(maximum , lis[i])
+
+ return maximum
+# end of lis function
+
+# Driver program to test above function
+arr = [10, 22, 9, 33, 21, 50, 41, 60]
+print "Length of lis is", lis(arr)
\ No newline at end of file
diff --git a/algorithms/dynamic-programming/matrix_chain_multiplication.py b/algorithms/dynamic-programming/matrix_chain_multiplication.py
new file mode 100644
index 0000000..f0c73a5
--- /dev/null
+++ b/algorithms/dynamic-programming/matrix_chain_multiplication.py
@@ -0,0 +1,39 @@
+# Python program to solve Matrix chain multiplication using Dynamic Programming
+# MatrixChain returns the minimum number of scalar multiplications needed to
+# Compute the product of the chain
+import sys
+# Matrix Ai has dimension p[i-1] x p[i] for i = 1..n
+def MatrixChain(p, n):
+ # For simplicity of the program, one extra row and one
+ # extra column are allocated in m[][]. 0th row and 0th
+ # column of m[][] are not used
+ m = [[0 for x in range(n)] for x in range(n)]
+
+ # m[i, j] = Minimum number of scalar multiplications needed
+ # to compute the matrix A[i]A[i + 1]...A[j] = A[i..j] where
+ # dimension of A[i] is p[i-1] x p[i]
+
+ # cost is zero when multiplying one matrix.
+ for i in range(1, n):
+ m[i][i] = 0
+
+ # L is chain length.
+ for L in range(2, n):
+ for i in range(1, n-L + 1):
+ j = i + L-1
+ m[i][j] = sys.maxsize # sys.maxsize is a very large integer value (Refer https://stackoverflow.com/questions/48138632/in-python-what-is-sys-maxsize for more details if intrested)
+ for k in range(i, j):
+
+ # q = cost / scalar multiplications
+ q = m[i][k] + m[k + 1][j] + p[i-1]*p[k]*p[j]
+ if q < m[i][j]:
+ m[i][j] = q
+
+ return m[1][n-1]
+
+# Program to test above function
+arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+size = len(arr)
+
+print("Minimum number of multiplications is " +
+ str(MatrixChain(arr, size)))
diff --git a/algorithms/dynamic-programming/rod_cutting.py b/algorithms/dynamic-programming/rod_cutting.py
new file mode 100644
index 0000000..2a6f819
--- /dev/null
+++ b/algorithms/dynamic-programming/rod_cutting.py
@@ -0,0 +1,35 @@
+"""
+ This module calculates optimized solution for rod cutting
+ by function rod_cutting() with arguments as defined
+ in main()
+"""
+
+
+def rod_cutting(price):
+ """
+ Computes maximum money that can be earned by cutting
+ a rod of length len(price) (Bottom-Up Approach).
+ Time Complexity : O((len(price))^2)
+ Space Complexity : O(len(price))
+ :param price: List in which price[i] denotes price of rod of length i.
+ :return: returns optimal solution for rod of length len(price).
+ """
+ length = len(price)
+ opt_price = [0] * (length + 1)
+
+ for i in range(1, length + 1):
+ opt_price[i] = max(
+ [-1] + [price[j] + opt_price[i - j - 1] for j in range(i)])
+ return opt_price[length]
+
+
+def main():
+ """
+ Main Function of this program.
+ """
+ price = [1, 5, 8, 9, 10, 17, 17, 20, 24, 30]
+ print(rod_cutting(price))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/algorithms/dynamic-programming/rod_cutting_problem.py b/algorithms/dynamic-programming/rod_cutting_problem.py
new file mode 100644
index 0000000..1d652e2
--- /dev/null
+++ b/algorithms/dynamic-programming/rod_cutting_problem.py
@@ -0,0 +1,20 @@
+# A Dynamic Programming solution for Rod cutting problem
+
+INT_MIN = -32767
+
+def cutRod(price, n):
+ val = [0 for x in range(n+1)]
+ val[0] = 0
+
+ for i in range(1, n+1):
+ max_val = INT_MIN
+ for j in range(i):
+ max_val = max(max_val, price[j] + val[i-j-1])
+ val[i] = max_val
+
+ return val[n]
+
+# Driver program to test above functions
+arr = [1, 5, 8, 9, 10, 17, 17, 20]
+size = len(arr)
+print("Maximum Obtainable Value is " + str(cutRod(arr, size)))
\ No newline at end of file
diff --git a/algorithms/graphs/Bron-Kerbosch.py b/algorithms/graphs/Bron-Kerbosch.py
new file mode 100644
index 0000000..d802445
--- /dev/null
+++ b/algorithms/graphs/Bron-Kerbosch.py
@@ -0,0 +1,29 @@
+# dealing with a graph as list of lists
+graph = [[0,1,0,0,1,0],[1,0,1,0,1,0],[0,1,0,1,0,0],[0,0,1,0,1,1],[1,1,0,1,0,0],[0,0,0,1,0,0]]
+
+
+#function determines the neighbors of a given vertex
+def N(vertex):
+ c = 0
+ l = []
+ for i in graph[vertex]:
+ if i is 1 :
+ l.append(c)
+ c+=1
+ return l
+
+#the Bron-Kerbosch recursive algorithm
+def bronk(r,p,x):
+ if len(p) == 0 and len(x) == 0: # when no more possible neighbors are found, the max clique is printed
+ print(r)
+ return
+ for vertex in p[:]: # iterates through all possible neigbors
+ r_new = r[::]
+ r_new.append(vertex)
+ p_new = [val for val in p if val in N(vertex)] # p intersects N(vertex)
+ x_new = [val for val in x if val in N(vertex)] # x intersects N(vertex)
+ bronk(r_new,p_new,x_new) # recursiv call with new r, p and x
+ p.remove(vertex)
+ x.append(vertex)
+
+bronk([], [0,1,2,3,4,5], [])
\ No newline at end of file
diff --git a/algorithms/graphs/bellman_ford.py b/algorithms/graphs/bellman_ford.py
new file mode 100644
index 0000000..9b2a572
--- /dev/null
+++ b/algorithms/graphs/bellman_ford.py
@@ -0,0 +1,69 @@
+# Python program for Bellman-Ford's single source
+# shortest path algorithm.
+
+from collections import defaultdict
+
+#Class to represent a graph
+class Graph:
+
+ def __init__(self,vertices):
+ self.V= vertices #No. of vertices
+ self.graph = [] # default dictionary to store graph
+
+ # function to add an edge to graph
+ def addEdge(self,u,v,w):
+ self.graph.append([u, v, w])
+
+ # utility function used to print the solution
+ def printArr(self, dist):
+ print("Vertex Distance from Source")
+ for i in range(self.V):
+ print("%d \t\t %d" % (i, dist[i]))
+
+ # The main function that finds shortest distances from src to
+ # all other vertices using Bellman-Ford algorithm. The function
+ # also detects negative weight cycle
+ def BellmanFord(self, src):
+
+ # Step 1: Initialize distances from src to all other vertices
+ # as INFINITE
+ dist = [float("Inf")] * self.V
+ dist[src] = 0
+
+
+ # Step 2: Relax all edges |V| - 1 times. A simple shortest
+ # path from src to any other vertex can have at-most |V| - 1
+ # edges
+ for i in range(self.V - 1):
+ # Update dist value and parent index of the adjacent vertices of
+ # the picked vertex. Consider only those vertices which are still in
+ # queue
+ for u, v, w in self.graph:
+ if dist[u] != float("Inf") and dist[u] + w < dist[v]:
+ dist[v] = dist[u] + w
+
+ # Step 3: check for negative-weight cycles. The above step
+ # guarantees shortest distances if graph doesn't contain
+ # negative weight cycle. If we get a shorter path, then there
+ # is a cycle.
+
+ for u, v, w in self.graph:
+ if dist[u] != float("Inf") and dist[u] + w < dist[v]:
+ print "Graph contains negative weight cycle"
+ return
+
+ # print all distance
+ self.printArr(dist)
+
+g = Graph(5)
+g.addEdge(0, 1, -1)
+g.addEdge(0, 2, 4)
+g.addEdge(1, 2, 3)
+g.addEdge(1, 3, 2)
+g.addEdge(1, 4, 2)
+g.addEdge(3, 2, 5)
+g.addEdge(3, 1, 1)
+g.addEdge(4, 3, -3)
+
+#Print the solution
+g.BellmanFord(0)
\ No newline at end of file
diff --git a/algorithms/graphs/bfs.py b/algorithms/graphs/bfs.py
new file mode 100644
index 0000000..864a3f4
--- /dev/null
+++ b/algorithms/graphs/bfs.py
@@ -0,0 +1,64 @@
+# Python3 Program to print BFS traversal
+# from a given source vertex. BFS(int s)
+# traverses vertices reachable from s.
+from collections import defaultdict
+
+# This class represents a directed graph
+# using adjacency list representation
+class Graph:
+
+ # Constructor
+ def __init__(self):
+
+ # default dictionary to store graph
+ self.graph = defaultdict(list)
+
+ # function to add an edge to graph
+ def addEdge(self,u,v):
+ self.graph[u].append(v)
+
+ # Function to print a BFS of graph
+ def BFS(self, s):
+
+ # Mark all the vertices as not visited
+ visited = [False] * (len(self.graph))
+
+ # Create a queue for BFS
+ queue = []
+
+ # Mark the source node as
+ # visited and enqueue it
+ queue.append(s)
+ visited[s] = True
+
+ while queue:
+
+ # Dequeue a vertex from
+ # queue and print it
+ s = queue.pop(0)
+ print (s, end = " ")
+
+ # Get all adjacent vertices of the
+ # dequeued vertex s. If a adjacent
+ # has not been visited, then mark it
+ # visited and enqueue it
+ for i in self.graph[s]:
+ if visited[i] == False:
+ queue.append(i)
+ visited[i] = True
+
+# Driver code
+
+# Create a graph given in
+# the above diagram
+g = Graph()
+g.addEdge(0, 1)
+g.addEdge(0, 2)
+g.addEdge(1, 2)
+g.addEdge(2, 0)
+g.addEdge(2, 3)
+g.addEdge(3, 3)
+
+print ("Following is Breadth First Traversal"
+ " (starting from vertex 2)")
+g.BFS(2)
\ No newline at end of file
diff --git a/algorithms/graphs/breadth_first_search.py b/algorithms/graphs/breadth_first_search.py
new file mode 100644
index 0000000..59fe472
--- /dev/null
+++ b/algorithms/graphs/breadth_first_search.py
@@ -0,0 +1,40 @@
+# Breadth First Search
+
+from collections import defaultdict
+
+class Graph:
+ def __init__(self):
+ self.graph = defaultdict(list)
+
+ def add_edges(self,_from,_to):
+ for t in _to:
+ self.graph[_from].append(t)
+
+ def display(self):
+ print self.graph
+
+ def bfs(self,graph,start):
+ queue = [start]
+ visited = []
+
+ while queue:
+ a = queue.pop(0)
+ if a not in visited:
+ visited.append(a)
+ for neighbor in graph[a]:
+ queue.append(neighbor)
+ print visited
+
+def main():
+
+ G = Graph()
+ G.add_edges(1,[2,7,8])
+ G.add_edges(2,[3,6])
+ G.add_edges(3,[4,5])
+ G.add_edges(8,[9,12])
+ G.add_edges(9,[10,11])
+ G.display()
+ G.bfs(G.graph,1)
+
+if __name__ == '__main__':
+ main()
diff --git a/algorithms/graphs/cycle_in_directed.py b/algorithms/graphs/cycle_in_directed.py
new file mode 100644
index 0000000..c9f6936
--- /dev/null
+++ b/algorithms/graphs/cycle_in_directed.py
@@ -0,0 +1,56 @@
+# Python program to detect cycle
+# in a graph
+
+from collections import defaultdict
+
+class Graph():
+ def __init__(self,vertices):
+ self.graph = defaultdict(list)
+ self.V = vertices
+
+ def addEdge(self,u,v):
+ self.graph[u].append(v)
+
+ def isCyclicUtil(self, v, visited, recStack):
+
+ # Mark current node as visited and
+ # adds to recursion stack
+ visited[v] = True
+ recStack[v] = True
+
+ # Recur for all neighbours
+ # if any neighbour is visited and in
+ # recStack then graph is cyclic
+ for neighbour in self.graph[v]:
+ if visited[neighbour] == False:
+ if self.isCyclicUtil(neighbour, visited, recStack) == True:
+ return True
+ elif recStack[neighbour] == True:
+ return True
+
+ # The node needs to be poped from
+ # recursion stack before function ends
+ recStack[v] = False
+ return False
+
+ # Returns true if graph is cyclic else false
+ def isCyclic(self):
+ visited = [False] * self.V
+ recStack = [False] * self.V
+ for node in range(self.V):
+ if visited[node] == False:
+ if self.isCyclicUtil(node,visited,recStack) == True:
+ return True
+ return False
+
+g = Graph(4)
+g.addEdge(0, 1)
+g.addEdge(0, 2)
+g.addEdge(1, 2)
+g.addEdge(2, 0)
+g.addEdge(2, 3)
+g.addEdge(3, 3)
+if g.isCyclic() == 1:
+ print "Graph has a cycle"
+else:
+ print "Graph has no cycle"
\ No newline at end of file
diff --git a/algorithms/graphs/cycle_in_undirected.py b/algorithms/graphs/cycle_in_undirected.py
new file mode 100644
index 0000000..f88c9a9
--- /dev/null
+++ b/algorithms/graphs/cycle_in_undirected.py
@@ -0,0 +1,72 @@
+# Python Program to detect cycle in an undirected graph
+
+from collections import defaultdict
+
+#This class represents a undirected graph using adjacency list representation
+class Graph:
+
+ def __init__(self,vertices):
+ self.V= vertices #No. of vertices
+ self.graph = defaultdict(list) # default dictionary to store graph
+
+
+ # function to add an edge to graph
+ def addEdge(self,v,w):
+ self.graph[v].append(w) #Add w to v_s list
+ self.graph[w].append(v) #Add v to w_s list
+
+ # A recursive function that uses visited[] and parent to detect
+ # cycle in subgraph reachable from vertex v.
+ def isCyclicUtil(self,v,visited,parent):
+
+ #Mark the current node as visited
+ visited[v]= True
+
+ #Recur for all the vertices adjacent to this vertex
+ for i in self.graph[v]:
+ # If the node is not visited then recurse on it
+ if visited[i]==False :
+ if(self.isCyclicUtil(i,visited,v)):
+ return True
+ # If an adjacent vertex is visited and not parent of current vertex,
+ # then there is a cycle
+ elif parent!=i:
+ return True
+
+ return False
+
+
+ #Returns true if the graph contains a cycle, else false.
+ def isCyclic(self):
+ # Mark all the vertices as not visited
+ visited =[False]*(self.V)
+ # Call the recursive helper function to detect cycle in different
+ #DFS trees
+ for i in range(self.V):
+ if visited[i] ==False: #Don't recur for u if it is already visited
+ if(self.isCyclicUtil(i,visited,-1))== True:
+ return True
+
+ return False
+
+# Create a graph given in the above diagram
+g = Graph(5)
+g.addEdge(1, 0)
+g.addEdge(0, 2)
+g.addEdge(2, 0)
+g.addEdge(0, 3)
+g.addEdge(3, 4)
+
+if g.isCyclic():
+ print "Graph contains cycle"
+else :
+ print "Graph does not contain cycle "
+g1 = Graph(3)
+g1.addEdge(0,1)
+g1.addEdge(1,2)
+
+
+if g1.isCyclic():
+ print "Graph contains cycle"
+else :
+ print "Graph does not contain cycle "
\ No newline at end of file
diff --git a/algorithms/graphs/dfs.py b/algorithms/graphs/dfs.py
new file mode 100644
index 0000000..4ccb73b
--- /dev/null
+++ b/algorithms/graphs/dfs.py
@@ -0,0 +1,56 @@
+# Python program to print DFS traversal from a
+# given given graph
+from collections import defaultdict
+
+# This class represents a directed graph using
+# adjacency list representation
+class Graph:
+
+ # Constructor
+ def __init__(self):
+
+ # default dictionary to store graph
+ self.graph = defaultdict(list)
+
+ # function to add an edge to graph
+ def addEdge(self,u,v):
+ self.graph[u].append(v)
+
+ # A function used by DFS
+ def DFSUtil(self,v,visited):
+
+ # Mark the current node as visited and print it
+ visited[v]= True
+ print v,
+
+ # Recur for all the vertices adjacent to this vertex
+ for i in self.graph[v]:
+ if visited[i] == False:
+ self.DFSUtil(i, visited)
+
+
+ # The function to do DFS traversal. It uses
+ # recursive DFSUtil()
+ def DFS(self,v):
+
+ # Mark all the vertices as not visited
+ visited = [False]*(len(self.graph))
+
+ # Call the recursive helper function to print
+ # DFS traversal
+ self.DFSUtil(v,visited)
+
+
+# Driver code
+# Create a graph given in the above diagram
+g = Graph()
+g.addEdge(0, 1)
+g.addEdge(0, 2)
+g.addEdge(1, 2)
+g.addEdge(2, 0)
+g.addEdge(2, 3)
+g.addEdge(3, 3)
+
+print "Following is DFS from (starting from vertex 2)"
+g.DFS(2)
+
\ No newline at end of file
diff --git a/algorithms/graphs/dijkstra.py b/algorithms/graphs/dijkstra.py
new file mode 100644
index 0000000..81d3fe7
--- /dev/null
+++ b/algorithms/graphs/dijkstra.py
@@ -0,0 +1,81 @@
+# Python program for Dijkstra's single
+# source shortest path algorithm. The program is
+# for adjacency matrix representation of the graph
+
+# Library for INT_MAX
+import sys
+
+class Graph():
+
+ def __init__(self, vertices):
+ self.V = vertices
+ self.graph = [[0 for column in range(vertices)]
+ for row in range(vertices)]
+
+ def printSolution(self, dist):
+ print "Vertex tDistance from Source"
+ for node in range(self.V):
+ print node,"t",dist[node]
+
+ # A utility function to find the vertex with
+ # minimum distance value, from the set of vertices
+ # not yet included in shortest path tree
+ def minDistance(self, dist, sptSet):
+
+ # Initilaize minimum distance for next node
+ min = sys.maxint
+
+ # Search not nearest vertex not in the
+ # shortest path tree
+ for v in range(self.V):
+ if dist[v] < min and sptSet[v] == False:
+ min = dist[v]
+ min_index = v
+
+ return min_index
+
+ # Funtion that implements Dijkstra's single source
+ # shortest path algorithm for a graph represented
+ # using adjacency matrix representation
+ def dijkstra(self, src):
+
+ dist = [sys.maxint] * self.V
+ dist[src] = 0
+ sptSet = [False] * self.V
+
+ for cout in range(self.V):
+
+ # Pick the minimum distance vertex from
+ # the set of vertices not yet processed.
+ # u is always equal to src in first iteration
+ u = self.minDistance(dist, sptSet)
+
+ # Put the minimum distance vertex in the
+ # shotest path tree
+ sptSet[u] = True
+
+ # Update dist value of the adjacent vertices
+ # of the picked vertex only if the current
+ # distance is greater than new distance and
+ # the vertex in not in the shotest path tree
+ for v in range(self.V):
+ if self.graph[u][v] > 0 and sptSet[v] == False and
+ dist[v] > dist[u] + self.graph[u][v]:
+ dist[v] = dist[u] + self.graph[u][v]
+
+ self.printSolution(dist)
+
+# Driver program
+g = Graph(9)
+g.graph = [[0, 4, 0, 0, 0, 0, 0, 8, 0],
+ [4, 0, 8, 0, 0, 0, 0, 11, 0],
+ [0, 8, 0, 7, 0, 4, 0, 0, 2],
+ [0, 0, 7, 0, 9, 14, 0, 0, 0],
+ [0, 0, 0, 9, 0, 10, 0, 0, 0],
+ [0, 0, 4, 14, 10, 0, 2, 0, 0],
+ [0, 0, 0, 0, 0, 2, 0, 1, 6],
+ [8, 11, 0, 0, 0, 0, 1, 0, 7],
+ [0, 0, 2, 0, 0, 0, 6, 7, 0]
+ ];
+
+g.dijkstra(0);
\ No newline at end of file
diff --git a/algorithms/graphs/floyd_warshall.py b/algorithms/graphs/floyd_warshall.py
new file mode 100644
index 0000000..2c8e6ee
--- /dev/null
+++ b/algorithms/graphs/floyd_warshall.py
@@ -0,0 +1,79 @@
+# Python Program for Floyd Warshall Algorithm
+
+# Number of vertices in the graph
+V = 4
+
+# Define infinity as the large enough value. This value will be
+# used for vertices not connected to each other
+INF = 99999
+
+# Solves all pair shortest path via Floyd Warshall Algorithm
+def floydWarshall(graph):
+
+ """ dist[][] will be the output matrix that will finally
+ have the shortest distances between every pair of vertices """
+ """ initializing the solution matrix same as input graph matrix
+ OR we can say that the initial values of shortest distances
+ are based on shortest paths considering no
+ intermediate vertices """
+ dist = map(lambda i : map(lambda j : j , i) , graph)
+
+ """ Add all vertices one by one to the set of intermediate
+ vertices.
+ ---> Before start of an iteration, we have shortest distances
+ between all pairs of vertices such that the shortest
+ distances consider only the vertices in the set
+ {0, 1, 2, .. k-1} as intermediate vertices.
+ ----> After the end of a iteration, vertex no. k is
+ added to the set of intermediate vertices and the
+ set becomes {0, 1, 2, .. k}
+ """
+ for k in range(V):
+
+ # pick all vertices as source one by one
+ for i in range(V):
+
+ # Pick all vertices as destination for the
+ # above picked source
+ for j in range(V):
+
+ # If vertex k is on the shortest path from
+ # i to j, then update the value of dist[i][j]
+ dist[i][j] = min(dist[i][j] ,
+ dist[i][k]+ dist[k][j]
+ )
+ printSolution(dist)
+
+
+# A utility function to print the solution
+def printSolution(dist):
+ print "Following matrix shows the shortest distances between every pair of vertices"
+ for i in range(V):
+ for j in range(V):
+ if(dist[i][j] == INF):
+ print "%7s" %("INF"),
+ else:
+ print "%7d\t" %(dist[i][j]),
+ if j == V-1:
+ print ""
+
+
+
+# Driver program to test the above program
+# Let us create the following weighted graph
+"""
+ 10
+ (0)------->(3)
+ | /|\
+ 5 | |
+ | | 1
+ \|/ |
+ (1)------->(2)
+ 3 """
+graph = [[0,5,INF,10],
+ [INF,0,3,INF],
+ [INF, INF, 0, 1],
+ [INF, INF, INF, 0]
+ ]
+# Print the solution
+floydWarshall(graph);
\ No newline at end of file
diff --git a/algorithms/graphs/ford_fulkerson.py b/algorithms/graphs/ford_fulkerson.py
new file mode 100644
index 0000000..9c4a07c
--- /dev/null
+++ b/algorithms/graphs/ford_fulkerson.py
@@ -0,0 +1,97 @@
+
+# Python program for implementation of Ford Fulkerson algorithm
+
+from collections import defaultdict
+
+#This class represents a directed graph using adjacency matrix representation
+class Graph:
+
+ def __init__(self,graph):
+ self.graph = graph # residual graph
+ self. ROW = len(graph)
+ #self.COL = len(gr[0])
+
+
+ '''Returns true if there is a path from source 's' to sink 't' in
+ residual graph. Also fills parent[] to store the path '''
+ def BFS(self,s, t, parent):
+
+ # Mark all the vertices as not visited
+ visited =[False]*(self.ROW)
+
+ # Create a queue for BFS
+ queue=[]
+
+ # Mark the source node as visited and enqueue it
+ queue.append(s)
+ visited[s] = True
+
+ # Standard BFS Loop
+ while queue:
+
+ #Dequeue a vertex from queue and print it
+ u = queue.pop(0)
+
+ # Get all adjacent vertices of the dequeued vertex u
+ # If a adjacent has not been visited, then mark it
+ # visited and enqueue it
+ for ind, val in enumerate(self.graph[u]):
+ if visited[ind] == False and val > 0 :
+ queue.append(ind)
+ visited[ind] = True
+ parent[ind] = u
+
+ # If we reached sink in BFS starting from source, then return
+ # true, else false
+ return True if visited[t] else False
+
+
+ # Returns tne maximum flow from s to t in the given graph
+ def FordFulkerson(self, source, sink):
+
+ # This array is filled by BFS and to store path
+ parent = [-1]*(self.ROW)
+
+ max_flow = 0 # There is no flow initially
+
+ # Augment the flow while there is path from source to sink
+ while self.BFS(source, sink, parent) :
+
+ # Find minimum residual capacity of the edges along the
+ # path filled by BFS. Or we can say find the maximum flow
+ # through the path found.
+ path_flow = float("Inf")
+ s = sink
+ while(s != source):
+ path_flow = min (path_flow, self.graph[parent[s]][s])
+ s = parent[s]
+
+ # Add path flow to overall flow
+ max_flow += path_flow
+
+ # update residual capacities of the edges and reverse edges
+ # along the path
+ v = sink
+ while(v != source):
+ u = parent[v]
+ self.graph[u][v] -= path_flow
+ self.graph[v][u] += path_flow
+ v = parent[v]
+
+ return max_flow
+
+
+# Create a graph given in the above diagram
+
+graph = [[0, 16, 13, 0, 0, 0],
+ [0, 0, 10, 12, 0, 0],
+ [0, 4, 0, 0, 14, 0],
+ [0, 0, 9, 0, 0, 20],
+ [0, 0, 0, 7, 0, 4],
+ [0, 0, 0, 0, 0, 0]]
+
+g = Graph(graph)
+
+source = 0; sink = 5
+
+print ("The maximum possible flow is %d " % g.FordFulkerson(source, sink))
diff --git a/algorithms/graphs/kruskals_MST.py b/algorithms/graphs/kruskals_MST.py
new file mode 100644
index 0000000..499bf83
--- /dev/null
+++ b/algorithms/graphs/kruskals_MST.py
@@ -0,0 +1,101 @@
+# Python program for Kruskal's algorithm to find
+# Minimum Spanning Tree of a given connected,
+# undirected and weighted graph
+
+from collections import defaultdict
+
+#Class to represent a graph
+class Graph:
+
+ def __init__(self,vertices):
+ self.V= vertices #No. of vertices
+ self.graph = [] # default dictionary
+ # to store graph
+
+
+ # function to add an edge to graph
+ def addEdge(self,u,v,w):
+ self.graph.append([u,v,w])
+
+ # A utility function to find set of an element i
+ # (uses path compression technique)
+ def find(self, parent, i):
+ if parent[i] == i:
+ return i
+ return self.find(parent, parent[i])
+
+ # A function that does union of two sets of x and y
+ # (uses union by rank)
+ def union(self, parent, rank, x, y):
+ xroot = self.find(parent, x)
+ yroot = self.find(parent, y)
+
+ # Attach smaller rank tree under root of
+ # high rank tree (Union by Rank)
+ if rank[xroot] < rank[yroot]:
+ parent[xroot] = yroot
+ elif rank[xroot] > rank[yroot]:
+ parent[yroot] = xroot
+
+ # If ranks are same, then make one as root
+ # and increment its rank by one
+ else :
+ parent[yroot] = xroot
+ rank[xroot] += 1
+
+ # The main function to construct MST using Kruskal's
+ # algorithm
+ def KruskalMST(self):
+
+ result =[] #This will store the resultant MST
+
+ i = 0 # An index variable, used for sorted edges
+ e = 0 # An index variable, used for result[]
+
+ # Step 1: Sort all the edges in non-decreasing
+ # order of their
+ # weight. If we are not allowed to change the
+ # given graph, we can create a copy of graph
+ self.graph = sorted(self.graph,key=lambda item: item[2])
+
+ parent = [] ; rank = []
+
+ # Create V subsets with single elements
+ for node in range(self.V):
+ parent.append(node)
+ rank.append(0)
+
+ # Number of edges to be taken is equal to V-1
+ while e < self.V -1 :
+
+ # Step 2: Pick the smallest edge and increment
+ # the index for next iteration
+ u,v,w = self.graph[i]
+ i = i + 1
+ x = self.find(parent, u)
+ y = self.find(parent ,v)
+
+ # If including this edge does't cause cycle,
+ # include it in result and increment the index
+ # of result for next edge
+ if x != y:
+ e = e + 1
+ result.append([u,v,w])
+ self.union(parent, rank, x, y)
+ # Else discard the edge
+
+ # print the contents of result[] to display the built MST
+ print "Following are the edges in the constructed MST"
+ for u,v,weight in result:
+ #print str(u) + " -- " + str(v) + " == " + str(weight)
+ print ("%d -- %d == %d" % (u,v,weight))
+
+# Driver code
+g = Graph(4)
+g.addEdge(0, 1, 10)
+g.addEdge(0, 2, 6)
+g.addEdge(0, 3, 5)
+g.addEdge(1, 3, 15)
+g.addEdge(2, 3, 4)
+
+g.KruskalMST()
\ No newline at end of file
diff --git a/algorithms/graphs/prims_MST.py b/algorithms/graphs/prims_MST.py
new file mode 100644
index 0000000..67aa867
--- /dev/null
+++ b/algorithms/graphs/prims_MST.py
@@ -0,0 +1,79 @@
+# A Python program for Prim's Minimum Spanning Tree (MST) algorithm.
+# The program is for adjacency matrix representation of the graph
+
+import sys # Library for INT_MAX
+
+class Graph():
+
+ def __init__(self, vertices):
+ self.V = vertices
+ self.graph = [[0 for column in range(vertices)]
+ for row in range(vertices)]
+
+ # A utility function to print the constructed MST stored in parent[]
+ def printMST(self, parent):
+ print "Edge \tWeight"
+ for i in range(1,self.V):
+ print parent[i],"-",i,"\t",self.graph[i][ parent[i] ]
+
+ # A utility function to find the vertex with
+ # minimum distance value, from the set of vertices
+ # not yet included in shortest path tree
+ def minKey(self, key, mstSet):
+
+ # Initilaize min value
+ min = sys.maxint
+
+ for v in range(self.V):
+ if key[v] < min and mstSet[v] == False:
+ min = key[v]
+ min_index = v
+
+ return min_index
+
+ # Function to construct and print MST for a graph
+ # represented using adjacency matrix representation
+ def primMST(self):
+
+ #Key values used to pick minimum weight edge in cut
+ key = [sys.maxint] * self.V
+ parent = [None] * self.V # Array to store constructed MST
+ # Make key 0 so that this vertex is picked as first vertex
+ key[0] = 0
+ mstSet = [False] * self.V
+
+ parent[0] = -1 # First node is always the root of
+
+ for cout in range(self.V):
+
+ # Pick the minimum distance vertex from
+ # the set of vertices not yet processed.
+ # u is always equal to src in first iteration
+ u = self.minKey(key, mstSet)
+
+ # Put the minimum distance vertex in
+ # the shortest path tree
+ mstSet[u] = True
+
+ # Update dist value of the adjacent vertices
+ # of the picked vertex only if the current
+ # distance is greater than new distance and
+ # the vertex in not in the shotest path tree
+ for v in range(self.V):
+ # graph[u][v] is non zero only for adjacent vertices of m
+ # mstSet[v] is false for vertices not yet included in MST
+ # Update the key only if graph[u][v] is smaller than key[v]
+ if self.graph[u][v] > 0 and mstSet[v] == False and key[v] > self.graph[u][v]:
+ key[v] = self.graph[u][v]
+ parent[v] = u
+
+ self.printMST(parent)
+
+g = Graph(5)
+g.graph = [ [0, 2, 0, 6, 0],
+ [2, 0, 3, 8, 5],
+ [0, 3, 0, 0, 7],
+ [6, 8, 0, 0, 9],
+ [0, 5, 7, 9, 0]]
+
+g.primMST();
\ No newline at end of file
diff --git a/algorithms/graphs/topological_sort.py b/algorithms/graphs/topological_sort.py
new file mode 100644
index 0000000..f5eaabc
--- /dev/null
+++ b/algorithms/graphs/topological_sort.py
@@ -0,0 +1,53 @@
+#Python program to print topological sorting of a DAG
+from collections import defaultdict
+
+#Class to represent a graph
+class Graph:
+ def __init__(self,vertices):
+ self.graph = defaultdict(list) #dictionary containing adjacency List
+ self.V = vertices #No. of vertices
+
+ # function to add an edge to graph
+ def addEdge(self,u,v):
+ self.graph[u].append(v)
+
+ # A recursive function used by topologicalSort
+ def topologicalSortUtil(self,v,visited,stack):
+
+ # Mark the current node as visited.
+ visited[v] = True
+
+ # Recur for all the vertices adjacent to this vertex
+ for i in self.graph[v]:
+ if visited[i] == False:
+ self.topologicalSortUtil(i,visited,stack)
+
+ # Push current vertex to stack which stores result
+ stack.insert(0,v)
+
+ # The function to do Topological Sort. It uses recursive
+ # topologicalSortUtil()
+ def topologicalSort(self):
+ # Mark all the vertices as not visited
+ visited = [False]*self.V
+ stack =[]
+
+ # Call the recursive helper function to store Topological
+ # Sort starting from all vertices one by one
+ for i in range(self.V):
+ if visited[i] == False:
+ self.topologicalSortUtil(i,visited,stack)
+
+ # Print contents of the stack
+ print stack
+
+g= Graph(6)
+g.addEdge(5, 2);
+g.addEdge(5, 0);
+g.addEdge(4, 0);
+g.addEdge(4, 1);
+g.addEdge(2, 3);
+g.addEdge(3, 1);
+
+print "Following is a Topological Sort of the given graph"
+g.topologicalSort()
\ No newline at end of file
diff --git a/algorithms/greedy/coin_change.py b/algorithms/greedy/coin_change.py
new file mode 100644
index 0000000..996ff92
--- /dev/null
+++ b/algorithms/greedy/coin_change.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python3
+
+"""
+Coin Change implementation in Python (Greedy Method)
+"""
+
+__author__ = "Aditya Krishnakumar"
+
+def minimum_coins(value, denominations):
+ result = []
+ # Assuming denominations is sorted in descendig order
+ for cur_denom in denominations:
+ while cur_denom <= value:
+ result.append(cur_denom)
+ value = value - cur_denom
+
+ return result
+
+# Testing
+def test():
+ scenarios = [[100, [50, 25, 10, 5, 1], [50, 50]],
+ [101, [50, 25, 10, 5, 1], [50, 50, 1]],
+ [77, [50, 25, 10, 5, 1], [50, 25, 1, 1]],
+ [38, [50, 25, 10, 5, 1], [25, 10, 1, 1, 1]],
+ [17, [50, 25, 10, 5, 1], [10, 5, 1, 1]],
+ [3, [50, 25, 10, 5, 1], [1, 1, 1]],
+ [191, [100, 50, 25, 10, 5, 1], [100, 50, 25, 10, 5, 1]]]
+
+ for scenario in scenarios:
+ actual = minimum_coins(scenario[0], scenario[1])
+ if actual != scenario[2]:
+ message = "Test Failed: Value: {}, Denominations: {}, Expected Result: {}, Actual Result: {}".format(scenario[0], scenario[1], scenario[2], actual)
+ print message
+
+ return None
+
+test()
\ No newline at end of file
diff --git a/algorithms/greedy/dijkstra_algo.py b/algorithms/greedy/dijkstra_algo.py
new file mode 100644
index 0000000..3faac0f
--- /dev/null
+++ b/algorithms/greedy/dijkstra_algo.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python3
+
+"""
+Dijkstra's Algorithm implementation in Python
+"""
+
+__author__ = "Aditya Krishnakumar"
+
+def dijkstra(graph, source):
+
+ vertices, edges = graph
+ dist = dict()
+ previous = dict()
+
+ for vertex in vertices:
+ dist[vertex] = float("inf")
+ previous[vertex] = None
+
+ dist[source] = 0
+ Q = set(vertices)
+
+ while len(Q) > 0:
+ u = minimum_distance(dist, Q)
+ print('Currently considering', u, 'with a distance of', dist[u])
+ Q.remove(u)
+
+ if dist[u] == float('inf'):
+ break
+
+ n = get_neighbours(graph, u)
+ for vertex in n:
+ alt = dist[u] + dist_between(graph, u, vertex)
+ if alt < dist[vertex]:
+ dist[vertex] = alt
+ previous[vertex] = u
+
+ return previous
\ No newline at end of file
diff --git a/algorithms/greedy/fractional_knapsack.py b/algorithms/greedy/fractional_knapsack.py
new file mode 100644
index 0000000..c0e7f5b
--- /dev/null
+++ b/algorithms/greedy/fractional_knapsack.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python3
+
+"""
+Implementation of Fractional Knapsack Algorithm in Python
+"""
+
+__author__ = "Aditya Krishnakumar"
+
+# Item class with weight and values
+class Item:
+
+ # intialize weight and values
+ def __init__(self, weight=0, value=0):
+
+ self.weight = weight
+ self.value = value
+
+ return
+
+
+def fractional_knapsack(items, W):
+
+ # Sorting items by value /weight
+ sorted(items, key = lambda item: float(item.value)/float(item.weight))
+
+ finalValue = 0.0
+ currentWeight = 0
+
+
+ for item in items:
+
+ if currentWeight + item.weight <= W :
+ # If adding Item won't overflow, add it completely
+ finalValue += item.value
+ currentWeight += item.weight
+
+ else:
+ #If we can't add current Item, add a fraction of it
+ remaining = W - currentWeight
+ finalValue += item.value*(float(remaining)/float(item.weight))
+ break
+
+ return finalValue
+
+def main():
+
+ W = 50
+
+ items = [
+ Item(10, 60),
+ Item(20, 100),
+ Item(30, 120)
+ ]
+
+ print("Maximum value we can obtain -{}".format(fractional_knapsack(items, W)))
+
+ return
+
+if __name__ == "__main__":
+
+ main()
diff --git a/algorithms/linkedlist/find_length_linkedList.py b/algorithms/linkedlist/find_length_linkedList.py
new file mode 100644
index 0000000..7fe4cf7
--- /dev/null
+++ b/algorithms/linkedlist/find_length_linkedList.py
@@ -0,0 +1,56 @@
+# A complete working Python program to find length of a
+# Linked List iteratively
+
+# Node class
+class Node:
+ # Function to initialise the node object
+ def __init__(self, data):
+ self.data = data # Assign data
+ self.next = None # Initialize next as null
+
+
+# Linked List class contains a Node object
+class LinkedList:
+
+ # Function to initialize head
+ def __init__(self):
+ self.head = None
+
+
+ # This function is in LinkedList class. It inserts
+ # a new node at the beginning of Linked List.
+ def push(self, new_data):
+
+ # 1 & 2: Allocate the Node &
+ # Put in the data
+ new_node = Node(new_data)
+
+ # 3. Make next of new Node as head
+ new_node.next = self.head
+
+ # 4. Move the head to point to new Node
+ self.head = new_node
+
+
+ # This function counts number of nodes in Linked List
+ # iteratively, given 'node' as starting node.
+ def getCount(self):
+ temp = self.head # Initialise temp
+ count = 0 # Initialise count
+
+ # Loop while end of linked list is not reached
+ while (temp):
+ count += 1
+ temp = temp.next
+ return count
+
+
+# Code execution starts here
+if __name__=='__main__':
+ llist = LinkedList()
+ llist.push(1)
+ llist.push(3)
+ llist.push(1)
+ llist.push(2)
+ llist.push(1)
+ print ("Count of nodes is :",llist.getCount())
diff --git a/algorithms/linkedlist/middle_of_linkedlist.py b/algorithms/linkedlist/middle_of_linkedlist.py
new file mode 100644
index 0000000..c0d55df
--- /dev/null
+++ b/algorithms/linkedlist/middle_of_linkedlist.py
@@ -0,0 +1,56 @@
+class Node:
+ def __init__(self,data):
+ self.data = data
+ self.next = None
+
+class LinkedList:
+ def __init__(self):
+ self.head = None
+ self.tail = None
+ self.count = 0
+
+ def isEmpty(self):
+ if self.count == 0:
+ return True
+ return False
+
+ def add_node(self,data):
+ new = Node(data)
+
+ if self.isEmpty():
+ self.head = new
+ self.tail = new
+ self.count += 1
+ else:
+ new.next = self.head
+ self.head = new
+ self.count += 1
+
+ def show(self):
+ list = ''
+ ptr = self.head
+ while ptr:
+ print ptr.data
+ print ' -> '
+ ptr = ptr.next
+ print list
+
+ def middle(self):
+ fast = self.head
+ slow = self.head
+ while fast and fast.next:
+ slow = slow.next
+ fast = fast.next.next
+ print slow.data
+
+
+def main():
+ L = LinkedList()
+ L.add_node(2)
+ L.add_node(32)
+ L.add_node(21)
+ L.add_node(67)
+ L.add_node(89)
+ L.middle()
+if __name__ == '__main__':
+ main()
diff --git a/algorithms/linkedlist/reverse_linkedlist.py b/algorithms/linkedlist/reverse_linkedlist.py
new file mode 100644
index 0000000..c5b75de
--- /dev/null
+++ b/algorithms/linkedlist/reverse_linkedlist.py
@@ -0,0 +1,64 @@
+# Recursively reverse a linked list
+
+class Node:
+ def __init__(self,data):
+ self.data = data
+ self.next = None
+
+class LinkedList:
+ def __init__(self):
+ self.head = None
+ self.tail = None
+ self.count = 0
+
+ def isEmpty(self):
+ if self.count == 0:
+ return True
+ return False
+
+ def addnode(self,data):
+ new = Node(data)
+ if self.isEmpty():
+ self.head = new
+ self.tail = new
+ self.count += 1
+ else:
+ new.next = self.head
+ self.head = new
+ self.count += 1
+
+ def show(self):
+ list = ''
+ ptr = self.head
+ while ptr:
+ list += str(ptr.data)
+ list += '->'
+ ptr = ptr.next
+ print list
+
+ def reverse(self,cur):
+ cur = cur
+ n = cur.next
+
+ if n.next:
+ self.reverse(cur.next)
+ n.next = cur
+ cur.next = None
+ else:
+ n.next = cur
+ self.head = n
+
+def main():
+ L = LinkedList()
+ L.addnode(89)
+ L.addnode(67)
+ L.addnode(21)
+ L.addnode(32)
+ L.addnode(2)
+ L.show()
+ L.reverse(L.head)
+ L.show()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/algorithms/math/Fibonacci_Sequence.py b/algorithms/math/Fibonacci_Sequence.py
new file mode 100644
index 0000000..507c766
--- /dev/null
+++ b/algorithms/math/Fibonacci_Sequence.py
@@ -0,0 +1,12 @@
+# Fibonacci Sequence
+
+if __name__ == '__main__':
+ f = [0, 1]
+ index1=0
+ index2=1
+ fibonacci_len = 10 # Lenght of Fibonacci Sequence
+ for n in range(fibonacci_len):
+ val = f[index1+n]+f[index2+n]
+ f.append(val)
+ f.pop(0)
+ print f
diff --git a/algorithms/math/Sieve of Eratosthenes.py b/algorithms/math/Sieve of Eratosthenes.py
new file mode 100644
index 0000000..d4b866d
--- /dev/null
+++ b/algorithms/math/Sieve of Eratosthenes.py
@@ -0,0 +1,20 @@
+def SieveOfEratosthenes(n):
+ prime = [True for i in range(n+1)]
+ p = 2
+ while (p * p <= n):
+ # If prime[p] is not changed, then it is a prime
+ if (prime[p] == True):
+ # Update all multiples of p
+ for i in range(p * p, n+1, p):
+ prime[i] = False
+ p += 1
+ # Print all prime numbers
+ for p in range(2, n):
+ if prime[p]:
+ print (p),
+ # driver program
+if __name__=='__main__':
+ n = 30
+ print ("Following are the prime numbers smaller")
+ print ("than or equal to", n)
+ SieveOfEratosthenes(n)
diff --git a/algorithms/math/SieveOfEratosthenes.py b/algorithms/math/SieveOfEratosthenes.py
new file mode 100644
index 0000000..8fbb1ba
--- /dev/null
+++ b/algorithms/math/SieveOfEratosthenes.py
@@ -0,0 +1,31 @@
+import math
+
+
+def sieve(number): # taking a number as input and we'll find all prime values below it
+ primes = [0] * number
+ primes[0] = primes[1] = 1 # initialise 0 and 1 to not prime numbers
+ for prime in range(2, int(math.sqrt(len(primes)))):
+ if primes[prime] == 0:
+ for y in range(prime * 2, len(primes), prime):
+ primes[y] = 1
+ else:
+ pass
+
+ return primes
+
+
+while True: # take input and reject any non integer inputs
+ try:
+ num = int(input("Type in a number: "))
+ break
+
+ except ValueError:
+ print("Type in an integer!")
+
+nums = sieve(num)
+
+for num in range(len(nums)):
+ if nums[num] == 0:
+ print(num)
+ else:
+ pass
diff --git a/algorithms/math/SieveOfEratosthenes_PrimeNumbers.py b/algorithms/math/SieveOfEratosthenes_PrimeNumbers.py
new file mode 100644
index 0000000..5285a72
--- /dev/null
+++ b/algorithms/math/SieveOfEratosthenes_PrimeNumbers.py
@@ -0,0 +1,22 @@
+#time complexity: O(n log(log n))
+
+def Sieve(n):
+ prime = [True for i in range(n + 1)]
+ p = 2
+
+ #Here, we mark all the numbers that are not prime
+ while(p * p <= n):
+ if prime[p] == True:
+ for i in range(p * p, n + 1, p):
+ prime[i] = False
+ p += 1
+
+ #only the numbers that are unmarked, are prime. Hence, we print them
+ for p in range(2, n):
+ if prime[p]:
+ print(p, end = ' ')
+
+#driver code
+n = int(input())
+print("All prime numbers till", n, "are: ")
+Sieve(n)
diff --git a/algorithms/math/armstrong_number.py b/algorithms/math/armstrong_number.py
new file mode 100644
index 0000000..4a37b0a
--- /dev/null
+++ b/algorithms/math/armstrong_number.py
@@ -0,0 +1,18 @@
+def armstrong(number):
+ l1=list(number)
+ Sum=0
+ order=len(l1)
+ for i in l1:
+ Sum+=(int(i)**order)
+
+ if Sum==int(number):
+
+ print(number,"is an Armstrong number")
+ else:
+
+ print(number,"is not an Armstrong number")
+
+
+
+number=input("Enter the number to check for Armstrong : ")
+armstrong(number)
\ No newline at end of file
diff --git a/algorithms/math/calcu_trig.py b/algorithms/math/calcu_trig.py
new file mode 100644
index 0000000..483a6c5
--- /dev/null
+++ b/algorithms/math/calcu_trig.py
@@ -0,0 +1,31 @@
+from math import sqrt
+
+sign = ["",
+ "","",'-','-', #sin
+ "",'-',"-",'', #cos
+ "",'-','',"-"] #tan
+
+def trig_func(name,value,quad=1):
+ if name == 'tan':
+ cos = sqrt(1 / (value ** 2 + 1))
+ sin = abs(value * cos)
+ print("sin={}{},cos={}{},tan={}".format(sign[quad],
+ sin,sign[quad+4],
+ cos,value))
+
+ elif name == 'sin':
+ cos = sqrt(1 - value ** 2)
+ tan = abs(value / cos)
+ print("sin={},cos={}{},tan={}{}".format(value,
+ sign[quad+4],cos,
+ sign[quad+8],tan))
+
+ elif name == 'cos':
+ sin = sqrt(1 - value ** 2)
+ tan = abs(sin / value)
+ print("sin={}{},cos={},tan={}{}".format(sign[quad],sin,
+ value,
+ sign[quad+8],tan))
+
+ else:
+ print('not sin,cos,tan')
diff --git a/algorithms/math/check_armstrong.py b/algorithms/math/check_armstrong.py
new file mode 100644
index 0000000..783e8d8
--- /dev/null
+++ b/algorithms/math/check_armstrong.py
@@ -0,0 +1,22 @@
+def main():
+ print("Enter the the number")
+ n=int(input())
+ for i in range(1,n+1):
+ b=checkamstrong(i)
+ if b:
+ print(str(i)+" is an armstrong number")
+
+def checkarmstrong(n):
+ t=n
+ sum=0
+ while t!=0:
+ r=t%10
+ sum=sum+(r*r*r)
+ t=t//10
+ if sum==n:
+ return True
+ else:
+ return False
+
+if __name__ == '__main__':
+ main()
\ No newline at end of file
diff --git a/algorithms/math/collatz.py b/algorithms/math/collatz.py
new file mode 100644
index 0000000..b167456
--- /dev/null
+++ b/algorithms/math/collatz.py
@@ -0,0 +1,20 @@
+"""Collatz sequence.
+
+@author: Pablo Trinidad
+"""
+
+
+def collatz(n):
+ """Sequence generation."""
+ l = []
+ while n > 1:
+ l.append(n)
+ if n % 2 == 0:
+ n = n / 2
+ else:
+ n = (3 * n) + 1
+ l.append(n)
+ return l
+
+n = int(input("Enter an integer n to compute the Collatz sequence: "))
+print(collatz(n))
diff --git a/algorithms/math/common_divisor_count.py b/algorithms/math/common_divisor_count.py
new file mode 100644
index 0000000..ef28f92
--- /dev/null
+++ b/algorithms/math/common_divisor_count.py
@@ -0,0 +1,31 @@
+
+
+
+'''
+
+The function takes two integers as input and return the number of common divisors of
+that pair
+
+
+
+'''
+def cd_count(a,b):
+
+ if a==0 or b==0:
+ return 2
+ a=(-1*a if a<0 else a)
+ b=(-1*b if b<0 else b)
+
+ result=0
+ while a!=0:
+ c=a
+ a=b%a
+ b=c
+
+ for i in range(1,int((b**0.5)+1)):
+ if b%i==0:
+ if b/i==i:
+ result=result+1
+ else:
+ result=result+2
+ return result
diff --git a/algorithms/math/ducci.py b/algorithms/math/ducci.py
new file mode 100644
index 0000000..57c5973
--- /dev/null
+++ b/algorithms/math/ducci.py
@@ -0,0 +1,15 @@
+def ducci_sequence(*ns):
+ while True:
+ yield ns
+ ns = tuple(abs(ns[i - 1] - ns[i]) for i in range(len(ns)))
+
+def ducci(*ns):
+ known = set()
+ for ns in ducci_sequence(*ns):
+ print(ns)
+ if ns in known or set(ns) == {0}:
+ break
+ known.add(ns)
+ return len(known) + 1
+
+print(ducci(0, 653, 1854, 4063), "steps")
diff --git a/algorithms/math/eulerTotient.py b/algorithms/math/eulerTotient.py
new file mode 100644
index 0000000..bb9af68
--- /dev/null
+++ b/algorithms/math/eulerTotient.py
@@ -0,0 +1,24 @@
+from math import sqrt
+
+"""
+this function calculate euler totien function
+"""
+def eulerTotienFunction(n):
+ if n == 1:
+ return 1
+ result = 1
+ temp = n
+ for i in range(2,int(sqrt(n))+10):
+ if (temp % i == 0):
+ j = 0
+ while(temp % i == 0):
+ j += 1
+ temp //= i
+ result = result * (i**(j-1)) * (i-1)
+ if temp == n:
+ return n-1
+ return result
+
+
+
+
diff --git a/algorithms/math/extendedEuclidean.py b/algorithms/math/extendedEuclidean.py
new file mode 100644
index 0000000..f220a37
--- /dev/null
+++ b/algorithms/math/extendedEuclidean.py
@@ -0,0 +1,20 @@
+"""
+ for numbers a, b returns x, y such as x * a + y * b = gcd(a,b)
+"""
+
+def extendedEuclidean(a,b):
+ a_old, b_old = a,b
+ a, b = max(a, b), min(a, b)
+ x, y, old_x, old_y = 0, 1, 1, 0
+ while b != 0:
+ quotient = a // b
+ residue = a % b
+ a, b = b, residue
+ x, old_x = old_x, (old_x - quotient * x)
+ y, old_y = old_y, (old_y - quotient * y)
+ if a_old > b_old:
+ return x, y
+ return y, x
+
+
+
diff --git a/algorithms/math/factorial.py b/algorithms/math/factorial.py
new file mode 100644
index 0000000..ac732ea
--- /dev/null
+++ b/algorithms/math/factorial.py
@@ -0,0 +1,21 @@
+'''
+To find factorial of a number
+'''
+def factorial(num): #recursive function
+ if num==1 or num==0:
+ return 1
+ else:
+ return factorial(num-1)*num #function calling itself
+
+num=int(input("Enter the number to find factorial:"))
+'''
+To check whether the number inputted is positive or not
+'''
+while num<0:
+ print("INVALID INPUT !")
+ num=int(input("Enter the number to find factorial:"))
+'''
+function calling
+'''
+x=factorial(num)
+print("Factorial of ",num," is ",x)
\ No newline at end of file
diff --git a/algorithms/math/factorial_iterative.py b/algorithms/math/factorial_iterative.py
new file mode 100644
index 0000000..1057d4e
--- /dev/null
+++ b/algorithms/math/factorial_iterative.py
@@ -0,0 +1,16 @@
+"""Factorial of n (iterative implementation).
+
+@author: Pablo Trinidad
+"""
+
+
+def factorial(n):
+ """Algorithm implementation."""
+ r = 1
+ while n > 0:
+ r = r * n
+ n = n - 1
+ return r
+
+n = int(input("Enter an integer n to compute its factorial: "))
+print(str(n) + "! = " + str(factorial(n)))
diff --git a/algorithms/math/factorial_recursive.py b/algorithms/math/factorial_recursive.py
new file mode 100644
index 0000000..1210a76
--- /dev/null
+++ b/algorithms/math/factorial_recursive.py
@@ -0,0 +1,12 @@
+"""Factorial of n (recursive implementation).
+
+@author: Pablo Trinidad
+"""
+
+
+def factorial(n):
+ """Algorithm implementation."""
+ return 1 if n <= 0 else n * factorial(n - 1)
+
+n = int(input("Enter an integer n to compute its factorial: "))
+print(str(n) + "! = " + str(factorial(n)))
diff --git a/algorithms/math/fibonacci-recursive.py b/algorithms/math/fibonacci-recursive.py
new file mode 100644
index 0000000..51b27a9
--- /dev/null
+++ b/algorithms/math/fibonacci-recursive.py
@@ -0,0 +1,13 @@
+def fibonacciUn(n,Un_2=None,Un_1=None):
+ if(n<1):
+ return Un_2 or n
+ if (n==1):
+ return Un_1 or n
+ return fibonacciUn(n-1,Un_2,Un_1) + fibonacciUn (n-2,Un_2,Un_1)
+# Test
+
+print("The first item of the sequence is:")
+print(fibonacciUn(1,10,15))
+
+print("The tweleth item of the sequence is:")
+print(fibonacciUn(12))
\ No newline at end of file
diff --git a/algorithms/math/fibonacci.py b/algorithms/math/fibonacci.py
new file mode 100644
index 0000000..4420883
--- /dev/null
+++ b/algorithms/math/fibonacci.py
@@ -0,0 +1,11 @@
+def fibonacciUn(Un_2,Un_1,n):
+ if(n<1):
+ return Un_2
+ if (n==1):
+ return Un_1
+ for i in range(n):
+ fib=Un_1+Un_2
+ Un_2=Un_1
+ Un_1=fib
+ return Un_1
+print(fibonacciUn(10,15,2))
\ No newline at end of file
diff --git a/algorithms/math/gaussfilter.py b/algorithms/math/gaussfilter.py
new file mode 100644
index 0000000..724a5e8
--- /dev/null
+++ b/algorithms/math/gaussfilter.py
@@ -0,0 +1,35 @@
+import math
+
+
+def gaussfilt(xdata, ydata, sigma, xfilt=None, M=None, extrap=None):
+ if xfilt is None:
+ xfilt = xdata
+ if M is None:
+ M = 3 * sigma
+ if extrap is None:
+ extrap = 0
+ yfilt = [0] * len(xfilt)
+ for i in range(0, len(xfilt), 1):
+ indices = [k for k, x in enumerate(xdata) if x > (xfilt[i] - M) and x < (xfilt[i] + M)]
+ if indices:
+ x = []
+ for ind in indices:
+ x.append(xdata[ind] - xfilt[i])
+ gaussfactors = gausskernel(x, sigma)
+ y = []
+ yd = []
+ for ind in indices:
+ yd.append(ydata[ind])
+ for j in range(0, len(gaussfactors), 1):
+ y.append(gaussfactors[j] * yd[j])
+ yfilt[i] = sum(y) / sum(gaussfactors)
+ if not indices:
+ yfilt[i] = extrap
+ return yfilt
+
+
+def gausskernel(x, sigma):
+ res = []
+ for element in x:
+ res.append(1 / (sigma * math.sqrt(2 * math.pi)) * math.exp(-0.5 * pow((element / sigma), 2)))
+ return res
diff --git a/algorithms/math/gcd.py b/algorithms/math/gcd.py
new file mode 100644
index 0000000..5eb748b
--- /dev/null
+++ b/algorithms/math/gcd.py
@@ -0,0 +1,10 @@
+def gcd(A, B):
+ if B>A:
+ A, B = B, A
+ while B!=0:
+ temp = B
+ B = A%B
+ A = temp
+ return A
+
+print(gcd(10,20))
diff --git a/algorithms/math/lucky_numbers.py b/algorithms/math/lucky_numbers.py
new file mode 100644
index 0000000..d37568f
--- /dev/null
+++ b/algorithms/math/lucky_numbers.py
@@ -0,0 +1,15 @@
+def generate_lucky_number_sequence(end):
+
+ #create a list of all odd numbers up to the final number
+ sequence = [*range(1, end+1, 2)]
+
+ #remove every xth number from the list where x = the nth element of the sequence
+ n = 1
+ while len(sequence) > sequence[n]:
+ number_to_delete = sequence[n]
+ del sequence[number_to_delete-1::number_to_delete]
+ n = n + 1
+
+ return sequence
+
+print(generate_lucky_number_sequence(int(input("Please enter the upper bound of the lucky number sequence: "))))
diff --git a/algorithms/math/magic_square.py b/algorithms/math/magic_square.py
new file mode 100644
index 0000000..dca9adf
--- /dev/null
+++ b/algorithms/math/magic_square.py
@@ -0,0 +1,42 @@
+
+
+
+"""A magic square is an N×N grid of numbers in which the entries in each row, column and main diagonal sum to the same number (equal to N(N2+1)/2)"""
+
+
+import numpy as np
+
+
+print("Hi! Welcome to the magic square algorithm")
+print("Please enter the number for which you would want a magic sqaure to be printed. Please enter an odd number")
+
+# The odd number for which the magic square is created is stored in the variable N
+
+N = int(input())
+
+# create a matrix with values 0 using numpy. The datatype is int for the elements in the matrix
+magic_square = np.zeros((N,N), dtype=int)
+
+n = 1
+i, j = 0, N//2
+
+# n iterates from 1 to N**2. The loop exits when n is equal to N**2
+
+while n <= N**2:
+ # Start in the middle of the first row.
+ # (i = 0 and j = N//2 ) and the element at magic_square[i,j] is the middle in the first row.
+ # insert n = 1 to begin with at magic_square[i,j]
+ magic_square[i, j] = n
+ # increment n by 1
+ n += 1
+ # Move diagonally up and right, wrapping to the first column or last row if the move leads outside the grid
+
+ new_i, new_j = (i-1) % N, (j+1)% N
+
+ # if the cell is already filled with a number, move vertically down one space.
+ if magic_square[new_i, new_j]:
+ i += 1
+ else:
+ i, j = new_i, new_j
+
+print(magic_square)
diff --git a/algorithms/math/nth_fibonacci_using_goldenratio.py b/algorithms/math/nth_fibonacci_using_goldenratio.py
new file mode 100644
index 0000000..c12fc86
--- /dev/null
+++ b/algorithms/math/nth_fibonacci_using_goldenratio.py
@@ -0,0 +1,33 @@
+# Python3 code to find n-th Fibonacci number
+# Adapted from code by Sharad Bhardwaj
+# Approximate value of golden ratio
+PHI = 1.6180339
+
+# Fibonacci numbers upto n = 5
+f = [ 0, 1, 1, 2, 3, 5 ]
+
+# Function to find nth
+# Fibonacci number
+def fib ( n ):
+
+ # Fibonacci numbers for n < 6
+ if n < 6:
+ return f[n]
+
+ # Else start counting from
+ # 5th term
+ t = 5
+ fn = 5
+
+ while t < n:
+ fn = round(fn * PHI)
+ t+=1
+
+ return fn
+
+#OUTPUTING 34
+print(n, "th Fibonacci Number =", fib(9))
+#OUTPUTING 21
+print(n, "th Fibonacci Number =", fib(8))
+#OUTPUTING 13
+print(n, "th Fibonacci Number =", fib(7))
diff --git a/algorithms/math/pascals_triangle.py b/algorithms/math/pascals_triangle.py
new file mode 100644
index 0000000..ea625d4
--- /dev/null
+++ b/algorithms/math/pascals_triangle.py
@@ -0,0 +1,26 @@
+
+"""
+Pascal's triangle is a triangular array of numbers in which those at the ends of the rows are 1 and each of the others is the sum of the nearest two numbers in the row above (the apex, 1, being at the top).
+
+"""
+print("Welcome to Pascal's traingle:")
+
+
+n=int(input("Enter number of rows for the pascal's traingle: "))
+a=[]
+for i in range(n):
+ a.append([])
+ a[i].append(1)
+ for j in range(1,i):
+ a[i].append(a[i-1][j-1]+a[i-1][j])
+ if(n!=0):
+ a[i].append(1)
+
+
+# printing pascal's triangle
+print( " Your Pascal's traiange for the number {}".format(n))
+for i in range(n):
+ print(" "*(n-i),end=" ",sep=" ")
+ for j in range(0,i+1):
+ print('{0:6}'.format(a[i][j]),end=" ",sep=" ")
+ print()
diff --git a/algorithms/math/recursive_greatest_common_divisor.py b/algorithms/math/recursive_greatest_common_divisor.py
new file mode 100644
index 0000000..5983355
--- /dev/null
+++ b/algorithms/math/recursive_greatest_common_divisor.py
@@ -0,0 +1,26 @@
+"""
+In mathematics, the greatest common divisor (gcd) of two or more integers,
+which are not all zero, is the largest positive integer that divides each of the integers.
+For example, the gcd of 8 and 12 is 4.
+» https://en.wikipedia.org/wiki/Greatest_common_divisor
+
+Due to limited recursion depth this algorithm is not suited for calculating the GCD of big integers.
+"""
+
+def recGCD(x, y, div = 0):
+ # Detemine which integer is greater and set the divisor accordingly
+ if div == 0:
+ if x > y:
+ div = x
+ else:
+ div = y
+ # If both integers can be divided without a remainder the gcd has been found
+ if x % div == 0 and y % div == 0:
+ return div
+ # Decrease divisor by one and try again
+ else:
+ return recGCD(x, y, div-1)
+
+x = int(input("x = "))
+y = int(input("y = "))
+print(f"gcd({x}, {y}) = {recGCD(x,y)}")
diff --git a/algorithms/math/zellers_birthday.py b/algorithms/math/zellers_birthday.py
new file mode 100644
index 0000000..5233730
--- /dev/null
+++ b/algorithms/math/zellers_birthday.py
@@ -0,0 +1,46 @@
+import argparse
+"""Zellers Congruence Birthday Algorithm
+ Find out what day of the week you were born on
+ Accepts birthday as a string in mm-dd-yyyy format
+"""
+
+def zeller(bday):
+
+ days = {
+ '0': 'Sunday',
+ '1': 'Monday',
+ '2': 'Tuesday',
+ '3': 'Wednesday',
+ '4': 'Thursday',
+ '5': 'Friday',
+ '6': 'Saturday'
+ }
+
+ m = int(bday[0] + bday[1])
+ d = int(bday[3] + bday[4])
+ y = int(bday[6] + bday[7] + bday[8] + bday[9])
+
+ if m <= 2:
+ y = y - 1
+ m = m + 12
+ c = int(str(y)[:2])
+ k = int(str(y)[2:])
+
+ t = int(2.6*m - 5.39)
+ u = int(c / 4)
+ v = int(k / 4)
+ x = d + k
+ z = t + u + v + x
+ w = z - (2 * c)
+
+ f = round(w%7)
+
+ for i in days:
+ if f == int(i):
+ print("Your birthday " + bday + ", was a " + days[i] + "!")
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(description='Find out what day of the week you were born on Accepts birthday as a string in mm-dd-yyyy or mm/dd/yyyy format')
+ parser.add_argument('bday', type=str, help='Date as a string (mm-dd-yyyy or mm/dd/yyyy)')
+ args = parser.parse_args()
+ zeller(args.bday)
\ No newline at end of file
diff --git a/algorithms/recursion/Coin-Change-Problem.py b/algorithms/recursion/Coin-Change-Problem.py
new file mode 100644
index 0000000..c88529f
--- /dev/null
+++ b/algorithms/recursion/Coin-Change-Problem.py
@@ -0,0 +1,11 @@
+def coin_change(v,items):
+ ans = 99
+ if v <= 0:
+ return 0;
+ for item in items:
+ if v - item >= 0:
+ update = 1 + coin_change(v - item, items)
+ ans = min(ans, update);
+ return ans;
+
+print(coin_change(4, [1,2,3,5]))
\ No newline at end of file
diff --git a/algorithms/recursion/Factorial By Recursion Python.py b/algorithms/recursion/Factorial By Recursion Python.py
new file mode 100644
index 0000000..25ec0d6
--- /dev/null
+++ b/algorithms/recursion/Factorial By Recursion Python.py
@@ -0,0 +1,11 @@
+#FINDING FACTORIAL THROUGH RECURSION
+def recursion(n):
+ if(n==0):
+ return 1
+ else:
+ return n*recursion(n-1)
+a=int(input("Enter The Number You Want The Factorial Of")) #Asking User The Number for the factorial
+if(a>=0): # Checking if the Number is positive or not
+ print(recursion())
+else:
+ print("Enter Valid Positive Number")
diff --git a/algorithms/recursion/Fibonacci-Series-by-python.py b/algorithms/recursion/Fibonacci-Series-by-python.py
new file mode 100644
index 0000000..33bf3a3
--- /dev/null
+++ b/algorithms/recursion/Fibonacci-Series-by-python.py
@@ -0,0 +1,13 @@
+
+### Program to calculate fibonacci series
+
+def fibo(n): // function to calculate fibonacci series
+ if(n == 0):
+ return 0
+ elif(n == 1):
+ return 1
+ else:
+ return(fibo(n-1) + fibo(n-2))
+num = int(input("Enter a number: ")) // enter number upto which you want to calculate fibonacci series
+for n in range(0,(num+1)):
+ print(fibo(n),end=" ")
diff --git a/algorithms/recursion/exponentiation.py b/algorithms/recursion/exponentiation.py
new file mode 100644
index 0000000..5709894
--- /dev/null
+++ b/algorithms/recursion/exponentiation.py
@@ -0,0 +1,21 @@
+
+def exponentiation(baseNumber, power):
+ answer = None
+
+ if power > 1:
+ halfAnswer = exponentiation(baseNumber, power//2)
+ answer = halfAnswer * halfAnswer
+
+ if power%2 == 1:
+ answer *= baseNumber
+
+ elif power == 1:
+ answer = baseNumber
+
+ elif power == 0:
+ answer = 1
+
+ else: # negative power
+ answer = 1 / exponentiation(baseNumber, abs(power))
+
+ return answer
diff --git a/searches/binary_search.py b/algorithms/searches/binary_search.py
similarity index 58%
rename from searches/binary_search.py
rename to algorithms/searches/binary_search.py
index 4140637..f32662c 100644
--- a/searches/binary_search.py
+++ b/algorithms/searches/binary_search.py
@@ -1,4 +1,10 @@
-def binarySearch(arr, l, r, x): # l is left, r is right, x is search item
+
+# Python Program for recursive binary search.
+
+# Returns index of x in arr if present, else -1
+def binarySearch (arr, l, r, x):
+
+ # Check base case
if r >= l:
mid = l + (r - l)/2
@@ -21,6 +27,14 @@ def binarySearch(arr, l, r, x): # l is left, r is right, x is search item
# Element is not present in the array
return -1
-# Tests
-result = binarySearch([ 2, 3, 4, 10, 40 ], 0, len(arr)-1, 10)
-print(result)
+# Test array
+arr = [ 2, 3, 4, 10, 40 ]
+x = 10
+
+# Function call
+result = binarySearch(arr, 0, len(arr)-1, x)
+
+if result != -1:
+ print "Element is present at index %d" % result
+else:
+ print "Element is not present in array"
diff --git a/algorithms/searches/exponential_search.py b/algorithms/searches/exponential_search.py
new file mode 100644
index 0000000..9021089
--- /dev/null
+++ b/algorithms/searches/exponential_search.py
@@ -0,0 +1,7 @@
+def exponentialSearch(lys, val):
+ if lys[0] == val:
+ return 0
+ index = 1
+ while index < len(lys) and lys[index] <= val:
+ index = index * 2
+ return BinarySearch( arr[:min(index, len(lys))], val)
diff --git a/algorithms/searches/fibonacci_search.py b/algorithms/searches/fibonacci_search.py
new file mode 100644
index 0000000..32be35d
--- /dev/null
+++ b/algorithms/searches/fibonacci_search.py
@@ -0,0 +1,65 @@
+# Python3 program for Fibonacci search.
+from bisect import bisect_left
+
+# Returns index of x if present, else
+# returns -1
+def fibMonaccianSearch(arr, x, n):
+
+ # Initialize fibonacci numbers
+ fibMMm2 = 0 # (m-2)'th Fibonacci No.
+ fibMMm1 = 1 # (m-1)'th Fibonacci No.
+ fibM = fibMMm2 + fibMMm1 # m'th Fibonacci
+
+ # fibM is going to store the smallest
+ # Fibonacci Number greater than or equal to n
+ while (fibM < n):
+ fibMMm2 = fibMMm1
+ fibMMm1 = fibM
+ fibM = fibMMm2 + fibMMm1
+
+ # Marks the eliminated range from front
+ offset = -1;
+
+ # while there are elements to be inspected.
+ # Note that we compare arr[fibMm2] with x.
+ # When fibM becomes 1, fibMm2 becomes 0
+ while (fibM > 1):
+
+ # Check if fibMm2 is a valid location
+ i = min(offset+fibMMm2, n-1)
+
+ # If x is greater than the value at
+ # index fibMm2, cut the subarray array
+ # from offset to i
+ if (arr[i] < x):
+ fibM = fibMMm1
+ fibMMm1 = fibMMm2
+ fibMMm2 = fibM - fibMMm1
+ offset = i
+
+ # If x is greater than the value at
+ # index fibMm2, cut the subarray
+ # after i+1
+ elif (arr[i] > x):
+ fibM = fibMMm2
+ fibMMm1 = fibMMm1 - fibMMm2
+ fibMMm2 = fibM - fibMMm1
+
+ # element found. return index
+ else :
+ return i
+
+ # comparing the last element with x */
+ if(fibMMm1 and arr[offset+1] == x):
+ return offset+1;
+
+ # element not found. return -1
+ return -1
+
+# Driver Code
+arr = [10, 22, 35, 40, 45, 50,
+ 80, 82, 85, 90, 100]
+n = len(arr)
+x = 85
+print("Found at index:",
+ fibMonaccianSearch(arr, x, n))
diff --git a/algorithms/searches/interpolation_search.py b/algorithms/searches/interpolation_search.py
new file mode 100644
index 0000000..7b765c4
--- /dev/null
+++ b/algorithms/searches/interpolation_search.py
@@ -0,0 +1,99 @@
+"""
+This is pure python implementation of interpolation search algorithm
+"""
+from __future__ import print_function
+import bisect
+
+try:
+ raw_input # Python 2
+except NameError:
+ raw_input = input # Python 3
+
+
+def interpolation_search(sorted_collection, item):
+ """Pure implementation of interpolation search algorithm in Python
+ Be careful collection must be sorted, otherwise result will be
+ unpredictable
+ :param sorted_collection: some sorted collection with comparable items
+ :param item: item value to search
+ :return: index of found item or None if item is not found
+ """
+ left = 0
+ right = len(sorted_collection) - 1
+
+ while left <= right:
+ point = left + ((item - sorted_collection[left]) * (right - left)) // (sorted_collection[right] - sorted_collection[left])
+
+ #out of range check
+ if point<0 or point>=len(sorted_collection):
+ return None
+
+ current_item = sorted_collection[point]
+ if current_item == item:
+ return point
+ else:
+ if item < current_item:
+ right = point - 1
+ else:
+ left = point + 1
+ return None
+
+
+def interpolation_search_by_recursion(sorted_collection, item, left, right):
+
+ """Pure implementation of interpolation search algorithm in Python by recursion
+ Be careful collection must be sorted, otherwise result will be
+ unpredictable
+ First recursion should be started with left=0 and right=(len(sorted_collection)-1)
+ :param sorted_collection: some sorted collection with comparable items
+ :param item: item value to search
+ :return: index of found item or None if item is not found
+ """
+ point = left + ((item - sorted_collection[left]) * (right - left)) // (sorted_collection[right] - sorted_collection[left])
+
+ #out of range check
+ if point<0 or point>=len(sorted_collection):
+ return None
+
+ if sorted_collection[point] == item:
+ return point
+ elif sorted_collection[point] > item:
+ return interpolation_search_by_recursion(sorted_collection, item, left, point-1)
+ else:
+ return interpolation_search_by_recursion(sorted_collection, item, point+1, right)
+
+def __assert_sorted(collection):
+ """Check if collection is sorted, if not - raises :py:class:`ValueError`
+ :param collection: collection
+ :return: True if collection is sorted
+ :raise: :py:class:`ValueError` if collection is not sorted
+ Examples:
+ >>> __assert_sorted([0, 1, 2, 4])
+ True
+ >>> __assert_sorted([10, -1, 5])
+ Traceback (most recent call last):
+ ...
+ ValueError: Collection must be sorted
+ """
+ if collection != sorted(collection):
+ raise ValueError('Collection must be sorted')
+ return True
+
+
+if __name__ == '__main__':
+ import sys
+
+ user_input = raw_input('Enter numbers separated by comma:\n').strip()
+ collection = [int(item) for item in user_input.split(',')]
+ try:
+ __assert_sorted(collection)
+ except ValueError:
+ sys.exit('Sequence must be sorted to apply interpolation search')
+
+ target_input = raw_input('Enter a single number to be found in the list:\n')
+ target = int(target_input)
+ result = interpolation_search(collection, target)
+ if result is not None:
+ print('{} found at positions: {}'.format(target, result))
+ else:
+ print('Not found')
diff --git a/algorithms/searches/jump_search.py b/algorithms/searches/jump_search.py
new file mode 100644
index 0000000..b34efc6
--- /dev/null
+++ b/algorithms/searches/jump_search.py
@@ -0,0 +1,20 @@
+import math
+
+def jumoSearch (listA, theGoalValue):
+ length = len(listA)
+ jump = int(math.sqrt(length))
+ left, right = 0, 0
+ while length > left && theGoalValue >= listA[left]:
+ right = min(length - 1, left + jump)
+ if listA[left] <= theGoalValue and listA[right] >= theGoalValue:
+ break
+ left += jump;
+ if left >= length or listA[left] > theGoalValue:
+ return -1
+ right = min(length - 1, right)
+ i = left
+ while i <= right and listA[i] <= theGoalValue:
+ if listA[i] == theGoalValue:
+ return i
+ i += 1
+ return -1
diff --git a/searches/linear_search.py b/algorithms/searches/linear_search.py
similarity index 58%
rename from searches/linear_search.py
rename to algorithms/searches/linear_search.py
index 9b45c7a..76a17a4 100644
--- a/searches/linear_search.py
+++ b/algorithms/searches/linear_search.py
@@ -1,3 +1,7 @@
+
+# Python code for linearly search x in arr[]. If x
+# is present then return its location, otherwise
+# return -1
def linear_search(arr, item):
for i in range(len(arr)):
if arr[i] == item:
diff --git a/algorithms/searches/ternary_search.py b/algorithms/searches/ternary_search.py
new file mode 100644
index 0000000..c610f9b
--- /dev/null
+++ b/algorithms/searches/ternary_search.py
@@ -0,0 +1,107 @@
+'''
+This is a type of divide and conquer algorithm which divides the search space into
+3 parts and finds the target value based on the property of the array or list
+(usually monotonic property).
+
+Time Complexity : O(log3 N)
+Space Complexity : O(1)
+'''
+from __future__ import print_function
+
+import sys
+
+try:
+ raw_input # Python 2
+except NameError:
+ raw_input = input # Python 3
+
+# This is the precision for this function which can be altered.
+# It is recommended for users to keep this number greater than or equal to 10.
+precision = 10
+
+# This is the linear search that will occur after the search space has become smaller.
+def lin_search(left, right, A, target):
+ for i in range(left, right+1):
+ if(A[i] == target):
+ return i
+
+# This is the iterative method of the ternary search algorithm.
+def ite_ternary_search(A, target):
+ left = 0
+ right = len(A) - 1;
+ while(True):
+ if(left= 0 and A[j] > k:
+ A[j + 1] = A[j]
+ A[j] = k
+ j -= 1
+ i += 1
+ return A
\ No newline at end of file
diff --git a/algorithms/sorting/cocktail_sort.py b/algorithms/sorting/cocktail_sort.py
new file mode 100644
index 0000000..71f7b38
--- /dev/null
+++ b/algorithms/sorting/cocktail_sort.py
@@ -0,0 +1,26 @@
+def cocktailSort(array)
+ n = len(array)
+ swap = 1
+ begin = 0
+ end = n-1
+ #Sorting start
+ while (swap == 1):
+ swap = 0
+
+ #sorting from begin
+ for i in range (begin, end):
+ if (a[i] > a[i+1]) :
+ a[i], a[i+1]= a[i+1], a[i]
+ swap=1
+
+ if (swap==0):
+ break swap = 0
+
+ end = end-1
+ #sorting from end
+ for i in range(end-1, begin-1,-1):
+ if (a[i] > a[i+1]):
+ a[i], a[i+1] = a[i+1], a[i]
+ swap = 1
+
+ begin = begin+1
\ No newline at end of file
diff --git a/algorithms/sorting/counting_sort.py b/algorithms/sorting/counting_sort.py
new file mode 100644
index 0000000..d6922fe
--- /dev/null
+++ b/algorithms/sorting/counting_sort.py
@@ -0,0 +1,35 @@
+#
+# Python implementation of counting sort.
+#
+#
+# The All ▲lgorithms Project
+#
+# https://allalgorithms.com/
+# https://github.com/allalgorithms/cpp
+#
+# Contributed by: Simon Faillace Mullen
+# Github: @macmullen
+#
+
+
+def counting_sort(arr):
+ # Create the counting sort array with length equal to the maximum number
+ # in the list.
+ count_array = [0] * (max(arr) + 1)
+ # Count the amount of repetitions for each number.
+ for number in arr:
+ count_array[number] += 1
+ # Append the amount of repetitions in order.
+ position = 0
+ for index, number in enumerate(count_array):
+ for amount in range(count_array[index]):
+ arr[position] = index
+ position += 1
+
+
+arr = [8, 5, 8, 4, 3, 3, 2, 1, 5, 5, 5, 9, 7, 7, 8, 1, 9, 3, 2]
+print("Unsorted array:")
+print(arr)
+counting_sort(arr)
+print("Sorted array:")
+print(arr)
diff --git a/algorithms/sorting/heap_sort.py b/algorithms/sorting/heap_sort.py
new file mode 100644
index 0000000..4c03ac4
--- /dev/null
+++ b/algorithms/sorting/heap_sort.py
@@ -0,0 +1,65 @@
+#!usr/bin/python3
+'''
+This is a pure python implementation of the heap sort algorithm.
+
+For doctests run following command:
+python -m doctest -v heap_sort.py
+or
+python3 -m doctest -v heap_sort.py
+
+For manual testing run:
+python heap_sort.py
+'''
+
+from __future__ import print_function
+
+
+def heapify(unsorted, index, heap_size):
+ largest = index
+ left_index = 2 * index + 1
+ right_index = 2 * index + 2
+ if left_index < heap_size and unsorted[left_index] > unsorted[largest]:
+ largest = left_index
+
+ if right_index < heap_size and unsorted[right_index] > unsorted[largest]:
+ largest = right_index
+
+ if largest != index:
+ unsorted[largest], unsorted[index] = unsorted[index], unsorted[largest]
+ heapify(unsorted, largest, heap_size)
+
+
+def heap_sort(unsorted):
+ '''
+ Pure implementation of the heap sort algorithm in Python
+ :param collection: some mutable ordered collection with heterogeneous
+ comparable items inside
+ :return: the same collection ordered by ascending
+
+ Examples:
+ >>> heap_sort([0, 5, 3, 2, 2])
+ [0, 2, 2, 3, 5]
+
+ >>> heap_sort([])
+ []
+
+ >>> heap_sort([-2, -5, -45])
+ [-45, -5, -2]
+ '''
+ n = len(unsorted)
+ for i in range(n // 2 - 1, -1, -1):
+ heapify(unsorted, i, n)
+ for i in range(n - 1, 0, -1):
+ unsorted[0], unsorted[i] = unsorted[i], unsorted[0]
+ heapify(unsorted, 0, i)
+ return unsorted
+
+if __name__ == '__main__':
+ try:
+ raw_input # Python 2
+ except NameError:
+ raw_input = input # Python 3
+
+ user_input = raw_input('Enter numbers separated by a comma:\n').strip()
+ unsorted = [int(item) for item in user_input.split(',')]
+ print(heap_sort(unsorted))
diff --git a/sorting/insertion_sort.py b/algorithms/sorting/insertion_sort.py
similarity index 100%
rename from sorting/insertion_sort.py
rename to algorithms/sorting/insertion_sort.py
diff --git a/algorithms/sorting/merge_sort.py b/algorithms/sorting/merge_sort.py
new file mode 100644
index 0000000..f4a37a5
--- /dev/null
+++ b/algorithms/sorting/merge_sort.py
@@ -0,0 +1,20 @@
+def merge_sort(l):
+ if len(l) < 2: return
+ pivot = len(l)//2
+ left, right = l[:pivot], l[pivot:]
+ merge_sort(left)
+ merge_sort(right)
+
+ k = 0
+ while len(left) > 0 and len(right) > 0:
+ if left[0] < right[0]:
+ l[k] = left.pop(0)
+ else:
+ l[k] = right.pop(0)
+ k += 1
+
+ rest = left + right
+ while len(rest) > 0:
+ l[k] = rest.pop(0)
+ k += 1
+
diff --git a/algorithms/sorting/quick_sort.py b/algorithms/sorting/quick_sort.py
new file mode 100644
index 0000000..16da17b
--- /dev/null
+++ b/algorithms/sorting/quick_sort.py
@@ -0,0 +1,14 @@
+"""
+Here is the implementation of quicksort algorithm in python by Pramod Bharti
+quick_sort() function takes an unsorted array and prints sorted array
+"""
+def quick_sort(arr):
+ if len(arr) <= 1:
+ return arr
+ pivot = arr[len(arr) // 2]
+ left = [x for x in arr if x < pivot]
+ middle = [x for x in arr if x == pivot]
+ right = [x for x in arr if x > pivot]
+ return quick_sort(left) + middle + quick_sort(right)
+
+print (quick_sort([5,2,8,3,9,12,43])) # This will print [2,3,5,8,9,12,43]
diff --git a/algorithms/sorting/radix_sort.py b/algorithms/sorting/radix_sort.py
new file mode 100644
index 0000000..981a976
--- /dev/null
+++ b/algorithms/sorting/radix_sort.py
@@ -0,0 +1,53 @@
+# Following is the implementation of Radix Sort.
+
+
+def radix_sort(arr, radix=10):
+ """
+ :param arr: Iterable of elements to sort.
+ :param radix: Base of input numbers
+ :return: Sorted list of input.
+ Time complexity: O(d * (n + b))
+ where, n is the size of input list.
+ b is base of representation.
+ d is number of digits in largest number in that base.
+ Space complexity: O(n + k)
+ where, k is the range of input.
+ """
+ max_length = False
+ tmp, digit = -1, 1
+
+ while not max_length:
+ max_length = True
+ # declare and initialize buckets
+ buckets = [[] for _ in range(radix)]
+
+ # split arr between lists
+ for i in arr:
+ tmp = i // digit
+ buckets[tmp % radix].append(i)
+ if max_length and tmp > 0:
+ max_length = False
+
+ # empty lists into arr array
+ a = 0
+ for b in range(radix):
+ buck = buckets[b]
+ for i in buck:
+ arr[a] = i
+ a += 1
+
+ # move to next digit
+ digit *= radix
+ return arr
+
+
+def main():
+ """
+ Driver function to test radix sort.
+ """
+ test = [170, 45, 75, 90, 802, 24, 2, 66]
+ print('Sorted array:', radix_sort(test))
+
+
+if __name__ == '__main__':
+ main()
\ No newline at end of file
diff --git a/algorithms/sorting/selection_sort.py b/algorithms/sorting/selection_sort.py
new file mode 100644
index 0000000..86e95f3
--- /dev/null
+++ b/algorithms/sorting/selection_sort.py
@@ -0,0 +1,26 @@
+from __future__ import print_function
+
+
+def selection_sort(collection):
+
+ length = len(collection)
+ for i in range(length):
+ least = i
+ for k in range(i + 1, length):
+ if collection[k] < collection[least]:
+ least = k
+ collection[least], collection[i] = (
+ collection[i], collection[least]
+ )
+ return collection
+
+
+if __name__ == '__main__':
+ try:
+ raw_input # Python 2
+ except NameError:
+ raw_input = input # Python 3
+
+ user_input = raw_input('Enter numbers separated by a comma:\n').strip()
+ unsorted = [int(item) for item in user_input.split(',')]
+ print(selection_sort(unsorted))
diff --git a/algorithms/sorting/shell_sort.py b/algorithms/sorting/shell_sort.py
new file mode 100644
index 0000000..1269179
--- /dev/null
+++ b/algorithms/sorting/shell_sort.py
@@ -0,0 +1,35 @@
+"""This is a Python implementation of the shell sort algorithm
+
+Shell sort is a variation of insertion sort. This method starts by sorting
+pairs of elements far away from each other, then progressively reducing the
+gap between elements to be compared.
+
+"""
+from random import randint
+
+
+def shell_sort(arr):
+
+ n = len(arr)
+ gap = n//2
+
+ while gap > 0:
+ for i in range(gap, n):
+ tmp = arr[i]
+
+ j = i
+ while j >= gap and arr[j-gap] > tmp:
+ arr[j] = arr[j-gap]
+ j -= gap
+ arr[j] = tmp
+
+ gap //= 2
+
+ return arr
+
+
+# Tests
+if __name__ == '__main__':
+ print(shell_sort([randint(0, 1000) for _ in range(10)]))
+ print(shell_sort([randint(-500, 500) for _ in range(10)]))
+
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/algorithms/strings/anagram_check.py b/algorithms/strings/anagram_check.py
new file mode 100644
index 0000000..5c20128
--- /dev/null
+++ b/algorithms/strings/anagram_check.py
@@ -0,0 +1,14 @@
+# function to check if two strings are
+# anagram or not
+def check(s1, s2):
+
+ # the sorted strings are checked
+ if(sorted(s1)== sorted(s2)):
+ print("The strings are anagrams.")
+ else:
+ print("The strings aren't anagrams.")
+
+# driver code
+s1 ="listen" #String 1
+s2 ="silent" #String 2
+check(s1, s2)
\ No newline at end of file
diff --git a/algorithms/strings/anagram_search.py b/algorithms/strings/anagram_search.py
new file mode 100644
index 0000000..fb902d2
--- /dev/null
+++ b/algorithms/strings/anagram_search.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python3
+
+"""
+Pythonic Implementation of Anagram search
+"""
+
+__author__ = "Aditya Krishnakumar"
+
+import collections
+
+# remove whitespaces
+def remove_whitespace(string):
+ return ''.join(string.split())
+
+"""
+ Checks if two strings are anagrams of each other, ignoring any whitespace.
+
+ First remove any whitespace and lower all characters of both strings.
+ Then create dictionaries of the counts of every character in each string.
+ As well as keep a set of all characters used in both strings.
+ Check to ensure every unique character are used in both strings the
+ same number of times.
+"""
+
+def is_anagram(string1, string2):
+ charCount1 = collections.Counter(remove_whitespace(string1.lower()))
+ charCount2 = collections.Counter(remove_whitespace(string2.lower()))
+
+ allChars = set(charCount1.keys())
+ allChars = allChars.union(charCount2.keys())
+
+ for c in allChars:
+ if (charCount1[c] != charCount2[c]):
+ return False
+
+ return True
+
+# Dry runs
+
+assert is_anagram("anagram", "not a gram") == False
+assert is_anagram("anagram", "na a marg") == True
+assert is_anagram("William Shakespeare", "I am \t a weakish speller") == True
+assert is_anagram("Madam Curie", "Radium came") == True
+assert is_anagramg("notagram", "notaflam") == False
\ No newline at end of file
diff --git a/algorithms/strings/change_case.py b/algorithms/strings/change_case.py
new file mode 100644
index 0000000..17da182
--- /dev/null
+++ b/algorithms/strings/change_case.py
@@ -0,0 +1,12 @@
+# Simple function that converts uppercase characters to lowercase and vice versa.
+# Author: jotslo
+
+def change_case(string):
+ # Iterates through string, if character is lowercase, convert to upper else lower
+ new_string = [char.upper() if char.islower() else char.lower() for char in string]
+
+ # Joins list with an empty string to form the new string and return
+ return "".join(new_string)
+
+print(change_case("Hello, world!")) # hELLO, WORLD!
+print(change_case("TEST")) # test
diff --git a/algorithms/strings/k_frequent_words.py b/algorithms/strings/k_frequent_words.py
new file mode 100644
index 0000000..2a748c2
--- /dev/null
+++ b/algorithms/strings/k_frequent_words.py
@@ -0,0 +1,17 @@
+# Python program to find the k most frequent words
+# from data set
+from collections import Counter
+
+data_set = "" #Enter long string or paragraph here
+
+# split() returns list of all the words in the string
+split_it = data_set.split()
+
+# Pass the split_it list to instance of Counter class.
+Counter = Counter(split_it)
+
+# most_common() produces k frequently encountered
+# input values and their respective counts.
+most_occur = Counter.most_common(4)
+
+print(most_occur)
\ No newline at end of file
diff --git a/algorithms/strings/letter_case_permutation.py b/algorithms/strings/letter_case_permutation.py
new file mode 100644
index 0000000..2fe616e
--- /dev/null
+++ b/algorithms/strings/letter_case_permutation.py
@@ -0,0 +1,19 @@
+# Python implementation of Letter Case Permutation
+# Author: Irsyad
+
+# This function will return every possible string with lowercase or uppercase combination of a given string.
+# Sample input and output
+# letterCasePermutation("abc") will produce ["abc","abC","aBc","aBC","Abc","AbC","ABc","ABC"]
+
+def letterCasePermutation(S):
+ result = ['']
+ for char in S:
+ if char.isalpha():
+ result = [i+j for i in result for j in [char.lower(), char.upper()]]
+ else:
+ result = [i+char for i in result]
+ print result
+ return result
+
+# Test
+print(letterCasePermutation("a1b2"))
\ No newline at end of file
diff --git a/algorithms/strings/levenstein.py b/algorithms/strings/levenstein.py
new file mode 100644
index 0000000..66ad47d
--- /dev/null
+++ b/algorithms/strings/levenstein.py
@@ -0,0 +1,9 @@
+def distance_levenstein(a, b):
+ f = [[(i+j) if i*j == 0 else 0 for j in range(len(b)+1)] for i in range(len(a) + 1)]
+ for i in range(1, len(a) + 1):
+ for j in range(1, len(b) + 1):
+ if a[i-1] == b[j-1]:
+ f[i][j] = f[i-1][j-1]
+ else:
+ f[i][j] = 1 + min(f[i-1][j], f[i][j-1], f[i-1][j-1])
+ return f[len(a)][len(b)]
diff --git a/algorithms/strings/longest_substring.py b/algorithms/strings/longest_substring.py
new file mode 100644
index 0000000..47dffcd
--- /dev/null
+++ b/algorithms/strings/longest_substring.py
@@ -0,0 +1,34 @@
+# Create an algorithm that prints the longest substring of s in which
+# the letters occur in alphabetical order. For example, if
+# s = 'azcbobobegghakl', then your program should print:
+# Longest substring in alphabetical order is: beggh
+
+# In the case of ties, print the first substring.
+# For example, if s = 'abcbcd', then your program should print:
+# Longest substring in alphabetical order is: abc
+
+
+def longest_substr(s):
+ count = 0
+ maxcount = 0
+ result = 0
+ for char in range(len(s) - 1):
+ if (s[char] <= s[char + 1]):
+ count += 1
+ if count > maxcount:
+ maxcount = count
+ result = char + 1
+ else:
+ count = 0
+ startposition = result - maxcount
+ return startposition, result
+
+
+# parent string
+s = 'azbeggaklbeggh'
+
+# longest substring indexes
+start, end = longest_substr(s)
+
+print('Longest substring in alphabetical order is:',
+ s[start:end + 1])
diff --git a/algorithms/strings/morse_code.py b/algorithms/strings/morse_code.py
new file mode 100644
index 0000000..4a48462
--- /dev/null
+++ b/algorithms/strings/morse_code.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+"""
+Pythonic Implementation of Morse Code encoding
+"""
+
+__author__ = "Aditya Krishnakumar"
+
+
+# The alphabet dictionary for morse codes
+morseAlphabet = {
+ "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": "--..",
+ "1": ".----",
+ "2": "..---",
+ "3": "...--",
+ "4": "....-",
+ "5": ".....",
+ "6": "-....",
+ "7": "--...",
+ "8": "---..",
+ "9": "----.",
+ "0": "-----"
+}
+
+# Lambda function for decoding the code to alphabet
+inverseAlphabet = reduce(lambda a, b: dict(a.items() + b.items()),
+ [{
+ morseAlphabet[k]: k
+ } for k in morseAlphabet.keys()], {})
+
+
+def encode(_text):
+ return ' '.join([morseAlphabet[_c.upper()] for _c in _text[:]])
+
+
+def decode(_text):
+ return ''.join([inverseAlphabet[_c] for _c in _text.split(' ')])
+
+# Dry runner
+def test():
+ print decode(encode("TEST")) == "TEST"
+
+
+if __name__ == "__main__":
+ test()
\ No newline at end of file
diff --git a/strings/palindrome.py b/algorithms/strings/palindrome.py
similarity index 63%
rename from strings/palindrome.py
rename to algorithms/strings/palindrome.py
index 82cc06e..698983b 100644
--- a/strings/palindrome.py
+++ b/algorithms/strings/palindrome.py
@@ -3,12 +3,14 @@ def reverse(s):
return s[::-1]
def isPalindrome(s):
+ # Convert s to uppercase to ignore case sensitivity
+ s = s.upper()
# Checking if both string are equal or not
if (s == reverse(s)):
return True
return False
# Tests
-print(isPalindrome('racecar'))
+print(isPalindrome('Racecar'))
print(isPalindrome('ferrari'))
-print(isPalindrome('civic'))
+print(isPalindrome('CiVIc'))
diff --git a/algorithms/strings/password_checker.py b/algorithms/strings/password_checker.py
new file mode 100644
index 0000000..8743ea5
--- /dev/null
+++ b/algorithms/strings/password_checker.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python3
+
+import re, pyperclip
+
+password = pyperclip.paste()
+
+eightLettersRegex = re.compile(r'\S{8,}')
+oneUppercaseRegex = re.compile(r'[A-Z]')
+oneNumberRegex = re.compile(r'\d')
+
+check = {
+ eightLettersRegex: 'Your password must be 8 letters',
+ oneUppercaseRegex: 'Your password must have at least one uppercase Letter.',
+ oneNumberRegex: 'Your password must have at least one number.'
+}
+
+print('Analyzing your password.')
+
+count = 1
+for regex, msg in check.items():
+ mo = regex.search(password)
+ if mo == None:
+ print(msg)
+ break
+ if count == len(check):
+ print('Good! Your password is strong enough!')
+ count += 1
+
+print('End.')
\ No newline at end of file
diff --git a/algorithms/strings/pattern_match.py b/algorithms/strings/pattern_match.py
new file mode 100644
index 0000000..9124049
--- /dev/null
+++ b/algorithms/strings/pattern_match.py
@@ -0,0 +1,24 @@
+# A Python program to demonstrate working
+# of re.match().
+import re
+
+# a sample function that uses regular expressions
+# to find month and day of a date.
+def findMonthAndDate(string):
+
+ regex = r"([a-zA-Z]+) (\d+)"
+ match = re.match(regex, string)
+
+ if match == None:
+ print "Not a valid date"
+ return
+
+ print "Given Data: %s" % (match.group())
+ print "Month: %s" % (match.group(1))
+ print "Day: %s" % (match.group(2))
+
+
+# Driver Code
+findMonthAndDate("" #Enter pattern to match)
+print("")
+findMonthAndDate("") #Enter string
\ No newline at end of file
diff --git a/algorithms/strings/rabin_karp.py b/algorithms/strings/rabin_karp.py
new file mode 100644
index 0000000..721e890
--- /dev/null
+++ b/algorithms/strings/rabin_karp.py
@@ -0,0 +1,46 @@
+#!/usr/local/bin/env python3
+
+# Rabin Karp Algorithm in python using hash values
+# d is the number of characters in input alphabet
+d = 2560
+
+
+def search(pat, txt, q):
+ M = len(pat)
+ N = len(txt)
+ i = 0
+ j = 0
+
+ p = 0
+ t = 0
+ h = 1
+
+ for i in range(M - 1):
+ h = (h * d) % q
+
+ for i in range(M):
+ p = (d * p + ord(pat[i])) % q
+ t = (d * t + ord(txt[i])) % q
+
+ for i in range(N - M + 1):
+ if p == t:
+ for j in range(M):
+ if txt[i + j] != pat[j]:
+ break
+
+ j += 1
+ if j == M:
+ print("Pattern found at index " + str(i))
+
+ if i < N - M:
+ t = (d * (t - ord(txt[i]) * h) + ord(txt[i + M])) % q
+ if t < 0:
+ t = t + q
+
+
+# Driver program to test the above function
+txt = "ALL WORLDS IS A STAGE AND ALL OF US ARE A PART OF THE PLAY"
+pat = "ALL"
+
+q = 101 # A prime number
+search(pat, txt, q)
\ No newline at end of file
diff --git a/algorithms/strings/recursive_palindrome.py b/algorithms/strings/recursive_palindrome.py
new file mode 100644
index 0000000..e216872
--- /dev/null
+++ b/algorithms/strings/recursive_palindrome.py
@@ -0,0 +1,10 @@
+def checkString(string):
+ string = string.lower()
+ if(len(string) > 2):
+ if(string[0] == string[-1]):
+ return checkString(string[1 : -1])
+ else:
+ return False
+ else: return string[0] == string[-1]
+
+print(checkString(input("check word for palindrome: ")))
diff --git a/algorithms/strings/substring_check.py b/algorithms/strings/substring_check.py
new file mode 100644
index 0000000..bb05678
--- /dev/null
+++ b/algorithms/strings/substring_check.py
@@ -0,0 +1,8 @@
+def substring_check(string, sub_str):
+ return sub_str in string
+
+string = "Hello everyone"
+sub_str_present ="llo e"
+sub_str_absent ="abcd"
+print(substring_check(string, sub_str_present)) # True
+print(substring_check(string, sub_str_absent)) # False
diff --git a/algorithms/strings/vowel_count.py b/algorithms/strings/vowel_count.py
new file mode 100644
index 0000000..948f4c4
--- /dev/null
+++ b/algorithms/strings/vowel_count.py
@@ -0,0 +1,28 @@
+# Python3 code to count vowel in
+# a string using set
+
+# Function to count vowel
+def vowel_count(str):
+
+ # Intializing count variable to 0
+ count = 0
+
+ # Creating a set of vowels
+ vowel = set("aeiouAEIOU")
+
+ # Loop to traverse the alphabet
+ # in the given string
+ for alphabet in str:
+
+ # If alphabet is present
+ # in set vowel
+ if alphabet in vowel:
+ count = count + 1
+
+ print("No. of vowels :", count)
+
+# Driver code
+str = "" #Enter string
+
+# Function Call
+vowel_count(str)
\ No newline at end of file
diff --git a/algorithms/strings/word_length_dict.py b/algorithms/strings/word_length_dict.py
new file mode 100644
index 0000000..673fb8d
--- /dev/null
+++ b/algorithms/strings/word_length_dict.py
@@ -0,0 +1,10 @@
+"""
+ Determines the length of each word in a string and puts the word and its length in a dictionary
+"""
+
+def word_length_dict(text):
+ d = {e: len(e) for e in text.split(" ")}
+ return d
+
+text = "The quick brown fox jumps over the lazy dog"
+print(word_length_dict(text))
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/Array Intersection.py b/data-structures/Array Intersection.py
new file mode 100644
index 0000000..86545d5
--- /dev/null
+++ b/data-structures/Array Intersection.py
@@ -0,0 +1,14 @@
+### Here You can Use this Program For Finding Same elements in two Arrays.
+def Array_Inter(arr1,n,arr2,m): ## Here I am Function
+ for i in range(n) :
+ for j in range(m) :
+ if arr1[i] == arr2[j] :
+ print(arr1[i], end = " ")
+ break
+t=int(input("Test cases: ")) ## take test cases to be run
+for k in range(t):
+ n=int(input("Size of Array One: ")) ## Size of array one by the user
+ arr1=[int(x) for x in input().split()] ## take inputs from user seperated by space
+ m=int(input("Size Of Array Two: "))
+ arr2=[int(y) for y in input().split()]
+Array_Inter(arr1,n,arr2,m)
diff --git a/data-structures/InorderTreeTraversal.py b/data-structures/InorderTreeTraversal.py
new file mode 100644
index 0000000..4929c7c
--- /dev/null
+++ b/data-structures/InorderTreeTraversal.py
@@ -0,0 +1,50 @@
+class Node:
+ """A binary tree node"""
+ def __init__(self, data, left=None, right=None):
+ self.data = data
+ self.left = left
+ self.right = right
+
+
+def morris_traversal(root):
+ """Generator function for iterative inorder tree traversal"""
+
+ current = root
+
+ while current is not None:
+
+ if current.left is None:
+ yield current.data
+ current = current.right
+ else:
+
+ # Find the inorder predecessor of current
+ pre = current.left
+ while pre.right is not None and pre.right is not current:
+ pre = pre.right
+
+ if pre.right is None:
+
+ # Make current as right child of its inorder predecessor
+ pre.right = current
+ current = current.left
+
+ else:
+ # Revert the changes made in the 'if' part to restore the
+ # original tree. i.e., fix the right child of predecessor
+ pre.right = None
+ yield current.data
+ current = current.right
+
+# Driver program to test the above function
+
+root = Node(1,
+ right = Node(3),
+ left = Node(2,
+ left = Node(4),
+ right = Node(5)
+ )
+ )
+
+for v in morris_traversal(root):
+ print(v, end=' ')
diff --git a/data-structures/binarySerach.py b/data-structures/binarySerach.py
new file mode 100644
index 0000000..4169aee
--- /dev/null
+++ b/data-structures/binarySerach.py
@@ -0,0 +1,25 @@
+def binSearch(a, x, low, high):
+ #Return True if target is found in indicated portion of a Python list.
+ #The search only considers the portion from data[low] to data[high] inclusive.
+
+ if low > high:
+ return False # interval is empty; no match
+ else:
+ mid = (low + high) // 2
+ if x == a[mid]: # found a match
+ return True
+ elif x < a[mid]:
+ # recur on the portion left of the middle
+ return binSearch(a, x, low, mid - 1)
+ else:
+ # recur on the portion right of the middle
+ return binSearch(a, x, mid + 1, high)
+a = [5, 10, 15, 20, 25, 30, 40]
+x = 20
+low = 0
+high = 6
+result = binSearch(a, x, low, high)
+if result:
+ print("The value ", x, " Found")
+else:
+ print("The value ", x, " Not found")
diff --git a/data-structures/dequeue.py b/data-structures/dequeue.py
new file mode 100644
index 0000000..884c698
--- /dev/null
+++ b/data-structures/dequeue.py
@@ -0,0 +1,48 @@
+class Dequeue:
+ def __init__(self):
+ self.items = []
+
+ def is_empty(self):
+ return self.items == []
+
+ def append(self, data):
+ self.items.append(data)
+
+ def append_left(self, data):
+ self.items.insert(0, data)
+
+ def pop(self):
+ return self.items.pop()
+
+ def pop_left(self):
+ return self.items.pop(0)
+
+
+q = Dequeue()
+print('Menu')
+print('append ')
+print('appendleft ')
+print('pop')
+print('popleft')
+print('quit')
+
+while True:
+ do = input('What would you like to do? ').split()
+
+ operation = do[0].strip().lower()
+ if operation == 'append':
+ q.append(int(do[1]))
+ elif operation == 'appendleft':
+ q.append_left(int(do[1]))
+ elif operation == 'pop':
+ if q.is_empty():
+ print('Dequeue is empty.')
+ else:
+ print('Popped value from right: ', q.pop())
+ elif operation == 'popleft':
+ if q.is_empty():
+ print('Dequeue is empty.')
+ else:
+ print('Popped value from left: ', q.pop_left())
+ elif operation == 'quit':
+ break
\ No newline at end of file
diff --git a/data-structures/linked-lists/circulardoublylinkedlist.py b/data-structures/linked-lists/circulardoublylinkedlist.py
new file mode 100644
index 0000000..eef2769
--- /dev/null
+++ b/data-structures/linked-lists/circulardoublylinkedlist.py
@@ -0,0 +1,109 @@
+class Node:
+ def __init__(self, data):
+ self.data = data
+ self.next = None
+ self.prev = None
+
+
+class CircularDoublyLinkedList:
+ def __init__(self):
+ self.first = None
+
+ def get_node(self, index):
+ current = self.first
+ for i in range(index):
+ current = current.next
+ if current == self.first:
+ return None
+ return current
+
+ def insert_after(self, ref_node, new_node):
+ new_node.prev = ref_node
+ new_node.next = ref_node.next
+ new_node.next.prev = new_node
+ ref_node.next = new_node
+
+ def insert_before(self, ref_node, new_node):
+ self.insert_after(ref_node.prev, new_node)
+
+ def insert_at_end(self, new_node):
+ if self.first is None:
+ self.first = new_node
+ new_node.next = new_node
+ new_node.prev = new_node
+ else:
+ self.insert_after(self.first.prev, new_node)
+
+ def insert_at_beg(self, new_node):
+ self.insert_at_end(new_node)
+ self.first = new_node
+
+ def remove(self, node):
+ if self.first.next == self.first:
+ self.first = None
+ else:
+ node.prev.next = node.next
+ node.next.prev = node.prev
+ if self.first == node:
+ self.first = node.next
+
+ def display(self):
+ if self.first is None:
+ return
+ current = self.first
+ while True:
+ print(current.data, end = ' ')
+ current = current.next
+ if current == self.first:
+ break
+
+
+a_cdllist = CircularDoublyLinkedList()
+
+print('Menu')
+print('insert after ')
+print('insert before ')
+print('insert at beg')
+print('insert at end')
+print('remove ')
+print('quit')
+
+while True:
+ print('The list: ', end = '')
+ a_cdllist.display()
+ print()
+ do = input('What would you like to do? ').split()
+
+ operation = do[0].strip().lower()
+
+ if operation == 'insert':
+ data = int(do[1])
+ position = do[3].strip().lower()
+ new_node = Node(data)
+ suboperation = do[2].strip().lower()
+ if suboperation == 'at':
+ if position == 'beg':
+ a_cdllist.insert_at_beg(new_node)
+ elif position == 'end':
+ a_cdllist.insert_at_end(new_node)
+ else:
+ index = int(position)
+ ref_node = a_cdllist.get_node(index)
+ if ref_node is None:
+ print('No such index.')
+ continue
+ if suboperation == 'after':
+ a_cdllist.insert_after(ref_node, new_node)
+ elif suboperation == 'before':
+ a_cdllist.insert_before(ref_node, new_node)
+
+ elif operation == 'remove':
+ index = int(do[1])
+ node = a_cdllist.get_node(index)
+ if node is None:
+ print('No such index.')
+ continue
+ a_cdllist.remove(node)
+
+ elif operation == 'quit':
+ break
\ No newline at end of file
diff --git a/data-structures/linked-lists/circularsinglelinkedlist.py b/data-structures/linked-lists/circularsinglelinkedlist.py
new file mode 100644
index 0000000..1ef3c6e
--- /dev/null
+++ b/data-structures/linked-lists/circularsinglelinkedlist.py
@@ -0,0 +1,116 @@
+class Node:
+ def __init__(self, data):
+ self.data = data
+ self.next = None
+
+
+class CircularLinkedList:
+ def __init__(self):
+ self.head = None
+
+ def get_node(self, index):
+ if self.head is None:
+ return None
+ current = self.head
+ for i in range(index):
+ current = current.next
+ if current == self.head:
+ return None
+ return current
+
+ def get_prev_node(self, ref_node):
+ if self.head is None:
+ return None
+ current = self.head
+ while current.next != ref_node:
+ current = current.next
+ return current
+
+ def insert_after(self, ref_node, new_node):
+ new_node.next = ref_node.next
+ ref_node.next = new_node
+
+ def insert_before(self, ref_node, new_node):
+ prev_node = self.get_prev_node(ref_node)
+ self.insert_after(prev_node, new_node)
+
+ def insert_at_end(self, new_node):
+ if self.head is None:
+ self.head = new_node
+ new_node.next = new_node
+ else:
+ self.insert_before(self.head, new_node)
+
+ def insert_at_beg(self, new_node):
+ self.insert_at_end(new_node)
+ self.head = new_node
+
+ def remove(self, node):
+ if self.head.next == self.head:
+ self.head = None
+ else:
+ prev_node = self.get_prev_node(node)
+ prev_node.next = node.next
+ if self.head == node:
+ self.head = node.next
+
+ def display(self):
+ if self.head is None:
+ return
+ current = self.head
+ while True:
+ print(current.data, end = ' ')
+ current = current.next
+ if current == self.head:
+ break
+
+
+a_cllist = CircularLinkedList()
+
+print('Menu')
+print('insert after ')
+print('insert before ')
+print('insert at beg')
+print('insert at end')
+print('remove ')
+print('quit')
+
+while True:
+ print('The list: ', end = '')
+ a_cllist.display()
+ print()
+ do = input('What would you like to do? ').split()
+
+ operation = do[0].strip().lower()
+
+ if operation == 'insert':
+ data = int(do[1])
+ position = do[3].strip().lower()
+ new_node = Node(data)
+ suboperation = do[2].strip().lower()
+ if suboperation == 'at':
+ if position == 'beg':
+ a_cllist.insert_at_beg(new_node)
+ elif position == 'end':
+ a_cllist.insert_at_end(new_node)
+ else:
+ index = int(position)
+ ref_node = a_cllist.get_node(index)
+ if ref_node is None:
+ print('No such index.')
+ continue
+ if suboperation == 'after':
+ a_cllist.insert_after(ref_node, new_node)
+ elif suboperation == 'before':
+ a_cllist.insert_before(ref_node, new_node)
+
+ elif operation == 'remove':
+ index = int(do[1])
+ node = a_cllist.get_node(index)
+ if node is None:
+ print('No such index.')
+ continue
+ a_cllist.remove(node)
+
+ elif operation == 'quit':
+ break
\ No newline at end of file
diff --git a/data-structures/linked-lists/is_palindrome.py b/data-structures/linked-lists/is_palindrome.py
new file mode 100644
index 0000000..22c93ce
--- /dev/null
+++ b/data-structures/linked-lists/is_palindrome.py
@@ -0,0 +1,72 @@
+def is_palindrome(head):
+ if not head:
+ return True
+ fast, slow = head.next, head
+ while fast and fast.next:
+ fast = fast.next.next
+ slow = slow.next
+ second = slow.next
+ node = None
+ while second:
+ nxt = second.next
+ second.next = node
+ node = second
+ second = nxt
+ while node:
+ if node.val != head.val:
+ return False
+ node = node.next
+ head = head.next
+ return True
+
+
+def is_palindrome_stack(head):
+ if not head or not head.next:
+ return True
+
+ # Get the midpoint
+ slow = fast = cur = head
+ while fast and fast.next:
+ fast, slow = fast.next.next, slow.next
+
+ # Push the second half into the stack
+ stack = [slow.val]
+ while slow.next:
+ slow = slow.next
+ stack.append(slow.val)
+
+ # Comparison
+ while stack:
+ if stack.pop() != cur.val:
+ return False
+ cur = cur.next
+
+ return True
+
+
+def is_palindrome_dict(head):
+ if not head or not head.next:
+ return True
+ d = {}
+ pos = 0
+ while head:
+ if head.val in d.keys():
+ d[head.val].append(pos)
+ else:
+ d[head.val] = [pos]
+ head = head.next
+ pos += 1
+ checksum = pos - 1
+ middle = 0
+ for v in d.values():
+ if len(v) % 2 != 0:
+ middle += 1
+ else:
+ step = 0
+ for i in range(0, len(v)):
+ if v[i] + v[len(v) - 1 - step] != checksum:
+ return False
+ step += 1
+ if middle > 1:
+ return False
+ return True
diff --git a/data-structures/linked-lists/singleLinkedModule.py b/data-structures/linked-lists/singleLinkedModule.py
new file mode 100644
index 0000000..bda9418
--- /dev/null
+++ b/data-structures/linked-lists/singleLinkedModule.py
@@ -0,0 +1,97 @@
+# The program that creates a single link list of true values
+# and implements the actions outlined in the link list.
+
+class LinkedList:
+ class ListNode:
+ def __init__(self, data, next= None):
+ self.info = data
+ self.next = next
+
+ def getInfo(self):
+ return self.info
+
+ def setInfo(self, value):
+ self.info = value
+
+ def getNext(self):
+ return self.next
+
+ def setNext(self, ptr):
+ self.next = ptr #end of listNode class
+
+ def __init__(self):
+ self.head = None
+ self.last = None
+ self.size = 0
+
+ def __del__(self):
+ current = self.head
+ while current:
+ ptr = current
+ current = current.next
+ del ptr
+
+ def getSize(self):
+ return self.size
+ def isEmpty(self):
+ return self.head == None
+
+#Search Node
+
+ def searchNode(self, data):
+ if (self.isEmpty()):
+ return None
+ else:
+ ptr = self.head
+ found = False
+ while ptr and found is False:
+ if ptr.getInfo() == data:
+ found == True
+ else:
+ ptr == ptr.getNext()
+ return ptr
+
+ def insertAtFirst(self, ptr):
+ self.head = ptr
+ self.size += 1
+ if self.getSize() == 1:
+ self.last = self.head
+ return True
+
+ def insertAfterNode(self, ptr):
+ if (self.isEmpty()):
+ self.head = self.last = ptr
+ else:
+ self.last.next = ptr
+ self.last = ptr
+ self.size += 1
+
+ def deleteNode(self, data):
+ current = self.head
+ pre = None
+ found = False
+ while current and found is False:
+ if current.getInfo() == data:
+ found = True
+ else:
+ pre = current
+ current = current.getNext()
+ if found:
+ if current == self.head: #first Node deleted
+ self.head = current.next
+ del current
+ else:
+ pre.next = current.next
+ current.next = None
+ del current #current = None
+ self.size -= 1
+ return found
+
+ def traverse(self):
+ if (self.isEmpty() != True):
+ ptr = self.head
+ while ptr:
+ print(ptr.info, end = "\n")
+ ptr = ptr.getNext()
+
+
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()
+
diff --git a/license b/license
new file mode 100644
index 0000000..559a12b
--- /dev/null
+++ b/license
@@ -0,0 +1,22 @@
+MIT License
+
+Copyright (c) 2018 All Algorithms and its contributors (allalgorithms.com)
+Copyright (c) 2018 Carlos Abraham (abranhe.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..dd64172
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,416 @@
+We are accepting all pull requests. [Read More](https://github.com/AllAlgorithms/algorithms/issues/40)
+
+
+
+## See
+
+- [What is an algorithm](#what-is-an-algorithm)
+- [Contributing](https://github.com/AllAlgorithms/algorithms/blob/master/.github/contributing.md)
+- [Code of Conduct](https://github.com/AllAlgorithms/algorithms/blob/master/.github/code-of-conduct.md)
+- [Stickers and T-Shirts](https://www.redbubble.com/people/abranhe/works/34285088)
+- [Twitter](https://twitter.com/AllAlgorithms)
+- [Instagram](https://instagram.com/AllAlgorithms)
+- [Algorithms Categories](#categories)
+- [Maintainers](#maintainers)
+- [License](#license)
+
+
+## What is an algorithm?
+
+Informally, an algorithm is any well-defined computational procedure that takes
+some value, or set of values, as input and produces some value, or set of values, as
+output. An algorithm is thus a sequence of computational steps that transform the
+input into the output.
+
+An algorithm should have three important characteristics to be considered valid:
+
+- **It should be finite**: If your algorithm never ends trying to solve the problem
+it was designed to solve then it is useless
+- **It should have well defined instructions**: Each step of the algorithm has to
+be precisely defined; the instructions should be unambiguously specified for each case.
+- **It should be effective**: The algorithm should solve the problem it was designed
+to solve. And it should be possible to demonstrate that the algorithm converges with
+just a paper and pencil.
+
+## Categories
+
+> Structure of The All ▲lgoritms project
+
+- [Artificial Intelligence](#artificial-intelligence)
+- [Backtracking](#backtracking)
+- [Bit Manipulation](#bit-manipulation)
+- [Cellular Automaton](#cellular-automaton)
+- [Ciphers](#ciphers)
+- [Computational Geometry](#computational-geometry)
+- [Cryptography](#cryptography)
+- [Data Structures](#data-structures)
+- [Divide and conquer](#divide-and-conquer)
+- [Dynamic Programming](#dynamic-programming)
+- [Gaming Theory](#gaming-theory)
+- [Graphs](#graphs)
+- [Greedy Algorithms](#greedy-algorithms)
+- [Math](#math)
+- [Networking](#networking)
+- [Numerical Analysis](#numerical-analysis)
+- [Operating system](#operating-system)
+- [Randomized Algorithms](#randomized-algorithms)
+- [Searches](#searches)
+- [Selections Algorithms](#selections-algorithms)
+- [Sorting](#sorting)
+- [Strings](#strings)
+- [Online Challenges](#online-challenges)
+- [Others](#others)
+
+## [Artificial Intelligence](artificial-intelligence)
+
+- [Density-based spatial clustering of applications with noise (DBSCAN Clustering)](https://allalgorithms.com/docs/dbscan)
+- [Interactive Self-Organizing Data Analysis Technique yAy! (ISODATA Clustering)](https://allalgorithms.com/docs/isodata)
+- [Linear Regression](https://allalgorithms.com/docs/linear-regression)
+- [Logistic Regression](https://allalgorithms.com/docs/logistic-regression)
+- [Neutral Style Transfer](https://allalgorithms.com/docs/neutral-style-transfer)
+- [SATisfiable (SAT)](https://allalgorithms.com/docs/sat)
+- [Travelling salesman problem (TSP)](https://allalgorithms.com/docs/tsp)
+- [A* (A Star)](https://allalgorithms.com/docs/a-star)
+- [Artificial Neutral Network](https://allalgorithms.com/docs/artificial-neutral-network)
+- [Convolutional Neutral Network](https://allalgorithms.com/docs/convolutional-neutral-network)
+- [Decision Tree](https://allalgorithms.com/docs/decision-tree)
+- [Factorization Machines](https://allalgorithms.com/docs/factorization-machines)
+- [Gaussian Mixture Model](https://allalgorithms.com/docs/gaussian-mixtrue-model)
+- [Gradient Boosting Trees](https://allalgorithms.com/docs/gradient-boostring-trees)
+- [Hierachical Clustering](https://allalgorithms.com/docs/hierachical-clustering)
+- [Image Processing](https://allalgorithms.com/docs/image-processing)
+- [K Nearest Neighbors](https://allalgorithms.com/docs/k-nearest-neighbors)
+- [K Means](https://allalgorithms.com/docs/k-means)
+- [Minimax](https://allalgorithms.com/docs/minimax)
+- [Native Bayes](https://allalgorithms.com/docs/native-bayes)
+- [Nearest Sequence Memory](https://allalgorithms.com/docs/nearest-sequence-memory)
+- [Neutral Network](https://allalgorithms.com/docs/neutral-network)
+- [Perceptron](https://allalgorithms.com/docs/perceptron)
+- [Principal Component Analysis](https://allalgorithms.com/docs/principal-component-analysis)
+- [Q Learing](https://allalgorithms.com/docs/q-learning)
+- [Random Forests](https://allalgorithms.com/docs/random-forest)
+- [Restricted Boltzman Machine](https://allalgorithms.com/docs/restricted-boltzman-machine)
+
+## [Backtracking](backtracking)
+
+- [Algorithm X](backtracking/algorithm-x)
+- [Crossword Puzzle](backtracking/crossword-Puzzle)
+- [Knight Tour](backtracking/knight-tour)
+- [M Coloring Problem](backtracking/m-coloring-problem)
+- [N Queen](backtracking/n-queen)
+- [Number of ways in Maze](backtracking/number-of-ways-in-maze)
+- [Partitions of set](backtracking/partitions-of-set)
+- [Permutation of Strings](backtracking/permutation-of-strings)
+- [Powerset](backtracking/powerset)
+- [Rat in maze](backtracking/rat-in-maze)
+- [Subset Sum](backtracking/subset-sum)
+- [Sudoku Solve](backtracking/sudoku-solve)
+
+## [Bit Manipulation](bit-manipulation)
+
+- [Addition using bits](bit-manipulation/adding-using-bits)
+- [Bit divisor](bit-manipulation/bit-divisor)
+- [Byte swapper](bit-manipulation/byte-swapper)
+- [Convert numbers to binary](bit-manipulation/convert-numbers-to-binary)
+- [Count set bits](bit-manipulation/count-set-bits)
+- [Flip bits](bit-manipulation/flip-bits)
+- [Hamming distance](bit-manipulation/hamming-distace)
+- [Invert bit](bit-manipulation/invert-bit)
+- [Lonely integer](bit-manipulation/lonely-integer)
+- [Magic Number](bit-manipulation/magic-number)
+- [Maximum XOR Value](bit-manipulation/maximun-xor-value)
+- [Power of 2](bit-manipulation/power-of-2)
+- [Subset Generation](bit-manipulation/subset-generation)
+- [Sum binary numbers](bit-manipulation/sum-binary-numbers)
+- [Sum equals XOR](bit-manipulation/sum-equals-xor)
+- [Thrice unique number](bit-manipulation/thrice-unique-number)
+- [Twice unique number](bit-manipulation/twice-unique-number)
+- [XOR Swap](bit-manipulation/xor-swap)
+
+## [Cellular Automaton](cellular-automaton)
+
+- [Brians Brain](cellular-automaton/brians-brain)
+- [Conways Game of life](cellular-automaton/conways-game-of-life)
+- [Elementary Cellular Automata](cellular-automaton/elementary-cellular-automata)
+- [Generic Algorithm](cellular-automaton/generic-algorithm)
+- [Langtons Ant](cellular-automaton/langtons-ant)
+- [Nobili Cellular Automata](cellular-automaton/nobili-cellular-automata)
+- [Von Neoumann Cellular Automata](cellular-automaton/von-neoumann-cellular-automata)
+
+## [Computational Geometry](computational-geometry)
+
+- [2D Line intersection](computational-geometry/)
+- [2D Separating Axis test](computational-geometry/)
+- [Area of polygon](computational-geometry/)
+- [Area of triangle](computational-geometry/)
+- [Axis aligned bounding box collision](computational-geometry/)
+- [Bresenham Line](computational-geometry/)
+- [Chans Algorithm](computational-geometry/)
+- [Cohen Sutherland Lineclip](computational-geometry/)
+- [Distance between points](computational-geometry/)
+- [Graham Scan](computational-geometry/)
+- [Halfplane intersection](computational-geometry/)
+- [Jarvis March](computational-geometry/)
+- [Quickull](computational-geometry/)
+- [Sphere tetrahedron intersection](computational-geometry/)
+- [Sutherland Hodgeman clipping](computational-geometry/)
+
+## [Cryptography](cryptography)
+
+- [Affine Cipher](cryptography/)
+- [Atbash Cipher](cryptography/)
+- [Autokey Cipher](cryptography/)
+- [Baconian Cipher](cryptography/)
+- [Caesar Cipher](cryptography/)
+- [Colummnar Cipher](cryptography/)
+- [Vigenere Cipher](cryptography/)
+
+## [Data Structures](data-structures)
+
+- [Bag](data-structures/bag/)
+- [Hashes](data-structures/hashes/)
+- [Linked List](data-structures/linked-list/)
+- [List](data-structures/list/)
+- [Queue](data-structures/queue/)
+- [Stack](data-structures/stack/)
+- [Tree](data-structures/tree/)
+
+## [Divide and conquer](divide-and-conquer)
+
+- [Strassen Matrix Manipulation](divide-and-conquer/)
+- [Closest Pair of Point](divide-and-conquer/)
+- [Inversion Count](divide-and-conquer/)
+- [Karatsuba Multiplication](divide-and-conquer/)
+- [Maximum Contiguous subsequence sum](divide-and-conquer/)
+- [Merge Sort using divide and conquer](divide-and-conquer/)
+- [Quick Sort using divide and conquer](divide-and-conquer/)
+- [Tournament Method to find min max](divide-and-conquer/)
+- [Warnock Algorithm](divide-and-conquer/)
+- [X Power Y](divide-and-conquer/)
+
+## [Dynamic Programming](dynamic-programming)
+
+- [Array Median](dynamic-programming)
+- [Optima Binary Search Tree](dynamic-programming)
+- [Binomial Coefficient](dynamic-programming)
+
+## [Gaming Theory](gaming-theory)
+
+- [Nim Next Best Move Game](gaming-theory/)
+- [Nim Win Loss Game](gaming-theory/)
+- [Grundy Numbers Kayle Game](gaming-theory/)
+
+## [Graphs](graphs)
+
+- [Bipartite Check](graphs/)
+- [Adjacency Lists graphs representation](graphs/)
+- [A* (A Star)](https://allalgorithms.com/docs/a-star)
+
+## [Greedy Algorithms](greedy-algorithms)
+
+- [Activity Selection](greedy-algorithms)
+- [Dijkstra Shortest Path](greedy-algorithms)
+- [Egyptian Fraction](greedy-algorithms)
+
+## [Math](math)
+
+- [2 Sum](math/)
+- [Add Polynomials](math/)
+- [Amicable Numbers](math/)
+- [Armstrong Numbers](math/)
+- [Automorphic Numbers](math/)
+- [Average Stream Numbers](math/)
+- [Babylonian Method](math/)
+- [Binomial Coefficient](math/)
+- [Catalan Number](math/)
+- [Check is Square](math/)
+- [Convolution](math/)
+- [Coprime Numbers](math/)
+- [Count Digits](math/)
+- [Count Trailing Zeroes](math/)
+- [Decoding of String](math/)
+- [Delannoy Number](math/)
+- [Derangements](math/)
+- [DFA Division](math/)
+- [Diophantine](math/)
+- [Divided Differences](math/)
+- [Euler Totient](math/)
+- [Exponentiation Power](math/)
+- [Factorial](math/factorial)
+- [Fast Fourier transform](math/)
+- [Fast inverse (sqrt) Square Root](math/)
+
+## [Networking](networking)
+
+- [Packet Sniffer](networking/)
+- [Determine Endianess](networking/)
+- [Validate IP](networking/)
+
+## [Numerical Analysis](numerical-analysis)
+
+- [Integral](numerical-analysis/integral)
+- [Monte Carlo](numerical-analysis/monte-carlo)
+- [Runge Kutt](numerical-analysis/runge-kutt)
+
+## [Operating system](operating-system)
+
+- [Currency](operating-system/)
+- [Deadlocks](operating-system/)
+- [Memory Management](operating-system/)
+- [Scheduling](operating-system/)
+- [Shell](operating-system/)
+
+## [Randomized Algorithms](randomized-algorithms)
+
+- [Birthday Paradox](randomized-algorithms)
+- [Karger Minimum Cut Algorithm](randomized-algorithms)
+- [Kth Smallest Element Algorithm](randomized-algorithms)
+- [Random from Stream](randomized-algorithms)
+- [Random Node Linked list](randomized-algorithms)
+- [Randomized Quicksort](randomized-algorithms)
+- [Reservoir Sampling](randomized-algorithms)
+- [Shuffle an Array](randomized-algorithms)
+
+## [Searches](searches)
+
+- [Binary Search](searches)
+- [Exponential Search](searches)
+- [Fibonacci Search](searches)
+- [Fuzzy Search](searches)
+- [Interpolation Search](searches)
+- [Jump Search](searches)
+- [Linear Search](searches)
+- [Ternay Search](searches)
+
+## [Selections Algorithms](selections-algorithms)
+
+- [Median of Medians](selections-algorithms)
+- [Quick Select](selections-algorithms)
+
+## [Sorting](sorting)
+
+- [Bead Sort](sorting/)
+- [Bogo Sort](sorting/)
+- [Bubble Sort](sorting/)
+- [Bucket Sort](sorting/)
+- [Circle Sort](sorting/)
+- [Comb Sort](sorting/)
+- [Counting Sort](sorting/)
+- [Cycle Sort](sorting/)
+- [Flash Sort](sorting/)
+- [Gnome Sort](sorting/)
+- [Heap Sort](sorting/)
+- [Insertion Sort](sorting/)
+- [Intro Sort](sorting/)
+- [Median Sort](sorting/)
+- [Merge Sort](sorting/)
+- [Pipeonhole Sort](sorting/)
+- [Quick Sort](sorting/)
+- [Radix Sort](sorting/)
+- [Selection Sort](sorting/)
+- [Shaker Sort](sorting/)
+- [Shell Sort](sorting/)
+- [Sleep Sort](sorting/)
+- [Stooge Sort](sorting/)
+- [Topological Sort](sorting/)
+- [Tree Sort](sorting/)
+
+## [Strings](strings)
+
+- [Aho Corasick Algorithm](strings)
+- [Anagram Search](strings)
+- [Arithmetic on large numbers](strings)
+- [Boyer Moore Algorithm](strings)
+- [Finite Automata](strings)
+- [Kasai Algorithm](strings)
+- [Kmp Algorithm](strings)
+- [Levenshteing Distance](strings)
+- [Lipogram Checker](strings)
+
+## [Online Challenges](online-challenges)
+
+- [Coderbyte](online-challenges/coderbyte)
+- [Code Chef](online-challenges/code-chef)
+- [Code Eval](online-challenges/code-eval)
+- [Hackerearth](online-challenges/hackerearth)
+- [Hackerrank](online-challenges/hackerrank)
+- [LeetCode](online-challenges/leetcode)
+- [Project Euler](online-challenges/project-euler)
+- [Rosalind](online-challenges/rosalind)
+- [SPOJ](online-challenges/spoj)
+- [Top Coder](online-challenges/top-coder)`
+
+## [Others](others)
+
+- [Average](others/)
+- [Biggest of n numbers](others/)
+- [Biggest Suffix](others/)
+- [Fifteen Puzzle](others/)
+- [Jaccard Similarity](others/)
+- [Jose Phus Problem](others/)
+- [Lapindrom Checker](others/)
+- [Leap Year](others/)
+- [Magic Square](others/)
+- [Majority Element](others/)
+- [Minimum subarray size with degree](others/)
+- [No operator addition](others/)
+- [Paint fill](others/)
+- [Split list](others/)
+- [Tokenizer](others/)
+- [Unique number](others/)
+
+## License
+
+This work is released under MIT License.
+
+To the extent possible under law, [Abraham Hernandez (@abranhe)](https://go.abranhe.com/github) has waived all copyright and related or neighboring rights to this work.
+
+
\ No newline at end of file
diff --git a/search/binarySearch.py b/search/binarySearch.py
deleted file mode 100644
index 94c27a6..0000000
--- a/search/binarySearch.py
+++ /dev/null
@@ -1,40 +0,0 @@
-
-# Python Program for recursive binary search.
-
-# Returns index of x in arr if present, else -1
-def binarySearch (arr, l, r, x):
-
- # Check base case
- if r >= l:
-
- mid = l + (r - l)/2
-
- # If element is present at the middle itself
- if arr[mid] == x:
- return mid
-
- # If element is smaller than mid, then it
- # can only be present in left subarray
- elif arr[mid] > x:
- return binarySearch(arr, l, mid-1, x)
-
- # Else the element can only be present
- # in right subarray
- else:
- return binarySearch(arr, mid+1, r, x)
-
- else:
- # Element is not present in the array
- return -1
-
-# Test array
-arr = [ 2, 3, 4, 10, 40 ]
-x = 10
-
-# Function call
-result = binarySearch(arr, 0, len(arr)-1, x)
-
-if result != -1:
- print "Element is present at index %d" % result
-else:
- print "Element is not present in array"
\ No newline at end of file
diff --git a/search/linear.py b/search/linear.py
deleted file mode 100644
index ce30d87..0000000
--- a/search/linear.py
+++ /dev/null
@@ -1,12 +0,0 @@
-
-# Python code for linearly search x in arr[]. If x
-# is present then return its location, otherwise
-# return -1
-def search(arr, x):
-
- for i in range(len(arr)):
-
- if arr[i] == x:
- return i
-
- return -1
\ No newline at end of file
diff --git a/src/.gitkeep b/src/.gitkeep
new file mode 100644
index 0000000..e69de29