diff --git a/applications/crack_caesar/crack_caesar.py b/applications/crack_caesar/crack_caesar.py index 1418f0ef3..a36db7c89 100644 --- a/applications/crack_caesar/crack_caesar.py +++ b/applications/crack_caesar/crack_caesar.py @@ -1,5 +1,20 @@ + # Use frequency analysis to find the key to ciphertext.txt, and then # decode it. # Your code here +import os + +f = open(f"{os.getcwd()}/applications/crack_caesar/ciphertext.txt") + +text = f.read() +print(text) + + +letter_frequencies = {'E': 11.53, 'T': 9.75, 'A': 8.46, 'O': 8.08, 'H': 7.71, + 'N': 6.73, 'R': 6.29, 'I': 5.84, 'S': 5.56, 'D': 4.74, + 'L': 3.92, 'W': 3.08, 'U': 2.59, 'G': 2.48, 'F': 2.42, + 'B': 2.19, 'M': 2.18, 'Y': 2.02, 'C': 1.58, 'P': 1.08, + 'K': 0.84, 'V': 0.59, 'Q': 0.17, 'J': 0.07, 'X': 0.07, + 'Z': 0.03} \ No newline at end of file diff --git a/applications/expensive_seq/expensive_seq.py b/applications/expensive_seq/expensive_seq.py index 5c82b8453..866d437c5 100644 --- a/applications/expensive_seq/expensive_seq.py +++ b/applications/expensive_seq/expensive_seq.py @@ -1,9 +1,18 @@ # Your code here - +dictionary = {} def expensive_seq(x, y, z): - # Your code here + if (x, y, z) in dictionary: + return dictionary[(x, y, z)] + + result = 0 + if x <= 0: + result = y + z + if x > 0: + result = expensive_seq(x-1,y+1,z) + expensive_seq(x-2,y+2,z*2) + expensive_seq(x-3,y+3,z*3) + dictionary[(x, y, z)] = result + return result if __name__ == "__main__": diff --git a/applications/histo/histo.py b/applications/histo/histo.py index 6014a8e13..23aa50813 100644 --- a/applications/histo/histo.py +++ b/applications/histo/histo.py @@ -1,2 +1,2 @@ -# Your code here - + +# Your code here \ No newline at end of file diff --git a/applications/lookup_table/lookup_table.py b/applications/lookup_table/lookup_table.py index 05b7d37fa..7b94a5383 100644 --- a/applications/lookup_table/lookup_table.py +++ b/applications/lookup_table/lookup_table.py @@ -1,22 +1,24 @@ -# Your code here +import math +import random +dictionary = {} -def slowfun_too_slow(x, y): - v = math.pow(x, y) - v = math.factorial(v) - v //= (x + y) - v %= 982451653 - 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. """ - # Your code here - + if (x, y) in dictionary: + return dictionary[(x, y)] + v = math.pow(x, y) + v = math.factorial(v) + v //= (x + y) + v %= 982451653 + dictionary[(x, y)] = v + return v # Do not modify below this line! diff --git a/applications/markov/markov.py b/applications/markov/markov.py index 1d138db10..017dda14b 100644 --- a/applications/markov/markov.py +++ b/applications/markov/markov.py @@ -10,4 +10,3 @@ # TODO: construct 5 random sentences # Your code here - diff --git a/applications/no_dups/no_dups.py b/applications/no_dups/no_dups.py index caa162c8c..ab9ca01fb 100644 --- a/applications/no_dups/no_dups.py +++ b/applications/no_dups/no_dups.py @@ -1,6 +1,20 @@ def no_dups(s): - # Your code here + array = [] + result_string = "" + split_string = s.split() + + if s == "": + return result_string + for word in split_string: + if word not in array: + array.append(word) + result_string += word + " " + + if result_string.endswith(" "): + return result_string[:-1] + + return result_string if __name__ == "__main__": diff --git a/applications/word_count/word_count.py b/applications/word_count/word_count.py index a20546425..dc2dabc32 100644 --- a/applications/word_count/word_count.py +++ b/applications/word_count/word_count.py @@ -1,6 +1,22 @@ def word_count(s): - # Your code here + dictionary = {} + special_characters = ['"', ":", ";", ",", ".", "-", "+", "=", "/", "|", "[", "]", "{", "}", "(", ")", "*", "^", "&", "\\"] + lower_case = s.lower() + + for i in special_characters: + lower_case = lower_case.replace(i, "") + + split_string = lower_case.split() + if split_string.count == 0: + return dictionary + + for word in split_string: + if word in dictionary: + dictionary[word] += 1 + else: + dictionary[word] = 1 + return dictionary if __name__ == "__main__": diff --git a/hashtable/hashtable.py b/hashtable/hashtable.py index 0205f0ba9..4e972a20b 100644 --- a/hashtable/hashtable.py +++ b/hashtable/hashtable.py @@ -11,58 +11,64 @@ def __init__(self, key, value): # Hash table can't have fewer than this many slots MIN_CAPACITY = 8 +MAX_LOAD_FACTOR = 0.7 +MIN_LOAD_FACTOR = 0.2 class HashTable: """ A hash table that with `capacity` buckets that accepts string keys - Implement this. """ - def __init__(self, capacity): - # Your code here - + def __init__(self, capacity=MIN_CAPACITY): + self.capacity = capacity + self.array = [None] * capacity + self.items = 0 def get_num_slots(self): """ Return the length of the list you're using to hold the hash table data. (Not the number of items stored in the hash table, but the number of slots in the main list.) - One of the tests relies on this. - Implement this. """ - # Your code here + return self.capacity def get_load_factor(self): """ Return the load factor for this hash table. - Implement this. """ - # Your code here + return self.items / self.get_num_slots() def fnv1(self, key): """ FNV-1 Hash, 64-bit - Implement this, and/or DJB2. """ - # Your code here + hash = 14638081039346656478 # Offset + + for s in key: + hash = hash * 1099511628211 # FVN prime + hash = hash ^ ord(s) + return hash % len(self.array) def djb2(self, key): """ DJB2 hash, 32-bit - Implement this, and/or FNV-1. """ - # Your code here + hash = 5381 + + for x in key: + hash = ((hash << 5) + hash) + ord(x) + return hash & 0xffffffff % self.capacity def hash_index(self, key): @@ -76,45 +82,109 @@ def hash_index(self, key): def put(self, key, value): """ Store the value with the given key. - Hash collisions should be handled with Linked List Chaining. - Implement this. """ - # Your code here + index = self.hash_index(key) + + entry = self.array[index] + + if entry is None: + self.array[index] = HashTableEntry(key, value) + self.items += 1 + self.resizeIfNeeded() + return + + while entry.next != None and entry.key !=key: + entry = entry.next + + if entry.key == key: + entry.value = value + else: + entry.next = HashTableEntry(key, value) + self.items += 1 + self.resizeIfNeeded() def delete(self, key): """ Remove the value stored with the given key. - Print a warning if the key is not found. - Implement this. """ - # Your code here + index = self.hash_index(key) + + entry = self.array[index] + prev_entry = None + + if entry is not None: + while entry.next != None and entry.key != key: + prev_entry = entry + entry = entry.next + + if entry.key == key: + if prev_entry is None: + self.array[index] = entry.next + else: + prev_entry.next = entry.next + self.items -= 1 + self.resizeIfNeeded() + return + + print(f"Warning: Attempted to delete value from HashTable but no value exists for key '{key}'") def get(self, key): - """ - Retrieve the value stored with the given key. + - Returns None if the key is not found. + index = self.hash_index(key) - Implement this. - """ - # Your code here + entry = self.array[index] + + if entry is None: + return None + + while entry.next != None and entry.key != key: + entry = entry.next + return entry.value if entry.key == key else None + + + def resizeIfNeeded(self): + if self.get_load_factor () > MAX_LOAD_FACTOR: + self.resize(self.capacity * 2) + elif self.get_load_factor() < MIN_LOAD_FACTOR and int(self.capacity / 2) >= MIN_CAPACITY: + self.resize(int(self.capacity / 2)) def resize(self, new_capacity): """ Changes the capacity of the hash table and rehashes all key/value pairs. - Implement this. """ - # Your code here + old_array = self.array + self.array = [None] * new_capacity + self.capacity = new_capacity + + for old_entry in old_array: + while old_entry is not None: + key = old_entry.key + value = old_entry.value + index = self.hash_index(key) + entry = self.array[index] + + # inserts old key/value into resized hash table + + if entry is None: + self.array[index] = HashTableEntry(key, value) + else: + while entry.next != None: + entry = entry.next + entry.next = HashTableEntry(key, value) + + old_entry = old_entry.next + if __name__ == "__main__": @@ -150,4 +220,4 @@ def resize(self, new_capacity): for i in range(1, 13): print(ht.get(f"line_{i}")) - print("") + print("") \ No newline at end of file