diff --git a/Graphs/A*.py b/Graphs/a_star.py similarity index 100% rename from Graphs/A*.py rename to Graphs/a_star.py diff --git a/Graphs/basic-graphs.py b/Graphs/basic-graphs.py new file mode 100644 index 000000000..fc78e5652 --- /dev/null +++ b/Graphs/basic-graphs.py @@ -0,0 +1,267 @@ +# 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, 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, n)): + # Sort edges on the basis of distance + 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 diff --git a/Project Euler/Problem 01/sol1.py b/Project Euler/Problem 01/sol1.py new file mode 100644 index 000000000..512154e29 --- /dev/null +++ b/Project Euler/Problem 01/sol1.py @@ -0,0 +1,12 @@ +''' +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. +''' +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; \ No newline at end of file diff --git a/Project Euler/Problem 01/sol2.py b/Project Euler/Problem 01/sol2.py new file mode 100644 index 000000000..5e368c220 --- /dev/null +++ b/Project Euler/Problem 01/sol2.py @@ -0,0 +1,15 @@ +''' +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. +''' +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 \ No newline at end of file diff --git a/Project Euler/Problem 01/sol3.py b/Project Euler/Problem 01/sol3.py new file mode 100644 index 000000000..0caa30a53 --- /dev/null +++ b/Project Euler/Problem 01/sol3.py @@ -0,0 +1,42 @@ +''' +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. +''' +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; \ No newline at end of file diff --git a/Project Euler/Problem 02/sol1.py b/Project Euler/Problem 02/sol1.py new file mode 100644 index 000000000..6cf520767 --- /dev/null +++ b/Project Euler/Problem 02/sol1.py @@ -0,0 +1,18 @@ +''' +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. +''' + +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 \ No newline at end of file diff --git a/Project Euler/Problem 03/sol1.py b/Project Euler/Problem 03/sol1.py new file mode 100644 index 000000000..bd3e237e7 --- /dev/null +++ b/Project Euler/Problem 03/sol1.py @@ -0,0 +1,38 @@ +''' +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. +''' + +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 + +max=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)): + max=n/i + break + elif(isprime(i)): + max=i + print max diff --git a/Project Euler/Problem 03/sol2.py b/Project Euler/Problem 03/sol2.py new file mode 100644 index 000000000..2577892c4 --- /dev/null +++ b/Project Euler/Problem 03/sol2.py @@ -0,0 +1,16 @@ +''' +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. +''' +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 diff --git a/Project Euler/Problem 04/sol1.py b/Project Euler/Problem 04/sol1.py new file mode 100644 index 000000000..f8ed832d8 --- /dev/null +++ b/Project Euler/Problem 04/sol1.py @@ -0,0 +1,15 @@ +''' +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. +''' +n=int(input()) +for i in range(n-1,10000,-1): + temp=str(i) + if(temp==temp[::-1]): + j=999 + while(j!=99): + if((i%j==0) and (len(str(i/j))==3)): + print i + exit(0) + j-=1 diff --git a/Project Euler/Problem 04/sol2.py b/Project Euler/Problem 04/sol2.py new file mode 100644 index 000000000..4d2006242 --- /dev/null +++ b/Project Euler/Problem 04/sol2.py @@ -0,0 +1,18 @@ +''' +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. +''' +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 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)) diff --git a/data_structures/Binary Tree/LazySegmentTree.py b/data_structures/Binary Tree/LazySegmentTree.py new file mode 100644 index 000000000..bbd880a06 --- /dev/null +++ b/data_structures/Binary Tree/LazySegmentTree.py @@ -0,0 +1,90 @@ +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() diff --git a/data_structures/Binary Tree/SegmentTree.py b/data_structures/Binary Tree/SegmentTree.py new file mode 100644 index 000000000..cf47ca7d7 --- /dev/null +++ b/data_structures/Binary Tree/SegmentTree.py @@ -0,0 +1,64 @@ +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() diff --git a/data_structures/Binary Tree/binary_seach_tree.py b/data_structures/Binary Tree/binary_seach_tree.py deleted file mode 100644 index 9e468f775..000000000 --- a/data_structures/Binary Tree/binary_seach_tree.py +++ /dev/null @@ -1,103 +0,0 @@ -''' -A binary search Tree -''' - - -class Node: - - def __init__(self, label): - self.label = label - self.left = None - self.right = None - - 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 - - -class BinarySearchTree: - - def __init__(self): - self.root = None - - def insert(self, label): - - # Create a new Node - - node = Node(label) - - if self.empty(): - self.root = node - else: - dad_node = None - curr_node = self.root - - while True: - if curr_node is not None: - - dad_node = curr_node - - if node.getLabel() < curr_node.getLabel(): - curr_node = curr_node.getLeft() - else: - curr_node = curr_node.getRight() - else: - if node.getLabel() < dad_node.getLabel(): - dad_node.setLeft(node) - else: - dad_node.setRight(node) - break - - def empty(self): - if self.root is None: - return True - return False - - def preShow(self, curr_node): - if curr_node is not None: - print(curr_node.getLabel(), end=" ") - - self.preShow(curr_node.getLeft()) - self.preShow(curr_node.getRight()) - - def getRoot(self): - return self.root - - -''' -Example - 8 - / \ - 3 10 - / \ \ - 1 6 14 - / \ / - 4 7 13 -''' - -t = BinarySearchTree() -t.insert(8) -t.insert(3) -t.insert(1) -t.insert(6) -t.insert(4) -t.insert(7) -t.insert(10) -t.insert(14) -t.insert(13) - -t.preShow(t.getRoot()) diff --git a/data_structures/Binary Tree/binary_search_tree.py b/data_structures/Binary Tree/binary_search_tree.py new file mode 100644 index 000000000..2993c3cdc --- /dev/null +++ b/data_structures/Binary Tree/binary_search_tree.py @@ -0,0 +1,130 @@ +''' +A binary search Tree +''' + +class Node: + + def __init__(self, label): + self.label = label + self.left = None + self.right = None + + 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 + + +class BinarySearchTree: + + def __init__(self): + self.root = None + + def insert(self, label): + # Create a new Node + new_node = Node(label) + # If Tree is empty + if self.empty(): + self.root = new_node + else: + #If Tree is not empty + parent_node = None + 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) + + 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 empty(self): + if self.root is None: + return True + return False + + def preShow(self, curr_node): + if curr_node is not None: + print(curr_node.getLabel()) + self.preShow(curr_node.getLeft()) + self.preShow(curr_node.getRight()) + + def getRoot(self): + return self.root + +''' +Example + 8 + / \ + 3 10 + / \ \ + 1 6 14 + / \ / + 4 7 13 +''' + + +if __name__ == "__main__": + t = BinarySearchTree() + t.insert(8) + t.insert(3) + t.insert(1) + t.insert(6) + t.insert(4) + t.insert(7) + t.insert(10) + t.insert(14) + t.insert(13) + + t.preShow(t.getRoot()) + + 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") + diff --git a/data_structures/LinkedList/singly_LinkedList.py b/data_structures/LinkedList/singly_LinkedList.py index c9a3cec27..8828ce6cc 100644 --- a/data_structures/LinkedList/singly_LinkedList.py +++ b/data_structures/LinkedList/singly_LinkedList.py @@ -47,4 +47,20 @@ class Linked_List: return Head def isEmpty(Head): - return Head is None #Return if Head is none \ No newline at end of file + 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 diff --git a/data_structures/Queue/DeQueue.py b/data_structures/Queue/DeQueue.py new file mode 100644 index 000000000..175c88163 --- /dev/null +++ b/data_structures/Queue/DeQueue.py @@ -0,0 +1,39 @@ +# 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) diff --git a/data_structures/UnionFind/__init__.py b/data_structures/UnionFind/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/data_structures/UnionFind/tests_union_find.py b/data_structures/UnionFind/tests_union_find.py new file mode 100644 index 000000000..bdcc01033 --- /dev/null +++ b/data_structures/UnionFind/tests_union_find.py @@ -0,0 +1,77 @@ +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() diff --git a/data_structures/UnionFind/union_find.py b/data_structures/UnionFind/union_find.py new file mode 100644 index 000000000..40eea67ac --- /dev/null +++ b/data_structures/UnionFind/union_find.py @@ -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) diff --git a/dynamic_programming/FloydWarshall.py b/dynamic_programming/FloydWarshall.py new file mode 100644 index 000000000..bf7714124 --- /dev/null +++ b/dynamic_programming/FloydWarshall.py @@ -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) diff --git a/other/nested_brackets.py b/other/nested_brackets.py index ea681ded5..f486190f4 100644 --- a/other/nested_brackets.py +++ b/other/nested_brackets.py @@ -18,28 +18,20 @@ returns true if S is nested and false otherwise. def is_balanced(S): stack = [] - + open_brackets = set({'(', '[', '{'}) + closed_brackets = set({')', ']', '}'}) + open_to_closed = dict({'{':'}', '[':']', '(':')'}) + for i in range(len(S)): - - if S[i] == '(' or S[i] == '{' or S[i] == '[': + + if S[i] in open_brackets: stack.append(S[i]) - - else: - - if len(stack) > 0: - - pair = stack.pop() + S[i] - - if pair != '[]' and pair != '()' and pair != '{}': - return False - - else: + + elif S[i] in closed_brackets: + if len(stack) == 0 or (len(stack) > 0 and open_to_closed[stack.pop()] != S[i]): return False - - if len(stack) == 0: - return True - - return False + + return len(stack) == 0 def main(): @@ -48,7 +40,7 @@ def main(): if is_balanced(S): print(S, "is balanced") - + else: print(S, "is not balanced") diff --git a/other/two-sum.py b/other/two-sum.py new file mode 100644 index 000000000..4a522b6d4 --- /dev/null +++ b/other/two-sum.py @@ -0,0 +1,28 @@ +""" +Given an array of integers, return indices of the two numbers such that they add up to a specific target. + +You may assume that each input would have exactly one solution, and you may not use the same element twice. + +Example: +Given nums = [2, 7, 11, 15], target = 9, + +Because nums[0] + nums[1] = 2 + 7 = 9, +return [0, 1]. +""" + +def twoSum(nums, target): + """ + :type nums: List[int] + :type target: int + :rtype: List[int] + """ + chk_map = {} + for index, val in enumerate(nums): + compl = target - val + if compl in chk_map: + indices = [chk_map[compl], index] + print(indices) + return [indices] + else: + chk_map[val] = index + return False