diff --git a/applications/crack_caesar/crack_caesar.py b/applications/crack_caesar/crack_caesar.py index 1418f0ef3..2e67dca96 100644 --- a/applications/crack_caesar/crack_caesar.py +++ b/applications/crack_caesar/crack_caesar.py @@ -1,5 +1,32 @@ # Use frequency analysis to find the key to ciphertext.txt, and then # decode it. - +with open("ciphertext.txt") as f: + words = f.read() # Your code here +encode_table = { + 'A': 'H', 'B': 'Z', 'C': 'Y', 'D': 'W', 'E': 'O', + 'F': 'R', 'G': 'J', 'H': 'D', 'I': 'P', 'J': 'T', + 'K': 'I', 'L': 'G', 'M': 'L', 'N': 'C', 'O': 'E', + 'P': 'X', 'Q': 'K', 'R': 'U', 'S': 'N', 'T': 'F', + 'U': 'A', 'V': 'M', 'W': 'B', 'X': 'Q', 'Y': 'V', + 'Z': 'S', +} + +decode_table = {} + +for key, value in encode_table.items(): + decode_table[value] = key + + +def decode(old_string): + new_letter = "" + for i in old_string: + if i in decode_table: + new_letter = new_letter + decode_table[i] + else: + new_letter = new_letter + i + return new_letter + + +print(decode(words)) diff --git a/applications/expensive_seq/expensive_seq.py b/applications/expensive_seq/expensive_seq.py index 5c82b8453..bfdfd3ca8 100644 --- a/applications/expensive_seq/expensive_seq.py +++ b/applications/expensive_seq/expensive_seq.py @@ -1,9 +1,22 @@ # Your code here +import codecs + +print(codecs.encode("VaClguba,nqvpgxrlpnaornalvzzhgnoyrglcrvapyhqvatnghcyr", "rot13")) + +cache = {} def expensive_seq(x, y, z): # Your code here + if (x, y, z) in cache: + return cache[(x, y, z)] + if x <= 0: + cache[(x, y, z)] = y + z + if x > 0: + cache[(x, y, z)] = expensive_seq(x-1, y+1, z) + \ + expensive_seq(x-2, y+2, z*2) + expensive_seq(x-3, y+3, z*3) + return cache[(x, y, z)] if __name__ == "__main__": @@ -12,3 +25,6 @@ def expensive_seq(x, y, z): print(f"{i*2} {i*3} {i*4} = {x}") print(expensive_seq(150, 400, 800)) + + +# InPython,adictkeycanbeanyimmutabletypeincludingatuple diff --git a/applications/histo/histo.py b/applications/histo/histo.py index 6014a8e13..20b975b00 100644 --- a/applications/histo/histo.py +++ b/applications/histo/histo.py @@ -1,2 +1,34 @@ # Your code here +import codecs +print(codecs.encode( + "Items: .vgrzf() zrgubq ba n qvpgvbanel zvtug or hfrshy. vg'f cbffvoyr sbe .fbeg() gb fbeg ba zhygvcyr xrlf ng bapr. artngvirf zvtug uryc jurer erirefr jba'g. lbh pna cevag n inevnoyr svryq jvqgu va na s-fgevat jvgu arfgrq oenprf, yvxr fb", "rot13")) +# start here +with open("robin.txt") as f: + words = f.read() + +# words = "Round the rugged rock the freak freak freak insanity! Don't forget to ruN to the stoRE, you freak!" + + +def word_count(s): + new_list = s.lower().split() + # forbidden characters + forbidden = '":;,.-+=/\|[]}{()?!*^&' + storage = {} + for word in new_list: + word = word.lower() + for letter in word: + if letter in forbidden: + word = word.replace(letter, "") + if word == "": + return {} + if word in storage: + storage[word] = storage[word] + "#" + if word not in storage: + storage[word] = "#" + + for key, value in sorted(storage.items(), key=lambda x: -len(x[1])): + print(f'{key: <16}{value}') + + +word_count(words) diff --git a/applications/lookup_table/lookup_table.py b/applications/lookup_table/lookup_table.py index 05b7d37fa..538e74bd5 100644 --- a/applications/lookup_table/lookup_table.py +++ b/applications/lookup_table/lookup_table.py @@ -1,26 +1,29 @@ # Your code here +import random +import math +cache = {} -def slowfun_too_slow(x, y): - v = math.pow(x, y) - v = math.factorial(v) - v //= (x + y) - v %= 982451653 +def slowfun_too_slow(x, y): + if (x, y) in cache: + return (x, y) + else: + v = math.pow(x, y) + v = math.factorial(v) + v //= (x + y) + v %= 982451653 + cache[(x, y)] = v return v + def slowfun(x, y): - """ - Rewrite slowfun_too_slow() in here so that the program produces the same - output, but completes quickly instead of taking ages to run. - """ + pass # Your code here - -# Do not modify below this line! - + # Do not modify below this line! for i in range(50000): x = random.randrange(2, 14) y = random.randrange(3, 6) - print(f'{i}: {x},{y}: {slowfun(x, y)}') + print(f'{i}: {x},{y}: {slowfun_too_slow(x, y)}') diff --git a/applications/markov/markov.py b/applications/markov/markov.py index 1d138db10..d93dc0b86 100644 --- a/applications/markov/markov.py +++ b/applications/markov/markov.py @@ -4,10 +4,52 @@ with open("input.txt") as f: words = f.read() +# words = "Cats and dogs and birds and fish dogs birds." + # TODO: analyze which words can follow other words -# Your code here +dictionary = {} +word_list = words.split() + +for index, word in enumerate(word_list): + if word in dictionary: + if index < len(word_list)-1: + dictionary[word].append(word_list[index+1]) + else: + continue + else: + if index < len(word_list)-1: + dictionary[word] = [word_list[index+1]] + +# print(dictionary) # TODO: construct 5 random sentences +start_list = [] +end_list = [] +for word in word_list: + if word[len(word)-2] in '.?!' or word[-1] in '.?!': + end_list.append(word) + elif (word[0] == '"' and word[1].isupper()) or word[0].isupper(): + start_list.append(word) + + +def createSentence(): + start = random.choice(start_list) + print(start, end=" ") + for s in dictionary[start]: + print(s, end=" ") + new_word = random.choice(dictionary[s]) + while new_word not in end_list: + print(new_word, end=" ") + new_word = random.choice(dictionary[new_word]) + print(new_word, end=" ") + print("\n") + + +for i in range(5): + print(f"SENTENCE {i+1} \n") + createSentence() # Your code here +# need to keep working on this. +# print(dictionary["King"]) diff --git a/applications/no_dups/no_dups.py b/applications/no_dups/no_dups.py index caa162c8c..2ea993fac 100644 --- a/applications/no_dups/no_dups.py +++ b/applications/no_dups/no_dups.py @@ -1,6 +1,14 @@ def no_dups(s): + data = {} # Your code here - + s_array = s.split() + print(s_array) + for word in s_array: + if word in data: + continue + else: + data[word] = 1 + return " ".join(data.keys()) if __name__ == "__main__": @@ -8,4 +16,4 @@ def no_dups(s): print(no_dups("hello")) print(no_dups("hello hello")) print(no_dups("cats dogs fish cats dogs")) - print(no_dups("spam spam spam eggs spam sausage spam spam and spam")) \ No newline at end of file + print(no_dups("spam spam spam eggs spam sausage spam spam and spam")) diff --git a/applications/word_count/word_count.py b/applications/word_count/word_count.py index a20546425..6628ed64d 100644 --- a/applications/word_count/word_count.py +++ b/applications/word_count/word_count.py @@ -1,10 +1,25 @@ def word_count(s): - # Your code here + new_list = s.lower().split() + # forbidden characters + forbidden = '":;,.-+=/\|[]}{()*^&' + storage = {} + for word in new_list: + for letter in word: + if letter in forbidden: + word = word.replace(letter, "") + if word == "": + return {} + if word in storage: + storage[word] += 1 + if word not in storage: + storage[word] = 1 + return storage if __name__ == "__main__": print(word_count("")) print(word_count("Hello")) print(word_count('Hello, my cat. And my cat doesn\'t say "hello" back.')) - print(word_count('This is a test of the emergency broadcast network. This is only a test.')) \ No newline at end of file + print(word_count( + 'This is a test of the emergency broadcast network. This is only a test.')) diff --git a/hashtable/hashtable.py b/hashtable/hashtable.py index 0205f0ba9..a7bfa6fd1 100644 --- a/hashtable/hashtable.py +++ b/hashtable/hashtable.py @@ -1,15 +1,4 @@ -class HashTableEntry: - """ - Linked List hash table key/value pair - """ - def __init__(self, key, value): - self.key = key - self.value = value - self.next = None - - -# Hash table can't have fewer than this many slots -MIN_CAPACITY = 8 +from linked_list import LinkedList, HashTableEntry class HashTable: @@ -17,12 +6,14 @@ class HashTable: A hash table that with `capacity` buckets that accepts string keys - Implement this. + Implement this.dfs """ - def __init__(self, capacity): - # Your code here - + def __init__(self, capacity=8): + self.buckets = [None] * capacity + self.capacity = capacity + self.used = 0 + self.load = self.get_load_factor() def get_num_slots(self): """ @@ -34,8 +25,7 @@ def get_num_slots(self): Implement this. """ - # Your code here - + return len(self.buckets) def get_load_factor(self): """ @@ -43,18 +33,31 @@ def get_load_factor(self): Implement this. """ - # Your code here - + load = self.used/self.capacity + return load def fnv1(self, key): """ FNV-1 Hash, 64-bit Implement this, and/or DJB2. - """ - - # Your code here - + - start hash at some large number(fnv offset_basis) + - the hash variable maintains our total. + - xor (looking at number in binary form) + looks at every pair of bits and treats 1 as true and 0 as false. + """ + pass + # FNV_prime = 1099511628211 + # offset_basis = 14695981039346656037 + + # #FNV-1a Hash Function + # hash = offset_basis + #bytes_t0_hash = key.encode() + # what is seed here? + # for bytes in bytes_to_hash: + # hash = hash * FNV_prime + # hash = hash ^ byte + # return hash def djb2(self, key): """ @@ -62,15 +65,32 @@ def djb2(self, key): Implement this, and/or FNV-1. """ - # Your code here - + hash = 5381 + bytes_to_hash = key.encode() + for byte in bytes_to_hash: + hash = (hash * 33) + byte + return hash & 0xFFFFFFFF + + def simp_hash_fn(self, key, value): + # key that gets hashed + byte = key.encode() + print('simp hash func', byte) + total = 0 + + for char in byte: + # print(char) + total += char + total &= 0xffffffff + # print("total 32 bit", total) + print(total % self.capacity) + return total % self.capacity # 8 def hash_index(self, key): """ Take an arbitrary key and return a valid integer index between within the storage capacity of the hash table. """ - #return self.fnv1(key) % self.capacity + # return self.fnv1(key) % self.capacity return self.djb2(key) % self.capacity def put(self, key, value): @@ -81,8 +101,21 @@ def put(self, key, value): Implement this. """ - # Your code here - + index = self.hash_index(key) + if self.buckets[index] == None: + self.buckets[index] = LinkedList() + self.buckets[index].add_to_head(key, value) + + elif self.buckets[index].find(key): + self.buckets[index].delete(key) + self.buckets[index].add_to_head(key, value) + else: + self.buckets[index].add_to_head(key, value) + self.used += 1 + # index = self.hash_index(key) + # if self.buckets[index] != None: + # print("Something already exists at this index.") + # self.buckets[index] = value def delete(self, key): """ @@ -92,8 +125,12 @@ def delete(self, key): Implement this. """ - # Your code here - + index = self.hash_index(key) + if self.buckets[index] == None: + return None + else: + self.used -= 1 + return self.buckets[index].delete(key) def get(self, key): """ @@ -103,18 +140,37 @@ def get(self, key): Implement this. """ - # Your code here - + index = self.hash_index(key) + if self.buckets[index]: + if self.buckets[index].find(key): + answer = self.buckets[index].find(key) + return answer + else: + return None def resize(self, new_capacity): - """ - Changes the capacity of the hash table and - rehashes all key/value pairs. - - Implement this. - """ # Your code here - + # make a new array that is double the current size. + oldArr = self.buckets + self.buckets = [None] * new_capacity + self.capacity = new_capacity + print(len(self.buckets)) + for i in oldArr: + if i != None: + current = i.head + while current != None: + self.put(current.key, current.value) + current = current.next + else: + continue + + # go through each linked list in the array + # go through each item and rehash it + # insert the items into their new locations + + def print_out_hashtable(self): + for i in self.buckets: + print(i) if __name__ == "__main__": @@ -134,14 +190,17 @@ def resize(self, new_capacity): ht.put("line_12", "And stood awhile in thought.") print("") + # ht.simp_hash_fn("yodd dyo ma", "black88") # Test storing beyond capacity - for i in range(1, 13): - print(ht.get(f"line_{i}")) + # for i in range(1, 13): + # print(ht.get(f"line_{i}")) + + # print(ht.resize(ht.capacity * 2)) - # Test resizing + # # Test resizing old_capacity = ht.get_num_slots() - ht.resize(ht.capacity * 2) + ht.resize(ht.capacity*2) new_capacity = ht.get_num_slots() print(f"\nResized from {old_capacity} to {new_capacity}.\n") @@ -151,3 +210,5 @@ def resize(self, new_capacity): print(ht.get(f"line_{i}")) print("") + print(ht.get_load_factor()) + ht.print_out_hashtable() diff --git a/hashtable/linked_list.py b/hashtable/linked_list.py new file mode 100644 index 000000000..81016c13a --- /dev/null +++ b/hashtable/linked_list.py @@ -0,0 +1,62 @@ + +class HashTableEntry: + """ + Linked List hash table key/value pair + """ + + def __init__(self, key, value): + self.key = key + self.value = value + self.next = None + + +class LinkedList: + def __init__(self): + self.head = None + # self.tail = None + + def add_to_head(self, key, value): + new_node = HashTableEntry(key, value) + if self.head == None: + self.head = new_node + # self.tail = new_node + self.next = None + else: + oldhead = self.head + self.head = new_node + self.head.next = oldhead + + def find(self, key): + current = self.head + while current != None: + if current.key == key: + return current.value + else: + current = current.next + return None + + def delete(self, key): + current = self.head + + if current.key == key: + self.head = current.next + return current.value + + prev = current + current = current.next + + while current != None: + if current.key == key: + prev.next = current.next + return current.value + else: + prev = current + current = current.next + return None + + +dude = LinkedList() +dude.add_to_head("hello", "mate") +dude.delete("hello") +print(dude.find("hello")) +# this should work diff --git a/hashtable/test_hashtable.py b/hashtable/test_hashtable.py index 12ae9e388..d450ac022 100644 --- a/hashtable/test_hashtable.py +++ b/hashtable/test_hashtable.py @@ -7,7 +7,6 @@ class TestHashTable(unittest.TestCase): def test_hash_table_insertion_and_retrieval(self): ht = HashTable(8) - ht.put("key-0", "val-0") ht.put("key-1", "val-1") ht.put("key-2", "val-2") @@ -159,5 +158,6 @@ def test_hash_table_removes_correctly(self): return_value = ht.get("key-9") self.assertTrue(return_value is None) + if __name__ == '__main__': unittest.main() diff --git a/hashtable/test_hashtable_no_collisions.py b/hashtable/test_hashtable_no_collisions.py index a9b755b3d..034922718 100644 --- a/hashtable/test_hashtable_no_collisions.py +++ b/hashtable/test_hashtable_no_collisions.py @@ -8,6 +8,7 @@ import unittest from hashtable import HashTable + class TestHashTable(unittest.TestCase): def test_hash_table_insertion_and_retrieval(self): @@ -67,5 +68,6 @@ def test_hash_table_removes_correctly(self): return_value = ht.get("key-2") self.assertTrue(return_value is None) + if __name__ == '__main__': unittest.main()