Trying to implement a hashMap using an array from LeetCode - python-3.x

I can't seem to pass all the tests that leetcode gives. I can pass 35/36 test cases and the one error that it has is the get key 623 on one of the test cases gives the wrong number. I have the test case that it didn't pass but it is really long so I don't want to post it on the question.
class pairValue:
def __init__(self, key, value):
self.key = key
self.value = value
class MyHashMap(object):
def __init__(self):
self.size = 0
self.capacity = 2
self.hashMap = [None, None]
def hash(self, key):
return key % self.capacity
def put(self, key, value):
"""
:type key: int
:type value: int
:rtype: None
"""
# if key == 623:
# print(value)
if self.size >= self.capacity //2:
self.rehash()
index = self.hash(key)
while self.hashMap[index] != None and self.hashMap[index].key != -1:
if self.hashMap[index].key == key:
self.hashMap[index].value = value
# print(self.hashMap[index].key,value)
return
index += 1
index %= self.capacity
self.hashMap[index] = pairValue(key, value)
if self.hashMap[index].key != -1:
self.size += 1
def rehash(self):
self.capacity *= 2
newMap = [None] * self.capacity
oldMap = self.hashMap
self.hashMap = newMap
self.size = 0
for x in range(len(oldMap)):
if oldMap[x] != None:
self.put(oldMap[x].key, oldMap[x].value)
# print(self.hashMap)
def get(self, key):
"""
:type key: int
:rtype: int
"""
index = self.hash(key)
# print(self.hashMap[index].key, self.hashMap[index].value)
while self.hashMap[index] != None:
if self.hashMap[index].key == 623:
print(self.hashMap[index].value)
if self.hashMap[index].key == key:
return self.hashMap[index].value
index += 1
index %= self.capacity
# print(self.hashMap)
return -1
def remove(self, key):
"""
:type key: int
:rtype: None
"""
index = self.hash(key)
while self.hashMap[index] != None:
if self.hashMap[index].key == key:
self.hashMap[index].key = -1
self.hashMap[index].value = None
self.size -= 1
index += 1
index %= self.capacity
There are five functions which are to put, get, remove, hash, and rehash, along with the initialization.

Related

AttibuteError when trying to make configs

AttributeError: module 'collections' has no attribute 'Sequence'
i get this error everything i try to run my code but there isn't any information about how to use Mothur except for the the documentation.
`# python3
import sys
import queue
import itertools
from collections import deque
from mothur_py import Mothur
import collections.abc as collections
class KmerIdMgmt:
def __init__(self):
self.id = 0
self.ids_map = {}
self.kmers = {}
def insert(self, kmer):
if kmer not in self.ids_map:
self.ids_map[kmer] = self.id
self.kmers[self.id] = kmer
self.id += 1
return self.ids_map[kmer]
class DeBruijnGraph(object):
def __init__(self, k, reads):
self.k = k
self.threshold = self.k + 1
self.kmer_ids = KmerIdMgmt()
self.coverage = {}
self.graph = {}
self.outgoing_num = lambda k: len(self.graph[k][0])
self.incoming_num = lambda k: self.graph[k][1]
self.make_deBruijn_graph(self.break_reads_into_kmers(reads))
def break_reads_into_kmers(self, reads):
break_read = lambda read: [ read[j:j + self.k] for j in range(len(read) - self.k + 1) ]
return [ kmer for read in reads for kmer in break_read(read) ]
def make_deBruijn_graph(self, kmers):
def add_edge(graph, coverage, left, right):
graph.setdefault(left, [set(), 0])
graph.setdefault(right, [set(), 0])
coverage.setdefault((left, right), 0)
coverage[(left, right)] += 1
if right not in graph[left][0]:
graph[left][0].add(right)
graph[right][1] += 1
for kmer in kmers:
left = self.kmer_ids.insert(kmer[:-1])
right = self.kmer_ids.insert(kmer[1:])
if left != right:
add_edge(self.graph, self.coverage, left, right)
def remove_leaves(self):
removable = [ k for k, v in self.graph.items() if len(v[0]) == 0 ]
for k in removable:
del self.graph[k]
def print_graph(self):
for k, v in self.graph.items():
print(k, v)
class TipRemoval(DeBruijnGraph):
def __init__(self, k, reads):
DeBruijnGraph.__init__(self, k, reads)
def remove_tips(self):
for k, v in self.graph.items():
find_and_remove = None
if self.outgoing_num(k) == 1 and self.incoming_num(k) == 0:
find_and_remove = self.find_and_remove_incoming
elif self.outgoing_num(k) > 1:
find_and_remove = self.find_and_remove_outgoing
else: continue
condition = True
while condition:
condition = False
for edge in v[0]:
if find_and_remove(edge, 0):
v[0].remove(edge)
condition = True
break
def find_and_remove_outgoing(self, current, depth):
if self.outgoing_num(current) > 1 or self.incoming_num(current) > 1:
return False
if depth == self.threshold:
return False
if self.outgoing_num(current) == 0:
return True
if self.find_and_remove_outgoing(next(iter(self.graph[current][0])), depth + 1):
to = next(iter(self.graph[current][0]))
self.graph[current][0].pop()
self.graph[to][1] -= 1
return True
return False
def find_and_remove_incoming(self, current, depth):
if self.outgoing_num(current) == 0 or self.incoming_num(current) > 1:
return True
if depth == self.threshold:
return False
if self.find_and_remove_incoming(next(iter(self.graph[current][0])), depth + 1):
to = next(iter(self.graph[current][0]))
self.graph[current][0].pop()
self.graph[to][1] -= 1
return True
return False
class BubbleRemoval(TipRemoval):
def __init__(self, k, reads):
TipRemoval.__init__(self, k, reads)
self.paths = {}
def remove_bubbles(self):
for k, v in self.graph.items():
if self.outgoing_num(k) > 1:
self.dfs(path=[k], current=k, depth=0)
for pair, candidates_list in self.paths.items():
source, target = pair[0], pair[1]
best_path = max(candidates_list, key=lambda item: item[1])[0]
for path, _ in candidates_list:
if best_path == path or not self.bubble_possible(source, target):
continue
if self.paths_disjoint(best_path, path) and self.path_exists(path):
self.remove_path(path)
def bubble_possible(self, source, target):
return len(self.graph[source][0]) > 1 and self.graph[target][1] > 1
def path_exists(self, path):
for j in range(len(path) -1):
if path[j +1] not in self.graph[path[j]][0]:
return False
return True
def remove_path(self, path):
for j in range(len(path) -1):
self.graph[path[j]][0].remove(path[j +1])
self.graph[path[j +1]][1] -= 1
del self.coverage[(path[j], path[j +1])]
def paths_disjoint(self, a, b):
return len(set(a) & set(b)) == 2
def dfs(self, path, current, depth):
if current != path[0] and self.incoming_num(current) > 1:
weight = sum(self.coverage[(path[i], path[i+1])] for i in range(len(path)-1)) / len(path)
self.paths.setdefault((path[0], current), list()).append((path[:], weight))
if depth == self.threshold:
return
for next_ in self.graph[current][0]:
if next_ not in path:
path.append(next_)
self.dfs(path, next_, depth + 1)
path.remove(next_)
class PhiX174GenomeAssembler(BubbleRemoval):
def __init__(self, k, reads):
BubbleRemoval.__init__(self, k, reads)
def make_Euler_cycle(self):
verteces = deque()
path = []
# line 191
current = next(iter(self.graph))
verteces.append(current)
while verteces:
current = verteces[0]
if len(self.graph[current][0]) != 0:
t = next(iter(self.graph[current][0]))
verteces.append(t)
self.graph[current][0].remove(t)
continue
path.append(current)
verteces.popleft()
return path
def assemble(self):
self.remove_tips()
self.remove_leaves()
self.remove_bubbles()
cycle = self.make_Euler_cycle()
circular_genome = self.kmer_ids.kmers[cycle[0]]
for i in range(1, len(cycle) - (self.k - 1)):
circular_genome += self.kmer_ids.kmers[cycle[i]][-1]
return circular_genome
if __name__ == "__main__":
n_kmers = int(input())
for _ in range(n_kmers):
reads = list(input())
reads = str(reads)
with open('reads.fasta', 'w') as read:
read.write(reads)
k = 100
m = Mothur()
contig = m.make.contigs(ffasta = read)
for x in range(n_kmers):
print(">CONTIG", x)
print(contig)
`

AVL Tree, delete mininum node (Python 3)

I want to implement a huffman coding using AVL tree. I perform some insertion, then I delete some node and everything is fine, but suddenly after another deletion the tree delete every nodes on the right side from root. It happens when the tree looks like this (the right side may be a bit different, but the height is correct):
after deleting the minim node (M) the tree has only nodes (S, R).
I think that it is because of my mistake in rotation function. Could you help me understand where is the mistake.
import random
from collections import Counter
class HuffmanCoding:
def __init__(self, data=None, space=False):
# Transform data to the form of dictionary
if data is None:
data = input("Enter string for coding: ")
self.data = Counter(data)
elif isinstance(data, str):
self.data = Counter(data)
elif isinstance(data, dict):
self.data = data
else:
raise TypeError("Type of data is incorrect!")
# Check whether to delete the space or not
if not space:
self.data.pop(' ', None)
self.my_tree = AVL_Tree()
self.root = None
for k, v in self.data.items():
self.root = self.my_tree.insert(self.root, TreeNode(k, v))
def sth(self):
n1 = self.my_tree.delete_min(self.root)
n2 = self.my_tree.delete_min(self.root)
self._create_new_internal_node(n1, n2)
def _create_new_internal_node(self, n1, n2):
new_node = HuffmanNode(n1, n2)
self.my_tree.insert(self.root, new_node)
class HuffmanNode:
def __init__(self, n1, n2):
self.character = n1.character + n2.character
self.freq = n1.freq + n2.freq
self.left = None
self.right = None
self.height = 1
class TreeNode:
def __init__(self, character, freq):
self.character = character
self.freq = freq
self.left = None
self.right = None
self.height = 1
class AVL_Tree:
def insert(self, root, n):
character = n.character
freq = n.freq
# Normal insert, like in BST
if not root:
return TreeNode(character, freq)
elif freq < root.freq:
root.left = self.insert(root.left, n)
else:
root.right = self.insert(root.right, n)
# Update the height of the ancestor node
root.height = 1 + max(self.get_height(root.left), self.get_height(root.right))
# Get the balance
balance = self.get_balance(root)
# Left left
if balance > 1 and freq < root.left.freq:
return self.right_rotate(root)
# Right right
if balance < -1 and freq > root.right.freq:
return self.left_rotate(root)
# Left right
if balance > 1 and freq > root.left.freq:
root.left = self.left_rotate(root.left)
return self.right_rotate(root)
# Right left
if balance < -1 and freq < root.right.freq:
root.right = self.right_rotate(root.right)
return self.left_rotate(root)
return root
def delete_min(self, root):
if not root:
return root
# Get parent of most left node
min_parent = self.get_parent_of_min_value_node(root)
min_node = min_parent.left
# Check if most left node has a right son
if min_parent.left.right is not None:
min_parent.left = min_parent.left.right
else:
min_parent.left = None
# Update the height
root.height = 1 + max(self.get_height(root.left), self.get_height(root.right))
balance = self.get_balance(root)
# Left left
if balance > 1 and min_parent.freq < root.left.freq:
self.right_rotate(root)
# Right right
if balance < -1 and min_parent.freq > root.right.freq:
self.left_rotate(root)
# Left right
if balance > 1 and min_parent.freq > root.left.freq:
root.left = self.left_rotate(root.left)
self.right_rotate(root)
# Right left
if balance < -1 and min_parent.freq < root.right.freq:
root.right = self.right_rotate(root.right)
self.left_rotate(root)
return min_node
def get_height(self, root):
if not root:
return 0
return root.height
def get_balance(self, root):
if not root:
return 0
return self.get_height(root.left) - self.get_height(root.right)
def right_rotate(self, z):
y = z.left
T3 = y.right
y.right = z
z.left = T3
z.height = 1 + max(self.get_height(z.left), self.get_height(z.right))
y.height = 1 + max(self.get_height(y.left), self.get_height(y.right))
return y
def left_rotate(self, z):
y = z.right
T2 = y.left
# Perform rotation
y.left = z
z.right = T2
# Update heights
z.height = 1 + max(self.get_height(z.left), self.get_height(z.right))
y.height = 1 + max(self.get_height(y.left), self.get_height(y.right))
# Return the new root
return y
def pre_order(self, root):
if not root:
return
print("C: {0}, F: {1}".format(root.character, root.freq))
self.pre_order(root.left)
self.pre_order(root.right)
def in_order(self, root):
if not root:
return
self.in_order(root.left)
print("C: {0}, F: {1}".format(root.character, root.freq))
self.in_order(root.right)
def post_order(self, root):
if not root:
return
self.post_order(root.left)
self.post_order(root.right)
print("C: {0}, F: {1}".format(root.character, root.freq))
def get_min_value_node(self, root):
if root is None or root.left is None:
return root
return self.get_min_value_node(root.left)
def get_parent_of_min_value_node(self, root):
if root.left is None or root.left.left is None:
return root
return self.get_parent_of_min_value_node(root.left)
if __name__ == "__main__":
huffman_coding = HuffmanCoding("Blogoslawieni milosierni")
huffman_coding.my_tree.in_order(huffman_coding.root)
print(huffman_coding.my_tree.delete_min(huffman_coding.root).character)
print(huffman_coding.my_tree.delete_min(huffman_coding.root).character)
print(huffman_coding.my_tree.delete_min(huffman_coding.root).character)
print(huffman_coding.my_tree.delete_min(huffman_coding.root).character)
huffman_coding.my_tree.in_order(huffman_coding.root)
print(huffman_coding.my_tree.delete_min(huffman_coding.root).character)
huffman_coding.my_tree.in_order(huffman_coding.root)
x = huffman_coding.root

Hash table implementation python

I was implementing my hash table function in python, how do I modify the put() and delete() functions so that the variable count is altered appropriated whenever a key-data pair is added to or deleted from the hash table.
and also how to change the len() function so that it returns this count.
I have no idea about modifying the code.....
class HashTable:
def __init__(self):
self.__size = 5
self.__slots = [None] * self.__size
self.__data = [None] * self.__size
self.__deleted = "\0"
def hash_function(self, key, size):
return key % size
def rehash(self, old_hash,size):
return (old_hash + 1) % size
def get(self, key):
start_slot = self.hash_function(key,len(self.__slots))
position = start_slot
while self.__slots[position] != None:
if self.__slots[position] == key:
return self.__data[position]
else:
position = self.rehash(position, len(self.__slots))
if position == start_slot:
return None
return None
def put(self,key,data):
hash_value = self.hash_function(key,len(self.__slots))
if self.__slots[hash_value] == None or \
self.__slots[hash_value] == self.__deleted:
self.__slots[hash_value] = key
self.__data[hash_value] = data
elif self.__slots[hash_value] == key:
self.__data[hash_value] = data
else:
next_slot = self.rehash(hash_value, len(self.__slots))
while self.__slots[next_slot] != None\
and self.__slots[next_slot] != self.__deleted \
and self.__slots[next_slot] != key:
next_slot = self.rehash(next_slot,len(self.__slots))
if next_slot == hash_value:
return
if self.__slots[next_slot] == None or \
self.__slots[next_slot] == self.__deleted:
self.__slots[next_slot] = key
self.__data[next_slot] = data
else:
self.__data[next_slot] = data
def delete(self, key):
start_slot = self.hash_function(key, len(self.__slots))
position = start_slot
key_in_slot = self.__slots[position]
while key_in_slot != None:
if key_in_slot == key:
self.__slots[position] = self.__deleted
self.__data[position] = self.__deleted
return None
else:
position = self.rehash(position, len(self.__slots))
key_in_slot = self.__slots[position]
if position == start_slot:
return None
def __delitem__(self, key):
return self.delete(key)
def __setitem__(self,key,data):
self.put(key,data)
def __getitem__(self,key):
return self.get(key)
def __len__(self):
count = 0
for value in self.__slots:
if value != None and value != self.__deleted:
count += 1
return count
def __contains__(self, key):
return self.get(key) != None
def __repr__(self):
str_rep = "["
for i in range(len(self.__slots)):
key = self.__slots[i]
data = self.__data[i]
info = ""
if key == None or key == self.__deleted:
info = ""
else:
if data == None:
info = str(key) + ":None"
else:
info = str(key) + ":" + str(data)
str_rep += info + ", "
return str_rep[:-2] + "]"

Return value fail

I am working on a doubly linked list and I am having trouble getting returning the value I remove an item from the middle of the list. I am not really sure why and would appreciate the a second pair of eyes look this through.
If I append three numbers and then remove the number at index 1, it should return the value at index 1.
class Linked_List:
class __Node:
def __init__(self, val):
self.val = val
self.next = None
self.prev = None
return
def __init__(self):
self.__header = self.__Node(None)
self.__trailer = self.__Node(None)
self.__header.next = self.__trailer
self.__trailer.prev = self.__header
self.__size = 0
def __len__(self):
return self.__size
def remove_element_at(self, index):
if index > self.__size or index < 0 or index == self.__size:
raise IndexError
cur = self.__header.next
element_to_return = cur
if index == 0:
self.__header.next = self.__header.next.next
else:
for i in range(0, index):
cur = cur.next
element_to_return = cur.val
cur.next = cur.next.next
self.__size -= 1
return str(element_to_return.val)
I added the addValue() and a debug() method (tip: read How to debug small programs (#1) ).
I modified the start/end node to have a value for clarity. I reduced/restructured (rewrote) your the remove method - it had some unneeded overhead and pointer errors. For double linked lists you have to take care of both the folloing and preceeding element and change all the pointers correctly to keep the integrity of the chain.
class Linked_List:
class __Node:
def __init__(self, val):
self.val = val
self.next = None
self.prev = None
return
def __init__(self):
self.__header = self.__Node('Start') # start node
self.__trailer = self.__Node('End') # end node
self.__header.next = self.__trailer
self.__trailer.prev = self.__header
self.__size = 0
def debug(self):
cur = self.__header
print("prev.val cur.val next.val")
i = 0
while cur:
print(" " * i, f'{cur.prev.val if cur.prev else None} {cur.val} {cur.next.val if cur.next else None}')
i+=1
cur = cur.next
def addValue(self, val):
"""Adds the str of val at the end."""
n = self.__Node(str(val))
n.next = self.__trailer
n.prev = self.__trailer.prev
self.__trailer.prev.next = n
self.__trailer.prev = n
self.__size += 1
def remove_element_at(self, index):
if not (0 <= index < self.__size ): # simplified
# better message on error
raise IndexError (f'Index {index} out of bounds [0,{self.__size-1}]')
cur = self.__header.next # simplified, element_to_return not needed
# there is no need for special cases for 0 or size - this will handle all
for i in range(0, index):
cur = cur.next # go ever deeper, if we are at 0 or self.__size not entering
cur.prev.next = cur.next # repointer prev's next to our next
cur.next.prev = cur.prev # repointer next's prev to our prev
self.__size -= 1 # decrease size
return str(cur.val) # return our value
k = Linked_List()
for n in range(5):
k.addValue(n)
k.debug()
removed = k.remove_element_at(4)
k.debug()
print(f'removed: {removed}')
Output:
prev.val cur.val next.val
None Start 0
Start 0 1
0 1 2
1 2 3
2 3 4
3 4 End
4 End None
None Start 0
Start 0 1
0 1 2
1 2 3
2 3 End
3 End None
removed: 4
Edit:
My add method is self-build. Make sure youres gets the pointers correctly - use the debug method to assure that cur.prev.next points to cur and cur.next.prev is cur as well.

Heap Structure with Key Function in initalizer

I'm basically trying to implement this Heap Structure in Python and I've editing the portions under def heap-iffy and def add but I'm not sure how to how to use the current initialize with a key function. This function will be used to extract a value from each element added to the heap; these values, in turn, will be used to order the elements. f no key function is provided, the default max-heap behavior should be used — the "lambda x:x" default value for the initialize method does just that.
class Heap:
def __init__(self, key=lambda x:x):
self.data = []
self.key = key
#staticmethod
def _parent(idx):
return (idx-1)//2
#staticmethod
def _left(idx):
return idx*2+1
#staticmethod
def _right(idx):
return idx*2+2
def _heapify(self, idx=0):
enter code here
while True:
l = Heap._left(idx)
r = Heap._right(idx)
maxidx = idx
if l < len(self) and self.data[l] > self.data[idx]:
maxidx = l
if r < len(self) and self.data[r] > self.data[maxidx]:
maxidx = r
if maxidx != idx:
self.data[idx], self.data[maxidx] = self.data[maxidx], self.data[idx]
idx = maxidx
else:
break
def add(self, x):
enter code here
self.data.append(x)
i = len(self.data) - 1
p = Heap._parent(i)
while i > 0 and self.data[p] < self.data[i]:
self.data[p], self.data[i] = self.data[i], self.data[p]
i = p
p = Heap._parent(i)
def peek(self):
return self.data[0]
def pop(self):
ret = self.data[0]
self.data[0] = self.data[len(self.data)-1]
del self.data[len(self.data)-1]
self._heapify()
return ret
def __bool__(self):
return len(self.data) > 0
def __len__(self):
return len(self.data)
def __repr__(self):
return repr(self.data)

Resources