Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
Binary file not shown.
214 changes: 214 additions & 0 deletions data_structures_and_algorithms/challenges/tree_intersection/hash.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@

from typing import Any

'''
A special kind of type is Any. A static type checker will treat every type as being compatible with Any and Any as being compatible with every type.

This means that it is possible to perform any operation or method call on a value of type Any and assign it to any variable
'''

class Node:
def __init__(self, key, val, _next):
self.key = key
self.val = val
self.next = _next

def __str__(self):
return f'{self.val}'

def __repr__(self):
return f'<Node | Val: {self.val} | Next: {self.next}>'

class LinkedList(object):
def __init__(self, initial_data=None, tuple_data=None):
"""This initializes the linked list object by creating a node for each value inputed.
ARGS:
Initial data can be either a list, or a single piece of data.
Tuple data can also be either a list, or a single piece of data.
"""
try:
self.head: Node = None
self._length: int = 0
if initial_data is not None:
try:
for item in initial_data:
self.insert(item)
except:
self.insert(initial_data)
if tuple_data is not None:
try:
for item in tuple_data:
self.insert(item)
except:
self.insert(tuple_data)
except TypeError:
return TypeError

def __str__(self):
return f'Head: {self.head} | Length: {self._length}'

def __repr__(self):
return f'<Linked List | Head: {self.head} | Length: {self._length}>'

def __len__(self):
return self._length

def insert(self, key, val: Any) -> Any:
'''Creates a new node and appends it to the beginning of the list
This is done by re-stating which node is the head(the one youre appending)
then setting the previous head equal to the next value of the appended item
'''
self.head = Node(key, val, self.head)
self._length += 1

def includes(self, key) -> bool:
'''Checks to see if a value is contained in the list by iterating through and
checking every node against the input value. If the value exists in the list
, the function will return true if it does not exist in the list, it will return false.
'''
current = self.head
while current is not None:
if current.key is key:
return True
current = current.next
return False

def append(self, val, key=None) -> bool:
'''Creates a new node and appends it at the end of the linked list
'''
current = self.head
while current.next is not None:
current = current.next
current.next = Node(key, val, None)
return True

def insert_before(self, val, target_val) -> bool:
'''Creates a new node and appends it before the target value
args:
new Node value, target Node value to insert before
returns:
True if the node was inserted
False if the target value is not in the SLL
'''
current = self.head
while current.next.val is not target_val:
current = current.next
if current.next == None:
return False
current.next = Node(val, current.next)
return True

def insert_after(self, val, target_val) -> bool:
'''Creates a new node and appends it after the target value
'''
current = self.head
while current.val is not target_val:
current = current.next
if current == None:
return False
current.next = Node(val, current.next)
return True

def find_k(self, k) ->bool:
'''Takes in an input value of K, which corresponds to that
many indexes from the end of the list. This function takes in the input,
and returns the value of the item at index of length - k.
'''
if k < 0:
raise IndexError
tortoise = self.head
hare = self.head
for i in range(k):
if hare is not None:
hare = hare.next
else:
raise IndexError
while hare.next is not None:
hare = hare.next
tortoise = tortoise.next
return tortoise.val

class HashTable:
"""A class for a hash table."""
entries_count = 0
alphabet_size = 52

def __init__(self, size=8192):
self.table_size = size
self.hashtable = [None] * self.table_size

def __repr__(self):
pass

def _hash_key(self, key):
"""Create a hash from a given key.
args:
key: a string to hash
returns: an integer corresponding to hashtable index
"""
hash_ = 0
for i, c in enumerate(key):
hash_ += pow(
self.alphabet_size, len(key) - i - 1) * ord(c)
return hash_ % self.table_size

def set(self, key, value):
"""Add a key and value into the hash table.
args:
key: the key to store
value: the value to store
"""
if self.hashtable[self._hash_key(key)] is None:
self.hashtable[self._hash_key(key)] = LinkedList()
self.hashtable[self._hash_key(key)].insert(key, value)
self.entries_count += 1
return True
if self.hashtable[self._hash_key(key)].includes(key):
raise TypeError
self.hashtable[self._hash_key(key)].insert(key, value)
self.entries_count += 1
return False

def get(self, key):
"""Retrieve a value from the hash table by key.
args:
key: a string to find the value in the hash table
returns: the value stored with the key
"""

linked_list = self.hashtable[self._hash_key(key)]
if linked_list is None:
raise TypeError
if linked_list.head is None:
raise TypeError
temp = linked_list.head
while linked_list:
if linked_list.head.key is key:
return linked_list.head.val
linked_list.head = linked_list.head.next
linked_list.head = temp
raise TypeError


def remove(self, key):
"""Retrieve and remove a value from the hash table by key.
args:
key: a string to find the value in the hash table
returns: the value stored with the key
"""
ll = self.hashtable[self._hash_key(key)]
if ll is None:
raise TypeError
temp = ll.head
if ll.head.key is key:
temp = ll.head
ll.head = ll.head.next
return temp.val
while ll:
if ll.head.next.key is key:
temp = ll.head.next
ll.head.next = ll.head.next.next
return temp.val
if ll.head is None:
self.hashtable[self._hash_key(key)] = None
raise TypeError
Binary file not shown.
Binary file not shown.
64 changes: 64 additions & 0 deletions data_structures_and_algorithms/data_structures/graph/graph.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
class Vertex:
def __init__(self, value):
self.value = value
self.neighbors = []

class Graph:

def __init__(self):
self.vertices = []

def addVertex(self, value):
"""
AddVertex()
Adds a new vertex to the graph
Takes in the value of that vertex
Returns the added vertex
"""

x = Vertex(value)

self.vertices.append(x)

return x

def addEdge(self, v1, v2, weight):
"""
AddEdge()
Adds a new edge between two nodes in the graph
Include the ability to have a “weight”
Takes in the two nodes to be connected by the edge
Both nodes should already be in the Graph
"""


if v1 in self.vertices and v2 in self.vertices:
v1.neighbors.append( {v2, weight} )
return

return 'Please ensure both v1 and v2 exist in the graph'


#Infomation Retreival Functions
def getVertices(self):
"""
GetNodes()
Returns all of the nodes in the graph as a collection (set, list, or similar)
return self.vertices
"""

def getNeighbors(self, vertex):
"""
GetNeighbors()
Returns a collection of nodes connected to the given node
Takes in a given node
Include the weight of the connection in the returned collection
"""

if vertex in self.vertices:
return vertex.neighbors

return 'Provided vertex does not exist in this graph'

def __len__(self):
return len(self.vertices)
26 changes: 26 additions & 0 deletions data_structures_and_algorithms/data_structures/graph/read.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
AddVertex()
Adds a new vertex to the graph
Takes in the value of that vertex
Returns the added vertex
AddEdge()
Adds a new edge between two nodes in the graph
Include the ability to have a “weight”
Takes in the two nodes to be connected by the edge
Both nodes should already be in the Graph
GetNodes()
Returns all of the nodes in the graph as a collection (set, list, or similar)
GetNeighbors()
Returns a collection of nodes connected to the given node
Takes in a given node
Include the weight of the connection in the returned collection


# Tests
1. Node can be successfully added to the graph
2. An edge can be successfully added to the graph
3. A collection of all nodes can be properly retrieved from the graph
4. All appropriate neighbors can be retrieved from the graph
5. Neighbors are returned with the weight between nodes included
6. The proper size is returned, representing the number of nodes in the graph
7. A graph with only one node and edge can be properly returned
8. An empty graph properly returns null
84 changes: 84 additions & 0 deletions data_structures_and_algorithms/data_structures/graph/test_graph.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
from graph import Graph
from graph import Vertex

import pytest

def test_init_graph_and_vertex():

assert Graph
assert Vertex

def test_add_node_to_graph():


g = Graph()

test = g.addVertex('potato')

assert isinstance(test, Vertex)
assert test in g.vertices
assert g.vertices[0].value == 'potato'

def test_add_edge_to_graph():

g = Graph()

apple = g.addVertex('apple')
banana = g.addVertex('banana')

g.addEdge(apple, banana, 50)

assert g.vertices[0].neighbors[0] == {banana, 50}

def test_add_edge_to_graph_doesnt_add_non_existant():

g = Graph()

apple = g.addVertex('apple')
answer = g.addEdge(apple, 'banana', 50)

assert answer == 'Please ensure both v1 and v2 exist in the graph'

def test_get_vertices():

g = Graph()

apple = g.addVertex('apple')
banana = g.addVertex('banana')
cucumber = g.addVertex('cucumber')

g.getVertices == [apple, banana, cucumber]


def test_get_neighbors():

g = Graph()

apple = g.addVertex('apple')
banana = g.addVertex('banana')
cucumber = g.addVertex('cucumber')
durian = Vertex('durian')

g.addEdge(apple, banana, 45)
g.addEdge(apple, cucumber, 60)

assert g.getNeighbors(apple) == [{banana, 45}, {cucumber, 60}]
assert g.getNeighbors(durian) == 'Provided vertex does not exist in this graph'


def test_graph_length():

g = Graph()
h = Graph()

g.addVertex('apple')
g.addVertex('banana')
g.addVertex('cucumber')

h.addVertex('apple')
h.addVertex('banana')
h.addVertex('cucumber')
h.addVertex('durian')

assert len(g) == 3
assert len(h) == 4
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading