Skip to content

Commit

Permalink
initial
Browse files Browse the repository at this point in the history
  • Loading branch information
keon committed Nov 17, 2016
0 parents commit f76c34b
Show file tree
Hide file tree
Showing 34 changed files with 1,541 additions and 0 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Pythonic Data Structures and Algorithms

Minimal and clean examples of data structures and algorithms.


Empty file added builtins/dictionary.py
Empty file.
Empty file added builtins/list.py
Empty file.
Empty file added builtins/set.py
Empty file.
14 changes: 14 additions & 0 deletions builtins/tuple.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
def append_to_sequence (myseq):
myseq += (9,9,9)
return myseq

tuple1 = (1,2,3) # tuples are immutable
list1 = [1,2,3] # lists are mutable

tuple2 = append_to_sequence(tuple1)
list2 = append_to_sequence(list1)

print 'tuple1 = ', tuple1 # outputs (1, 2, 3)
print 'tuple2 = ', tuple2 # outputs (1, 2, 3, 9, 9, 9)
print 'list1 = ', list1 # outputs [1, 2, 3, 9, 9, 9]
print 'list2 = ', list2 # outputs [1, 2, 3, 9, 9, 9]
54 changes: 54 additions & 0 deletions graph/find_path.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
myGraph = {'A': ['B', 'C'],
'B': ['C', 'D'],
'C': ['D', 'F'],
'D': ['C'],
'E': ['F'],
'F': ['C']}

# find path from start to end using recursion with backtracking
def find_path(graph, start, end, path=[]):
path = path + [start]
if (start == end):
return path
if not start in graph:
return None
for node in graph[start]:
if node not in path:
newpath = find_path(graph, node, end, path)
return newpath
return None

# find all path
def find_all_path(graph, start, end, path=[]):
path = path + [start]
print(path)
if (start == end):
return [path]
if not start in graph:
return None
paths = []
for node in graph[start]:
if node not in path:
newpaths = find_all_path(graph, node, end, path)
for newpath in newpaths:
paths.append(newpath)
return paths


def find_shortest_path(graph, start, end, path=[]):
path = path + [start]
if start == end:
return path
if start not in graph:
return None
shortest = None
for node in graph[start]:
if node not in path:
newpath = find_shortest_path(graph, start, end, path)
if newpath:
if not shortest or len(newpath) < len(shortest):
shortest = newpath
return shortest

print(find_all_path(myGraph, 'A', 'F'))
# print(find_shortest_path(myGraph, 'A', 'D'))
3 changes: 3 additions & 0 deletions graph/graph.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class Graph:
def __init__(self, node, edges, source):
pass
66 changes: 66 additions & 0 deletions graph/traversal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
graph = {'A': set(['B', 'C', 'F']),
'B': set(['A', 'D', 'E']),
'C': set(['A', 'F']),
'D': set(['B']),
'E': set(['B', 'F']),
'F': set(['A', 'C', 'E'])}

# dfs and bfs are the ultimately same except that they are visiting nodes in
# different order. To simulate this ordering we would use stack for dfs and
# queue for bfs.
#

def dfs_traverse(graph, start):
visited, stack = set(), [start]
while stack:
node = stack.pop()
if node not in visited:
visited.add(node)
for nextNode in graph[node]:
if nextNode not in visited:
stack.append(nextNode)
return visited

# print(dfs_traverse(graph, 'A'))


def bfs_traverse(graph, start):
visited, queue = set(), [start]
while queue:
node = queue.pop(0)
if node not in visited:
visited.add(node)
for nextNode in graph[node]:
if nextNode not in visited:
queue.append(nextNode)
return visited

# print(bfs_traverse(graph, 'A'))

def dfs_traverse_recursive(graph, start, visited=None):
if visited is None:
visited = set()
visited.add(start)
for nextNode in graph[start]:
if nextNode not in visited:
dfs_traverse_recursive(graph, nextNode, visited)
return visited

# print(dfs_traverse_recursive(graph, 'A'))

# def find_path(graph, start, end, visited=[]):
# # basecase
# visitied = visited + [start]
# if start == end:
# return visited
# if start not in graph:
# return None
# for node in graph[start]:
# if node not in visited:
# new_visited = find_path(graph, node, end, visited)
# return new_visited
# return None

# print(find_path(graph, 'A', 'F'))


53 changes: 53 additions & 0 deletions hashtable/hashtable.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# MAP Abstract Data Type
# Map() Create a new, empty map. It returns an empty map collection.
# put(key,val) Add a new key-value pair to the map. If the key is already in the map then replace the old value with the new value.
# get(key) Given a key, return the value stored in the map or None otherwise.
# del Delete the key-value pair from the map using a statement of the form del map[key].
# len() Return the number of key-value pairs stored in the map.
# in Return True for a statement of the form key in map, if the given key is in the map, False otherwise.

class HashTable(object):
def __init__(self, size = 11):
self.size = size
self.keys = [None] * size # keys
self.values = [None] * size # values

def put(self, key, value):
hashval = self.hash(key)

if hashval not in keys:
self.keys[hashval] = key
self.values[hashval] = value
else:
if self.keys[hashval] == key: # replace
self.values[hashval] = value
else: # probing
rehashval = self.rehash(key)
while self.keys[rehashval] is not None and \
self.keys[rehashval] != key:
rehashval = self.rehash(rehashval)
if keys[rehashval] is None:
self.keys[rehashval] = key
self.values[rehashval] = value
else:
self.values[rehashval] = value # replacee

def get(self, key):
pass

def hash(self, key):
return key % self.size

def rehash(self, oldhash):
"""
linear probing
"""
return (oldhash + 1) % self.size

def __getitem__(self,key):
return self.get(key)

def __setitem__(self, key, value):
self.put(key, value)


24 changes: 24 additions & 0 deletions linkedlist/linkedlist.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Pros
# Linked Lists have constant-time insertions and deletions in any position,
# in comparison, arrays require O(n) time to do the same thing.
# Linked lists can continue to expand without having to specify
# their size ahead of time (remember our lectures on Array sizing
# form the Array Sequence section of the course!)

# Cons
# To access an element in a linked list, you need to take O(k) time
# to go from the head of the list to the kth element.
# In contrast, arrays have constant time operations to access
# elements in an array.

class DoublyLinkedList(object):
def __init__(self, value):
self.value = value
self.next = None
self.prev = None


class SinglyLinkedList(object):
def __init__(self, value):
self.value = value
self.next = None
65 changes: 65 additions & 0 deletions longestAbsPath.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# def lengthLongestPath(input):
# maxlen = 0
# pathlen = {0: 0}
# for line in input.splitlines():
# print("---------------")
# print("line:", line)
# name = line.strip('\t')
# print("name:", name)
# depth = len(line) - len(name)
# print("depth:", depth)
# if '.' in name:
# maxlen = max(maxlen, pathlen[depth] + len(name))
# else:
# pathlen[depth + 1] = pathlen[depth] + len(name) + 1
# print("maxlen:", maxlen)
# return maxlen

# def lengthLongestPath(input):
# paths = input.split("\n")
# level = [0] * 10
# maxLength = 0
# for path in paths:
# print("-------------")
# levelIdx = path.rfind("\t")
# print("Path: ", path)
# print("path.rfind(\\t)", path.rfind("\t"))
# print("levelIdx: ", levelIdx)
# print("level: ", level)
# level[levelIdx + 1] = level[levelIdx] + len(path) - levelIdx + 1
# print("level: ", level)
# if "." in path:
# maxLength = max(maxLength, level[levelIdx+1] - 1)
# print("maxlen: ", maxLength)
# return maxLength

def lengthLongestPath(input):
"""
:type input: str
:rtype: int
"""
currlen, maxlen = 0, 0 # running length and max length
stack = [] # keep track of the name length
for s in input.split('\n'):
print("---------")
print("<path>:", s)
depth = s.count('\t') # the depth of current dir or file
print("depth: ", depth)
print("stack: ", stack)
print("curlen: ", currlen)
while len(stack) > depth: # go back to the correct depth
currlen -= stack.pop()
stack.append(len(s.strip('\t'))+1) # 1 is the length of '/'
currlen += stack[-1] # increase current length
print("stack: ", stack)
print("curlen: ", currlen)
if '.' in s: # update maxlen only when it is a file
maxlen = max(maxlen, currlen-1) # -1 is to minus one '/'
return maxlen

st= "dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdirectory1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext"
st2 = "a\n\tb1\n\t\tf1.txt\n\taaaaa\n\t\tf2.txt"
print("path:", st2)

print("answer:", lengthLongestPath(st2))

Loading

0 comments on commit f76c34b

Please sign in to comment.