mirror of
https://github.com/TheAlgorithms/Python.git
synced 2025-02-20 16:22:02 +00:00
Merge branch 'master' into revert-22-patch-1
This commit is contained in:
commit
1611f40c51
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -88,3 +88,4 @@ ENV/
|
|||
# Rope project settings
|
||||
.ropeproject
|
||||
.idea
|
||||
.DS_Store
|
33
.travis.yml
33
.travis.yml
|
@ -1,11 +1,26 @@
|
|||
language: python
|
||||
cache: pip
|
||||
python:
|
||||
- "3.2"
|
||||
- "3.3"
|
||||
- "3.4"
|
||||
- "3.5"
|
||||
install:
|
||||
- if [ "$TRAVIS_PYTHON_VERSION" == "3.2" ]; then travis_retry pip install coverage==3.7.1; fi
|
||||
- if [ "$TRAVIS_PYTHON_VERSION" != "3.2" ]; then travis_retry pip install coverage; fi
|
||||
- "pip install pytest pytest-cov"
|
||||
script: py.test --doctest-modules --cov ./
|
||||
- 2.7
|
||||
- 3.6
|
||||
#- nightly
|
||||
#- pypy
|
||||
#- pypy3
|
||||
matrix:
|
||||
allow_failures:
|
||||
- python: nightly
|
||||
- python: pypy
|
||||
- python: pypy3
|
||||
install:
|
||||
#- pip install -r requirements.txt
|
||||
- pip install flake8 # pytest # add another testing frameworks later
|
||||
before_script:
|
||||
# stop the build if there are Python syntax errors or undefined names
|
||||
- flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics
|
||||
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
|
||||
- flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
|
||||
script:
|
||||
- true # pytest --capture=sys # add other tests here
|
||||
notifications:
|
||||
on_success: change
|
||||
on_failure: change # `always` will be the setting once code changes slow down
|
||||
|
|
33
Bisection.py
Normal file
33
Bisection.py
Normal file
|
@ -0,0 +1,33 @@
|
|||
import math
|
||||
|
||||
|
||||
def bisection(function, a, b): # finds where the function becomes 0 in [a,b] using bolzano
|
||||
|
||||
start = a
|
||||
end = b
|
||||
if function(a) == 0: # one of the a or b is a root for the function
|
||||
return a
|
||||
elif function(b) == 0:
|
||||
return b
|
||||
elif function(a) * function(b) > 0: # if none of these are root and they are both positive or negative,
|
||||
# then his algorithm can't find the root
|
||||
print("couldn't find root in [a,b]")
|
||||
return
|
||||
else:
|
||||
mid = (start + end) / 2
|
||||
while abs(start - mid) > 0.0000001: # until we achieve precise equals to 10^-7
|
||||
if function(mid) == 0:
|
||||
return mid
|
||||
elif function(mid) * function(start) < 0:
|
||||
end = mid
|
||||
else:
|
||||
start = mid
|
||||
mid = (start + end) / 2
|
||||
return mid
|
||||
|
||||
|
||||
def f(x):
|
||||
return math.pow(x, 3) - 2*x - 5
|
||||
|
||||
|
||||
print(bisection(f, 1, 1000))
|
58
File_Transfer_Protocol/ftp_client_server.py
Normal file
58
File_Transfer_Protocol/ftp_client_server.py
Normal file
|
@ -0,0 +1,58 @@
|
|||
# server
|
||||
|
||||
import socket # Import socket module
|
||||
|
||||
port = 60000 # Reserve a port for your service.
|
||||
s = socket.socket() # Create a socket object
|
||||
host = socket.gethostname() # Get local machine name
|
||||
s.bind((host, port)) # Bind to the port
|
||||
s.listen(5) # Now wait for client connection.
|
||||
|
||||
print 'Server listening....'
|
||||
|
||||
while True:
|
||||
conn, addr = s.accept() # Establish connection with client.
|
||||
print 'Got connection from', addr
|
||||
data = conn.recv(1024)
|
||||
print('Server received', repr(data))
|
||||
|
||||
filename='mytext.txt'
|
||||
f = open(filename,'rb')
|
||||
l = f.read(1024)
|
||||
while (l):
|
||||
conn.send(l)
|
||||
print('Sent ',repr(l))
|
||||
l = f.read(1024)
|
||||
f.close()
|
||||
|
||||
print('Done sending')
|
||||
conn.send('Thank you for connecting')
|
||||
conn.close()
|
||||
|
||||
|
||||
# client side server
|
||||
|
||||
import socket # Import socket module
|
||||
|
||||
s = socket.socket() # Create a socket object
|
||||
host = socket.gethostname() # Get local machine name
|
||||
port = 60000 # Reserve a port for your service.
|
||||
|
||||
s.connect((host, port))
|
||||
s.send("Hello server!")
|
||||
|
||||
with open('received_file', 'wb') as f:
|
||||
print 'file opened'
|
||||
while True:
|
||||
print('receiving data...')
|
||||
data = s.recv(1024)
|
||||
print('data=%s', (data))
|
||||
if not data:
|
||||
break
|
||||
# write data to a file
|
||||
f.write(data)
|
||||
|
||||
f.close()
|
||||
print('Successfully get the file')
|
||||
s.close()
|
||||
print('connection closed')
|
36
File_Transfer_Protocol/ftp_send_receive.py
Normal file
36
File_Transfer_Protocol/ftp_send_receive.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
"""
|
||||
File transfer protocol used to send and receive files using FTP server.
|
||||
Use credentials to provide access to the FTP client
|
||||
|
||||
Note: Do not use root username & password for security reasons
|
||||
Create a seperate user and provide access to a home directory of the user
|
||||
Use login id and password of the user created
|
||||
cwd here stands for current working directory
|
||||
"""
|
||||
|
||||
from ftplib import FTP
|
||||
ftp = FTP('xxx.xxx.x.x') # Enter the ip address or the domain name here
|
||||
ftp.login(user='username', passwd='password')
|
||||
ftp.cwd('/Enter the directory here/')
|
||||
|
||||
"""
|
||||
The file which will be received via the FTP server
|
||||
Enter the location of the file where the file is received
|
||||
"""
|
||||
|
||||
def ReceiveFile():
|
||||
FileName = 'example.txt' """ Enter the location of the file """
|
||||
LocalFile = open(FileName, 'wb')
|
||||
ftp.retrbinary('RETR ' + FileName, LocalFile.write, 1024)
|
||||
ftp.quit()
|
||||
LocalFile.close()
|
||||
|
||||
"""
|
||||
The file which will be sent via the FTP server
|
||||
The file send will be send to the current working directory
|
||||
"""
|
||||
|
||||
def SendFile():
|
||||
FileName = 'example.txt' """ Enter the name of the file """
|
||||
ftp.storbinary('STOR ' + FileName, open(FileName, 'rb'))
|
||||
ftp.quit()
|
102
Graphs/a_star.py
Normal file
102
Graphs/a_star.py
Normal file
|
@ -0,0 +1,102 @@
|
|||
from __future__ import print_function
|
||||
|
||||
grid = [[0, 1, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0],#0 are free path whereas 1's are obstacles
|
||||
[0, 1, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 1, 0],
|
||||
[0, 0, 0, 0, 1, 0]]
|
||||
|
||||
'''
|
||||
heuristic = [[9, 8, 7, 6, 5, 4],
|
||||
[8, 7, 6, 5, 4, 3],
|
||||
[7, 6, 5, 4, 3, 2],
|
||||
[6, 5, 4, 3, 2, 1],
|
||||
[5, 4, 3, 2, 1, 0]]'''
|
||||
|
||||
init = [0, 0]
|
||||
goal = [len(grid)-1, len(grid[0])-1] #all coordinates are given in format [y,x]
|
||||
cost = 1
|
||||
|
||||
#the cost map which pushes the path closer to the goal
|
||||
heuristic = [[0 for row in range(len(grid[0]))] for col in range(len(grid))]
|
||||
for i in range(len(grid)):
|
||||
for j in range(len(grid[0])):
|
||||
heuristic[i][j] = abs(i - goal[0]) + abs(j - goal[1])
|
||||
if grid[i][j] == 1:
|
||||
heuristic[i][j] = 99 #added extra penalty in the heuristic map
|
||||
|
||||
|
||||
#the actions we can take
|
||||
delta = [[-1, 0 ], # go up
|
||||
[ 0, -1], # go left
|
||||
[ 1, 0 ], # go down
|
||||
[ 0, 1 ]] # go right
|
||||
|
||||
|
||||
#function to search the path
|
||||
def search(grid,init,goal,cost,heuristic):
|
||||
|
||||
closed = [[0 for col in range(len(grid[0]))] for row in range(len(grid))]# the referrence grid
|
||||
closed[init[0]][init[1]] = 1
|
||||
action = [[0 for col in range(len(grid[0]))] for row in range(len(grid))]#the action grid
|
||||
|
||||
x = init[0]
|
||||
y = init[1]
|
||||
g = 0
|
||||
f = g + heuristic[init[0]][init[0]]
|
||||
cell = [[f, g, x, y]]
|
||||
|
||||
found = False # flag that is set when search is complete
|
||||
resign = False # flag set if we can't find expand
|
||||
|
||||
while not found and not resign:
|
||||
if len(cell) == 0:
|
||||
resign = True
|
||||
return "FAIL"
|
||||
else:
|
||||
cell.sort()#to choose the least costliest action so as to move closer to the goal
|
||||
cell.reverse()
|
||||
next = cell.pop()
|
||||
x = next[2]
|
||||
y = next[3]
|
||||
g = next[1]
|
||||
f = next[0]
|
||||
|
||||
|
||||
if x == goal[0] and y == goal[1]:
|
||||
found = True
|
||||
else:
|
||||
for i in range(len(delta)):#to try out different valid actions
|
||||
x2 = x + delta[i][0]
|
||||
y2 = y + delta[i][1]
|
||||
if x2 >= 0 and x2 < len(grid) and y2 >=0 and y2 < len(grid[0]):
|
||||
if closed[x2][y2] == 0 and grid[x2][y2] == 0:
|
||||
g2 = g + cost
|
||||
f2 = g2 + heuristic[x2][y2]
|
||||
cell.append([f2, g2, x2, y2])
|
||||
closed[x2][y2] = 1
|
||||
action[x2][y2] = i
|
||||
invpath = []
|
||||
x = goal[0]
|
||||
y = goal[1]
|
||||
invpath.append([x, y])#we get the reverse path from here
|
||||
while x != init[0] or y != init[1]:
|
||||
x2 = x - delta[action[x][y]][0]
|
||||
y2 = y - delta[action[x][y]][1]
|
||||
x = x2
|
||||
y = y2
|
||||
invpath.append([x, y])
|
||||
|
||||
path = []
|
||||
for i in range(len(invpath)):
|
||||
path.append(invpath[len(invpath) - 1 - i])
|
||||
print("ACTION MAP")
|
||||
for i in range(len(action)):
|
||||
print(action[i])
|
||||
|
||||
return path
|
||||
|
||||
a = search(grid,init,goal,cost,heuristic)
|
||||
for i in range(len(a)):
|
||||
print(a[i])
|
||||
|
281
Graphs/basic-graphs.py
Normal file
281
Graphs/basic-graphs.py
Normal file
|
@ -0,0 +1,281 @@
|
|||
from __future__ import print_function
|
||||
|
||||
try:
|
||||
raw_input # Python 2
|
||||
except NameError:
|
||||
raw_input = input # Python 3
|
||||
|
||||
try:
|
||||
xrange # Python 2
|
||||
except NameError:
|
||||
xrange = range # Python 3
|
||||
|
||||
# Accept No. of Nodes and edges
|
||||
n, m = map(int, raw_input().split(" "))
|
||||
|
||||
# Initialising Dictionary of edges
|
||||
g = {}
|
||||
for i in xrange(n):
|
||||
g[i + 1] = []
|
||||
|
||||
"""
|
||||
--------------------------------------------------------------------------------
|
||||
Accepting edges of Unweighted Directed Graphs
|
||||
--------------------------------------------------------------------------------
|
||||
"""
|
||||
for _ in xrange(m):
|
||||
x, y = map(int, raw_input().split(" "))
|
||||
g[x].append(y)
|
||||
|
||||
"""
|
||||
--------------------------------------------------------------------------------
|
||||
Accepting edges of Unweighted Undirected Graphs
|
||||
--------------------------------------------------------------------------------
|
||||
"""
|
||||
for _ in xrange(m):
|
||||
x, y = map(int, raw_input().split(" "))
|
||||
g[x].append(y)
|
||||
g[y].append(x)
|
||||
|
||||
"""
|
||||
--------------------------------------------------------------------------------
|
||||
Accepting edges of Weighted Undirected Graphs
|
||||
--------------------------------------------------------------------------------
|
||||
"""
|
||||
for _ in xrange(m):
|
||||
x, y, r = map(int, raw_input().split(" "))
|
||||
g[x].append([y, r])
|
||||
g[y].append([x, r])
|
||||
|
||||
"""
|
||||
--------------------------------------------------------------------------------
|
||||
Depth First Search.
|
||||
Args : G - Dictionary of edges
|
||||
s - Starting Node
|
||||
Vars : vis - Set of visited nodes
|
||||
S - Traversal Stack
|
||||
--------------------------------------------------------------------------------
|
||||
"""
|
||||
|
||||
|
||||
def dfs(G, s):
|
||||
vis, S = set([s]), [s]
|
||||
print(s)
|
||||
while S:
|
||||
flag = 0
|
||||
for i in G[S[-1]]:
|
||||
if i not in vis:
|
||||
S.append(i)
|
||||
vis.add(i)
|
||||
flag = 1
|
||||
print(i)
|
||||
break
|
||||
if not flag:
|
||||
S.pop()
|
||||
|
||||
|
||||
"""
|
||||
--------------------------------------------------------------------------------
|
||||
Breadth First Search.
|
||||
Args : G - Dictionary of edges
|
||||
s - Starting Node
|
||||
Vars : vis - Set of visited nodes
|
||||
Q - Traveral Stack
|
||||
--------------------------------------------------------------------------------
|
||||
"""
|
||||
from collections import deque
|
||||
|
||||
|
||||
def bfs(G, s):
|
||||
vis, Q = set([s]), deque([s])
|
||||
print(s)
|
||||
while Q:
|
||||
u = Q.popleft()
|
||||
for v in G[u]:
|
||||
if v not in vis:
|
||||
vis.add(v)
|
||||
Q.append(v)
|
||||
print(v)
|
||||
|
||||
|
||||
"""
|
||||
--------------------------------------------------------------------------------
|
||||
Dijkstra's shortest path Algorithm
|
||||
Args : G - Dictionary of edges
|
||||
s - Starting Node
|
||||
Vars : dist - Dictionary storing shortest distance from s to every other node
|
||||
known - Set of knows nodes
|
||||
path - Preceding node in path
|
||||
--------------------------------------------------------------------------------
|
||||
"""
|
||||
|
||||
|
||||
def dijk(G, s):
|
||||
dist, known, path = {s: 0}, set(), {s: 0}
|
||||
while True:
|
||||
if len(known) == len(G) - 1:
|
||||
break
|
||||
mini = 100000
|
||||
for i in dist:
|
||||
if i not in known and dist[i] < mini:
|
||||
mini = dist[i]
|
||||
u = i
|
||||
known.add(u)
|
||||
for v in G[u]:
|
||||
if v[0] not in known:
|
||||
if dist[u] + v[1] < dist.get(v[0], 100000):
|
||||
dist[v[0]] = dist[u] + v[1]
|
||||
path[v[0]] = u
|
||||
for i in dist:
|
||||
if i != s:
|
||||
print(dist[i])
|
||||
|
||||
|
||||
"""
|
||||
--------------------------------------------------------------------------------
|
||||
Topological Sort
|
||||
--------------------------------------------------------------------------------
|
||||
"""
|
||||
from collections import deque
|
||||
|
||||
|
||||
def topo(G, ind=None, Q=[1]):
|
||||
if ind == None:
|
||||
ind = [0] * (len(G) + 1) # SInce oth Index is ignored
|
||||
for u in G:
|
||||
for v in G[u]:
|
||||
ind[v] += 1
|
||||
Q = deque()
|
||||
for i in G:
|
||||
if ind[i] == 0:
|
||||
Q.append(i)
|
||||
if len(Q) == 0:
|
||||
return
|
||||
v = Q.popleft()
|
||||
print(v)
|
||||
for w in G[v]:
|
||||
ind[w] -= 1
|
||||
if ind[w] == 0:
|
||||
Q.append(w)
|
||||
topo(G, ind, Q)
|
||||
|
||||
|
||||
"""
|
||||
--------------------------------------------------------------------------------
|
||||
Reading an Adjacency matrix
|
||||
--------------------------------------------------------------------------------
|
||||
"""
|
||||
|
||||
|
||||
def adjm():
|
||||
n, a = input(), []
|
||||
for i in xrange(n):
|
||||
a.append(map(int, raw_input().split()))
|
||||
return a, n
|
||||
|
||||
|
||||
"""
|
||||
--------------------------------------------------------------------------------
|
||||
Floyd Warshall's algorithm
|
||||
Args : G - Dictionary of edges
|
||||
s - Starting Node
|
||||
Vars : dist - Dictionary storing shortest distance from s to every other node
|
||||
known - Set of knows nodes
|
||||
path - Preceding node in path
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
"""
|
||||
|
||||
|
||||
def floy(A_and_n):
|
||||
(A, n) = A_and_n
|
||||
dist = list(A)
|
||||
path = [[0] * n for i in xrange(n)]
|
||||
for k in xrange(n):
|
||||
for i in xrange(n):
|
||||
for j in xrange(n):
|
||||
if dist[i][j] > dist[i][k] + dist[k][j]:
|
||||
dist[i][j] = dist[i][k] + dist[k][j]
|
||||
path[i][k] = k
|
||||
print(dist)
|
||||
|
||||
|
||||
"""
|
||||
--------------------------------------------------------------------------------
|
||||
Prim's MST Algorithm
|
||||
Args : G - Dictionary of edges
|
||||
s - Starting Node
|
||||
Vars : dist - Dictionary storing shortest distance from s to nearest node
|
||||
known - Set of knows nodes
|
||||
path - Preceding node in path
|
||||
--------------------------------------------------------------------------------
|
||||
"""
|
||||
|
||||
|
||||
def prim(G, s):
|
||||
dist, known, path = {s: 0}, set(), {s: 0}
|
||||
while True:
|
||||
if len(known) == len(G) - 1:
|
||||
break
|
||||
mini = 100000
|
||||
for i in dist:
|
||||
if i not in known and dist[i] < mini:
|
||||
mini = dist[i]
|
||||
u = i
|
||||
known.add(u)
|
||||
for v in G[u]:
|
||||
if v[0] not in known:
|
||||
if v[1] < dist.get(v[0], 100000):
|
||||
dist[v[0]] = v[1]
|
||||
path[v[0]] = u
|
||||
|
||||
|
||||
"""
|
||||
--------------------------------------------------------------------------------
|
||||
Accepting Edge list
|
||||
Vars : n - Number of nodes
|
||||
m - Number of edges
|
||||
Returns : l - Edge list
|
||||
n - Number of Nodes
|
||||
--------------------------------------------------------------------------------
|
||||
"""
|
||||
|
||||
|
||||
def edglist():
|
||||
n, m = map(int, raw_input().split(" "))
|
||||
l = []
|
||||
for i in xrange(m):
|
||||
l.append(map(int, raw_input().split(' ')))
|
||||
return l, n
|
||||
|
||||
|
||||
"""
|
||||
--------------------------------------------------------------------------------
|
||||
Kruskal's MST Algorithm
|
||||
Args : E - Edge list
|
||||
n - Number of Nodes
|
||||
Vars : s - Set of all nodes as unique disjoint sets (initially)
|
||||
--------------------------------------------------------------------------------
|
||||
"""
|
||||
|
||||
|
||||
def krusk(E_and_n):
|
||||
# Sort edges on the basis of distance
|
||||
(E, n) = E_and_n
|
||||
E.sort(reverse=True, key=lambda x: x[2])
|
||||
s = [set([i]) for i in range(1, n + 1)]
|
||||
while True:
|
||||
if len(s) == 1:
|
||||
break
|
||||
print(s)
|
||||
x = E.pop()
|
||||
for i in xrange(len(s)):
|
||||
if x[0] in s[i]:
|
||||
break
|
||||
for j in xrange(len(s)):
|
||||
if x[1] in s[j]:
|
||||
if i == j:
|
||||
break
|
||||
s[j].update(s[i])
|
||||
s.pop(i)
|
||||
break
|
32
Graphs/minimum_spanning_tree_kruskal.py
Normal file
32
Graphs/minimum_spanning_tree_kruskal.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
from __future__ import print_function
|
||||
num_nodes, num_edges = list(map(int,input().split()))
|
||||
|
||||
edges = []
|
||||
|
||||
for i in range(num_edges):
|
||||
node1, node2, cost = list(map(int,input().split()))
|
||||
edges.append((i,node1,node2,cost))
|
||||
|
||||
edges = sorted(edges, key=lambda edge: edge[3])
|
||||
|
||||
parent = [i for i in range(num_nodes)]
|
||||
|
||||
def find_parent(i):
|
||||
if(i != parent[i]):
|
||||
parent[i] = find_parent(parent[i])
|
||||
return parent[i]
|
||||
|
||||
minimum_spanning_tree_cost = 0
|
||||
minimum_spanning_tree = []
|
||||
|
||||
for edge in edges:
|
||||
parent_a = find_parent(edge[1])
|
||||
parent_b = find_parent(edge[2])
|
||||
if(parent_a != parent_b):
|
||||
minimum_spanning_tree_cost += edge[3]
|
||||
minimum_spanning_tree.append(edge)
|
||||
parent[parent_a] = parent_b
|
||||
|
||||
print(minimum_spanning_tree_cost)
|
||||
for edge in minimum_spanning_tree:
|
||||
print(edge)
|
46
Graphs/scc_kosaraju.py
Normal file
46
Graphs/scc_kosaraju.py
Normal file
|
@ -0,0 +1,46 @@
|
|||
from __future__ import print_function
|
||||
# n - no of nodes, m - no of edges
|
||||
n, m = list(map(int,input().split()))
|
||||
|
||||
g = [[] for i in range(n)] #graph
|
||||
r = [[] for i in range(n)] #reversed graph
|
||||
# input graph data (edges)
|
||||
for i in range(m):
|
||||
u, v = list(map(int,input().split()))
|
||||
g[u].append(v)
|
||||
r[v].append(u)
|
||||
|
||||
stack = []
|
||||
visit = [False]*n
|
||||
scc = []
|
||||
component = []
|
||||
|
||||
def dfs(u):
|
||||
global g, r, scc, component, visit, stack
|
||||
if visit[u]: return
|
||||
visit[u] = True
|
||||
for v in g[u]:
|
||||
dfs(v)
|
||||
stack.append(u)
|
||||
|
||||
def dfs2(u):
|
||||
global g, r, scc, component, visit, stack
|
||||
if visit[u]: return
|
||||
visit[u] = True
|
||||
component.append(u)
|
||||
for v in r[u]:
|
||||
dfs2(v)
|
||||
|
||||
def kosaraju():
|
||||
global g, r, scc, component, visit, stack
|
||||
for i in range(n):
|
||||
dfs(i)
|
||||
visit = [False]*n
|
||||
for i in stack[::-1]:
|
||||
if visit[i]: continue
|
||||
component = []
|
||||
dfs2(i)
|
||||
scc.append(component)
|
||||
return scc
|
||||
|
||||
print(kosaraju())
|
78
Graphs/tarjans_scc.py
Normal file
78
Graphs/tarjans_scc.py
Normal file
|
@ -0,0 +1,78 @@
|
|||
from collections import deque
|
||||
|
||||
|
||||
def tarjan(g):
|
||||
"""
|
||||
Tarjan's algo for finding strongly connected components in a directed graph
|
||||
|
||||
Uses two main attributes of each node to track reachability, the index of that node within a component(index),
|
||||
and the lowest index reachable from that node(lowlink).
|
||||
|
||||
We then perform a dfs of the each component making sure to update these parameters for each node and saving the
|
||||
nodes we visit on the way.
|
||||
|
||||
If ever we find that the lowest reachable node from a current node is equal to the index of the current node then it
|
||||
must be the root of a strongly connected component and so we save it and it's equireachable vertices as a strongly
|
||||
connected component.
|
||||
|
||||
Complexity: strong_connect() is called at most once for each node and has a complexity of O(|E|) as it is DFS.
|
||||
Therefore this has complexity O(|V| + |E|) for a graph G = (V, E)
|
||||
|
||||
"""
|
||||
|
||||
n = len(g)
|
||||
stack = deque()
|
||||
on_stack = [False for _ in range(n)]
|
||||
index_of = [-1 for _ in range(n)]
|
||||
lowlink_of = index_of[:]
|
||||
|
||||
def strong_connect(v, index, components):
|
||||
index_of[v] = index # the number when this node is seen
|
||||
lowlink_of[v] = index # lowest rank node reachable from here
|
||||
index += 1
|
||||
stack.append(v)
|
||||
on_stack[v] = True
|
||||
|
||||
for w in g[v]:
|
||||
if index_of[w] == -1:
|
||||
index = strong_connect(w, index, components)
|
||||
lowlink_of[v] = lowlink_of[w] if lowlink_of[w] < lowlink_of[v] else lowlink_of[v]
|
||||
elif on_stack[w]:
|
||||
lowlink_of[v] = lowlink_of[w] if lowlink_of[w] < lowlink_of[v] else lowlink_of[v]
|
||||
|
||||
if lowlink_of[v] == index_of[v]:
|
||||
component = []
|
||||
w = stack.pop()
|
||||
on_stack[w] = False
|
||||
component.append(w)
|
||||
while w != v:
|
||||
w = stack.pop()
|
||||
on_stack[w] = False
|
||||
component.append(w)
|
||||
components.append(component)
|
||||
return index
|
||||
|
||||
components = []
|
||||
for v in range(n):
|
||||
if index_of[v] == -1:
|
||||
strong_connect(v, 0, components)
|
||||
|
||||
return components
|
||||
|
||||
|
||||
def create_graph(n, edges):
|
||||
g = [[] for _ in range(n)]
|
||||
for u, v in edges:
|
||||
g[u].append(v)
|
||||
return g
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Test
|
||||
n_vertices = 7
|
||||
source = [0, 0, 1, 2, 3, 3, 4, 4, 6]
|
||||
target = [1, 3, 2, 0, 1, 4, 5, 6, 5]
|
||||
edges = [(u, v) for u, v in zip(source, target)]
|
||||
g = create_graph(n_vertices, edges)
|
||||
|
||||
assert [[5], [6], [4], [3, 2, 1, 0]] == tarjan(g)
|
16
Intersection.py
Normal file
16
Intersection.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
import math
|
||||
|
||||
def intersection(function,x0,x1): #function is the f we want to find its root and x0 and x1 are two random starting points
|
||||
x_n = x0
|
||||
x_n1 = x1
|
||||
while True:
|
||||
x_n2 = x_n1-(function(x_n1)/((function(x_n1)-function(x_n))/(x_n1-x_n)))
|
||||
if abs(x_n2 - x_n1)<0.00001 :
|
||||
return x_n2
|
||||
x_n=x_n1
|
||||
x_n1=x_n2
|
||||
|
||||
def f(x):
|
||||
return math.pow(x,3)-2*x-5
|
||||
|
||||
print(intersection(f,3,3.5))
|
21
License
Normal file
21
License
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2016 The Algorithms
|
||||
|
||||
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.
|
20
Maths/ModularExponential.py
Normal file
20
Maths/ModularExponential.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
def modularExponential(base, power, mod):
|
||||
if power < 0:
|
||||
return -1
|
||||
base %= mod
|
||||
result = 1
|
||||
|
||||
while power > 0:
|
||||
if power & 1:
|
||||
result = (result * base) % mod
|
||||
power = power >> 1
|
||||
base = (base * base) % mod
|
||||
return result
|
||||
|
||||
|
||||
def main():
|
||||
print(modularExponential(3, 200, 13))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
268
Multi_Hueristic_Astar.py
Normal file
268
Multi_Hueristic_Astar.py
Normal file
|
@ -0,0 +1,268 @@
|
|||
from __future__ import print_function
|
||||
import heapq
|
||||
import numpy as np
|
||||
import math
|
||||
import copy
|
||||
|
||||
try:
|
||||
xrange # Python 2
|
||||
except NameError:
|
||||
xrange = range # Python 3
|
||||
|
||||
|
||||
class PriorityQueue:
|
||||
def __init__(self):
|
||||
self.elements = []
|
||||
self.set = set()
|
||||
|
||||
def minkey(self):
|
||||
if not self.empty():
|
||||
return self.elements[0][0]
|
||||
else:
|
||||
return float('inf')
|
||||
|
||||
def empty(self):
|
||||
return len(self.elements) == 0
|
||||
|
||||
def put(self, item, priority):
|
||||
if item not in self.set:
|
||||
heapq.heappush(self.elements, (priority, item))
|
||||
self.set.add(item)
|
||||
else:
|
||||
# update
|
||||
# print("update", item)
|
||||
temp = []
|
||||
(pri, x) = heapq.heappop(self.elements)
|
||||
while x != item:
|
||||
temp.append((pri, x))
|
||||
(pri, x) = heapq.heappop(self.elements)
|
||||
temp.append((priority, item))
|
||||
for (pro, xxx) in temp:
|
||||
heapq.heappush(self.elements, (pro, xxx))
|
||||
|
||||
def remove_element(self, item):
|
||||
if item in self.set:
|
||||
self.set.remove(item)
|
||||
temp = []
|
||||
(pro, x) = heapq.heappop(self.elements)
|
||||
while x != item:
|
||||
temp.append((pro, x))
|
||||
(pro, x) = heapq.heappop(self.elements)
|
||||
for (prito, yyy) in temp:
|
||||
heapq.heappush(self.elements, (prito, yyy))
|
||||
|
||||
def top_show(self):
|
||||
return self.elements[0][1]
|
||||
|
||||
def get(self):
|
||||
(priority, item) = heapq.heappop(self.elements)
|
||||
self.set.remove(item)
|
||||
return (priority, item)
|
||||
|
||||
def consistent_hueristic(P, goal):
|
||||
# euclidean distance
|
||||
a = np.array(P)
|
||||
b = np.array(goal)
|
||||
return np.linalg.norm(a - b)
|
||||
|
||||
def hueristic_2(P, goal):
|
||||
# integer division by time variable
|
||||
return consistent_hueristic(P, goal) // t
|
||||
|
||||
def hueristic_1(P, goal):
|
||||
# manhattan distance
|
||||
return abs(P[0] - goal[0]) + abs(P[1] - goal[1])
|
||||
|
||||
def key(start, i, goal, g_function):
|
||||
ans = g_function[start] + W1 * hueristics[i](start, goal)
|
||||
return ans
|
||||
|
||||
def do_something(back_pointer, goal, start):
|
||||
grid = np.chararray((n, n))
|
||||
for i in range(n):
|
||||
for j in range(n):
|
||||
grid[i][j] = '*'
|
||||
|
||||
for i in range(n):
|
||||
for j in range(n):
|
||||
if (j, (n-1)-i) in blocks:
|
||||
grid[i][j] = "#"
|
||||
|
||||
grid[0][(n-1)] = "-"
|
||||
x = back_pointer[goal]
|
||||
while x != start:
|
||||
(x_c, y_c) = x
|
||||
# print(x)
|
||||
grid[(n-1)-y_c][x_c] = "-"
|
||||
x = back_pointer[x]
|
||||
grid[(n-1)][0] = "-"
|
||||
|
||||
|
||||
for i in xrange(n):
|
||||
for j in range(n):
|
||||
if (i, j) == (0, n-1):
|
||||
print(grid[i][j], end=' ')
|
||||
print("<-- End position", end=' ')
|
||||
else:
|
||||
print(grid[i][j], end=' ')
|
||||
print()
|
||||
print("^")
|
||||
print("Start position")
|
||||
print()
|
||||
print("# is an obstacle")
|
||||
print("- is the path taken by algorithm")
|
||||
print("PATH TAKEN BY THE ALGORITHM IS:-")
|
||||
x = back_pointer[goal]
|
||||
while x != start:
|
||||
print(x, end=' ')
|
||||
x = back_pointer[x]
|
||||
print(x)
|
||||
quit()
|
||||
|
||||
def valid(p):
|
||||
if p[0] < 0 or p[0] > n-1:
|
||||
return False
|
||||
if p[1] < 0 or p[1] > n-1:
|
||||
return False
|
||||
return True
|
||||
|
||||
def expand_state(s, j, visited, g_function, close_list_anchor, close_list_inad, open_list, back_pointer):
|
||||
for itera in range(n_hueristic):
|
||||
open_list[itera].remove_element(s)
|
||||
# print("s", s)
|
||||
# print("j", j)
|
||||
(x, y) = s
|
||||
left = (x-1, y)
|
||||
right = (x+1, y)
|
||||
up = (x, y+1)
|
||||
down = (x, y-1)
|
||||
|
||||
for neighbours in [left, right, up, down]:
|
||||
if neighbours not in blocks:
|
||||
if valid(neighbours) and neighbours not in visited:
|
||||
# print("neighbour", neighbours)
|
||||
visited.add(neighbours)
|
||||
back_pointer[neighbours] = -1
|
||||
g_function[neighbours] = float('inf')
|
||||
|
||||
if valid(neighbours) and g_function[neighbours] > g_function[s] + 1:
|
||||
g_function[neighbours] = g_function[s] + 1
|
||||
back_pointer[neighbours] = s
|
||||
if neighbours not in close_list_anchor:
|
||||
open_list[0].put(neighbours, key(neighbours, 0, goal, g_function))
|
||||
if neighbours not in close_list_inad:
|
||||
for var in range(1,n_hueristic):
|
||||
if key(neighbours, var, goal, g_function) <= W2 * key(neighbours, 0, goal, g_function):
|
||||
# print("why not plssssssssss")
|
||||
open_list[j].put(neighbours, key(neighbours, var, goal, g_function))
|
||||
|
||||
|
||||
# print
|
||||
|
||||
def make_common_ground():
|
||||
some_list = []
|
||||
# block 1
|
||||
for x in range(1, 5):
|
||||
for y in range(1, 6):
|
||||
some_list.append((x, y))
|
||||
|
||||
# line
|
||||
for x in range(15, 20):
|
||||
some_list.append((x, 17))
|
||||
|
||||
# block 2 big
|
||||
for x in range(10, 19):
|
||||
for y in range(1, 15):
|
||||
some_list.append((x, y))
|
||||
|
||||
# L block
|
||||
for x in range(1, 4):
|
||||
for y in range(12, 19):
|
||||
some_list.append((x, y))
|
||||
for x in range(3, 13):
|
||||
for y in range(16, 19):
|
||||
some_list.append((x, y))
|
||||
return some_list
|
||||
|
||||
hueristics = {0: consistent_hueristic, 1: hueristic_1, 2: hueristic_2}
|
||||
|
||||
blocks_blk = [(0, 1),(1, 1),(2, 1),(3, 1),(4, 1),(5, 1),(6, 1),(7, 1),(8, 1),(9, 1),(10, 1),(11, 1),(12, 1),(13, 1),(14, 1),(15, 1),(16, 1),(17, 1),(18, 1), (19, 1)]
|
||||
blocks_no = []
|
||||
blocks_all = make_common_ground()
|
||||
|
||||
|
||||
|
||||
|
||||
blocks = blocks_blk
|
||||
# hyper parameters
|
||||
W1 = 1
|
||||
W2 = 1
|
||||
n = 20
|
||||
n_hueristic = 3 # one consistent and two other inconsistent
|
||||
|
||||
# start and end destination
|
||||
start = (0, 0)
|
||||
goal = (n-1, n-1)
|
||||
|
||||
t = 1
|
||||
def multi_a_star(start, goal, n_hueristic):
|
||||
g_function = {start: 0, goal: float('inf')}
|
||||
back_pointer = {start:-1, goal:-1}
|
||||
open_list = []
|
||||
visited = set()
|
||||
|
||||
for i in range(n_hueristic):
|
||||
open_list.append(PriorityQueue())
|
||||
open_list[i].put(start, key(start, i, goal, g_function))
|
||||
|
||||
close_list_anchor = []
|
||||
close_list_inad = []
|
||||
while open_list[0].minkey() < float('inf'):
|
||||
for i in range(1, n_hueristic):
|
||||
# print("i", i)
|
||||
# print(open_list[0].minkey(), open_list[i].minkey())
|
||||
if open_list[i].minkey() <= W2 * open_list[0].minkey():
|
||||
global t
|
||||
t += 1
|
||||
# print("less prio")
|
||||
if g_function[goal] <= open_list[i].minkey():
|
||||
if g_function[goal] < float('inf'):
|
||||
do_something(back_pointer, goal, start)
|
||||
else:
|
||||
_, get_s = open_list[i].top_show()
|
||||
visited.add(get_s)
|
||||
expand_state(get_s, i, visited, g_function, close_list_anchor, close_list_inad, open_list, back_pointer)
|
||||
close_list_inad.append(get_s)
|
||||
else:
|
||||
# print("more prio")
|
||||
if g_function[goal] <= open_list[0].minkey():
|
||||
if g_function[goal] < float('inf'):
|
||||
do_something(back_pointer, goal, start)
|
||||
else:
|
||||
# print("hoolla")
|
||||
get_s = open_list[0].top_show()
|
||||
visited.add(get_s)
|
||||
expand_state(get_s, 0, visited, g_function, close_list_anchor, close_list_inad, open_list, back_pointer)
|
||||
close_list_anchor.append(get_s)
|
||||
print("No path found to goal")
|
||||
print()
|
||||
for i in range(n-1,-1, -1):
|
||||
for j in range(n):
|
||||
if (j, i) in blocks:
|
||||
print('#', end=' ')
|
||||
elif (j, i) in back_pointer:
|
||||
if (j, i) == (n-1, n-1):
|
||||
print('*', end=' ')
|
||||
else:
|
||||
print('-', end=' ')
|
||||
else:
|
||||
print('*', end=' ')
|
||||
if (j, i) == (n-1, n-1):
|
||||
print('<-- End position', end=' ')
|
||||
print()
|
||||
print("^")
|
||||
print("Start position")
|
||||
print()
|
||||
print("# is an obstacle")
|
||||
print("- is the path taken by algorithm")
|
||||
multi_a_star(start, goal, n_hueristic)
|
190
Neural_Network/bpnn.py
Normal file
190
Neural_Network/bpnn.py
Normal file
|
@ -0,0 +1,190 @@
|
|||
'''
|
||||
|
||||
A Framework of Back Propagation Neural Network(BP) model
|
||||
|
||||
Easy to use:
|
||||
* add many layers as you want !!!
|
||||
* clearly see how the loss decreasing
|
||||
Easy to expand:
|
||||
* more activation functions
|
||||
* more loss functions
|
||||
* more optimization method
|
||||
|
||||
Author: Stephen Lee
|
||||
Github : https://github.com/RiptideBo
|
||||
Date: 2017.11.23
|
||||
|
||||
'''
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
|
||||
def sigmoid(x):
|
||||
return 1 / (1 + np.exp(-1 * x))
|
||||
|
||||
class DenseLayer():
|
||||
'''
|
||||
Layers of BP neural network
|
||||
'''
|
||||
def __init__(self,units,activation=None,learning_rate=None,is_input_layer=False):
|
||||
'''
|
||||
common connected layer of bp network
|
||||
:param units: numbers of neural units
|
||||
:param activation: activation function
|
||||
:param learning_rate: learning rate for paras
|
||||
:param is_input_layer: whether it is input layer or not
|
||||
'''
|
||||
self.units = units
|
||||
self.weight = None
|
||||
self.bias = None
|
||||
self.activation = activation
|
||||
if learning_rate is None:
|
||||
learning_rate = 0.3
|
||||
self.learn_rate = learning_rate
|
||||
self.is_input_layer = is_input_layer
|
||||
|
||||
def initializer(self,back_units):
|
||||
self.weight = np.asmatrix(np.random.normal(0,0.5,(self.units,back_units)))
|
||||
self.bias = np.asmatrix(np.random.normal(0,0.5,self.units)).T
|
||||
if self.activation is None:
|
||||
self.activation = sigmoid
|
||||
|
||||
def cal_gradient(self):
|
||||
if self.activation == sigmoid:
|
||||
gradient_mat = np.dot(self.output ,(1- self.output).T)
|
||||
gradient_activation = np.diag(np.diag(gradient_mat))
|
||||
else:
|
||||
gradient_activation = 1
|
||||
return gradient_activation
|
||||
|
||||
def forward_propagation(self,xdata):
|
||||
self.xdata = xdata
|
||||
if self.is_input_layer:
|
||||
# input layer
|
||||
self.wx_plus_b = xdata
|
||||
self.output = xdata
|
||||
return xdata
|
||||
else:
|
||||
self.wx_plus_b = np.dot(self.weight,self.xdata) - self.bias
|
||||
self.output = self.activation(self.wx_plus_b)
|
||||
return self.output
|
||||
|
||||
def back_propagation(self,gradient):
|
||||
|
||||
gradient_activation = self.cal_gradient() # i * i 维
|
||||
gradient = np.asmatrix(np.dot(gradient.T,gradient_activation))
|
||||
|
||||
self._gradient_weight = np.asmatrix(self.xdata)
|
||||
self._gradient_bias = -1
|
||||
self._gradient_x = self.weight
|
||||
|
||||
self.gradient_weight = np.dot(gradient.T,self._gradient_weight.T)
|
||||
self.gradient_bias = gradient * self._gradient_bias
|
||||
self.gradient = np.dot(gradient,self._gradient_x).T
|
||||
# ----------------------upgrade
|
||||
# -----------the Negative gradient direction --------
|
||||
self.weight = self.weight - self.learn_rate * self.gradient_weight
|
||||
self.bias = self.bias - self.learn_rate * self.gradient_bias.T
|
||||
|
||||
return self.gradient
|
||||
|
||||
|
||||
class BPNN():
|
||||
'''
|
||||
Back Propagation Neural Network model
|
||||
'''
|
||||
def __init__(self):
|
||||
self.layers = []
|
||||
self.train_mse = []
|
||||
self.fig_loss = plt.figure()
|
||||
self.ax_loss = self.fig_loss.add_subplot(1,1,1)
|
||||
|
||||
def add_layer(self,layer):
|
||||
self.layers.append(layer)
|
||||
|
||||
def build(self):
|
||||
for i,layer in enumerate(self.layers[:]):
|
||||
if i < 1:
|
||||
layer.is_input_layer = True
|
||||
else:
|
||||
layer.initializer(self.layers[i-1].units)
|
||||
|
||||
def summary(self):
|
||||
for i,layer in enumerate(self.layers[:]):
|
||||
print('------- layer %d -------'%i)
|
||||
print('weight.shape ',np.shape(layer.weight))
|
||||
print('bias.shape ',np.shape(layer.bias))
|
||||
|
||||
def train(self,xdata,ydata,train_round,accuracy):
|
||||
self.train_round = train_round
|
||||
self.accuracy = accuracy
|
||||
|
||||
self.ax_loss.hlines(self.accuracy, 0, self.train_round * 1.1)
|
||||
|
||||
x_shape = np.shape(xdata)
|
||||
for round_i in range(train_round):
|
||||
all_loss = 0
|
||||
for row in range(x_shape[0]):
|
||||
_xdata = np.asmatrix(xdata[row,:]).T
|
||||
_ydata = np.asmatrix(ydata[row,:]).T
|
||||
|
||||
# forward propagation
|
||||
for layer in self.layers:
|
||||
_xdata = layer.forward_propagation(_xdata)
|
||||
|
||||
loss, gradient = self.cal_loss(_ydata, _xdata)
|
||||
all_loss = all_loss + loss
|
||||
|
||||
# back propagation
|
||||
# the input_layer does not upgrade
|
||||
for layer in self.layers[:0:-1]:
|
||||
gradient = layer.back_propagation(gradient)
|
||||
|
||||
mse = all_loss/x_shape[0]
|
||||
self.train_mse.append(mse)
|
||||
|
||||
self.plot_loss()
|
||||
|
||||
if mse < self.accuracy:
|
||||
print('----达到精度----')
|
||||
return mse
|
||||
|
||||
def cal_loss(self,ydata,ydata_):
|
||||
self.loss = np.sum(np.power((ydata - ydata_),2))
|
||||
self.loss_gradient = 2 * (ydata_ - ydata)
|
||||
# vector (shape is the same as _ydata.shape)
|
||||
return self.loss,self.loss_gradient
|
||||
|
||||
def plot_loss(self):
|
||||
if self.ax_loss.lines:
|
||||
self.ax_loss.lines.remove(self.ax_loss.lines[0])
|
||||
self.ax_loss.plot(self.train_mse, 'r-')
|
||||
plt.ion()
|
||||
plt.show()
|
||||
plt.pause(0.1)
|
||||
|
||||
|
||||
|
||||
|
||||
def example():
|
||||
|
||||
x = np.random.randn(10,10)
|
||||
y = np.asarray([[0.8,0.4],[0.4,0.3],[0.34,0.45],[0.67,0.32],
|
||||
[0.88,0.67],[0.78,0.77],[0.55,0.66],[0.55,0.43],[0.54,0.1],
|
||||
[0.1,0.5]])
|
||||
|
||||
model = BPNN()
|
||||
model.add_layer(DenseLayer(10))
|
||||
model.add_layer(DenseLayer(20))
|
||||
model.add_layer(DenseLayer(30))
|
||||
model.add_layer(DenseLayer(2))
|
||||
|
||||
model.build()
|
||||
|
||||
model.summary()
|
||||
|
||||
model.train(xdata=x,ydata=y,train_round=100,accuracy=0.01)
|
||||
|
||||
if __name__ == '__main__':
|
||||
example()
|
306
Neural_Network/convolution_neural_network.py
Normal file
306
Neural_Network/convolution_neural_network.py
Normal file
|
@ -0,0 +1,306 @@
|
|||
#-*- coding: utf-8 -*-
|
||||
|
||||
'''
|
||||
- - - - - -- - - - - - - - - - - - - - - - - - - - - - -
|
||||
Name - - CNN - Convolution Neural Network For Photo Recognizing
|
||||
Goal - - Recognize Handing Writting Word Photo
|
||||
Detail:Total 5 layers neural network
|
||||
* Convolution layer
|
||||
* Pooling layer
|
||||
* Input layer layer of BP
|
||||
* Hiden layer of BP
|
||||
* Output layer of BP
|
||||
Author: Stephen Lee
|
||||
Github: 245885195@qq.com
|
||||
Date: 2017.9.20
|
||||
- - - - - -- - - - - - - - - - - - - - - - - - - - - - -
|
||||
'''
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
class CNN():
|
||||
|
||||
def __init__(self,conv1_get,size_p1,bp_num1,bp_num2,bp_num3,rate_w=0.2,rate_t=0.2):
|
||||
'''
|
||||
:param conv1_get: [a,c,d],size, number, step of convolution kernel
|
||||
:param size_p1: pooling size
|
||||
:param bp_num1: units number of flatten layer
|
||||
:param bp_num2: units number of hidden layer
|
||||
:param bp_num3: units number of output layer
|
||||
:param rate_w: rate of weight learning
|
||||
:param rate_t: rate of threshold learning
|
||||
'''
|
||||
self.num_bp1 = bp_num1
|
||||
self.num_bp2 = bp_num2
|
||||
self.num_bp3 = bp_num3
|
||||
self.conv1 = conv1_get[:2]
|
||||
self.step_conv1 = conv1_get[2]
|
||||
self.size_pooling1 = size_p1
|
||||
self.rate_weight = rate_w
|
||||
self.rate_thre = rate_t
|
||||
self.w_conv1 = [np.mat(-1*np.random.rand(self.conv1[0],self.conv1[0])+0.5) for i in range(self.conv1[1])]
|
||||
self.wkj = np.mat(-1 * np.random.rand(self.num_bp3, self.num_bp2) + 0.5)
|
||||
self.vji = np.mat(-1*np.random.rand(self.num_bp2, self.num_bp1)+0.5)
|
||||
self.thre_conv1 = -2*np.random.rand(self.conv1[1])+1
|
||||
self.thre_bp2 = -2*np.random.rand(self.num_bp2)+1
|
||||
self.thre_bp3 = -2*np.random.rand(self.num_bp3)+1
|
||||
|
||||
|
||||
def save_model(self,save_path):
|
||||
#save model dict with pickle
|
||||
import pickle
|
||||
model_dic = {'num_bp1':self.num_bp1,
|
||||
'num_bp2':self.num_bp2,
|
||||
'num_bp3':self.num_bp3,
|
||||
'conv1':self.conv1,
|
||||
'step_conv1':self.step_conv1,
|
||||
'size_pooling1':self.size_pooling1,
|
||||
'rate_weight':self.rate_weight,
|
||||
'rate_thre':self.rate_thre,
|
||||
'w_conv1':self.w_conv1,
|
||||
'wkj':self.wkj,
|
||||
'vji':self.vji,
|
||||
'thre_conv1':self.thre_conv1,
|
||||
'thre_bp2':self.thre_bp2,
|
||||
'thre_bp3':self.thre_bp3}
|
||||
with open(save_path, 'wb') as f:
|
||||
pickle.dump(model_dic, f)
|
||||
|
||||
print('Model saved: %s'% save_path)
|
||||
|
||||
@classmethod
|
||||
def ReadModel(cls,model_path):
|
||||
#read saved model
|
||||
import pickle
|
||||
with open(model_path, 'rb') as f:
|
||||
model_dic = pickle.load(f)
|
||||
|
||||
conv_get= model_dic.get('conv1')
|
||||
conv_get.append(model_dic.get('step_conv1'))
|
||||
size_p1 = model_dic.get('size_pooling1')
|
||||
bp1 = model_dic.get('num_bp1')
|
||||
bp2 = model_dic.get('num_bp2')
|
||||
bp3 = model_dic.get('num_bp3')
|
||||
r_w = model_dic.get('rate_weight')
|
||||
r_t = model_dic.get('rate_thre')
|
||||
#create model instance
|
||||
conv_ins = CNN(conv_get,size_p1,bp1,bp2,bp3,r_w,r_t)
|
||||
#modify model parameter
|
||||
conv_ins.w_conv1 = model_dic.get('w_conv1')
|
||||
conv_ins.wkj = model_dic.get('wkj')
|
||||
conv_ins.vji = model_dic.get('vji')
|
||||
conv_ins.thre_conv1 = model_dic.get('thre_conv1')
|
||||
conv_ins.thre_bp2 = model_dic.get('thre_bp2')
|
||||
conv_ins.thre_bp3 = model_dic.get('thre_bp3')
|
||||
return conv_ins
|
||||
|
||||
|
||||
def sig(self,x):
|
||||
return 1 / (1 + np.exp(-1*x))
|
||||
|
||||
def do_round(self,x):
|
||||
return round(x, 3)
|
||||
|
||||
def convolute(self,data,convs,w_convs,thre_convs,conv_step):
|
||||
#convolution process
|
||||
size_conv = convs[0]
|
||||
num_conv =convs[1]
|
||||
size_data = np.shape(data)[0]
|
||||
#get the data slice of original image data, data_focus
|
||||
data_focus = []
|
||||
for i_focus in range(0, size_data - size_conv + 1, conv_step):
|
||||
for j_focus in range(0, size_data - size_conv + 1, conv_step):
|
||||
focus = data[i_focus:i_focus + size_conv, j_focus:j_focus + size_conv]
|
||||
data_focus.append(focus)
|
||||
#caculate the feature map of every single kernel, and saved as list of matrix
|
||||
data_featuremap = []
|
||||
Size_FeatureMap = int((size_data - size_conv) / conv_step + 1)
|
||||
for i_map in range(num_conv):
|
||||
featuremap = []
|
||||
for i_focus in range(len(data_focus)):
|
||||
net_focus = np.sum(np.multiply(data_focus[i_focus], w_convs[i_map])) - thre_convs[i_map]
|
||||
featuremap.append(self.sig(net_focus))
|
||||
featuremap = np.asmatrix(featuremap).reshape(Size_FeatureMap, Size_FeatureMap)
|
||||
data_featuremap.append(featuremap)
|
||||
|
||||
#expanding the data slice to One dimenssion
|
||||
focus1_list = []
|
||||
for each_focus in data_focus:
|
||||
focus1_list.extend(self.Expand_Mat(each_focus))
|
||||
focus_list = np.asarray(focus1_list)
|
||||
return focus_list,data_featuremap
|
||||
|
||||
def pooling(self,featuremaps,size_pooling,type='average_pool'):
|
||||
#pooling process
|
||||
size_map = len(featuremaps[0])
|
||||
size_pooled = int(size_map/size_pooling)
|
||||
featuremap_pooled = []
|
||||
for i_map in range(len(featuremaps)):
|
||||
map = featuremaps[i_map]
|
||||
map_pooled = []
|
||||
for i_focus in range(0,size_map,size_pooling):
|
||||
for j_focus in range(0, size_map, size_pooling):
|
||||
focus = map[i_focus:i_focus + size_pooling, j_focus:j_focus + size_pooling]
|
||||
if type == 'average_pool':
|
||||
#average pooling
|
||||
map_pooled.append(np.average(focus))
|
||||
elif type == 'max_pooling':
|
||||
#max pooling
|
||||
map_pooled.append(np.max(focus))
|
||||
map_pooled = np.asmatrix(map_pooled).reshape(size_pooled,size_pooled)
|
||||
featuremap_pooled.append(map_pooled)
|
||||
return featuremap_pooled
|
||||
|
||||
def _expand(self,datas):
|
||||
#expanding three dimension data to one dimension list
|
||||
data_expanded = []
|
||||
for i in range(len(datas)):
|
||||
shapes = np.shape(datas[i])
|
||||
data_listed = datas[i].reshape(1,shapes[0]*shapes[1])
|
||||
data_listed = data_listed.getA().tolist()[0]
|
||||
data_expanded.extend(data_listed)
|
||||
data_expanded = np.asarray(data_expanded)
|
||||
return data_expanded
|
||||
|
||||
def _expand_mat(self,data_mat):
|
||||
#expanding matrix to one dimension list
|
||||
data_mat = np.asarray(data_mat)
|
||||
shapes = np.shape(data_mat)
|
||||
data_expanded = data_mat.reshape(1,shapes[0]*shapes[1])
|
||||
return data_expanded
|
||||
|
||||
def _calculate_gradient_from_pool(self,out_map,pd_pool,num_map,size_map,size_pooling):
|
||||
'''
|
||||
calcluate the gradient from the data slice of pool layer
|
||||
pd_pool: list of matrix
|
||||
out_map: the shape of data slice(size_map*size_map)
|
||||
return: pd_all: list of matrix, [num, size_map, size_map]
|
||||
'''
|
||||
pd_all = []
|
||||
i_pool = 0
|
||||
for i_map in range(num_map):
|
||||
pd_conv1 = np.ones((size_map, size_map))
|
||||
for i in range(0, size_map, size_pooling):
|
||||
for j in range(0, size_map, size_pooling):
|
||||
pd_conv1[i:i + size_pooling, j:j + size_pooling] = pd_pool[i_pool]
|
||||
i_pool = i_pool + 1
|
||||
pd_conv2 = np.multiply(pd_conv1,np.multiply(out_map[i_map],(1-out_map[i_map])))
|
||||
pd_all.append(pd_conv2)
|
||||
return pd_all
|
||||
|
||||
def trian(self,patterns,datas_train, datas_teach, n_repeat, error_accuracy,draw_e = bool):
|
||||
#model traning
|
||||
print('----------------------Start Training-------------------------')
|
||||
print((' - - Shape: Train_Data ',np.shape(datas_train)))
|
||||
print((' - - Shape: Teach_Data ',np.shape(datas_teach)))
|
||||
rp = 0
|
||||
all_mse = []
|
||||
mse = 10000
|
||||
while rp < n_repeat and mse >= error_accuracy:
|
||||
alle = 0
|
||||
print('-------------Learning Time %d--------------'%rp)
|
||||
for p in range(len(datas_train)):
|
||||
#print('------------Learning Image: %d--------------'%p)
|
||||
data_train = np.asmatrix(datas_train[p])
|
||||
data_teach = np.asarray(datas_teach[p])
|
||||
data_focus1,data_conved1 = self.convolute(data_train,self.conv1,self.w_conv1,
|
||||
self.thre_conv1,conv_step=self.step_conv1)
|
||||
data_pooled1 = self.pooling(data_conved1,self.size_pooling1)
|
||||
shape_featuremap1 = np.shape(data_conved1)
|
||||
'''
|
||||
print(' -----original shape ', np.shape(data_train))
|
||||
print(' ---- after convolution ',np.shape(data_conv1))
|
||||
print(' -----after pooling ',np.shape(data_pooled1))
|
||||
'''
|
||||
data_bp_input = self._expand(data_pooled1)
|
||||
bp_out1 = data_bp_input
|
||||
|
||||
bp_net_j = np.dot(bp_out1,self.vji.T) - self.thre_bp2
|
||||
bp_out2 = self.sig(bp_net_j)
|
||||
bp_net_k = np.dot(bp_out2 ,self.wkj.T) - self.thre_bp3
|
||||
bp_out3 = self.sig(bp_net_k)
|
||||
|
||||
#--------------Model Leaning ------------------------
|
||||
# calcluate error and gradient---------------
|
||||
pd_k_all = np.multiply((data_teach - bp_out3), np.multiply(bp_out3, (1 - bp_out3)))
|
||||
pd_j_all = np.multiply(np.dot(pd_k_all,self.wkj), np.multiply(bp_out2, (1 - bp_out2)))
|
||||
pd_i_all = np.dot(pd_j_all,self.vji)
|
||||
|
||||
pd_conv1_pooled = pd_i_all / (self.size_pooling1*self.size_pooling1)
|
||||
pd_conv1_pooled = pd_conv1_pooled.T.getA().tolist()
|
||||
pd_conv1_all = self._calculate_gradient_from_pool(data_conved1,pd_conv1_pooled,shape_featuremap1[0],
|
||||
shape_featuremap1[1],self.size_pooling1)
|
||||
#weight and threshold learning process---------
|
||||
#convolution layer
|
||||
for k_conv in range(self.conv1[1]):
|
||||
pd_conv_list = self._expand_mat(pd_conv1_all[k_conv])
|
||||
delta_w = self.rate_weight * np.dot(pd_conv_list,data_focus1)
|
||||
|
||||
self.w_conv1[k_conv] = self.w_conv1[k_conv] + delta_w.reshape((self.conv1[0],self.conv1[0]))
|
||||
|
||||
self.thre_conv1[k_conv] = self.thre_conv1[k_conv] - np.sum(pd_conv1_all[k_conv]) * self.rate_thre
|
||||
#all connected layer
|
||||
self.wkj = self.wkj + pd_k_all.T * bp_out2 * self.rate_weight
|
||||
self.vji = self.vji + pd_j_all.T * bp_out1 * self.rate_weight
|
||||
self.thre_bp3 = self.thre_bp3 - pd_k_all * self.rate_thre
|
||||
self.thre_bp2 = self.thre_bp2 - pd_j_all * self.rate_thre
|
||||
# calculate the sum error of all single image
|
||||
errors = np.sum(abs((data_teach - bp_out3)))
|
||||
alle = alle + errors
|
||||
#print(' ----Teach ',data_teach)
|
||||
#print(' ----BP_output ',bp_out3)
|
||||
rp = rp + 1
|
||||
mse = alle/patterns
|
||||
all_mse.append(mse)
|
||||
def draw_error():
|
||||
yplot = [error_accuracy for i in range(int(n_repeat * 1.2))]
|
||||
plt.plot(all_mse, '+-')
|
||||
plt.plot(yplot, 'r--')
|
||||
plt.xlabel('Learning Times')
|
||||
plt.ylabel('All_mse')
|
||||
plt.grid(True, alpha=0.5)
|
||||
plt.show()
|
||||
print('------------------Training Complished---------------------')
|
||||
print((' - - Training epoch: ', rp, ' - - Mse: %.6f' % mse))
|
||||
if draw_e:
|
||||
draw_error()
|
||||
return mse
|
||||
|
||||
def predict(self,datas_test):
|
||||
#model predict
|
||||
produce_out = []
|
||||
print('-------------------Start Testing-------------------------')
|
||||
print((' - - Shape: Test_Data ',np.shape(datas_test)))
|
||||
for p in range(len(datas_test)):
|
||||
data_test = np.asmatrix(datas_test[p])
|
||||
data_focus1, data_conved1 = self.convolute(data_test, self.conv1, self.w_conv1,
|
||||
self.thre_conv1, conv_step=self.step_conv1)
|
||||
data_pooled1 = self.pooling(data_conved1, self.size_pooling1)
|
||||
data_bp_input = self._expand(data_pooled1)
|
||||
|
||||
bp_out1 = data_bp_input
|
||||
bp_net_j = bp_out1 * self.vji.T - self.thre_bp2
|
||||
bp_out2 = self.sig(bp_net_j)
|
||||
bp_net_k = bp_out2 * self.wkj.T - self.thre_bp3
|
||||
bp_out3 = self.sig(bp_net_k)
|
||||
produce_out.extend(bp_out3.getA().tolist())
|
||||
res = [list(map(self.do_round,each)) for each in produce_out]
|
||||
return np.asarray(res)
|
||||
|
||||
def convolution(self,data):
|
||||
#return the data of image after convoluting process so we can check it out
|
||||
data_test = np.asmatrix(data)
|
||||
data_focus1, data_conved1 = self.convolute(data_test, self.conv1, self.w_conv1,
|
||||
self.thre_conv1, conv_step=self.step_conv1)
|
||||
data_pooled1 = self.pooling(data_conved1, self.size_pooling1)
|
||||
|
||||
return data_conved1,data_pooled1
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pass
|
||||
'''
|
||||
I will put the example on other file
|
||||
'''
|
124
Neural_Network/perceptron.py
Normal file
124
Neural_Network/perceptron.py
Normal file
|
@ -0,0 +1,124 @@
|
|||
'''
|
||||
|
||||
Perceptron
|
||||
w = w + N * (d(k) - y) * x(k)
|
||||
|
||||
Using perceptron network for oil analysis,
|
||||
with Measuring of 3 parameters that represent chemical characteristics we can classify the oil, in p1 or p2
|
||||
p1 = -1
|
||||
p2 = 1
|
||||
|
||||
'''
|
||||
from __future__ import print_function
|
||||
|
||||
import random
|
||||
|
||||
|
||||
class Perceptron:
|
||||
def __init__(self, sample, exit, learn_rate=0.01, epoch_number=1000, bias=-1):
|
||||
self.sample = sample
|
||||
self.exit = exit
|
||||
self.learn_rate = learn_rate
|
||||
self.epoch_number = epoch_number
|
||||
self.bias = bias
|
||||
self.number_sample = len(sample)
|
||||
self.col_sample = len(sample[0])
|
||||
self.weight = []
|
||||
|
||||
def trannig(self):
|
||||
for sample in self.sample:
|
||||
sample.insert(0, self.bias)
|
||||
|
||||
for i in range(self.col_sample):
|
||||
self.weight.append(random.random())
|
||||
|
||||
self.weight.insert(0, self.bias)
|
||||
|
||||
epoch_count = 0
|
||||
|
||||
while True:
|
||||
erro = False
|
||||
for i in range(self.number_sample):
|
||||
u = 0
|
||||
for j in range(self.col_sample + 1):
|
||||
u = u + self.weight[j] * self.sample[i][j]
|
||||
y = self.sign(u)
|
||||
if y != self.exit[i]:
|
||||
|
||||
for j in range(self.col_sample + 1):
|
||||
|
||||
self.weight[j] = self.weight[j] + self.learn_rate * (self.exit[i] - y) * self.sample[i][j]
|
||||
erro = True
|
||||
#print('Epoch: \n',epoch_count)
|
||||
epoch_count = epoch_count + 1
|
||||
# if you want controle the epoch or just by erro
|
||||
if erro == False:
|
||||
print(('\nEpoch:\n',epoch_count))
|
||||
print('------------------------\n')
|
||||
#if epoch_count > self.epoch_number or not erro:
|
||||
break
|
||||
|
||||
def sort(self, sample):
|
||||
sample.insert(0, self.bias)
|
||||
u = 0
|
||||
for i in range(self.col_sample + 1):
|
||||
u = u + self.weight[i] * sample[i]
|
||||
|
||||
y = self.sign(u)
|
||||
|
||||
if y == -1:
|
||||
print(('Sample: ', sample))
|
||||
print('classification: P1')
|
||||
else:
|
||||
print(('Sample: ', sample))
|
||||
print('classification: P2')
|
||||
|
||||
def sign(self, u):
|
||||
return 1 if u >= 0 else -1
|
||||
|
||||
|
||||
samples = [
|
||||
[-0.6508, 0.1097, 4.0009],
|
||||
[-1.4492, 0.8896, 4.4005],
|
||||
[2.0850, 0.6876, 12.0710],
|
||||
[0.2626, 1.1476, 7.7985],
|
||||
[0.6418, 1.0234, 7.0427],
|
||||
[0.2569, 0.6730, 8.3265],
|
||||
[1.1155, 0.6043, 7.4446],
|
||||
[0.0914, 0.3399, 7.0677],
|
||||
[0.0121, 0.5256, 4.6316],
|
||||
[-0.0429, 0.4660, 5.4323],
|
||||
[0.4340, 0.6870, 8.2287],
|
||||
[0.2735, 1.0287, 7.1934],
|
||||
[0.4839, 0.4851, 7.4850],
|
||||
[0.4089, -0.1267, 5.5019],
|
||||
[1.4391, 0.1614, 8.5843],
|
||||
[-0.9115, -0.1973, 2.1962],
|
||||
[0.3654, 1.0475, 7.4858],
|
||||
[0.2144, 0.7515, 7.1699],
|
||||
[0.2013, 1.0014, 6.5489],
|
||||
[0.6483, 0.2183, 5.8991],
|
||||
[-0.1147, 0.2242, 7.2435],
|
||||
[-0.7970, 0.8795, 3.8762],
|
||||
[-1.0625, 0.6366, 2.4707],
|
||||
[0.5307, 0.1285, 5.6883],
|
||||
[-1.2200, 0.7777, 1.7252],
|
||||
[0.3957, 0.1076, 5.6623],
|
||||
[-0.1013, 0.5989, 7.1812],
|
||||
[2.4482, 0.9455, 11.2095],
|
||||
[2.0149, 0.6192, 10.9263],
|
||||
[0.2012, 0.2611, 5.4631]
|
||||
|
||||
]
|
||||
|
||||
exit = [-1, -1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1]
|
||||
|
||||
network = Perceptron(sample=samples, exit = exit, learn_rate=0.01, epoch_number=1000, bias=-1)
|
||||
|
||||
network.trannig()
|
||||
|
||||
while True:
|
||||
sample = []
|
||||
for i in range(3):
|
||||
sample.insert(i, float(input('value: ')))
|
||||
network.sort(sample)
|
15
NeutonMethod.py
Normal file
15
NeutonMethod.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
def newton(function,function1,startingInt): #function is the f(x) and function1 is the f'(x)
|
||||
x_n=startingInt
|
||||
while True:
|
||||
x_n1=x_n-function(x_n)/function1(x_n)
|
||||
if abs(x_n-x_n1)<0.00001:
|
||||
return x_n1
|
||||
x_n=x_n1
|
||||
|
||||
def f(x):
|
||||
return (x**3)-2*x-5
|
||||
|
||||
def f1(x):
|
||||
return 3*(x**2)-2
|
||||
|
||||
print(newton(f,f1,3))
|
17
Project Euler/Problem 01/sol1.py
Normal file
17
Project Euler/Problem 01/sol1.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
'''
|
||||
Problem Statement:
|
||||
If we list all the natural numbers below 10 that are multiples of 3 or 5,
|
||||
we get 3,5,6 and 9. The sum of these multiples is 23.
|
||||
Find the sum of all the multiples of 3 or 5 below N.
|
||||
'''
|
||||
from __future__ import print_function
|
||||
try:
|
||||
raw_input # Python 2
|
||||
except NameError:
|
||||
raw_input = input # Python 3
|
||||
n = int(raw_input().strip())
|
||||
sum=0
|
||||
for a in range(3,n):
|
||||
if(a%3==0 or a%5==0):
|
||||
sum+=a
|
||||
print(sum)
|
20
Project Euler/Problem 01/sol2.py
Normal file
20
Project Euler/Problem 01/sol2.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
'''
|
||||
Problem Statement:
|
||||
If we list all the natural numbers below 10 that are multiples of 3 or 5,
|
||||
we get 3,5,6 and 9. The sum of these multiples is 23.
|
||||
Find the sum of all the multiples of 3 or 5 below N.
|
||||
'''
|
||||
from __future__ import print_function
|
||||
try:
|
||||
raw_input # Python 2
|
||||
except NameError:
|
||||
raw_input = input # Python 3
|
||||
n = int(raw_input().strip())
|
||||
sum = 0
|
||||
terms = (n-1)/3
|
||||
sum+= ((terms)*(6+(terms-1)*3))/2 #sum of an A.P.
|
||||
terms = (n-1)/5
|
||||
sum+= ((terms)*(10+(terms-1)*5))/2
|
||||
terms = (n-1)/15
|
||||
sum-= ((terms)*(30+(terms-1)*15))/2
|
||||
print(sum)
|
48
Project Euler/Problem 01/sol3.py
Normal file
48
Project Euler/Problem 01/sol3.py
Normal file
|
@ -0,0 +1,48 @@
|
|||
'''
|
||||
Problem Statement:
|
||||
If we list all the natural numbers below 10 that are multiples of 3 or 5,
|
||||
we get 3,5,6 and 9. The sum of these multiples is 23.
|
||||
Find the sum of all the multiples of 3 or 5 below N.
|
||||
'''
|
||||
'''
|
||||
This solution is based on the pattern that the successive numbers in the series follow: 0+3,+2,+1,+3,+1,+2,+3.
|
||||
'''
|
||||
from __future__ import print_function
|
||||
try:
|
||||
raw_input # Python 2
|
||||
except NameError:
|
||||
raw_input = input # Python 3
|
||||
n = int(raw_input().strip())
|
||||
sum=0
|
||||
num=0
|
||||
while(1):
|
||||
num+=3
|
||||
if(num>=n):
|
||||
break
|
||||
sum+=num
|
||||
num+=2
|
||||
if(num>=n):
|
||||
break
|
||||
sum+=num
|
||||
num+=1
|
||||
if(num>=n):
|
||||
break
|
||||
sum+=num
|
||||
num+=3
|
||||
if(num>=n):
|
||||
break
|
||||
sum+=num
|
||||
num+=1
|
||||
if(num>=n):
|
||||
break
|
||||
sum+=num
|
||||
num+=2
|
||||
if(num>=n):
|
||||
break
|
||||
sum+=num
|
||||
num+=3
|
||||
if(num>=n):
|
||||
break
|
||||
sum+=num
|
||||
|
||||
print(sum);
|
26
Project Euler/Problem 02/sol1.py
Normal file
26
Project Euler/Problem 02/sol1.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
'''
|
||||
Problem:
|
||||
Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2,
|
||||
the first 10 terms will be:
|
||||
1,2,3,5,8,13,21,34,55,89,..
|
||||
By considering the terms in the Fibonacci sequence whose values do not exceed n, find the sum of the even-valued terms.
|
||||
e.g. for n=10, we have {2,8}, sum is 10.
|
||||
'''
|
||||
from __future__ import print_function
|
||||
|
||||
try:
|
||||
raw_input # Python 2
|
||||
except NameError:
|
||||
raw_input = input # Python 3
|
||||
|
||||
n = int(raw_input().strip())
|
||||
i=1
|
||||
j=2
|
||||
sum=0
|
||||
while(j<=n):
|
||||
if((j&1)==0): #can also use (j%2==0)
|
||||
sum+=j
|
||||
temp=i
|
||||
i=j
|
||||
j=temp+i
|
||||
print(sum)
|
39
Project Euler/Problem 03/sol1.py
Normal file
39
Project Euler/Problem 03/sol1.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
'''
|
||||
Problem:
|
||||
The prime factors of 13195 are 5,7,13 and 29. What is the largest prime factor of a given number N?
|
||||
e.g. for 10, largest prime factor = 5. For 17, largest prime factor = 17.
|
||||
'''
|
||||
from __future__ import print_function
|
||||
|
||||
import math
|
||||
|
||||
def isprime(no):
|
||||
if(no==2):
|
||||
return True
|
||||
elif (no%2==0):
|
||||
return False
|
||||
sq = int(math.sqrt(no))+1
|
||||
for i in range(3,sq,2):
|
||||
if(no%i==0):
|
||||
return False
|
||||
return True
|
||||
|
||||
maxNumber = 0
|
||||
n=int(input())
|
||||
if(isprime(n)):
|
||||
print(n)
|
||||
else:
|
||||
while (n%2==0):
|
||||
n=n/2
|
||||
if(isprime(n)):
|
||||
print(n)
|
||||
else:
|
||||
n1 = int(math.sqrt(n))+1
|
||||
for i in range(3,n1,2):
|
||||
if(n%i==0):
|
||||
if(isprime(n/i)):
|
||||
maxNumber = n/i
|
||||
break
|
||||
elif(isprime(i)):
|
||||
maxNumber = i
|
||||
print(maxNumber)
|
17
Project Euler/Problem 03/sol2.py
Normal file
17
Project Euler/Problem 03/sol2.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
'''
|
||||
Problem:
|
||||
The prime factors of 13195 are 5,7,13 and 29. What is the largest prime factor of a given number N?
|
||||
e.g. for 10, largest prime factor = 5. For 17, largest prime factor = 17.
|
||||
'''
|
||||
from __future__ import print_function
|
||||
n=int(input())
|
||||
prime=1
|
||||
i=2
|
||||
while(i*i<=n):
|
||||
while(n%i==0):
|
||||
prime=i
|
||||
n/=i
|
||||
i+=1
|
||||
if(n>1):
|
||||
prime=n
|
||||
print(prime)
|
29
Project Euler/Problem 04/sol1.py
Normal file
29
Project Euler/Problem 04/sol1.py
Normal file
|
@ -0,0 +1,29 @@
|
|||
'''
|
||||
Problem:
|
||||
A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 x 99.
|
||||
Find the largest palindrome made from the product of two 3-digit numbers which is less than N.
|
||||
'''
|
||||
from __future__ import print_function
|
||||
limit = int(input("limit? "))
|
||||
|
||||
# fetchs the next number
|
||||
for number in range(limit-1,10000,-1):
|
||||
|
||||
# converts number into string.
|
||||
strNumber = str(number)
|
||||
|
||||
# checks whether 'strNumber' is a palindrome.
|
||||
if(strNumber == strNumber[::-1]):
|
||||
|
||||
divisor = 999
|
||||
|
||||
# if 'number' is a product of two 3-digit numbers
|
||||
# then number is the answer otherwise fetch next number.
|
||||
while(divisor != 99):
|
||||
|
||||
if((number % divisor == 0) and (len(str(number / divisor)) == 3)):
|
||||
|
||||
print(number)
|
||||
exit(0)
|
||||
|
||||
divisor -=1
|
19
Project Euler/Problem 04/sol2.py
Normal file
19
Project Euler/Problem 04/sol2.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
'''
|
||||
Problem:
|
||||
A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 x 99.
|
||||
Find the largest palindrome made from the product of two 3-digit numbers which is less than N.
|
||||
'''
|
||||
from __future__ import print_function
|
||||
arr = []
|
||||
for i in range(999,100,-1):
|
||||
for j in range(999,100,-1):
|
||||
t = str(i*j)
|
||||
if t == t[::-1]:
|
||||
arr.append(i*j)
|
||||
arr.sort()
|
||||
|
||||
n=int(input())
|
||||
for i in arr[::-1]:
|
||||
if(i<n):
|
||||
print(i)
|
||||
exit(0)
|
21
Project Euler/Problem 05/sol1.py
Normal file
21
Project Euler/Problem 05/sol1.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
'''
|
||||
Problem:
|
||||
2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
|
||||
What is the smallest positive number that is evenly divisible(divisible with no remainder) by all of the numbers from 1 to N?
|
||||
'''
|
||||
from __future__ import print_function
|
||||
|
||||
n = int(input())
|
||||
i = 0
|
||||
while 1:
|
||||
i+=n*(n-1)
|
||||
nfound=0
|
||||
for j in range(2,n):
|
||||
if (i%j != 0):
|
||||
nfound=1
|
||||
break
|
||||
if(nfound==0):
|
||||
if(i==0):
|
||||
i=1
|
||||
print(i)
|
||||
break
|
20
Project Euler/Problem 06/sol1.py
Normal file
20
Project Euler/Problem 06/sol1.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Problem:
|
||||
The sum of the squares of the first ten natural numbers is,
|
||||
1^2 + 2^2 + ... + 10^2 = 385
|
||||
The square of the sum of the first ten natural numbers is,
|
||||
(1 + 2 + ... + 10)^2 = 552 = 3025
|
||||
Hence the difference between the sum of the squares of the first ten natural numbers and the square of the sum is 3025 − 385 = 2640.
|
||||
Find the difference between the sum of the squares of the first N natural numbers and the square of the sum.
|
||||
'''
|
||||
from __future__ import print_function
|
||||
|
||||
suma = 0
|
||||
sumb = 0
|
||||
n = int(input())
|
||||
for i in range(1,n+1):
|
||||
suma += i**2
|
||||
sumb += i
|
||||
sum = sumb**2 - suma
|
||||
print(sum)
|
16
Project Euler/Problem 06/sol2.py
Normal file
16
Project Euler/Problem 06/sol2.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Problem:
|
||||
The sum of the squares of the first ten natural numbers is,
|
||||
1^2 + 2^2 + ... + 10^2 = 385
|
||||
The square of the sum of the first ten natural numbers is,
|
||||
(1 + 2 + ... + 10)^2 = 552 = 3025
|
||||
Hence the difference between the sum of the squares of the first ten natural numbers and the square of the sum is 3025 − 385 = 2640.
|
||||
Find the difference between the sum of the squares of the first N natural numbers and the square of the sum.
|
||||
'''
|
||||
from __future__ import print_function
|
||||
n = int(input())
|
||||
suma = n*(n+1)/2
|
||||
suma **= 2
|
||||
sumb = n*(n+1)*(2*n+1)/6
|
||||
print(suma-sumb)
|
30
Project Euler/Problem 07/sol1.py
Normal file
30
Project Euler/Problem 07/sol1.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
'''
|
||||
By listing the first six prime numbers:
|
||||
2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.
|
||||
What is the Nth prime number?
|
||||
'''
|
||||
from __future__ import print_function
|
||||
from math import sqrt
|
||||
def isprime(n):
|
||||
if (n==2):
|
||||
return True
|
||||
elif (n%2==0):
|
||||
return False
|
||||
else:
|
||||
sq = int(sqrt(n))+1
|
||||
for i in range(3,sq,2):
|
||||
if(n%i==0):
|
||||
return False
|
||||
return True
|
||||
n = int(input())
|
||||
i=0
|
||||
j=1
|
||||
while(i!=n and j<3):
|
||||
j+=1
|
||||
if (isprime(j)):
|
||||
i+=1
|
||||
while(i!=n):
|
||||
j+=2
|
||||
if(isprime(j)):
|
||||
i+=1
|
||||
print(j)
|
16
Project Euler/Problem 07/sol2.py
Normal file
16
Project Euler/Problem 07/sol2.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
# By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13. What is the Nth prime number?
|
||||
def isprime(number):
|
||||
for i in range(2,int(number**0.5)+1):
|
||||
if number%i==0:
|
||||
return False
|
||||
return True
|
||||
n = int(input('Enter The N\'th Prime Number You Want To Get: ')) # Ask For The N'th Prime Number Wanted
|
||||
primes = []
|
||||
num = 2
|
||||
while len(primes) < n:
|
||||
if isprime(num):
|
||||
primes.append(num)
|
||||
num += 1
|
||||
else:
|
||||
num += 1
|
||||
print(primes[len(primes) - 1])
|
14
Project Euler/Problem 13/sol1.py
Normal file
14
Project Euler/Problem 13/sol1.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
'''
|
||||
Problem Statement:
|
||||
Work out the first ten digits of the sum of the N 50-digit numbers.
|
||||
'''
|
||||
from __future__ import print_function
|
||||
|
||||
n = int(input().strip())
|
||||
|
||||
array = []
|
||||
for i in range(n):
|
||||
array.append(int(input().strip()))
|
||||
|
||||
print(str(sum(array))[:10])
|
||||
|
21
Project Euler/Problem 14/sol1.py
Normal file
21
Project Euler/Problem 14/sol1.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
from __future__ import print_function
|
||||
largest_number = 0
|
||||
pre_counter = 0
|
||||
|
||||
for input1 in range(750000,1000000):
|
||||
counter = 1
|
||||
number = input1
|
||||
|
||||
while number > 1:
|
||||
if number % 2 == 0:
|
||||
number /=2
|
||||
counter += 1
|
||||
else:
|
||||
number = (3*number)+1
|
||||
counter += 1
|
||||
|
||||
if counter > pre_counter:
|
||||
largest_number = input1
|
||||
pre_counter = counter
|
||||
|
||||
print(('Largest Number:',largest_number,'->',pre_counter,'digits'))
|
15
Project Euler/Problem 16/sol1.py
Normal file
15
Project Euler/Problem 16/sol1.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
power = int(input("Enter the power of 2: "))
|
||||
num = 2**power
|
||||
|
||||
string_num = str(num)
|
||||
|
||||
list_num = list(string_num)
|
||||
|
||||
sum_of_num = 0
|
||||
|
||||
print("2 ^",power,"=",num)
|
||||
|
||||
for i in list_num:
|
||||
sum_of_num += int(i)
|
||||
|
||||
print("Sum of the digits are:",sum_of_num)
|
27
Project Euler/Problem 20/sol1.py
Normal file
27
Project Euler/Problem 20/sol1.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
# Finding the factorial.
|
||||
def factorial(n):
|
||||
fact = 1
|
||||
for i in range(1,n+1):
|
||||
fact *= i
|
||||
return fact
|
||||
|
||||
# Spliting the digits and adding it.
|
||||
def split_and_add(number):
|
||||
sum_of_digits = 0
|
||||
while(number>0):
|
||||
last_digit = number % 10
|
||||
sum_of_digits += last_digit
|
||||
number = int(number/10) # Removing the last_digit from the given number.
|
||||
return sum_of_digits
|
||||
|
||||
# Taking the user input.
|
||||
number = int(input("Enter the Number: "))
|
||||
|
||||
# Assigning the factorial from the factorial function.
|
||||
factorial = factorial(number)
|
||||
|
||||
# Spliting and adding the factorial into answer.
|
||||
answer = split_and_add(factorial)
|
||||
|
||||
# Printing the answer.
|
||||
print(answer)
|
34
Project Euler/Problem 29/solution.py
Normal file
34
Project Euler/Problem 29/solution.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
def main():
|
||||
"""
|
||||
Consider all integer combinations of ab for 2 <= a <= 5 and 2 <= b <= 5:
|
||||
|
||||
22=4, 23=8, 24=16, 25=32
|
||||
32=9, 33=27, 34=81, 35=243
|
||||
42=16, 43=64, 44=256, 45=1024
|
||||
52=25, 53=125, 54=625, 55=3125
|
||||
If they are then placed in numerical order, with any repeats removed, we get the following sequence of 15 distinct terms:
|
||||
|
||||
4, 8, 9, 16, 25, 27, 32, 64, 81, 125, 243, 256, 625, 1024, 3125
|
||||
|
||||
How many distinct terms are in the sequence generated by ab for 2 <= a <= 100 and 2 <= b <= 100?
|
||||
"""
|
||||
|
||||
collectPowers = set()
|
||||
|
||||
currentPow = 0
|
||||
|
||||
N = 101 # maximum limit
|
||||
|
||||
for a in range(2,N):
|
||||
|
||||
for b in range (2,N):
|
||||
|
||||
currentPow = a**b # calculates the current power
|
||||
collectPowers.add(currentPow) # adds the result to the set
|
||||
|
||||
|
||||
print "Number of terms ", len(collectPowers)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
15
Project Euler/Problem 9/sol1.py
Normal file
15
Project Euler/Problem 9/sol1.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
from __future__ import print_function
|
||||
# Program to find the product of a,b,c which are Pythagorean Triplet that satisfice the following:
|
||||
# 1. a < b < c
|
||||
# 2. a**2 + b**2 = c**2
|
||||
# 3. a + b + c = 1000
|
||||
|
||||
print("Please Wait...")
|
||||
for a in range(300):
|
||||
for b in range(400):
|
||||
for c in range(500):
|
||||
if(a < b < c):
|
||||
if((a**2) + (b**2) == (c**2)):
|
||||
if((a+b+c) == 1000):
|
||||
print(("Product of",a,"*",b,"*",c,"=",(a*b*c)))
|
||||
break
|
58
Project Euler/README.md
Normal file
58
Project Euler/README.md
Normal file
|
@ -0,0 +1,58 @@
|
|||
# ProjectEuler
|
||||
|
||||
Problems are taken from https://projecteuler.net/.
|
||||
|
||||
Project Euler is a series of challenging mathematical/computer programming problems that will require more than just mathematical
|
||||
insights to solve. Project Euler is ideal for mathematicians who are learning to code.
|
||||
|
||||
Here the efficiency of your code is also checked.
|
||||
I've tried to provide all the best possible solutions.
|
||||
|
||||
PROBLEMS:
|
||||
|
||||
1. If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3,5,6 and 9. The sum of these multiples is 23.
|
||||
Find the sum of all the multiples of 3 or 5 below N.
|
||||
|
||||
2. Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2,
|
||||
the first 10 terms will be:
|
||||
1,2,3,5,8,13,21,34,55,89,..
|
||||
By considering the terms in the Fibonacci sequence whose values do not exceed n, find the sum of the even-valued terms.
|
||||
e.g. for n=10, we have {2,8}, sum is 10.
|
||||
|
||||
3. The prime factors of 13195 are 5,7,13 and 29. What is the largest prime factor of a given number N?
|
||||
e.g. for 10, largest prime factor = 5. For 17, largest prime factor = 17.
|
||||
|
||||
4. A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
|
||||
Find the largest palindrome made from the product of two 3-digit numbers which is less than N.
|
||||
|
||||
5. 2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
|
||||
What is the smallest positive number that is evenly divisible(divisible with no remainder) by all of the numbers from 1 to N?
|
||||
|
||||
6. The sum of the squares of the first ten natural numbers is,
|
||||
1^2 + 2^2 + ... + 10^2 = 385
|
||||
The square of the sum of the first ten natural numbers is,
|
||||
(1 + 2 + ... + 10)^2 = 552 = 3025
|
||||
Hence the difference between the sum of the squares of the first ten natural numbers and the square of the sum is 3025 − 385 = 2640.
|
||||
Find the difference between the sum of the squares of the first N natural numbers and the square of the sum.
|
||||
|
||||
7. By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.
|
||||
What is the Nth prime number?
|
||||
|
||||
9. A Pythagorean triplet is a set of three natural numbers, a < b < c, for which,
|
||||
a^2 + b^2 = c^2
|
||||
There exists exactly one Pythagorean triplet for which a + b + c = 1000.
|
||||
Find the product abc.
|
||||
|
||||
14. The following iterative sequence is defined for the set of positive integers:
|
||||
n → n/2 (n is even)
|
||||
n → 3n + 1 (n is odd)
|
||||
Using the rule above and starting with 13, we generate the following sequence:
|
||||
13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1
|
||||
Which starting number, under one million, produces the longest chain?
|
||||
|
||||
16. 2^15 = 32768 and the sum of its digits is 3 + 2 + 7 + 6 + 8 = 26.
|
||||
What is the sum of the digits of the number 2^1000?
|
||||
20. n! means n × (n − 1) × ... × 3 × 2 × 1
|
||||
For example, 10! = 10 × 9 × ... × 3 × 2 × 1 = 3628800,
|
||||
and the sum of the digits in the number 10! is 3 + 6 + 2 + 8 + 8 + 0 + 0 = 27.
|
||||
Find the sum of the digits in the number 100!
|
21
README.md
21
README.md
|
@ -1,4 +1,4 @@
|
|||
# The Algorithms - Python [](https://travis-ci.org/TheAlgorithms/Python)
|
||||
# The Algorithms - Python <!-- [](https://travis-ci.org/TheAlgorithms/Python) -->
|
||||
|
||||
### All algorithms implemented in Python (for education)
|
||||
|
||||
|
@ -74,7 +74,7 @@ __Properties__
|
|||
### Shell
|
||||
![alt text][shell-image]
|
||||
|
||||
From [Wikipedia][shell-wiki]: Shellsort is a generalization of insertion sort that allows the exchange of items that are far apart. The idea is to arrange the list of elements so that, starting anywherem considereing every nth element gives a sorted list. Such a list is said to be h-sorted. Equivanelty, it can be thought of as h intterleaved lists, each individually sorted.
|
||||
From [Wikipedia][shell-wiki]: Shellsort is a generalization of insertion sort that allows the exchange of items that are far apart. The idea is to arrange the list of elements so that, starting anywhere, considering every nth element gives a sorted list. Such a list is said to be h-sorted. Equivalently, it can be thought of as h interleaved lists, each individually sorted.
|
||||
|
||||
__Properties__
|
||||
* Worst case performance O(nlog2 2n)
|
||||
|
@ -83,6 +83,14 @@ __Properties__
|
|||
|
||||
###### View the algorithm in [action][shell-toptal]
|
||||
|
||||
### Time-Compexity Graphs
|
||||
|
||||
Comparing the complexity of sorting algorithms (Bubble Sort, Insertion Sort, Selection Sort)
|
||||
|
||||
[Complexity Graphs](https://github.com/prateekiiest/Python/blob/master/sorts/sortinggraphs.png)
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
## Search Algorithms
|
||||
|
||||
### Linear
|
||||
|
@ -108,6 +116,8 @@ __Properties__
|
|||
* Average case performance O(log n)
|
||||
* Worst case space complexity O(1)
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
## Ciphers
|
||||
|
||||
### Caesar
|
||||
|
@ -118,6 +128,13 @@ The method is named after **Julius Caesar**, who used it in his private correspo
|
|||
The encryption step performed by a Caesar cipher is often incorporated as part of more complex schemes, such as the Vigenère cipher, and still has modern application in the ROT13 system. As with all single-alphabet substitution ciphers, the Caesar cipher is easily broken and in modern practice offers essentially no communication security.
|
||||
###### Source: [Wikipedia](https://en.wikipedia.org/wiki/Caesar_cipher)
|
||||
|
||||
### Vigenère
|
||||
The **Vigenère cipher** is a method of encrypting alphabetic text by using a series of **interwoven Caesar ciphers** based on the letters of a keyword. It is **a form of polyalphabetic substitution**.<br>
|
||||
The Vigenère cipher has been reinvented many times. The method was originally described by Giovan Battista Bellaso in his 1553 book La cifra del. Sig. Giovan Battista Bellaso; however, the scheme was later misattributed to Blaise de Vigenère in the 19th century, and is now widely known as the "Vigenère cipher".<br>
|
||||
Though the cipher is easy to understand and implement, for three centuries it resisted all attempts to break it; this earned it the description **le chiffre indéchiffrable**(French for 'the indecipherable cipher').
|
||||
Many people have tried to implement encryption schemes that are essentially Vigenère ciphers. Friedrich Kasiski was the first to publish a general method of deciphering a Vigenère cipher in 1863.
|
||||
###### Source: [Wikipedia](https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher)
|
||||
|
||||
### Transposition
|
||||
In cryptography, a **transposition cipher** is a method of encryption by which the positions held by units of plaintext (which are commonly characters or groups of characters) are shifted according to a regular system, so that the ciphertext constitutes a permutation of the plaintext. That is, the order of the units is changed (the plaintext is reordered).<br>
|
||||
Mathematically a bijective function is used on the characters' positions to encrypt and an inverse function to decrypt.
|
||||
|
|
209
ciphers/XOR_cipher.py
Normal file
209
ciphers/XOR_cipher.py
Normal file
|
@ -0,0 +1,209 @@
|
|||
"""
|
||||
author: Christian Bender
|
||||
date: 21.12.2017
|
||||
class: XORCipher
|
||||
|
||||
This class implements the XOR-cipher algorithm and provides
|
||||
some useful methods for encrypting and decrypting strings and
|
||||
files.
|
||||
|
||||
Overview about methods
|
||||
|
||||
- encrypt : list of char
|
||||
- decrypt : list of char
|
||||
- encrypt_string : str
|
||||
- decrypt_string : str
|
||||
- encrypt_file : boolean
|
||||
- decrypt_file : boolean
|
||||
"""
|
||||
class XORCipher(object):
|
||||
|
||||
def __init__(self, key = 0):
|
||||
"""
|
||||
simple constructor that receives a key or uses
|
||||
default key = 0
|
||||
"""
|
||||
|
||||
#private field
|
||||
self.__key = key
|
||||
|
||||
def encrypt(self, content, key):
|
||||
"""
|
||||
input: 'content' of type string and 'key' of type int
|
||||
output: encrypted string 'content' as a list of chars
|
||||
if key not passed the method uses the key by the constructor.
|
||||
otherwise key = 1
|
||||
"""
|
||||
|
||||
# precondition
|
||||
assert (isinstance(key,int) and isinstance(content,str))
|
||||
|
||||
key = key or self.__key or 1
|
||||
|
||||
# make sure key can be any size
|
||||
while (key > 255):
|
||||
key -= 255
|
||||
|
||||
# This will be returned
|
||||
ans = []
|
||||
|
||||
for ch in content:
|
||||
ans.append(chr(ord(ch) ^ key))
|
||||
|
||||
return ans
|
||||
|
||||
def decrypt(self,content,key):
|
||||
"""
|
||||
input: 'content' of type list and 'key' of type int
|
||||
output: decrypted string 'content' as a list of chars
|
||||
if key not passed the method uses the key by the constructor.
|
||||
otherwise key = 1
|
||||
"""
|
||||
|
||||
# precondition
|
||||
assert (isinstance(key,int) and isinstance(content,list))
|
||||
|
||||
key = key or self.__key or 1
|
||||
|
||||
# make sure key can be any size
|
||||
while (key > 255):
|
||||
key -= 255
|
||||
|
||||
# This will be returned
|
||||
ans = []
|
||||
|
||||
for ch in content:
|
||||
ans.append(chr(ord(ch) ^ key))
|
||||
|
||||
return ans
|
||||
|
||||
|
||||
def encrypt_string(self,content, key = 0):
|
||||
"""
|
||||
input: 'content' of type string and 'key' of type int
|
||||
output: encrypted string 'content'
|
||||
if key not passed the method uses the key by the constructor.
|
||||
otherwise key = 1
|
||||
"""
|
||||
|
||||
# precondition
|
||||
assert (isinstance(key,int) and isinstance(content,str))
|
||||
|
||||
key = key or self.__key or 1
|
||||
|
||||
# make sure key can be any size
|
||||
while (key > 255):
|
||||
key -= 255
|
||||
|
||||
# This will be returned
|
||||
ans = ""
|
||||
|
||||
for ch in content:
|
||||
ans += chr(ord(ch) ^ key)
|
||||
|
||||
return ans
|
||||
|
||||
def decrypt_string(self,content,key = 0):
|
||||
"""
|
||||
input: 'content' of type string and 'key' of type int
|
||||
output: decrypted string 'content'
|
||||
if key not passed the method uses the key by the constructor.
|
||||
otherwise key = 1
|
||||
"""
|
||||
|
||||
# precondition
|
||||
assert (isinstance(key,int) and isinstance(content,str))
|
||||
|
||||
key = key or self.__key or 1
|
||||
|
||||
# make sure key can be any size
|
||||
while (key > 255):
|
||||
key -= 255
|
||||
|
||||
# This will be returned
|
||||
ans = ""
|
||||
|
||||
for ch in content:
|
||||
ans += chr(ord(ch) ^ key)
|
||||
|
||||
return ans
|
||||
|
||||
|
||||
def encrypt_file(self, file, key = 0):
|
||||
"""
|
||||
input: filename (str) and a key (int)
|
||||
output: returns true if encrypt process was
|
||||
successful otherwise false
|
||||
if key not passed the method uses the key by the constructor.
|
||||
otherwise key = 1
|
||||
"""
|
||||
|
||||
#precondition
|
||||
assert (isinstance(file,str) and isinstance(key,int))
|
||||
|
||||
try:
|
||||
with open(file,"r") as fin:
|
||||
with open("encrypt.out","w+") as fout:
|
||||
|
||||
# actual encrypt-process
|
||||
for line in fin:
|
||||
fout.write(self.encrypt_string(line,key))
|
||||
|
||||
except:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def decrypt_file(self,file, key):
|
||||
"""
|
||||
input: filename (str) and a key (int)
|
||||
output: returns true if decrypt process was
|
||||
successful otherwise false
|
||||
if key not passed the method uses the key by the constructor.
|
||||
otherwise key = 1
|
||||
"""
|
||||
|
||||
#precondition
|
||||
assert (isinstance(file,str) and isinstance(key,int))
|
||||
|
||||
try:
|
||||
with open(file,"r") as fin:
|
||||
with open("decrypt.out","w+") as fout:
|
||||
|
||||
# actual encrypt-process
|
||||
for line in fin:
|
||||
fout.write(self.decrypt_string(line,key))
|
||||
|
||||
except:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
||||
|
||||
# Tests
|
||||
# crypt = XORCipher()
|
||||
# key = 67
|
||||
|
||||
# # test enrcypt
|
||||
# print crypt.encrypt("hallo welt",key)
|
||||
# # test decrypt
|
||||
# print crypt.decrypt(crypt.encrypt("hallo welt",key), key)
|
||||
|
||||
# # test encrypt_string
|
||||
# print crypt.encrypt_string("hallo welt",key)
|
||||
|
||||
# # test decrypt_string
|
||||
# print crypt.decrypt_string(crypt.encrypt_string("hallo welt",key),key)
|
||||
|
||||
# if (crypt.encrypt_file("test.txt",key)):
|
||||
# print "encrypt successful"
|
||||
# else:
|
||||
# print "encrypt unsuccessful"
|
||||
|
||||
# if (crypt.decrypt_file("encrypt.out",key)):
|
||||
# print "decrypt successful"
|
||||
# else:
|
||||
# print "decrypt unsuccessful"
|
|
@ -1,3 +1,4 @@
|
|||
from __future__ import print_function
|
||||
import sys, random, cryptomath_module as cryptoMath
|
||||
|
||||
SYMBOLS = """ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"""
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from __future__ import print_function
|
||||
def decrypt(message):
|
||||
"""
|
||||
>>> decrypt('TMDETUX PMDVU')
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
from __future__ import print_function
|
||||
# The Caesar Cipher Algorithm
|
||||
|
||||
def main():
|
||||
message = input("Enter message: ")
|
||||
key = int(input("Key [1-26]: "))
|
||||
mode = input("Encrypt or Decrypt [e/d]: ")
|
||||
key = int(input("Key [1-26]: "))
|
||||
mode = input("Encrypt or Decrypt [e/d]: ")
|
||||
|
||||
if mode.lower().startswith('e'):
|
||||
mode = "encrypt"
|
||||
|
@ -11,41 +12,34 @@ def main():
|
|||
mode = "decrypt"
|
||||
|
||||
translated = encdec(message, key, mode)
|
||||
if mode == "encrypt":
|
||||
print("Encryption:", translated)
|
||||
if mode == "encrypt":
|
||||
print(("Encryption:", translated))
|
||||
elif mode == "decrypt":
|
||||
print("Decryption:", translated)
|
||||
print(("Decryption:", translated))
|
||||
|
||||
def encdec(message, key, mode):
|
||||
"""
|
||||
>>> encdec('Harshil Darji', 12, 'encrypt')
|
||||
'TMDETUX PMDVU'
|
||||
|
||||
>>> encdec('TMDETUX PMDVU', 12, 'decrypt')
|
||||
'HARSHIL DARJI'
|
||||
"""
|
||||
message = message.upper()
|
||||
message = message.upper()
|
||||
translated = ""
|
||||
LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
for symbol in message:
|
||||
if symbol in LETTERS:
|
||||
num = LETTERS.find(symbol)
|
||||
if mode == "encrypt":
|
||||
if mode == "encrypt":
|
||||
num = num + key
|
||||
elif mode == "decrypt":
|
||||
num = num - key
|
||||
|
||||
if num >= len(LETTERS):
|
||||
num = num - len(LETTERS)
|
||||
num -= len(LETTERS)
|
||||
elif num < 0:
|
||||
num = num + len(LETTERS)
|
||||
num += len(LETTERS)
|
||||
|
||||
translated = translated + LETTERS[num]
|
||||
translated += LETTERS[num]
|
||||
else:
|
||||
translated = translated + symbol
|
||||
translated += symbol
|
||||
return translated
|
||||
|
||||
if __name__ == '__main__':
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
main()
|
||||
main()
|
||||
|
|
102
ciphers/playfair_cipher.py
Normal file
102
ciphers/playfair_cipher.py
Normal file
|
@ -0,0 +1,102 @@
|
|||
import string
|
||||
import itertools
|
||||
|
||||
def chunker(seq, size):
|
||||
it = iter(seq)
|
||||
while True:
|
||||
chunk = tuple(itertools.islice(it, size))
|
||||
if not chunk:
|
||||
return
|
||||
yield chunk
|
||||
|
||||
|
||||
|
||||
def prepare_input(dirty):
|
||||
"""
|
||||
Prepare the plaintext by up-casing it
|
||||
and separating repeated letters with X's
|
||||
"""
|
||||
|
||||
dirty = ''.join([c.upper() for c in dirty if c in string.ascii_letters])
|
||||
clean = ""
|
||||
|
||||
if len(dirty) < 2:
|
||||
return dirty
|
||||
|
||||
for i in range(len(dirty)-1):
|
||||
clean += dirty[i]
|
||||
|
||||
if dirty[i] == dirty[i+1]:
|
||||
clean += 'X'
|
||||
|
||||
clean += dirty[-1]
|
||||
|
||||
if len(clean) & 1:
|
||||
clean += 'X'
|
||||
|
||||
return clean
|
||||
|
||||
def generate_table(key):
|
||||
|
||||
# I and J are used interchangeably to allow
|
||||
# us to use a 5x5 table (25 letters)
|
||||
alphabet = "ABCDEFGHIKLMNOPQRSTUVWXYZ"
|
||||
# we're using a list instead of a '2d' array because it makes the math
|
||||
# for setting up the table and doing the actual encoding/decoding simpler
|
||||
table = []
|
||||
|
||||
# copy key chars into the table if they are in `alphabet` ignoring duplicates
|
||||
for char in key.upper():
|
||||
if char not in table and char in alphabet:
|
||||
table.append(char)
|
||||
|
||||
# fill the rest of the table in with the remaining alphabet chars
|
||||
for char in alphabet:
|
||||
if char not in table:
|
||||
table.append(char)
|
||||
|
||||
return table
|
||||
|
||||
def encode(plaintext, key):
|
||||
table = generate_table(key)
|
||||
plaintext = prepare_input(plaintext)
|
||||
ciphertext = ""
|
||||
|
||||
# https://en.wikipedia.org/wiki/Playfair_cipher#Description
|
||||
for char1, char2 in chunker(plaintext, 2):
|
||||
row1, col1 = divmod(table.index(char1), 5)
|
||||
row2, col2 = divmod(table.index(char2), 5)
|
||||
|
||||
if row1 == row2:
|
||||
ciphertext += table[row1*5+(col1+1)%5]
|
||||
ciphertext += table[row2*5+(col2+1)%5]
|
||||
elif col1 == col2:
|
||||
ciphertext += table[((row1+1)%5)*5+col1]
|
||||
ciphertext += table[((row2+1)%5)*5+col2]
|
||||
else: # rectangle
|
||||
ciphertext += table[row1*5+col2]
|
||||
ciphertext += table[row2*5+col1]
|
||||
|
||||
return ciphertext
|
||||
|
||||
|
||||
def decode(ciphertext, key):
|
||||
table = generate_table(key)
|
||||
plaintext = ""
|
||||
|
||||
# https://en.wikipedia.org/wiki/Playfair_cipher#Description
|
||||
for char1, char2 in chunker(ciphertext, 2):
|
||||
row1, col1 = divmod(table.index(char1), 5)
|
||||
row2, col2 = divmod(table.index(char2), 5)
|
||||
|
||||
if row1 == row2:
|
||||
plaintext += table[row1*5+(col1-1)%5]
|
||||
plaintext += table[row2*5+(col2-1)%5]
|
||||
elif col1 == col2:
|
||||
plaintext += table[((row1-1)%5)*5+col1]
|
||||
plaintext += table[((row2-1)%5)*5+col2]
|
||||
else: # rectangle
|
||||
plaintext += table[row1*5+col2]
|
||||
plaintext += table[row2*5+col1]
|
||||
|
||||
return plaintext
|
|
@ -1,3 +1,4 @@
|
|||
from __future__ import print_function
|
||||
# Primality Testing with the Rabin-Miller Algorithm
|
||||
|
||||
import random
|
||||
|
@ -59,5 +60,5 @@ def generateLargePrime(keysize = 1024):
|
|||
|
||||
if __name__ == '__main__':
|
||||
num = generateLargePrime()
|
||||
print('Prime number:', num)
|
||||
print('isPrime:', isPrime(num))
|
||||
print(('Prime number:', num))
|
||||
print(('isPrime:', isPrime(num)))
|
25
ciphers/rot13.py
Normal file
25
ciphers/rot13.py
Normal file
|
@ -0,0 +1,25 @@
|
|||
from __future__ import print_function
|
||||
def dencrypt(s, n):
|
||||
out = ''
|
||||
for c in s:
|
||||
if c >= 'A' and c <= 'Z':
|
||||
out += chr(ord('A') + (ord(c) - ord('A') + n) % 26)
|
||||
elif c >= 'a' and c <= 'z':
|
||||
out += chr(ord('a') + (ord(c) - ord('a') + n) % 26)
|
||||
else:
|
||||
out += c
|
||||
return out
|
||||
|
||||
|
||||
def main():
|
||||
s0 = 'HELLO'
|
||||
|
||||
s1 = dencrypt(s0, 13)
|
||||
print(s1) # URYYB
|
||||
|
||||
s2 = dencrypt(s1, 13)
|
||||
print(s2) # HELLO
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
125
ciphers/rsa_cipher.py
Normal file
125
ciphers/rsa_cipher.py
Normal file
|
@ -0,0 +1,125 @@
|
|||
from __future__ import print_function
|
||||
import sys, rsa_key_generator as rkg, os
|
||||
|
||||
DEFAULT_BLOCK_SIZE = 128
|
||||
BYTE_SIZE = 256
|
||||
|
||||
def main():
|
||||
filename = 'encrypted_file.txt'
|
||||
response = input('Encrypte\Decrypt [e\d]: ')
|
||||
|
||||
if response.lower().startswith('e'):
|
||||
mode = 'encrypt'
|
||||
elif response.lower().startswith('d'):
|
||||
mode = 'decrypt'
|
||||
|
||||
if mode == 'encrypt':
|
||||
if not os.path.exists('rsa_pubkey.txt'):
|
||||
rkg.makeKeyFiles('rsa', 1024)
|
||||
|
||||
message = input('\nEnter message: ')
|
||||
pubKeyFilename = 'rsa_pubkey.txt'
|
||||
print('Encrypting and writing to %s...' % (filename))
|
||||
encryptedText = encryptAndWriteToFile(filename, pubKeyFilename, message)
|
||||
|
||||
print('\nEncrypted text:')
|
||||
print(encryptedText)
|
||||
|
||||
elif mode == 'decrypt':
|
||||
privKeyFilename = 'rsa_privkey.txt'
|
||||
print('Reading from %s and decrypting...' % (filename))
|
||||
decryptedText = readFromFileAndDecrypt(filename, privKeyFilename)
|
||||
print('writing decryption to rsa_decryption.txt...')
|
||||
with open('rsa_decryption.txt', 'w') as dec:
|
||||
dec.write(decryptedText)
|
||||
|
||||
print('\nDecryption:')
|
||||
print(decryptedText)
|
||||
|
||||
|
||||
def getBlocksFromText(message, blockSize=DEFAULT_BLOCK_SIZE):
|
||||
messageBytes = message.encode('ascii')
|
||||
|
||||
blockInts = []
|
||||
for blockStart in range(0, len(messageBytes), blockSize):
|
||||
blockInt = 0
|
||||
for i in range(blockStart, min(blockStart + blockSize, len(messageBytes))):
|
||||
blockInt += messageBytes[i] * (BYTE_SIZE ** (i % blockSize))
|
||||
blockInts.append(blockInt)
|
||||
return blockInts
|
||||
|
||||
|
||||
def getTextFromBlocks(blockInts, messageLength, blockSize=DEFAULT_BLOCK_SIZE):
|
||||
message = []
|
||||
for blockInt in blockInts:
|
||||
blockMessage = []
|
||||
for i in range(blockSize - 1, -1, -1):
|
||||
if len(message) + i < messageLength:
|
||||
asciiNumber = blockInt // (BYTE_SIZE ** i)
|
||||
blockInt = blockInt % (BYTE_SIZE ** i)
|
||||
blockMessage.insert(0, chr(asciiNumber))
|
||||
message.extend(blockMessage)
|
||||
return ''.join(message)
|
||||
|
||||
|
||||
def encryptMessage(message, key, blockSize=DEFAULT_BLOCK_SIZE):
|
||||
encryptedBlocks = []
|
||||
n, e = key
|
||||
|
||||
for block in getBlocksFromText(message, blockSize):
|
||||
encryptedBlocks.append(pow(block, e, n))
|
||||
return encryptedBlocks
|
||||
|
||||
|
||||
def decryptMessage(encryptedBlocks, messageLength, key, blockSize=DEFAULT_BLOCK_SIZE):
|
||||
decryptedBlocks = []
|
||||
n, d = key
|
||||
for block in encryptedBlocks:
|
||||
decryptedBlocks.append(pow(block, d, n))
|
||||
return getTextFromBlocks(decryptedBlocks, messageLength, blockSize)
|
||||
|
||||
|
||||
def readKeyFile(keyFilename):
|
||||
fo = open(keyFilename)
|
||||
content = fo.read()
|
||||
fo.close()
|
||||
keySize, n, EorD = content.split(',')
|
||||
return (int(keySize), int(n), int(EorD))
|
||||
|
||||
|
||||
def encryptAndWriteToFile(messageFilename, keyFilename, message, blockSize=DEFAULT_BLOCK_SIZE):
|
||||
keySize, n, e = readKeyFile(keyFilename)
|
||||
if keySize < blockSize * 8:
|
||||
sys.exit('ERROR: Block size is %s bits and key size is %s bits. The RSA cipher requires the block size to be equal to or greater than the key size. Either decrease the block size or use different keys.' % (blockSize * 8, keySize))
|
||||
|
||||
encryptedBlocks = encryptMessage(message, (n, e), blockSize)
|
||||
|
||||
for i in range(len(encryptedBlocks)):
|
||||
encryptedBlocks[i] = str(encryptedBlocks[i])
|
||||
encryptedContent = ','.join(encryptedBlocks)
|
||||
encryptedContent = '%s_%s_%s' % (len(message), blockSize, encryptedContent)
|
||||
fo = open(messageFilename, 'w')
|
||||
fo.write(encryptedContent)
|
||||
fo.close()
|
||||
return encryptedContent
|
||||
|
||||
|
||||
def readFromFileAndDecrypt(messageFilename, keyFilename):
|
||||
keySize, n, d = readKeyFile(keyFilename)
|
||||
fo = open(messageFilename)
|
||||
content = fo.read()
|
||||
messageLength, blockSize, encryptedMessage = content.split('_')
|
||||
messageLength = int(messageLength)
|
||||
blockSize = int(blockSize)
|
||||
|
||||
if keySize < blockSize * 8:
|
||||
sys.exit('ERROR: Block size is %s bits and key size is %s bits. The RSA cipher requires the block size to be equal to or greater than the key size. Did you specify the correct key file and encrypted file?' % (blockSize * 8, keySize))
|
||||
|
||||
encryptedBlocks = []
|
||||
for block in encryptedMessage.split(','):
|
||||
encryptedBlocks.append(int(block))
|
||||
|
||||
return decryptMessage(encryptedBlocks, messageLength, (n, d), blockSize)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
46
ciphers/rsa_key_generator.py
Normal file
46
ciphers/rsa_key_generator.py
Normal file
|
@ -0,0 +1,46 @@
|
|||
from __future__ import print_function
|
||||
import random, sys, os
|
||||
import rabin_miller as rabinMiller, cryptomath_module as cryptoMath
|
||||
|
||||
def main():
|
||||
print('Making key files...')
|
||||
makeKeyFiles('rsa', 1024)
|
||||
print('Key files generation successful.')
|
||||
|
||||
def generateKey(keySize):
|
||||
print('Generating prime p...')
|
||||
p = rabinMiller.generateLargePrime(keySize)
|
||||
print('Generating prime q...')
|
||||
q = rabinMiller.generateLargePrime(keySize)
|
||||
n = p * q
|
||||
|
||||
print('Generating e that is relatively prime to (p - 1) * (q - 1)...')
|
||||
while True:
|
||||
e = random.randrange(2 ** (keySize - 1), 2 ** (keySize))
|
||||
if cryptoMath.gcd(e, (p - 1) * (q - 1)) == 1:
|
||||
break
|
||||
|
||||
print('Calculating d that is mod inverse of e...')
|
||||
d = cryptoMath.findModInverse(e, (p - 1) * (q - 1))
|
||||
|
||||
publicKey = (n, e)
|
||||
privateKey = (n, d)
|
||||
return (publicKey, privateKey)
|
||||
|
||||
def makeKeyFiles(name, keySize):
|
||||
if os.path.exists('%s_pubkey.txt' % (name)) or os.path.exists('%s_privkey.txt' % (name)):
|
||||
print('\nWARNING:')
|
||||
print('"%s_pubkey.txt" or "%s_privkey.txt" already exists. \nUse a different name or delete these files and re-run this program.' % (name, name))
|
||||
sys.exit()
|
||||
|
||||
publicKey, privateKey = generateKey(keySize)
|
||||
print('\nWriting public key to file %s_pubkey.txt...' % name)
|
||||
with open('%s_pubkey.txt' % name, 'w') as fo:
|
||||
fo.write('%s,%s,%s' % (keySize, publicKey[0], publicKey[1]))
|
||||
|
||||
print('Writing private key to file %s_privkey.txt...' % name)
|
||||
with open('%s_privkey.txt' % name, 'w') as fo:
|
||||
fo.write('%s,%s,%s' % (keySize, privateKey[0], privateKey[1]))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,3 +1,4 @@
|
|||
from __future__ import print_function
|
||||
import sys, random
|
||||
|
||||
LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from __future__ import print_function
|
||||
import math
|
||||
|
||||
def main():
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from __future__ import print_function
|
||||
import time, os, sys
|
||||
import transposition_cipher as transCipher
|
||||
|
||||
|
@ -29,7 +30,7 @@ def main():
|
|||
outputObj.close()
|
||||
|
||||
totalTime = round(time.time() - startTime, 2)
|
||||
print('Done (', totalTime, 'seconds )')
|
||||
print(('Done (', totalTime, 'seconds )'))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from __future__ import print_function
|
||||
LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
|
||||
def main():
|
||||
|
|
181
data_structures/AVL/AVL.py
Normal file
181
data_structures/AVL/AVL.py
Normal file
|
@ -0,0 +1,181 @@
|
|||
"""
|
||||
An AVL tree
|
||||
"""
|
||||
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)
|
1
data_structures/Arrays
Normal file
1
data_structures/Arrays
Normal file
|
@ -0,0 +1 @@
|
|||
Arrays implementation using python programming.
|
29
data_structures/Binary Tree/FenwickTree.py
Normal file
29
data_structures/Binary Tree/FenwickTree.py
Normal file
|
@ -0,0 +1,29 @@
|
|||
from __future__ import print_function
|
||||
class FenwickTree:
|
||||
|
||||
def __init__(self, SIZE): # create fenwick tree with size SIZE
|
||||
self.Size = SIZE
|
||||
self.ft = [0 for i in range (0,SIZE)]
|
||||
|
||||
def update(self, i, val): # update data (adding) in index i in O(lg N)
|
||||
while (i < self.Size):
|
||||
self.ft[i] += val
|
||||
i += i & (-i)
|
||||
|
||||
def query(self, i): # query cumulative data from index 0 to i in O(lg N)
|
||||
ret = 0
|
||||
while (i > 0):
|
||||
ret += self.ft[i]
|
||||
i -= i & (-i)
|
||||
return ret
|
||||
|
||||
if __name__ == '__main__':
|
||||
f = FenwickTree(100)
|
||||
f.update(1,20)
|
||||
f.update(4,4)
|
||||
print (f.query(1))
|
||||
print (f.query(3))
|
||||
print (f.query(4))
|
||||
f.update(2,-5)
|
||||
print (f.query(1))
|
||||
print (f.query(3))
|
91
data_structures/Binary Tree/LazySegmentTree.py
Normal file
91
data_structures/Binary Tree/LazySegmentTree.py
Normal file
|
@ -0,0 +1,91 @@
|
|||
from __future__ import print_function
|
||||
import math
|
||||
|
||||
class SegmentTree:
|
||||
|
||||
def __init__(self, N):
|
||||
self.N = N
|
||||
self.st = [0 for i in range(0,4*N)] # approximate the overall size of segment tree with array N
|
||||
self.lazy = [0 for i in range(0,4*N)] # create array to store lazy update
|
||||
self.flag = [0 for i in range(0,4*N)] # flag for lazy update
|
||||
|
||||
def left(self, idx):
|
||||
return idx*2
|
||||
|
||||
def right(self, idx):
|
||||
return idx*2 + 1
|
||||
|
||||
def build(self, idx, l, r, A):
|
||||
if l==r:
|
||||
self.st[idx] = A[l-1]
|
||||
else :
|
||||
mid = (l+r)//2
|
||||
self.build(self.left(idx),l,mid, A)
|
||||
self.build(self.right(idx),mid+1,r, A)
|
||||
self.st[idx] = max(self.st[self.left(idx)] , self.st[self.right(idx)])
|
||||
|
||||
# update with O(lg N) (Normal segment tree without lazy update will take O(Nlg N) for each update)
|
||||
def update(self, idx, l, r, a, b, val): # update(1, 1, N, a, b, v) for update val v to [a,b]
|
||||
if self.flag[idx] == True:
|
||||
self.st[idx] = self.lazy[idx]
|
||||
self.flag[idx] = False
|
||||
if l!=r:
|
||||
self.lazy[self.left(idx)] = self.lazy[idx]
|
||||
self.lazy[self.right(idx)] = self.lazy[idx]
|
||||
self.flag[self.left(idx)] = True
|
||||
self.flag[self.right(idx)] = True
|
||||
|
||||
if r < a or l > b:
|
||||
return True
|
||||
if l >= a and r <= b :
|
||||
self.st[idx] = val
|
||||
if l!=r:
|
||||
self.lazy[self.left(idx)] = val
|
||||
self.lazy[self.right(idx)] = val
|
||||
self.flag[self.left(idx)] = True
|
||||
self.flag[self.right(idx)] = True
|
||||
return True
|
||||
mid = (l+r)//2
|
||||
self.update(self.left(idx),l,mid,a,b,val)
|
||||
self.update(self.right(idx),mid+1,r,a,b,val)
|
||||
self.st[idx] = max(self.st[self.left(idx)] , self.st[self.right(idx)])
|
||||
return True
|
||||
|
||||
# query with O(lg N)
|
||||
def query(self, idx, l, r, a, b): #query(1, 1, N, a, b) for query max of [a,b]
|
||||
if self.flag[idx] == True:
|
||||
self.st[idx] = self.lazy[idx]
|
||||
self.flag[idx] = False
|
||||
if l != r:
|
||||
self.lazy[self.left(idx)] = self.lazy[idx]
|
||||
self.lazy[self.right(idx)] = self.lazy[idx]
|
||||
self.flag[self.left(idx)] = True
|
||||
self.flag[self.right(idx)] = True
|
||||
if r < a or l > b:
|
||||
return -math.inf
|
||||
if l >= a and r <= b:
|
||||
return self.st[idx]
|
||||
mid = (l+r)//2
|
||||
q1 = self.query(self.left(idx),l,mid,a,b)
|
||||
q2 = self.query(self.right(idx),mid+1,r,a,b)
|
||||
return max(q1,q2)
|
||||
|
||||
def showData(self):
|
||||
showList = []
|
||||
for i in range(1,N+1):
|
||||
showList += [self.query(1, 1, self.N, i, i)]
|
||||
print (showList)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
A = [1,2,-4,7,3,-5,6,11,-20,9,14,15,5,2,-8]
|
||||
N = 15
|
||||
segt = SegmentTree(N)
|
||||
segt.build(1,1,N,A)
|
||||
print (segt.query(1,1,N,4,6))
|
||||
print (segt.query(1,1,N,7,11))
|
||||
print (segt.query(1,1,N,7,12))
|
||||
segt.update(1,1,N,1,3,111)
|
||||
print (segt.query(1,1,N,1,15))
|
||||
segt.update(1,1,N,7,8,235)
|
||||
segt.showData()
|
65
data_structures/Binary Tree/SegmentTree.py
Normal file
65
data_structures/Binary Tree/SegmentTree.py
Normal file
|
@ -0,0 +1,65 @@
|
|||
from __future__ import print_function
|
||||
import math
|
||||
|
||||
class SegmentTree:
|
||||
|
||||
def __init__(self, N):
|
||||
self.N = N
|
||||
self.st = [0 for i in range(0,4*N)] # approximate the overall size of segment tree with array N
|
||||
|
||||
def left(self, idx):
|
||||
return idx*2
|
||||
|
||||
def right(self, idx):
|
||||
return idx*2 + 1
|
||||
|
||||
def build(self, idx, l, r, A):
|
||||
if l==r:
|
||||
self.st[idx] = A[l-1]
|
||||
else :
|
||||
mid = (l+r)//2
|
||||
self.build(self.left(idx),l,mid, A)
|
||||
self.build(self.right(idx),mid+1,r, A)
|
||||
self.st[idx] = max(self.st[self.left(idx)] , self.st[self.right(idx)])
|
||||
|
||||
def update(self, idx, l, r, a, b, val): # update(1, 1, N, a, b, v) for update val v to [a,b]
|
||||
if r < a or l > b:
|
||||
return True
|
||||
if l == r :
|
||||
self.st[idx] = val
|
||||
return True
|
||||
mid = (l+r)//2
|
||||
self.update(self.left(idx),l,mid,a,b,val)
|
||||
self.update(self.right(idx),mid+1,r,a,b,val)
|
||||
self.st[idx] = max(self.st[self.left(idx)] , self.st[self.right(idx)])
|
||||
return True
|
||||
|
||||
def query(self, idx, l, r, a, b): #query(1, 1, N, a, b) for query max of [a,b]
|
||||
if r < a or l > b:
|
||||
return -math.inf
|
||||
if l >= a and r <= b:
|
||||
return self.st[idx]
|
||||
mid = (l+r)//2
|
||||
q1 = self.query(self.left(idx),l,mid,a,b)
|
||||
q2 = self.query(self.right(idx),mid+1,r,a,b)
|
||||
return max(q1,q2)
|
||||
|
||||
def showData(self):
|
||||
showList = []
|
||||
for i in range(1,N+1):
|
||||
showList += [self.query(1, 1, self.N, i, i)]
|
||||
print (showList)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
A = [1,2,-4,7,3,-5,6,11,-20,9,14,15,5,2,-8]
|
||||
N = 15
|
||||
segt = SegmentTree(N)
|
||||
segt.build(1,1,N,A)
|
||||
print (segt.query(1,1,N,4,6))
|
||||
print (segt.query(1,1,N,7,11))
|
||||
print (segt.query(1,1,N,7,12))
|
||||
segt.update(1,1,N,1,3,111)
|
||||
print (segt.query(1,1,N,1,15))
|
||||
segt.update(1,1,N,7,8,235)
|
||||
segt.showData()
|
258
data_structures/Binary Tree/binary_search_tree.py
Normal file
258
data_structures/Binary Tree/binary_search_tree.py
Normal file
|
@ -0,0 +1,258 @@
|
|||
'''
|
||||
A binary search Tree
|
||||
'''
|
||||
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():
|
||||
'''
|
||||
Example
|
||||
8
|
||||
/ \
|
||||
3 10
|
||||
/ \ \
|
||||
1 6 14
|
||||
/ \ /
|
||||
4 7 13
|
||||
'''
|
||||
|
||||
'''
|
||||
Example After Deletion
|
||||
7
|
||||
/ \
|
||||
1 4
|
||||
|
||||
'''
|
||||
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()
|
54
data_structures/Graph/BellmanFord.py
Normal file
54
data_structures/Graph/BellmanFord.py
Normal file
|
@ -0,0 +1,54 @@
|
|||
from __future__ import print_function
|
||||
|
||||
def printDist(dist, V):
|
||||
print("\nVertex Distance")
|
||||
for i in range(V):
|
||||
if dist[i] != float('inf') :
|
||||
print(i,"\t",int(dist[i]),end = "\t")
|
||||
else:
|
||||
print(i,"\t","INF",end="\t")
|
||||
print()
|
||||
|
||||
def BellmanFord(graph, V, E, src):
|
||||
mdist=[float('inf') for i in range(V)]
|
||||
mdist[src] = 0.0
|
||||
|
||||
for i in range(V-1):
|
||||
for j in range(V):
|
||||
u = graph[j]["src"]
|
||||
v = graph[j]["dst"]
|
||||
w = graph[j]["weight"]
|
||||
|
||||
if mdist[u] != float('inf') and mdist[u] + w < mdist[v]:
|
||||
mdist[v] = mdist[u] + w
|
||||
for j in range(V):
|
||||
u = graph[j]["src"]
|
||||
v = graph[j]["dst"]
|
||||
w = graph[j]["weight"]
|
||||
|
||||
if mdist[u] != float('inf') and mdist[u] + w < mdist[v]:
|
||||
print("Negative cycle found. Solution not possible.")
|
||||
return
|
||||
|
||||
printDist(mdist, V)
|
||||
|
||||
|
||||
|
||||
#MAIN
|
||||
V = int(input("Enter number of vertices: "))
|
||||
E = int(input("Enter number of edges: "))
|
||||
|
||||
graph = [dict() for j in range(E)]
|
||||
|
||||
for i in range(V):
|
||||
graph[i][i] = 0.0
|
||||
|
||||
for i in range(E):
|
||||
print("\nEdge ",i+1)
|
||||
src = int(input("Enter source:"))
|
||||
dst = int(input("Enter destination:"))
|
||||
weight = float(input("Enter weight:"))
|
||||
graph[i] = {"src": src,"dst": dst, "weight": weight}
|
||||
|
||||
gsrc = int(input("\nEnter shortest path source:"))
|
||||
BellmanFord(graph, V, E, gsrc)
|
63
data_structures/Graph/BreadthFirstSearch.py
Normal file
63
data_structures/Graph/BreadthFirstSearch.py
Normal file
|
@ -0,0 +1,63 @@
|
|||
# Author: OMKAR PATHAK
|
||||
from __future__ import print_function
|
||||
|
||||
|
||||
class Graph():
|
||||
def __init__(self):
|
||||
self.vertex = {}
|
||||
|
||||
# for printing the Graph vertexes
|
||||
def printGraph(self):
|
||||
for i in self.vertex.keys():
|
||||
print(i,' -> ', ' -> '.join([str(j) for j in self.vertex[i]]))
|
||||
|
||||
# for adding the edge beween two vertexes
|
||||
def addEdge(self, fromVertex, toVertex):
|
||||
# check if vertex is already present,
|
||||
if fromVertex in self.vertex.keys():
|
||||
self.vertex[fromVertex].append(toVertex)
|
||||
else:
|
||||
# else make a new vertex
|
||||
self.vertex[fromVertex] = [toVertex]
|
||||
|
||||
def BFS(self, startVertex):
|
||||
# Take a list for stoting already visited vertexes
|
||||
visited = [False] * len(self.vertex)
|
||||
|
||||
# create a list to store all the vertexes for BFS
|
||||
queue = []
|
||||
|
||||
# mark the source node as visited and enqueue it
|
||||
visited[startVertex] = True
|
||||
queue.append(startVertex)
|
||||
|
||||
while queue:
|
||||
startVertex = queue.pop(0)
|
||||
print(startVertex, end = ' ')
|
||||
|
||||
# mark all adjacent nodes as visited and print them
|
||||
for i in self.vertex[startVertex]:
|
||||
if visited[i] == False:
|
||||
queue.append(i)
|
||||
visited[i] = True
|
||||
|
||||
if __name__ == '__main__':
|
||||
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)
|
||||
|
||||
g.printGraph()
|
||||
print('BFS:')
|
||||
g.BFS(2)
|
||||
|
||||
# OUTPUT:
|
||||
# 0 -> 1 -> 2
|
||||
# 1 -> 2
|
||||
# 2 -> 0 -> 3
|
||||
# 3 -> 3
|
||||
# BFS:
|
||||
# 2 0 3 1
|
63
data_structures/Graph/DepthFirstSearch.py
Normal file
63
data_structures/Graph/DepthFirstSearch.py
Normal file
|
@ -0,0 +1,63 @@
|
|||
# Author: OMKAR PATHAK
|
||||
from __future__ import print_function
|
||||
|
||||
|
||||
class Graph():
|
||||
def __init__(self):
|
||||
self.vertex = {}
|
||||
|
||||
# for printing the Graph vertexes
|
||||
def printGraph(self):
|
||||
print(self.vertex)
|
||||
for i in self.vertex.keys():
|
||||
print(i,' -> ', ' -> '.join([str(j) for j in self.vertex[i]]))
|
||||
|
||||
# for adding the edge beween two vertexes
|
||||
def addEdge(self, fromVertex, toVertex):
|
||||
# check if vertex is already present,
|
||||
if fromVertex in self.vertex.keys():
|
||||
self.vertex[fromVertex].append(toVertex)
|
||||
else:
|
||||
# else make a new vertex
|
||||
self.vertex[fromVertex] = [toVertex]
|
||||
|
||||
def DFS(self):
|
||||
# visited array for storing already visited nodes
|
||||
visited = [False] * len(self.vertex)
|
||||
|
||||
# call the recursive helper function
|
||||
for i in range(len(self.vertex)):
|
||||
if visited[i] == False:
|
||||
self.DFSRec(i, visited)
|
||||
|
||||
def DFSRec(self, startVertex, visited):
|
||||
# mark start vertex as visited
|
||||
visited[startVertex] = True
|
||||
|
||||
print(startVertex, end = ' ')
|
||||
|
||||
# Recur for all the vertexes that are adjacent to this node
|
||||
for i in self.vertex.keys():
|
||||
if visited[i] == False:
|
||||
self.DFSRec(i, visited)
|
||||
|
||||
if __name__ == '__main__':
|
||||
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)
|
||||
|
||||
g.printGraph()
|
||||
print('DFS:')
|
||||
g.DFS()
|
||||
|
||||
# OUTPUT:
|
||||
# 0 -> 1 -> 2
|
||||
# 1 -> 2
|
||||
# 2 -> 0 -> 3
|
||||
# 3 -> 3
|
||||
# DFS:
|
||||
# 0 1 2 3
|
57
data_structures/Graph/Dijkstra.py
Normal file
57
data_structures/Graph/Dijkstra.py
Normal file
|
@ -0,0 +1,57 @@
|
|||
from __future__ import print_function
|
||||
|
||||
def printDist(dist, V):
|
||||
print("\nVertex Distance")
|
||||
for i in range(V):
|
||||
if dist[i] != float('inf') :
|
||||
print(i,"\t",int(dist[i]),end = "\t")
|
||||
else:
|
||||
print(i,"\t","INF",end="\t")
|
||||
print()
|
||||
|
||||
def minDist(mdist, vset, V):
|
||||
minVal = float('inf')
|
||||
minInd = -1
|
||||
for i in range(V):
|
||||
if (not vset[i]) and mdist[i] < minVal :
|
||||
minInd = i
|
||||
minVal = mdist[i]
|
||||
return minInd
|
||||
|
||||
def Dijkstra(graph, V, src):
|
||||
mdist=[float('inf') for i in range(V)]
|
||||
vset = [False for i in range(V)]
|
||||
mdist[src] = 0.0;
|
||||
|
||||
for i in range(V-1):
|
||||
u = minDist(mdist, vset, V)
|
||||
vset[u] = True
|
||||
|
||||
for v in range(V):
|
||||
if (not vset[v]) and graph[u][v]!=float('inf') and mdist[u] + graph[u][v] < mdist[v]:
|
||||
mdist[v] = mdist[u] + graph[u][v]
|
||||
|
||||
|
||||
|
||||
printDist(mdist, V)
|
||||
|
||||
|
||||
|
||||
#MAIN
|
||||
V = int(input("Enter number of vertices: "))
|
||||
E = int(input("Enter number of edges: "))
|
||||
|
||||
graph = [[float('inf') for i in range(V)] for j in range(V)]
|
||||
|
||||
for i in range(V):
|
||||
graph[i][i] = 0.0
|
||||
|
||||
for i in range(E):
|
||||
print("\nEdge ",i+1)
|
||||
src = int(input("Enter source:"))
|
||||
dst = int(input("Enter destination:"))
|
||||
weight = float(input("Enter weight:"))
|
||||
graph[src][dst] = weight
|
||||
|
||||
gsrc = int(input("\nEnter shortest path source:"))
|
||||
Dijkstra(graph, V, gsrc)
|
48
data_structures/Graph/FloydWarshall.py
Normal file
48
data_structures/Graph/FloydWarshall.py
Normal file
|
@ -0,0 +1,48 @@
|
|||
from __future__ import print_function
|
||||
|
||||
def printDist(dist, V):
|
||||
print("\nThe shortest path matrix using Floyd Warshall algorithm\n")
|
||||
for i in range(V):
|
||||
for j in range(V):
|
||||
if dist[i][j] != float('inf') :
|
||||
print(int(dist[i][j]),end = "\t")
|
||||
else:
|
||||
print("INF",end="\t")
|
||||
print()
|
||||
|
||||
|
||||
|
||||
def FloydWarshall(graph, V):
|
||||
dist=[[float('inf') for i in range(V)] for j in range(V)]
|
||||
|
||||
for i in range(V):
|
||||
for j in range(V):
|
||||
dist[i][j] = graph[i][j]
|
||||
|
||||
for k in range(V):
|
||||
for i in range(V):
|
||||
for j in range(V):
|
||||
if dist[i][k]!=float('inf') and dist[k][j]!=float('inf') and dist[i][k]+dist[k][j] < dist[i][j]:
|
||||
dist[i][j] = dist[i][k] + dist[k][j]
|
||||
|
||||
printDist(dist, V)
|
||||
|
||||
|
||||
|
||||
#MAIN
|
||||
V = int(input("Enter number of vertices: "))
|
||||
E = int(input("Enter number of edges: "))
|
||||
|
||||
graph = [[float('inf') for i in range(V)] for j in range(V)]
|
||||
|
||||
for i in range(V):
|
||||
graph[i][i] = 0.0
|
||||
|
||||
for i in range(E):
|
||||
print("\nEdge ",i+1)
|
||||
src = int(input("Enter source:"))
|
||||
dst = int(input("Enter destination:"))
|
||||
weight = float(input("Enter weight:"))
|
||||
graph[src][dst] = weight
|
||||
|
||||
FloydWarshall(graph, V)
|
41
data_structures/Graph/Graph.py
Normal file
41
data_structures/Graph/Graph.py
Normal file
|
@ -0,0 +1,41 @@
|
|||
from __future__ import print_function
|
||||
# Author: OMKAR PATHAK
|
||||
|
||||
# We can use Python's dictionary for constructing the graph
|
||||
|
||||
class AdjacencyList(object):
|
||||
def __init__(self):
|
||||
self.List = {}
|
||||
|
||||
def addEdge(self, fromVertex, toVertex):
|
||||
# check if vertex is already present
|
||||
if fromVertex in self.List.keys():
|
||||
self.List[fromVertex].append(toVertex)
|
||||
else:
|
||||
self.List[fromVertex] = [toVertex]
|
||||
|
||||
def printList(self):
|
||||
for i in self.List:
|
||||
print((i,'->',' -> '.join([str(j) for j in self.List[i]])))
|
||||
|
||||
if __name__ == '__main__':
|
||||
al = AdjacencyList()
|
||||
al.addEdge(0, 1)
|
||||
al.addEdge(0, 4)
|
||||
al.addEdge(4, 1)
|
||||
al.addEdge(4, 3)
|
||||
al.addEdge(1, 0)
|
||||
al.addEdge(1, 4)
|
||||
al.addEdge(1, 3)
|
||||
al.addEdge(1, 2)
|
||||
al.addEdge(2, 3)
|
||||
al.addEdge(3, 4)
|
||||
|
||||
al.printList()
|
||||
|
||||
# OUTPUT:
|
||||
# 0 -> 1 -> 4
|
||||
# 1 -> 0 -> 4 -> 3 -> 2
|
||||
# 2 -> 3
|
||||
# 3 -> 4
|
||||
# 4 -> 1 -> 3
|
31
data_structures/Graph/Graph_list.py
Normal file
31
data_structures/Graph/Graph_list.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
from __future__ import print_function
|
||||
|
||||
|
||||
class Graph:
|
||||
def __init__(self, vertex):
|
||||
self.vertex = vertex
|
||||
self.graph = [[0] for i in range(vertex)]
|
||||
|
||||
def add_edge(self, u, v):
|
||||
self.graph[u - 1].append(v - 1)
|
||||
|
||||
def show(self):
|
||||
for i in range(self.vertex):
|
||||
print('%d: '% (i + 1), end=' ')
|
||||
for j in self.graph[i]:
|
||||
print('%d-> '% (j + 1), end=' ')
|
||||
print(' ')
|
||||
|
||||
|
||||
|
||||
g = Graph(100)
|
||||
|
||||
g.add_edge(1,3)
|
||||
g.add_edge(2,3)
|
||||
g.add_edge(3,4)
|
||||
g.add_edge(3,5)
|
||||
g.add_edge(4,5)
|
||||
|
||||
|
||||
g.show()
|
||||
|
32
data_structures/Graph/Graph_matrix.py
Normal file
32
data_structures/Graph/Graph_matrix.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
from __future__ import print_function
|
||||
|
||||
|
||||
class Graph:
|
||||
|
||||
def __init__(self, vertex):
|
||||
self.vertex = vertex
|
||||
self.graph = [[0] * vertex for i in range(vertex) ]
|
||||
|
||||
def add_edge(self, u, v):
|
||||
self.graph[u - 1][v - 1] = 1
|
||||
self.graph[v - 1][u - 1] = 1
|
||||
|
||||
def show(self):
|
||||
|
||||
for i in self.graph:
|
||||
for j in i:
|
||||
print(j, end=' ')
|
||||
print(' ')
|
||||
|
||||
|
||||
|
||||
|
||||
g = Graph(100)
|
||||
|
||||
g.add_edge(1,4)
|
||||
g.add_edge(4,2)
|
||||
g.add_edge(4,5)
|
||||
g.add_edge(2,5)
|
||||
g.add_edge(5,3)
|
||||
g.show()
|
||||
|
212
data_structures/Graph/dijkstra_algorithm.py
Normal file
212
data_structures/Graph/dijkstra_algorithm.py
Normal file
|
@ -0,0 +1,212 @@
|
|||
# Title: Dijkstra's Algorithm for finding single source shortest path from scratch
|
||||
# Author: Shubham Malik
|
||||
# References: https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
|
||||
|
||||
from __future__ import print_function
|
||||
import math
|
||||
import sys
|
||||
# For storing the vertex set to retreive node with the lowest distance
|
||||
|
||||
|
||||
class PriorityQueue:
|
||||
# Based on Min Heap
|
||||
def __init__(self):
|
||||
self.cur_size = 0
|
||||
self.array = []
|
||||
self.pos = {} # To store the pos of node in array
|
||||
|
||||
def isEmpty(self):
|
||||
return self.cur_size == 0
|
||||
|
||||
def min_heapify(self, idx):
|
||||
lc = self.left(idx)
|
||||
rc = self.right(idx)
|
||||
if lc < self.cur_size and self.array(lc)[0] < self.array(idx)[0]:
|
||||
smallest = lc
|
||||
else:
|
||||
smallest = idx
|
||||
if rc < self.cur_size and self.array(rc)[0] < self.array(smallest)[0]:
|
||||
smallest = rc
|
||||
if smallest != idx:
|
||||
self.swap(idx, smallest)
|
||||
self.min_heapify(smallest)
|
||||
|
||||
def insert(self, tup):
|
||||
# Inserts a node into the Priority Queue
|
||||
self.pos[tup[1]] = self.cur_size
|
||||
self.cur_size += 1
|
||||
self.array.append((sys.maxsize, tup[1]))
|
||||
self.decrease_key((sys.maxsize, tup[1]), tup[0])
|
||||
|
||||
def extract_min(self):
|
||||
# Removes and returns the min element at top of priority queue
|
||||
min_node = self.array[0][1]
|
||||
self.array[0] = self.array[self.cur_size - 1]
|
||||
self.cur_size -= 1
|
||||
self.min_heapify(1)
|
||||
del self.pos[min_node]
|
||||
return min_node
|
||||
|
||||
def left(self, i):
|
||||
# returns the index of left child
|
||||
return 2 * i + 1
|
||||
|
||||
def right(self, i):
|
||||
# returns the index of right child
|
||||
return 2 * i + 2
|
||||
|
||||
def par(self, i):
|
||||
# returns the index of parent
|
||||
return math.floor(i / 2)
|
||||
|
||||
def swap(self, i, j):
|
||||
# swaps array elements at indices i and j
|
||||
# update the pos{}
|
||||
self.pos[self.array[i][1]] = j
|
||||
self.pos[self.array[j][1]] = i
|
||||
temp = self.array[i]
|
||||
self.array[i] = self.array[j]
|
||||
self.array[j] = temp
|
||||
|
||||
def decrease_key(self, tup, new_d):
|
||||
idx = self.pos[tup[1]]
|
||||
# assuming the new_d is atmost old_d
|
||||
self.array[idx] = (new_d, tup[1])
|
||||
while idx > 0 and self.array[self.par(idx)][0] > self.array[idx][0]:
|
||||
self.swap(idx, self.par(idx))
|
||||
idx = self.par(idx)
|
||||
|
||||
|
||||
class Graph:
|
||||
def __init__(self, num):
|
||||
self.adjList = {} # To store graph: u -> (v,w)
|
||||
self.num_nodes = num # Number of nodes in graph
|
||||
# To store the distance from source vertex
|
||||
self.dist = [0] * self.num_nodes
|
||||
self.par = [-1] * self.num_nodes # To store the path
|
||||
|
||||
def add_edge(self, u, v, w):
|
||||
# Edge going from node u to v and v to u with weight w
|
||||
# u (w)-> v, v (w) -> u
|
||||
# Check if u already in graph
|
||||
if u in self.adjList.keys():
|
||||
self.adjList[u].append((v, w))
|
||||
else:
|
||||
self.adjList[u] = [(v, w)]
|
||||
|
||||
# Assuming undirected graph
|
||||
if v in self.adjList.keys():
|
||||
self.adjList[v].append((u, w))
|
||||
else:
|
||||
self.adjList[v] = [(u, w)]
|
||||
|
||||
def show_graph(self):
|
||||
# u -> v(w)
|
||||
for u in self.adjList:
|
||||
print(u, '->', ' -> '.join(str("{}({})".format(v, w))
|
||||
for v, w in self.adjList[u]))
|
||||
|
||||
def dijkstra(self, src):
|
||||
# Flush old junk values in par[]
|
||||
self.par = [-1] * self.num_nodes
|
||||
# src is the source node
|
||||
self.dist[src] = 0
|
||||
Q = PriorityQueue()
|
||||
Q.insert((0, src)) # (dist from src, node)
|
||||
for u in self.adjList.keys():
|
||||
if u != src:
|
||||
self.dist[u] = sys.maxsize # Infinity
|
||||
self.par[u] = -1
|
||||
|
||||
while not Q.isEmpty():
|
||||
u = Q.extract_min() # Returns node with the min dist from source
|
||||
# Update the distance of all the neighbours of u and
|
||||
# if their prev dist was INFINITY then push them in Q
|
||||
for v, w in self.adjList[u]:
|
||||
new_dist = self.dist[u] + w
|
||||
if self.dist[v] > new_dist:
|
||||
if self.dist[v] == sys.maxsize:
|
||||
Q.insert((new_dist, v))
|
||||
else:
|
||||
Q.decrease_key((self.dist[v], v), new_dist)
|
||||
self.dist[v] = new_dist
|
||||
self.par[v] = u
|
||||
|
||||
# Show the shortest distances from src
|
||||
self.show_distances(src)
|
||||
|
||||
def show_distances(self, src):
|
||||
print("Distance from node: {}".format(src))
|
||||
for u in range(self.num_nodes):
|
||||
print('Node {} has distance: {}'.format(u, self.dist[u]))
|
||||
|
||||
def show_path(self, src, dest):
|
||||
# To show the shortest path from src to dest
|
||||
# WARNING: Use it *after* calling dijkstra
|
||||
path = []
|
||||
cost = 0
|
||||
temp = dest
|
||||
# Backtracking from dest to src
|
||||
while self.par[temp] != -1:
|
||||
path.append(temp)
|
||||
if temp != src:
|
||||
for v, w in self.adjList[temp]:
|
||||
if v == self.par[temp]:
|
||||
cost += w
|
||||
break
|
||||
temp = self.par[temp]
|
||||
path.append(src)
|
||||
path.reverse()
|
||||
|
||||
print('----Path to reach {} from {}----'.format(dest, src))
|
||||
for u in path:
|
||||
print('{}'.format(u), end=' ')
|
||||
if u != dest:
|
||||
print('-> ', end='')
|
||||
|
||||
print('\nTotal cost of path: ', cost)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
graph = Graph(9)
|
||||
graph.add_edge(0, 1, 4)
|
||||
graph.add_edge(0, 7, 8)
|
||||
graph.add_edge(1, 2, 8)
|
||||
graph.add_edge(1, 7, 11)
|
||||
graph.add_edge(2, 3, 7)
|
||||
graph.add_edge(2, 8, 2)
|
||||
graph.add_edge(2, 5, 4)
|
||||
graph.add_edge(3, 4, 9)
|
||||
graph.add_edge(3, 5, 14)
|
||||
graph.add_edge(4, 5, 10)
|
||||
graph.add_edge(5, 6, 2)
|
||||
graph.add_edge(6, 7, 1)
|
||||
graph.add_edge(6, 8, 6)
|
||||
graph.add_edge(7, 8, 7)
|
||||
graph.show_graph()
|
||||
graph.dijkstra(0)
|
||||
graph.show_path(0, 4)
|
||||
|
||||
# OUTPUT
|
||||
# 0 -> 1(4) -> 7(8)
|
||||
# 1 -> 0(4) -> 2(8) -> 7(11)
|
||||
# 7 -> 0(8) -> 1(11) -> 6(1) -> 8(7)
|
||||
# 2 -> 1(8) -> 3(7) -> 8(2) -> 5(4)
|
||||
# 3 -> 2(7) -> 4(9) -> 5(14)
|
||||
# 8 -> 2(2) -> 6(6) -> 7(7)
|
||||
# 5 -> 2(4) -> 3(14) -> 4(10) -> 6(2)
|
||||
# 4 -> 3(9) -> 5(10)
|
||||
# 6 -> 5(2) -> 7(1) -> 8(6)
|
||||
# Distance from node: 0
|
||||
# Node 0 has distance: 0
|
||||
# Node 1 has distance: 4
|
||||
# Node 2 has distance: 12
|
||||
# Node 3 has distance: 19
|
||||
# Node 4 has distance: 21
|
||||
# Node 5 has distance: 11
|
||||
# Node 6 has distance: 9
|
||||
# Node 7 has distance: 8
|
||||
# Node 8 has distance: 14
|
||||
# ----Path to reach 4 from 0----
|
||||
# 0 -> 7 -> 6 -> 5 -> 4
|
||||
# Total cost of path: 21
|
70
data_structures/Graph/even_tree.py
Normal file
70
data_structures/Graph/even_tree.py
Normal file
|
@ -0,0 +1,70 @@
|
|||
"""
|
||||
You are given a tree(a simple connected graph with no cycles). The tree has N
|
||||
nodes numbered from 1 to N and is rooted at node 1.
|
||||
|
||||
Find the maximum number of edges you can remove from the tree to get a forest
|
||||
such that each connected component of the forest contains an even number of
|
||||
nodes.
|
||||
|
||||
Constraints
|
||||
2 <= 2 <= 100
|
||||
|
||||
Note: The tree input will be such that it can always be decomposed into
|
||||
components containing an even number of nodes.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
# pylint: disable=invalid-name
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
def dfs(start):
|
||||
"""DFS traversal"""
|
||||
# pylint: disable=redefined-outer-name
|
||||
ret = 1
|
||||
visited[start] = True
|
||||
for v in tree.get(start):
|
||||
if v not in visited:
|
||||
ret += dfs(v)
|
||||
if ret % 2 == 0:
|
||||
cuts.append(start)
|
||||
return ret
|
||||
|
||||
|
||||
def even_tree():
|
||||
"""
|
||||
2 1
|
||||
3 1
|
||||
4 3
|
||||
5 2
|
||||
6 1
|
||||
7 2
|
||||
8 6
|
||||
9 8
|
||||
10 8
|
||||
On removing edges (1,3) and (1,6), we can get the desired result 2.
|
||||
"""
|
||||
dfs(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
n, m = 10, 9
|
||||
tree = defaultdict(list)
|
||||
visited = {}
|
||||
cuts = []
|
||||
count = 0
|
||||
edges = [
|
||||
(2, 1),
|
||||
(3, 1),
|
||||
(4, 3),
|
||||
(5, 2),
|
||||
(6, 1),
|
||||
(7, 2),
|
||||
(8, 6),
|
||||
(9, 8),
|
||||
(10, 8),
|
||||
]
|
||||
for u, v in edges:
|
||||
tree[u].append(v)
|
||||
tree[v].append(u)
|
||||
even_tree()
|
||||
print(len(cuts) - 1)
|
90
data_structures/Heap/heap.py
Normal file
90
data_structures/Heap/heap.py
Normal file
|
@ -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()
|
||||
|
||||
|
76
data_structures/LinkedList/DoublyLinkedList.py
Normal file
76
data_structures/LinkedList/DoublyLinkedList.py
Normal file
|
@ -0,0 +1,76 @@
|
|||
'''
|
||||
- A linked list is similar to an array, it holds values. However, links in a linked list do not have indexes.
|
||||
- This is an example of a double ended, doubly linked list.
|
||||
- Each link references the next link and the previous one.
|
||||
'''
|
||||
from __future__ import print_function
|
||||
|
||||
|
||||
class LinkedList:
|
||||
def __init__(self):
|
||||
self.head = None
|
||||
self.tail = None
|
||||
|
||||
def insertHead(self, x):
|
||||
newLink = Link(x) #Create a new link with a value attached to it
|
||||
if(self.isEmpty() == True): #Set the first element added to be the tail
|
||||
self.tail = newLink
|
||||
else:
|
||||
self.head.previous = newLink # newLink <-- currenthead(head)
|
||||
newLink.next = self.head # newLink <--> currenthead(head)
|
||||
self.head = newLink # newLink(head) <--> oldhead
|
||||
|
||||
def deleteHead(self):
|
||||
temp = self.head
|
||||
self.head = self.head.next # oldHead <--> 2ndElement(head)
|
||||
self.head.previous = None # oldHead --> 2ndElement(head) nothing pointing at it so the old head will be removed
|
||||
if(self.head == None):
|
||||
self.tail = None
|
||||
return temp
|
||||
|
||||
def insertTail(self, x):
|
||||
newLink = Link(x)
|
||||
newLink.next = None # currentTail(tail) newLink -->
|
||||
self.tail.next = newLink # currentTail(tail) --> newLink -->
|
||||
newLink.previous = self.tail #currentTail(tail) <--> newLink -->
|
||||
self.tail = newLink # oldTail <--> newLink(tail) -->
|
||||
|
||||
def deleteTail(self):
|
||||
temp = self.tail
|
||||
self.tail = self.tail.previous # 2ndLast(tail) <--> oldTail --> None
|
||||
self.tail.next = None # 2ndlast(tail) --> None
|
||||
return temp
|
||||
|
||||
def delete(self, x):
|
||||
current = self.head
|
||||
|
||||
while(current.value != x): # Find the position to delete
|
||||
current = current.next
|
||||
|
||||
if(current == self.head):
|
||||
self.deleteHead()
|
||||
|
||||
elif(current == self.tail):
|
||||
self.deleteTail()
|
||||
|
||||
else: #Before: 1 <--> 2(current) <--> 3
|
||||
current.previous.next = current.next # 1 --> 3
|
||||
current.next.previous = current.previous # 1 <--> 3
|
||||
|
||||
def isEmpty(self): #Will return True if the list is empty
|
||||
return(self.head == None)
|
||||
|
||||
def display(self): #Prints contents of the list
|
||||
current = self.head
|
||||
while(current != None):
|
||||
current.displayLink()
|
||||
current = current.next
|
||||
print()
|
||||
|
||||
class Link:
|
||||
next = None #This points to the link in front of the new link
|
||||
previous = None #This points to the link behind the new link
|
||||
def __init__(self, x):
|
||||
self.value = x
|
||||
def displayLink(self):
|
||||
print("{}".format(self.value), end=" ")
|
22
data_structures/LinkedList/__init__.py
Normal file
22
data_structures/LinkedList/__init__.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
class Node:
|
||||
def __init__(self, item, next):
|
||||
self.item = item
|
||||
self.next = next
|
||||
|
||||
class LinkedList:
|
||||
def __init__(self):
|
||||
self.head = None
|
||||
|
||||
def add(self, item):
|
||||
self.head = Node(item, self.head)
|
||||
|
||||
def remove(self):
|
||||
if self.is_empty():
|
||||
return None
|
||||
else:
|
||||
item = self.head.item
|
||||
self.head = self.head.next
|
||||
return item
|
||||
|
||||
def is_empty(self):
|
||||
return self.head == None
|
67
data_structures/LinkedList/singly_LinkedList.py
Normal file
67
data_structures/LinkedList/singly_LinkedList.py
Normal file
|
@ -0,0 +1,67 @@
|
|||
from __future__ import print_function
|
||||
class Node:#create a Node
|
||||
def __int__(self,data):
|
||||
self.data=data#given data
|
||||
self.next=None#given next to None
|
||||
class Linked_List:
|
||||
|
||||
pass
|
||||
|
||||
def insert_tail(Head,data):
|
||||
if(Head.next is None):
|
||||
Head.next = Node(data)
|
||||
else:
|
||||
insert_tail(Head.next, data)
|
||||
|
||||
def insert_head(Head,data):
|
||||
tamp = Head
|
||||
if (tamp == None):
|
||||
newNod = Node()#create a new Node
|
||||
newNod.data = data
|
||||
newNod.next = None
|
||||
Head = newNod#make new node to Head
|
||||
else:
|
||||
newNod = Node()
|
||||
newNod.data = data
|
||||
newNod.next = Head#put the Head at NewNode Next
|
||||
Head=newNod#make a NewNode to Head
|
||||
return Head
|
||||
|
||||
def printList(Head):#print every node data
|
||||
tamp=Head
|
||||
while tamp!=None:
|
||||
print(tamp.data)
|
||||
tamp=tamp.next
|
||||
|
||||
def delete_head(Head):#delete from head
|
||||
if Head!=None:
|
||||
Head=Head.next
|
||||
return Head#return new Head
|
||||
|
||||
def delete_tail(Head):#delete from tail
|
||||
if Head!=None:
|
||||
tamp = Node()
|
||||
tamp = Head
|
||||
while (tamp.next).next!= None:#find the 2nd last element
|
||||
tamp = tamp.next
|
||||
tamp.next=None#delete the last element by give next None to 2nd last Element
|
||||
return Head
|
||||
|
||||
def isEmpty(Head):
|
||||
return Head is None #Return if Head is none
|
||||
|
||||
def reverse(Head):
|
||||
prev = None
|
||||
current = Head
|
||||
|
||||
while(current):
|
||||
# Store the current node's next node.
|
||||
next_node = current.next
|
||||
# Make the current node's next point backwards
|
||||
current.next = prev
|
||||
# Make the previous node be the current node
|
||||
prev = current
|
||||
# Make the current node the next node (to progress iteration)
|
||||
current = next_node
|
||||
# Return prev in order to put the head at the end
|
||||
Head = prev
|
40
data_structures/Queue/DeQueue.py
Normal file
40
data_structures/Queue/DeQueue.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
from __future__ import print_function
|
||||
# Python code to demonstrate working of
|
||||
# extend(), extendleft(), rotate(), reverse()
|
||||
|
||||
# importing "collections" for deque operations
|
||||
import collections
|
||||
|
||||
# initializing deque
|
||||
de = collections.deque([1, 2, 3,])
|
||||
|
||||
# using extend() to add numbers to right end
|
||||
# adds 4,5,6 to right end
|
||||
de.extend([4,5,6])
|
||||
|
||||
# printing modified deque
|
||||
print ("The deque after extending deque at end is : ")
|
||||
print (de)
|
||||
|
||||
# using extendleft() to add numbers to left end
|
||||
# adds 7,8,9 to right end
|
||||
de.extendleft([7,8,9])
|
||||
|
||||
# printing modified deque
|
||||
print ("The deque after extending deque at beginning is : ")
|
||||
print (de)
|
||||
|
||||
# using rotate() to rotate the deque
|
||||
# rotates by 3 to left
|
||||
de.rotate(-3)
|
||||
|
||||
# printing modified deque
|
||||
print ("The deque after rotating deque is : ")
|
||||
print (de)
|
||||
|
||||
# using reverse() to reverse the deque
|
||||
de.reverse()
|
||||
|
||||
# printing modified deque
|
||||
print ("The deque after reversing deque is : ")
|
||||
print (de)
|
45
data_structures/Queue/QueueOnList.py
Normal file
45
data_structures/Queue/QueueOnList.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
"""Queue represented by a python list"""
|
||||
class Queue():
|
||||
def __init__(self):
|
||||
self.entries = []
|
||||
self.length = 0
|
||||
self.front=0
|
||||
|
||||
def __str__(self):
|
||||
printed = '<' + str(self.entries)[1:-1] + '>'
|
||||
return printed
|
||||
|
||||
"""Enqueues {@code item}
|
||||
@param item
|
||||
item to enqueue"""
|
||||
def put(self, item):
|
||||
self.entries.append(item)
|
||||
self.length = self.length + 1
|
||||
|
||||
|
||||
"""Dequeues {@code item}
|
||||
@requirement: |self.length| > 0
|
||||
@return dequeued
|
||||
item that was dequeued"""
|
||||
def get(self):
|
||||
self.length = self.length - 1
|
||||
dequeued = self.entries[self.front]
|
||||
self.front-=1
|
||||
self.entries = self.entries[self.front:]
|
||||
return dequeued
|
||||
|
||||
"""Rotates the queue {@code rotation} times
|
||||
@param rotation
|
||||
number of times to rotate queue"""
|
||||
def rotate(self, rotation):
|
||||
for i in range(rotation):
|
||||
self.put(self.get())
|
||||
|
||||
"""Enqueues {@code item}
|
||||
@return item at front of self.entries"""
|
||||
def front(self):
|
||||
return self.entries[0]
|
||||
|
||||
"""Returns the length of this.entries"""
|
||||
def size(self):
|
||||
return self.length
|
50
data_structures/Queue/QueueOnPseudoStack.py
Normal file
50
data_structures/Queue/QueueOnPseudoStack.py
Normal file
|
@ -0,0 +1,50 @@
|
|||
"""Queue represented by a pseudo stack (represented by a list with pop and append)"""
|
||||
class Queue():
|
||||
def __init__(self):
|
||||
self.stack = []
|
||||
self.length = 0
|
||||
|
||||
def __str__(self):
|
||||
printed = '<' + str(self.stack)[1:-1] + '>'
|
||||
return printed
|
||||
|
||||
"""Enqueues {@code item}
|
||||
@param item
|
||||
item to enqueue"""
|
||||
def put(self, item):
|
||||
self.stack.append(item)
|
||||
self.length = self.length + 1
|
||||
|
||||
"""Dequeues {@code item}
|
||||
@requirement: |self.length| > 0
|
||||
@return dequeued
|
||||
item that was dequeued"""
|
||||
def get(self):
|
||||
self.rotate(1)
|
||||
dequeued = self.stack[self.length-1]
|
||||
self.stack = self.stack[:-1]
|
||||
self.rotate(self.length-1)
|
||||
self.length = self.length -1
|
||||
return dequeued
|
||||
|
||||
"""Rotates the queue {@code rotation} times
|
||||
@param rotation
|
||||
number of times to rotate queue"""
|
||||
def rotate(self, rotation):
|
||||
for i in range(rotation):
|
||||
temp = self.stack[0]
|
||||
self.stack = self.stack[1:]
|
||||
self.put(temp)
|
||||
self.length = self.length - 1
|
||||
|
||||
"""Reports item at the front of self
|
||||
@return item at front of self.stack"""
|
||||
def front(self):
|
||||
front = self.get()
|
||||
self.put(front)
|
||||
self.rotate(self.length-1)
|
||||
return front
|
||||
|
||||
"""Returns the length of this.stack"""
|
||||
def size(self):
|
||||
return self.length
|
0
data_structures/Queue/__init__.py
Normal file
0
data_structures/Queue/__init__.py
Normal file
23
data_structures/Stacks/__init__.py
Normal file
23
data_structures/Stacks/__init__.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
class Stack:
|
||||
|
||||
def __init__(self):
|
||||
self.stack = []
|
||||
self.top = 0
|
||||
|
||||
def is_empty(self):
|
||||
return (self.top == 0)
|
||||
|
||||
def push(self, item):
|
||||
if self.top < len(self.stack):
|
||||
self.stack[self.top] = item
|
||||
else:
|
||||
self.stack.append(item)
|
||||
|
||||
self.top += 1
|
||||
|
||||
def pop(self):
|
||||
if self.is_empty():
|
||||
return None
|
||||
else:
|
||||
self.top -= 1
|
||||
return self.stack[self.top]
|
23
data_structures/Stacks/balanced_parentheses.py
Normal file
23
data_structures/Stacks/balanced_parentheses.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
from __future__ import print_function
|
||||
from __future__ import absolute_import
|
||||
from .Stack import Stack
|
||||
|
||||
__author__ = 'Omkar Pathak'
|
||||
|
||||
|
||||
def balanced_parentheses(parentheses):
|
||||
""" Use a stack to check if a string of parentheses are balanced."""
|
||||
stack = Stack(len(parentheses))
|
||||
for parenthesis in parentheses:
|
||||
if parenthesis == '(':
|
||||
stack.push(parenthesis)
|
||||
elif parenthesis == ')':
|
||||
stack.pop()
|
||||
return not stack.is_empty()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
examples = ['((()))', '((())']
|
||||
print('Balanced parentheses demonstration:\n')
|
||||
for example in examples:
|
||||
print(example + ': ' + str(balanced_parentheses(example)))
|
64
data_structures/Stacks/infix_to_postfix_conversion.py
Normal file
64
data_structures/Stacks/infix_to_postfix_conversion.py
Normal file
|
@ -0,0 +1,64 @@
|
|||
from __future__ import print_function
|
||||
from __future__ import absolute_import
|
||||
import string
|
||||
|
||||
from .Stack import Stack
|
||||
|
||||
__author__ = 'Omkar Pathak'
|
||||
|
||||
|
||||
def is_operand(char):
|
||||
return char in string.ascii_letters or char in string.digits
|
||||
|
||||
|
||||
def precedence(char):
|
||||
""" Return integer value representing an operator's precedence, or
|
||||
order of operation.
|
||||
|
||||
https://en.wikipedia.org/wiki/Order_of_operations
|
||||
"""
|
||||
dictionary = {'+': 1, '-': 1,
|
||||
'*': 2, '/': 2,
|
||||
'^': 3}
|
||||
return dictionary.get(char, -1)
|
||||
|
||||
|
||||
def infix_to_postfix(expression):
|
||||
""" Convert infix notation to postfix notation using the Shunting-yard
|
||||
algorithm.
|
||||
|
||||
https://en.wikipedia.org/wiki/Shunting-yard_algorithm
|
||||
https://en.wikipedia.org/wiki/Infix_notation
|
||||
https://en.wikipedia.org/wiki/Reverse_Polish_notation
|
||||
"""
|
||||
stack = Stack(len(expression))
|
||||
postfix = []
|
||||
for char in expression:
|
||||
if is_operand(char):
|
||||
postfix.append(char)
|
||||
elif char not in {'(', ')'}:
|
||||
while (not stack.is_empty()
|
||||
and precedence(char) <= precedence(stack.peek())):
|
||||
postfix.append(stack.pop())
|
||||
stack.push(char)
|
||||
elif char == '(':
|
||||
stack.push(char)
|
||||
elif char == ')':
|
||||
while not stack.is_empty() and stack.peek() != '(':
|
||||
postfix.append(stack.pop())
|
||||
# Pop '(' from stack. If there is no '(', there is a mismatched
|
||||
# parentheses.
|
||||
if stack.peek() != '(':
|
||||
raise ValueError('Mismatched parentheses')
|
||||
stack.pop()
|
||||
while not stack.is_empty():
|
||||
postfix.append(stack.pop())
|
||||
return ' '.join(postfix)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
expression = 'a+b*(c^d-e)^(f+g*h)-i'
|
||||
|
||||
print('Infix to Postfix Notation demonstration:\n')
|
||||
print('Infix notation: ' + expression)
|
||||
print('Postfix notation: ' + infix_to_postfix(expression))
|
17
data_structures/Stacks/next.py
Normal file
17
data_structures/Stacks/next.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
from __future__ import print_function
|
||||
# Function to print element and NGE pair for all elements of list
|
||||
def printNGE(arr):
|
||||
|
||||
for i in range(0, len(arr), 1):
|
||||
|
||||
next = -1
|
||||
for j in range(i+1, len(arr), 1):
|
||||
if arr[i] < arr[j]:
|
||||
next = arr[j]
|
||||
break
|
||||
|
||||
print(str(arr[i]) + " -- " + str(next))
|
||||
|
||||
# Driver program to test above function
|
||||
arr = [11,13,21,3]
|
||||
printNGE(arr)
|
69
data_structures/Stacks/stack.py
Normal file
69
data_structures/Stacks/stack.py
Normal file
|
@ -0,0 +1,69 @@
|
|||
from __future__ import print_function
|
||||
__author__ = 'Omkar Pathak'
|
||||
|
||||
|
||||
class Stack(object):
|
||||
""" A stack is an abstract data type that serves as a collection of
|
||||
elements with two principal operations: push() and pop(). push() adds an
|
||||
element to the top of the stack, and pop() removes an element from the top
|
||||
of a stack. The order in which elements come off of a stack are
|
||||
Last In, First Out (LIFO).
|
||||
|
||||
https://en.wikipedia.org/wiki/Stack_(abstract_data_type)
|
||||
"""
|
||||
|
||||
def __init__(self, limit=10):
|
||||
self.stack = []
|
||||
self.limit = limit
|
||||
|
||||
def __bool__(self):
|
||||
return not bool(self.stack)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.stack)
|
||||
|
||||
def push(self, data):
|
||||
""" Push an element to the top of the stack."""
|
||||
if len(self.stack) >= self.limit:
|
||||
raise StackOverflowError
|
||||
self.stack.append(data)
|
||||
|
||||
def pop(self):
|
||||
""" Pop an element off of the top of the stack."""
|
||||
if self.stack:
|
||||
return self.stack.pop()
|
||||
else:
|
||||
raise IndexError('pop from an empty stack')
|
||||
|
||||
def peek(self):
|
||||
""" Peek at the top-most element of the stack."""
|
||||
if self.stack:
|
||||
return self.stack[-1]
|
||||
|
||||
def is_empty(self):
|
||||
""" Check if a stack is empty."""
|
||||
return not bool(self.stack)
|
||||
|
||||
def size(self):
|
||||
""" Return the size of the stack."""
|
||||
return len(self.stack)
|
||||
|
||||
|
||||
class StackOverflowError(BaseException):
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
stack = Stack()
|
||||
for i in range(10):
|
||||
stack.push(i)
|
||||
|
||||
print('Stack demonstration:\n')
|
||||
print('Initial stack: ' + str(stack))
|
||||
print('pop(): ' + str(stack.pop()))
|
||||
print('After pop(), the stack is now: ' + str(stack))
|
||||
print('peek(): ' + str(stack.peek()))
|
||||
stack.push(100)
|
||||
print('After push(100), the stack is now: ' + str(stack))
|
||||
print('is_empty(): ' + str(stack.is_empty()))
|
||||
print('size(): ' + str(stack.size()))
|
75
data_structures/Trie/Trie.py
Normal file
75
data_structures/Trie/Trie.py
Normal file
|
@ -0,0 +1,75 @@
|
|||
"""
|
||||
A Trie/Prefix Tree is a kind of search tree used to provide quick lookup
|
||||
of words/patterns in a set of words. A basic Trie however has O(n^2) space complexity
|
||||
making it impractical in practice. It however provides O(max(search_string, length of longest word)) lookup
|
||||
time making it an optimal approach when space is not an issue.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
class TrieNode:
|
||||
def __init__(self):
|
||||
self.nodes = dict() # Mapping from char to TrieNode
|
||||
self.is_leaf = False
|
||||
|
||||
def insert_many(self, words: [str]):
|
||||
"""
|
||||
Inserts a list of words into the Trie
|
||||
:param words: list of string words
|
||||
:return: None
|
||||
"""
|
||||
for word in words:
|
||||
self.insert(word)
|
||||
|
||||
def insert(self, word: str):
|
||||
"""
|
||||
Inserts a word into the Trie
|
||||
:param word: word to be inserted
|
||||
:return: None
|
||||
"""
|
||||
curr = self
|
||||
for char in word:
|
||||
if char not in curr.nodes:
|
||||
curr.nodes[char] = TrieNode()
|
||||
curr = curr.nodes[char]
|
||||
curr.is_leaf = True
|
||||
|
||||
def find(self, word: str) -> bool:
|
||||
"""
|
||||
Tries to find word in a Trie
|
||||
:param word: word to look for
|
||||
:return: Returns True if word is found, False otherwise
|
||||
"""
|
||||
curr = self
|
||||
for char in word:
|
||||
if char not in curr.nodes:
|
||||
return False
|
||||
curr = curr.nodes[char]
|
||||
return curr.is_leaf
|
||||
|
||||
|
||||
def print_words(node: TrieNode, word: str):
|
||||
"""
|
||||
Prints all the words in a Trie
|
||||
:param node: root node of Trie
|
||||
:param word: Word variable should be empty at start
|
||||
:return: None
|
||||
"""
|
||||
if node.is_leaf:
|
||||
print(word, end=' ')
|
||||
|
||||
for key, value in node.nodes.items():
|
||||
print_words(value, word + key)
|
||||
|
||||
|
||||
def test():
|
||||
words = ['banana', 'bananas', 'bandana', 'band', 'apple', 'all', 'beast']
|
||||
root = TrieNode()
|
||||
root.insert_many(words)
|
||||
# print_words(root, '')
|
||||
assert root.find('banana')
|
||||
assert not root.find('bandanas')
|
||||
assert not root.find('apps')
|
||||
assert root.find('apple')
|
||||
|
||||
test()
|
0
data_structures/UnionFind/__init__.py
Normal file
0
data_structures/UnionFind/__init__.py
Normal file
78
data_structures/UnionFind/tests_union_find.py
Normal file
78
data_structures/UnionFind/tests_union_find.py
Normal file
|
@ -0,0 +1,78 @@
|
|||
from __future__ import absolute_import
|
||||
from .union_find import UnionFind
|
||||
import unittest
|
||||
|
||||
|
||||
class TestUnionFind(unittest.TestCase):
|
||||
def test_init_with_valid_size(self):
|
||||
uf = UnionFind(5)
|
||||
self.assertEqual(uf.size, 5)
|
||||
|
||||
def test_init_with_invalid_size(self):
|
||||
with self.assertRaises(ValueError):
|
||||
uf = UnionFind(0)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
uf = UnionFind(-5)
|
||||
|
||||
def test_union_with_valid_values(self):
|
||||
uf = UnionFind(10)
|
||||
|
||||
for i in range(11):
|
||||
for j in range(11):
|
||||
uf.union(i, j)
|
||||
|
||||
def test_union_with_invalid_values(self):
|
||||
uf = UnionFind(10)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
uf.union(-1, 1)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
uf.union(11, 1)
|
||||
|
||||
def test_same_set_with_valid_values(self):
|
||||
uf = UnionFind(10)
|
||||
|
||||
for i in range(11):
|
||||
for j in range(11):
|
||||
if i == j:
|
||||
self.assertTrue(uf.same_set(i, j))
|
||||
else:
|
||||
self.assertFalse(uf.same_set(i, j))
|
||||
|
||||
uf.union(1, 2)
|
||||
self.assertTrue(uf.same_set(1, 2))
|
||||
|
||||
uf.union(3, 4)
|
||||
self.assertTrue(uf.same_set(3, 4))
|
||||
|
||||
self.assertFalse(uf.same_set(1, 3))
|
||||
self.assertFalse(uf.same_set(1, 4))
|
||||
self.assertFalse(uf.same_set(2, 3))
|
||||
self.assertFalse(uf.same_set(2, 4))
|
||||
|
||||
uf.union(1, 3)
|
||||
self.assertTrue(uf.same_set(1, 3))
|
||||
self.assertTrue(uf.same_set(1, 4))
|
||||
self.assertTrue(uf.same_set(2, 3))
|
||||
self.assertTrue(uf.same_set(2, 4))
|
||||
|
||||
uf.union(4, 10)
|
||||
self.assertTrue(uf.same_set(1, 10))
|
||||
self.assertTrue(uf.same_set(2, 10))
|
||||
self.assertTrue(uf.same_set(3, 10))
|
||||
self.assertTrue(uf.same_set(4, 10))
|
||||
|
||||
def test_same_set_with_invalid_values(self):
|
||||
uf = UnionFind(10)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
uf.same_set(-1, 1)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
uf.same_set(11, 0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
87
data_structures/UnionFind/union_find.py
Normal file
87
data_structures/UnionFind/union_find.py
Normal file
|
@ -0,0 +1,87 @@
|
|||
class UnionFind():
|
||||
"""
|
||||
https://en.wikipedia.org/wiki/Disjoint-set_data_structure
|
||||
|
||||
The union-find is a disjoint-set data structure
|
||||
|
||||
You can merge two sets and tell if one set belongs to
|
||||
another one.
|
||||
|
||||
It's used on the Kruskal Algorithm
|
||||
(https://en.wikipedia.org/wiki/Kruskal%27s_algorithm)
|
||||
|
||||
The elements are in range [0, size]
|
||||
"""
|
||||
def __init__(self, size):
|
||||
if size <= 0:
|
||||
raise ValueError("size should be greater than 0")
|
||||
|
||||
self.size = size
|
||||
|
||||
# The below plus 1 is because we are using elements
|
||||
# in range [0, size]. It makes more sense.
|
||||
|
||||
# Every set begins with only itself
|
||||
self.root = [i for i in range(size+1)]
|
||||
|
||||
# This is used for heuristic union by rank
|
||||
self.weight = [0 for i in range(size+1)]
|
||||
|
||||
def union(self, u, v):
|
||||
"""
|
||||
Union of the sets u and v.
|
||||
Complexity: log(n).
|
||||
Amortized complexity: < 5 (it's very fast).
|
||||
"""
|
||||
|
||||
self._validate_element_range(u, "u")
|
||||
self._validate_element_range(v, "v")
|
||||
|
||||
if u == v:
|
||||
return
|
||||
|
||||
# Using union by rank will guarantee the
|
||||
# log(n) complexity
|
||||
rootu = self._root(u)
|
||||
rootv = self._root(v)
|
||||
weight_u = self.weight[rootu]
|
||||
weight_v = self.weight[rootv]
|
||||
if weight_u >= weight_v:
|
||||
self.root[rootv] = rootu
|
||||
if weight_u == weight_v:
|
||||
self.weight[rootu] += 1
|
||||
else:
|
||||
self.root[rootu] = rootv
|
||||
|
||||
def same_set(self, u, v):
|
||||
"""
|
||||
Return true if the elements u and v belongs to
|
||||
the same set
|
||||
"""
|
||||
|
||||
self._validate_element_range(u, "u")
|
||||
self._validate_element_range(v, "v")
|
||||
|
||||
return self._root(u) == self._root(v)
|
||||
|
||||
def _root(self, u):
|
||||
"""
|
||||
Get the element set root.
|
||||
This uses the heuristic path compression
|
||||
See wikipedia article for more details.
|
||||
"""
|
||||
|
||||
if u != self.root[u]:
|
||||
self.root[u] = self._root(self.root[u])
|
||||
|
||||
return self.root[u]
|
||||
|
||||
def _validate_element_range(self, u, element_name):
|
||||
"""
|
||||
Raises ValueError if element is not in range
|
||||
"""
|
||||
if u < 0 or u > self.size:
|
||||
msg = ("element {0} with value {1} "
|
||||
"should be in range [0~{2}]")\
|
||||
.format(element_name, u, self.size)
|
||||
raise ValueError(msg)
|
0
data_structures/__init__.py
Normal file
0
data_structures/__init__.py
Normal file
37
dynamic_programming/FloydWarshall.py
Normal file
37
dynamic_programming/FloydWarshall.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
import math
|
||||
|
||||
class Graph:
|
||||
|
||||
def __init__(self, N = 0): # a graph with Node 0,1,...,N-1
|
||||
self.N = N
|
||||
self.W = [[math.inf for j in range(0,N)] for i in range(0,N)] # adjacency matrix for weight
|
||||
self.dp = [[math.inf for j in range(0,N)] for i in range(0,N)] # dp[i][j] stores minimum distance from i to j
|
||||
|
||||
def addEdge(self, u, v, w):
|
||||
self.dp[u][v] = w
|
||||
|
||||
def floyd_warshall(self):
|
||||
for k in range(0,self.N):
|
||||
for i in range(0,self.N):
|
||||
for j in range(0,self.N):
|
||||
self.dp[i][j] = min(self.dp[i][j], self.dp[i][k] + self.dp[k][j])
|
||||
|
||||
def showMin(self, u, v):
|
||||
return self.dp[u][v]
|
||||
|
||||
if __name__ == '__main__':
|
||||
graph = Graph(5)
|
||||
graph.addEdge(0,2,9)
|
||||
graph.addEdge(0,4,10)
|
||||
graph.addEdge(1,3,5)
|
||||
graph.addEdge(2,3,7)
|
||||
graph.addEdge(3,0,10)
|
||||
graph.addEdge(3,1,2)
|
||||
graph.addEdge(3,2,1)
|
||||
graph.addEdge(3,4,6)
|
||||
graph.addEdge(4,1,3)
|
||||
graph.addEdge(4,2,4)
|
||||
graph.addEdge(4,3,9)
|
||||
graph.floyd_warshall()
|
||||
graph.showMin(1,4)
|
||||
graph.showMin(0,3)
|
29
dynamic_programming/abbreviation.py
Normal file
29
dynamic_programming/abbreviation.py
Normal file
|
@ -0,0 +1,29 @@
|
|||
"""
|
||||
https://www.hackerrank.com/challenges/abbr/problem
|
||||
You can perform the following operation on some string, :
|
||||
|
||||
1. Capitalize zero or more of 's lowercase letters at some index i
|
||||
(i.e., make them uppercase).
|
||||
2. Delete all of the remaining lowercase letters in .
|
||||
|
||||
Example:
|
||||
a=daBcd and b="ABC"
|
||||
daBcd -> capitalize a and c(dABCd) -> remove d (ABC)
|
||||
"""
|
||||
def abbr(a, b):
|
||||
n = len(a)
|
||||
m = len(b)
|
||||
dp = [[False for _ in range(m + 1)] for _ in range(n + 1)]
|
||||
dp[0][0] = True
|
||||
for i in range(n):
|
||||
for j in range(m + 1):
|
||||
if dp[i][j]:
|
||||
if j < m and a[i].upper() == b[j]:
|
||||
dp[i + 1][j + 1] = True
|
||||
if a[i].islower():
|
||||
dp[i + 1][j] = True
|
||||
return dp[n][m]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print abbr("daBcd", "ABC") # expect True
|
26
dynamic_programming/coin_change.py
Normal file
26
dynamic_programming/coin_change.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
"""
|
||||
You have m types of coins available in infinite quantities
|
||||
where the value of each coins is given in the array S=[S0,... Sm-1]
|
||||
Can you determine number of ways of making change for n units using
|
||||
the given types of coins?
|
||||
https://www.hackerrank.com/challenges/coin-change/problem
|
||||
"""
|
||||
from __future__ import print_function
|
||||
def dp_count(S, m, n):
|
||||
table = [0] * (n + 1)
|
||||
|
||||
# Base case (If given value is 0)
|
||||
table[0] = 1
|
||||
|
||||
# Pick all coins one by one and update table[] values
|
||||
# after the index greater than or equal to the value of the
|
||||
# picked coin
|
||||
for i in range(0, m):
|
||||
for j in range(S[i], n + 1):
|
||||
table[j] += table[j - S[i]]
|
||||
|
||||
return table[n]
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(dp_count([1, 2, 3], 3, 4)) # answer 4
|
||||
print(dp_count([2, 5, 3, 6], 4, 10)) # answer 5
|
75
dynamic_programming/edit_distance.py
Normal file
75
dynamic_programming/edit_distance.py
Normal file
|
@ -0,0 +1,75 @@
|
|||
"""
|
||||
Author : Turfa Auliarachman
|
||||
Date : October 12, 2016
|
||||
|
||||
This is a pure Python implementation of Dynamic Programming solution to the edit distance problem.
|
||||
|
||||
The problem is :
|
||||
Given two strings A and B. Find the minimum number of operations to string B such that A = B. The permitted operations are removal, insertion, and substitution.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
|
||||
class EditDistance:
|
||||
"""
|
||||
Use :
|
||||
solver = EditDistance()
|
||||
editDistanceResult = solver.solve(firstString, secondString)
|
||||
"""
|
||||
|
||||
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)
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
raw_input # Python 2
|
||||
except NameError:
|
||||
raw_input = input # Python 3
|
||||
|
||||
solver = EditDistance()
|
||||
|
||||
print("****************** Testing Edit Distance DP Algorithm ******************")
|
||||
print()
|
||||
|
||||
print("Enter the first string: ", end="")
|
||||
S1 = raw_input().strip()
|
||||
|
||||
print("Enter the second string: ", end="")
|
||||
S2 = raw_input().strip()
|
||||
|
||||
print()
|
||||
print("The minimum Edit Distance is: %d" % (solver.solve(S1, S2)))
|
||||
print()
|
||||
print("*************** End of Testing Edit Distance DP Algorithm ***************")
|
43
dynamic_programming/fastfibonacci.py
Normal file
43
dynamic_programming/fastfibonacci.py
Normal file
|
@ -0,0 +1,43 @@
|
|||
"""
|
||||
This program calculates the nth Fibonacci number in O(log(n)).
|
||||
It's possible to calculate F(1000000) in less than a second.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
|
||||
|
||||
# returns F(n)
|
||||
def fibonacci(n: int):
|
||||
if n < 0:
|
||||
raise ValueError("Negative arguments are not supported")
|
||||
return _fib(n)[0]
|
||||
|
||||
|
||||
# returns (F(n), F(n-1))
|
||||
def _fib(n: int):
|
||||
if n == 0:
|
||||
# (F(0), F(1))
|
||||
return (0, 1)
|
||||
else:
|
||||
# F(2n) = F(n)[2F(n+1) − F(n)]
|
||||
# F(2n+1) = F(n+1)^2+F(n)^2
|
||||
a, b = _fib(n // 2)
|
||||
c = a * (b * 2 - a)
|
||||
d = a * a + b * b
|
||||
if n % 2 == 0:
|
||||
return (c, d)
|
||||
else:
|
||||
return (d, c + d)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = sys.argv[1:]
|
||||
if len(args) != 1:
|
||||
print("Too few or too much parameters given.")
|
||||
exit(1)
|
||||
try:
|
||||
n = int(args[0])
|
||||
except ValueError:
|
||||
print("Could not convert data to an integer.")
|
||||
exit(1)
|
||||
print("F(%d) = %d" % (n, fibonacci(n)))
|
54
dynamic_programming/fibonacci.py
Normal file
54
dynamic_programming/fibonacci.py
Normal file
|
@ -0,0 +1,54 @@
|
|||
"""
|
||||
This is a pure Python implementation of Dynamic Programming solution to the fibonacci sequence problem.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
|
||||
class Fibonacci:
|
||||
|
||||
def __init__(self, N=None):
|
||||
self.fib_array = []
|
||||
if N:
|
||||
N = int(N)
|
||||
self.fib_array.append(0)
|
||||
self.fib_array.append(1)
|
||||
for i in range(2, N + 1):
|
||||
self.fib_array.append(self.fib_array[i - 1] + self.fib_array[i - 2])
|
||||
elif N == 0:
|
||||
self.fib_array.append(0)
|
||||
|
||||
def get(self, sequence_no=None):
|
||||
if sequence_no != None:
|
||||
if sequence_no < len(self.fib_array):
|
||||
return print(self.fib_array[:sequence_no + 1])
|
||||
else:
|
||||
print("Out of bound.")
|
||||
else:
|
||||
print("Please specify a value")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("\n********* Fibonacci Series Using Dynamic Programming ************\n")
|
||||
try:
|
||||
raw_input # Python 2
|
||||
except NameError:
|
||||
raw_input = input # Python 3
|
||||
|
||||
print("\n Enter the upper limit for the fibonacci sequence: ", end="")
|
||||
try:
|
||||
N = eval(raw_input().strip())
|
||||
fib = Fibonacci(N)
|
||||
print(
|
||||
"\n********* Enter different values to get the corresponding fibonacci sequence, enter any negative number to exit. ************\n")
|
||||
while True:
|
||||
print("Enter value: ", end=" ")
|
||||
try:
|
||||
i = eval(raw_input().strip())
|
||||
if i < 0:
|
||||
print("\n********* Good Bye!! ************\n")
|
||||
break
|
||||
fib.get(i)
|
||||
except NameError:
|
||||
print("\nInvalid input, please try again.")
|
||||
except NameError:
|
||||
print("\n********* Invalid input, good bye!! ************\n")
|
141
dynamic_programming/k_means_clustering_tensorflow.py
Normal file
141
dynamic_programming/k_means_clustering_tensorflow.py
Normal file
|
@ -0,0 +1,141 @@
|
|||
import tensorflow as tf
|
||||
from random import choice, shuffle
|
||||
from numpy import array
|
||||
|
||||
|
||||
def TFKMeansCluster(vectors, noofclusters):
|
||||
"""
|
||||
K-Means Clustering using TensorFlow.
|
||||
'vectors' should be a n*k 2-D NumPy array, where n is the number
|
||||
of vectors of dimensionality k.
|
||||
'noofclusters' should be an integer.
|
||||
"""
|
||||
|
||||
noofclusters = int(noofclusters)
|
||||
assert noofclusters < len(vectors)
|
||||
|
||||
#Find out the dimensionality
|
||||
dim = len(vectors[0])
|
||||
|
||||
#Will help select random centroids from among the available vectors
|
||||
vector_indices = list(range(len(vectors)))
|
||||
shuffle(vector_indices)
|
||||
|
||||
#GRAPH OF COMPUTATION
|
||||
#We initialize a new graph and set it as the default during each run
|
||||
#of this algorithm. This ensures that as this function is called
|
||||
#multiple times, the default graph doesn't keep getting crowded with
|
||||
#unused ops and Variables from previous function calls.
|
||||
|
||||
graph = tf.Graph()
|
||||
|
||||
with graph.as_default():
|
||||
|
||||
#SESSION OF COMPUTATION
|
||||
|
||||
sess = tf.Session()
|
||||
|
||||
##CONSTRUCTING THE ELEMENTS OF COMPUTATION
|
||||
|
||||
##First lets ensure we have a Variable vector for each centroid,
|
||||
##initialized to one of the vectors from the available data points
|
||||
centroids = [tf.Variable((vectors[vector_indices[i]]))
|
||||
for i in range(noofclusters)]
|
||||
##These nodes will assign the centroid Variables the appropriate
|
||||
##values
|
||||
centroid_value = tf.placeholder("float64", [dim])
|
||||
cent_assigns = []
|
||||
for centroid in centroids:
|
||||
cent_assigns.append(tf.assign(centroid, centroid_value))
|
||||
|
||||
##Variables for cluster assignments of individual vectors(initialized
|
||||
##to 0 at first)
|
||||
assignments = [tf.Variable(0) for i in range(len(vectors))]
|
||||
##These nodes will assign an assignment Variable the appropriate
|
||||
##value
|
||||
assignment_value = tf.placeholder("int32")
|
||||
cluster_assigns = []
|
||||
for assignment in assignments:
|
||||
cluster_assigns.append(tf.assign(assignment,
|
||||
assignment_value))
|
||||
|
||||
##Now lets construct the node that will compute the mean
|
||||
#The placeholder for the input
|
||||
mean_input = tf.placeholder("float", [None, dim])
|
||||
#The Node/op takes the input and computes a mean along the 0th
|
||||
#dimension, i.e. the list of input vectors
|
||||
mean_op = tf.reduce_mean(mean_input, 0)
|
||||
|
||||
##Node for computing Euclidean distances
|
||||
#Placeholders for input
|
||||
v1 = tf.placeholder("float", [dim])
|
||||
v2 = tf.placeholder("float", [dim])
|
||||
euclid_dist = tf.sqrt(tf.reduce_sum(tf.pow(tf.sub(
|
||||
v1, v2), 2)))
|
||||
|
||||
##This node will figure out which cluster to assign a vector to,
|
||||
##based on Euclidean distances of the vector from the centroids.
|
||||
#Placeholder for input
|
||||
centroid_distances = tf.placeholder("float", [noofclusters])
|
||||
cluster_assignment = tf.argmin(centroid_distances, 0)
|
||||
|
||||
##INITIALIZING STATE VARIABLES
|
||||
|
||||
##This will help initialization of all Variables defined with respect
|
||||
##to the graph. The Variable-initializer should be defined after
|
||||
##all the Variables have been constructed, so that each of them
|
||||
##will be included in the initialization.
|
||||
init_op = tf.initialize_all_variables()
|
||||
|
||||
#Initialize all variables
|
||||
sess.run(init_op)
|
||||
|
||||
##CLUSTERING ITERATIONS
|
||||
|
||||
#Now perform the Expectation-Maximization steps of K-Means clustering
|
||||
#iterations. To keep things simple, we will only do a set number of
|
||||
#iterations, instead of using a Stopping Criterion.
|
||||
noofiterations = 100
|
||||
for iteration_n in range(noofiterations):
|
||||
|
||||
##EXPECTATION STEP
|
||||
##Based on the centroid locations till last iteration, compute
|
||||
##the _expected_ centroid assignments.
|
||||
#Iterate over each vector
|
||||
for vector_n in range(len(vectors)):
|
||||
vect = vectors[vector_n]
|
||||
#Compute Euclidean distance between this vector and each
|
||||
#centroid. Remember that this list cannot be named
|
||||
#'centroid_distances', since that is the input to the
|
||||
#cluster assignment node.
|
||||
distances = [sess.run(euclid_dist, feed_dict={
|
||||
v1: vect, v2: sess.run(centroid)})
|
||||
for centroid in centroids]
|
||||
#Now use the cluster assignment node, with the distances
|
||||
#as the input
|
||||
assignment = sess.run(cluster_assignment, feed_dict = {
|
||||
centroid_distances: distances})
|
||||
#Now assign the value to the appropriate state variable
|
||||
sess.run(cluster_assigns[vector_n], feed_dict={
|
||||
assignment_value: assignment})
|
||||
|
||||
##MAXIMIZATION STEP
|
||||
#Based on the expected state computed from the Expectation Step,
|
||||
#compute the locations of the centroids so as to maximize the
|
||||
#overall objective of minimizing within-cluster Sum-of-Squares
|
||||
for cluster_n in range(noofclusters):
|
||||
#Collect all the vectors assigned to this cluster
|
||||
assigned_vects = [vectors[i] for i in range(len(vectors))
|
||||
if sess.run(assignments[i]) == cluster_n]
|
||||
#Compute new centroid location
|
||||
new_location = sess.run(mean_op, feed_dict={
|
||||
mean_input: array(assigned_vects)})
|
||||
#Assign value to appropriate variable
|
||||
sess.run(cent_assigns[cluster_n], feed_dict={
|
||||
centroid_value: new_location})
|
||||
|
||||
#Return centroids and assignments
|
||||
centroids = sess.run(centroids)
|
||||
assignments = sess.run(assignments)
|
||||
return centroids, assignments
|
||||
|
14
dynamic_programming/knapsack.py
Normal file
14
dynamic_programming/knapsack.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
"""
|
||||
Given weights and values of n items, put these items in a knapsack of capacity W to get the maximum total value in the knapsack.
|
||||
"""
|
||||
def knapsack(W, wt, val, n):
|
||||
dp = [[0 for i in range(W+1)]for j in range(n+1)]
|
||||
|
||||
for i in range(1,n+1):
|
||||
for w in range(1,W+1):
|
||||
if(wt[i-1]<=w):
|
||||
dp[i][w] = max(val[i-1]+dp[i-1][w-wt[i-1]],dp[i-1][w])
|
||||
else:
|
||||
dp[i][w] = dp[i-1][w]
|
||||
|
||||
return dp[n][w]
|
37
dynamic_programming/longest_common_subsequence.py
Normal file
37
dynamic_programming/longest_common_subsequence.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
"""
|
||||
LCS Problem Statement: Given two sequences, find the length of longest subsequence present in both of them.
|
||||
A subsequence is a sequence that appears in the same relative order, but not necessarily continious.
|
||||
Example:"abc", "abg" are subsequences of "abcdefgh".
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
try:
|
||||
xrange # Python 2
|
||||
except NameError:
|
||||
xrange = range # Python 3
|
||||
|
||||
def lcs_dp(x, y):
|
||||
# find the length of 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)]
|
||||
seq = []
|
||||
|
||||
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
|
||||
seq.append(x[i -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], seq
|
||||
|
||||
if __name__=='__main__':
|
||||
x = 'AGGTAB'
|
||||
y = 'GXTXAYB'
|
||||
print(lcs_dp(x, y))
|
42
dynamic_programming/longest_increasing_subsequence.py
Normal file
42
dynamic_programming/longest_increasing_subsequence.py
Normal file
|
@ -0,0 +1,42 @@
|
|||
'''
|
||||
Author : Mehdi ALAOUI
|
||||
|
||||
This is a pure Python implementation of Dynamic Programming solution to the longest increasing subsequence of a given sequence.
|
||||
|
||||
The problem is :
|
||||
Given an ARRAY, to find the longest and increasing sub ARRAY in that given ARRAY and return it.
|
||||
Example: [10, 22, 9, 33, 21, 50, 41, 60, 80] as input will return [10, 22, 33, 41, 60, 80] as output
|
||||
'''
|
||||
from __future__ import print_function
|
||||
|
||||
def longestSub(ARRAY): #This function is recursive
|
||||
|
||||
ARRAY_LENGTH = len(ARRAY)
|
||||
if(ARRAY_LENGTH <= 1): #If the array contains only one element, we return it (it's the stop condition of recursion)
|
||||
return ARRAY
|
||||
#Else
|
||||
PIVOT=ARRAY[0]
|
||||
isFound=False
|
||||
i=1
|
||||
LONGEST_SUB=[]
|
||||
while(not isFound and i<ARRAY_LENGTH):
|
||||
if (ARRAY[i] < PIVOT):
|
||||
isFound=True
|
||||
TEMPORARY_ARRAY = [ element for element in ARRAY[i:] if element >= ARRAY[i] ]
|
||||
TEMPORARY_ARRAY = longestSub(TEMPORARY_ARRAY)
|
||||
if ( len(TEMPORARY_ARRAY) > len(LONGEST_SUB) ):
|
||||
LONGEST_SUB = TEMPORARY_ARRAY
|
||||
else:
|
||||
i+=1
|
||||
|
||||
TEMPORARY_ARRAY = [ element for element in ARRAY[1:] if element >= PIVOT ]
|
||||
TEMPORARY_ARRAY = [PIVOT] + longestSub(TEMPORARY_ARRAY)
|
||||
if ( len(TEMPORARY_ARRAY) > len(LONGEST_SUB) ):
|
||||
return TEMPORARY_ARRAY
|
||||
else:
|
||||
return LONGEST_SUB
|
||||
|
||||
#Some examples
|
||||
|
||||
print(longestSub([4,8,7,5,1,12,2,3,9]))
|
||||
print(longestSub([9,8,7,6,5,7]))
|
|
@ -0,0 +1,41 @@
|
|||
from __future__ import print_function
|
||||
#############################
|
||||
# Author: Aravind Kashyap
|
||||
# File: lis.py
|
||||
# comments: This programme outputs the Longest Strictly Increasing Subsequence in O(NLogN)
|
||||
# Where N is the Number of elements in the list
|
||||
#############################
|
||||
def CeilIndex(v,l,r,key):
|
||||
while r-l > 1:
|
||||
m = (l + r)/2
|
||||
if v[m] >= key:
|
||||
r = m
|
||||
else:
|
||||
l = m
|
||||
|
||||
return r
|
||||
|
||||
|
||||
def LongestIncreasingSubsequenceLength(v):
|
||||
if(len(v) == 0):
|
||||
return 0
|
||||
|
||||
tail = [0]*len(v)
|
||||
length = 1
|
||||
|
||||
tail[0] = v[0]
|
||||
|
||||
for i in range(1,len(v)):
|
||||
if v[i] < tail[0]:
|
||||
tail[0] = v[i]
|
||||
elif v[i] > tail[length-1]:
|
||||
tail[length] = v[i]
|
||||
length += 1
|
||||
else:
|
||||
tail[CeilIndex(tail,-1,length-1,v[i])] = v[i]
|
||||
|
||||
return length
|
||||
|
||||
|
||||
v = [2, 5, 3, 7, 11, 8, 10, 13, 6]
|
||||
print(LongestIncreasingSubsequenceLength(v))
|
33
dynamic_programming/longest_sub_array.py
Normal file
33
dynamic_programming/longest_sub_array.py
Normal file
|
@ -0,0 +1,33 @@
|
|||
'''
|
||||
Auther : Yvonne
|
||||
|
||||
This is a pure Python implementation of Dynamic Programming solution to the longest_sub_array problem.
|
||||
|
||||
The problem is :
|
||||
Given an array, to find the longest and continuous sub array and get the max sum of the sub array in the given array.
|
||||
'''
|
||||
from __future__ import print_function
|
||||
|
||||
|
||||
class SubArray:
|
||||
|
||||
def __init__(self, arr):
|
||||
# we need a list not a string, so do something to change the type
|
||||
self.array = arr.split(',')
|
||||
print(("the input array is:", self.array))
|
||||
|
||||
def solve_sub_array(self):
|
||||
rear = [int(self.array[0])]*len(self.array)
|
||||
sum_value = [int(self.array[0])]*len(self.array)
|
||||
for i in range(1, len(self.array)):
|
||||
sum_value[i] = max(int(self.array[i]) + sum_value[i-1], int(self.array[i]))
|
||||
rear[i] = max(sum_value[i], rear[i-1])
|
||||
return rear[len(self.array)-1]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
whole_array = input("please input some numbers:")
|
||||
array = SubArray(whole_array)
|
||||
re = array.solve_sub_array()
|
||||
print(("the results is:", re))
|
||||
|
60
dynamic_programming/max_sub_array.py
Normal file
60
dynamic_programming/max_sub_array.py
Normal file
|
@ -0,0 +1,60 @@
|
|||
"""
|
||||
author : Mayank Kumar Jha (mk9440)
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
import time
|
||||
import matplotlib.pyplot as plt
|
||||
from random import randint
|
||||
def find_max_sub_array(A,low,high):
|
||||
if low==high:
|
||||
return low,high,A[low]
|
||||
else :
|
||||
mid=(low+high)//2
|
||||
left_low,left_high,left_sum=find_max_sub_array(A,low,mid)
|
||||
right_low,right_high,right_sum=find_max_sub_array(A,mid+1,high)
|
||||
cross_left,cross_right,cross_sum=find_max_cross_sum(A,low,mid,high)
|
||||
if left_sum>=right_sum and left_sum>=cross_sum:
|
||||
return left_low,left_high,left_sum
|
||||
elif right_sum>=left_sum and right_sum>=cross_sum :
|
||||
return right_low,right_high,right_sum
|
||||
else:
|
||||
return cross_left,cross_right,cross_sum
|
||||
|
||||
def find_max_cross_sum(A,low,mid,high):
|
||||
left_sum,max_left=-999999999,-1
|
||||
right_sum,max_right=-999999999,-1
|
||||
summ=0
|
||||
for i in range(mid,low-1,-1):
|
||||
summ+=A[i]
|
||||
if summ > left_sum:
|
||||
left_sum=summ
|
||||
max_left=i
|
||||
summ=0
|
||||
for i in range(mid+1,high+1):
|
||||
summ+=A[i]
|
||||
if summ > right_sum:
|
||||
right_sum=summ
|
||||
max_right=i
|
||||
return max_left,max_right,(left_sum+right_sum)
|
||||
|
||||
|
||||
if __name__=='__main__':
|
||||
inputs=[10,100,1000,10000,50000,100000,200000,300000,400000,500000]
|
||||
tim=[]
|
||||
for i in inputs:
|
||||
li=[randint(1,i) for j in range(i)]
|
||||
strt=time.time()
|
||||
(find_max_sub_array(li,0,len(li)-1))
|
||||
end=time.time()
|
||||
tim.append(end-strt)
|
||||
print("No of Inputs Time Taken")
|
||||
for i in range(len(inputs)):
|
||||
print((inputs[i],'\t\t',tim[i]))
|
||||
plt.plot(inputs,tim)
|
||||
plt.xlabel("Number of Inputs");plt.ylabel("Time taken in seconds ")
|
||||
plt.show()
|
||||
|
||||
|
||||
|
||||
|
28
dynamic_programming/minimum_partition.py
Normal file
28
dynamic_programming/minimum_partition.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
"""
|
||||
Partition a set into two subsets such that the difference of subset sums is minimum
|
||||
"""
|
||||
def findMin(arr):
|
||||
n = len(arr)
|
||||
s = sum(arr)
|
||||
|
||||
dp = [[False for x in range(s+1)]for y in range(n+1)]
|
||||
|
||||
for i in range(1, n+1):
|
||||
dp[i][0] = True
|
||||
|
||||
for i in range(1, s+1):
|
||||
dp[0][i] = False
|
||||
|
||||
for i in range(1, n+1):
|
||||
for j in range(1, s+1):
|
||||
dp[i][j]= dp[i][j-1]
|
||||
|
||||
if (arr[i-1] <= j):
|
||||
dp[i][j] = dp[i][j] or dp[i-1][j-arr[i-1]]
|
||||
|
||||
for j in range(int(s/2), -1, -1):
|
||||
if dp[n][j] == True:
|
||||
diff = s-2*j
|
||||
break;
|
||||
|
||||
return diff
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user