diff --git a/338/scripts/makefile b/338/scripts/makefile index e18c8d5..9cb4a95 100644 --- a/338/scripts/makefile +++ b/338/scripts/makefile @@ -1,9 +1,11 @@ cc=javac -fxlib=--module-path /home/shockrah/Downloads/javafx-sdk-11.0.2/lib -ctrl=--add-modules javafx.controls - env=java -cfile="adsf" +#fxlib=--module-path /home/shockrah/Downloads/javafx-sdk-11.0.2/lib +#ctrl=--add-modules javafx.controls + +jfile="Main.java" +# Target class file to run(no extension) +cfile="Main" default: %.java # takes a java file as entry to build diff --git a/370/homework/huffman.py b/370/homework/huffman.py index 9e55470..7b5c95a 100644 --- a/370/homework/huffman.py +++ b/370/homework/huffman.py @@ -1,94 +1,20 @@ import queue -class Node(): +import heapq + +class Node: def __init__(self, c, weight): self.c = c self.freq = weight self.left = None self.right = None + + self.code = '' def __repr__(self): return f'{self.c}|{self.freq}' -class MinHeap(): - def __init__(self): - self.data = [] - - def empty(self): - return self.size() == 0 - - def size(self): - return len(self.data) - - def print(self): - for x in self.data: - print(x.c + str(x.freq)) - - def insert(self, val): - self.data.append(val) - self.__heapifyUp(len(self.data) - 1) - - def extractMin(self): - temp = self.data[0] - self.__swap(0, -1) - self.data.remove(self.data[-1]) - self.__heapifyDown(0) - return temp - - def __swap(self,i,j): - self.data[i], self.data[j] = self.data[j], self.data[i] - - def __heapifyUp(self, idx): - if idx > 0: - parent = (idx - 1) // 2 - if (self.data[parent].freq > self.data[idx].freq): - self.__swap(parent, idx) - self.__heapifyUp(parent) - - def __heapifyDown(self, idx): - data = self.data - left = 2 * idx + 1 - right = 2 * idx + 2 - mini = idx - if (left < len(data) and (data[left].freq < data[mini].freq)): - mini = left - if (right < len(data) and (data[right].freq < data[mini].freq)): - mini = right - if (mini is not idx): - self.__swap(mini, idx) - self.__heapifyDown(mini) - - def printChar(self, c): - # TODO: this method - curr = self.data[0] - for i in bin: - if i == '1' and curr.right is not None: - curr = curr.right - if i == '0' and curr.left is not None: - curr = curr.left - - - - - -def main(): - pq = MinHeap() - pq.insert(Node(' ', 1)) - pq.insert(Node('d', 4)) - pq.insert(Node('e', 10)) - pq.insert(Node('i', 13)) - pq.insert(Node('s', 2)) - pq.insert(Node('m', 8)) - pq.insert(Node('o', 6)) - - - assert(list(map(lambda x: x.freq, pq.data)) == [1, 2, 6, 13, 4, 10, 8]) - assert(pq.extractMin().freq == 1) - assert(list(map(lambda x: x.freq, pq.data)) == [2, 4, 6, 13, 8, 10]) - assert(pq.extractMin().freq == 2) - assert(list(map(lambda x: x.freq, pq.data)) == [4, 8, 6, 13, 10]) - assert(pq.extractMin().freq == 4) - pq.print() - print("Heap works") + def __lt__(self, other): + return self.weight < other.weight def frequencyMap(string): ret = [] @@ -103,31 +29,50 @@ def frequencyMap(string): if k.c == i: k.freq += 1 - # Sort the charmap based on the frequencies - ret.sort(key=lambda x: x.freq) + # Sort the charmap alphabetically + ret.sort(key=lambda x: x.c) return ret -def buildMinHeap(freqs): - heap = MinHeap() - _queue = queue.Queue() - while _queue.qsize() >= 2: - left = _queue.get() - right = _queue.get() - weight = left.freq+ right.freq - root = Node('*', weight) +def encode(freqs): + # add things to our min heap + heap = [i for i in freqs] + heapq.heapify(heap) - # insert the new sub-tree into the minheap and add the tree to the queue - heap.insert(root) - _queue.put(root) + # now we can merge all the nodes together + while len(heap) > 1: + # pop two items from the queuee + left = heapq.heappop(heap) + right = heapq.heappop(heap) - # Once there is one item in the queue left we can simply return the new thing - heap.print() + # setup the new root node + root = Node('*', left.weight + right.weight) + root.left = left + root.right = right + + # re-insert the new subtree into the minheap + heapq.heappush(heap, root) + # return the heap itself so we cna do stuff with it return heap +def decode(root, binaryStr): + string = '' + curr = root + for i in binaryStr: + if i == '0': + curr = curr.left + else: + curr = curr.right + # check if we're at a leaf + if curr.left is None and curr.right is None: + string += curr.c + curr = root + print(string) + def printEncoding(text, heap): + # prints out the encoding for a given string for i in text: heap.printChar(i) @@ -136,8 +81,15 @@ def printEncoding(text, heap): if __name__ == "__main__": text = input() binary = input() + #print(f'{text}\n{binary}\n===================') + # calculate the frequency of each character frequencies = frequencyMap(text) - print(frequencies) - heap = buildMinHeap(frequencies) - printEncoding(binary, heap) + + # build up our heap to display info from + heap = encode(frequencies)[0] + #print(heap) + + # decode the binary + decode(heap, binary) + diff --git a/370/notes/a-star.md b/370/notes/a-star.md index a6aa0ad..7db418b 100644 --- a/370/notes/a-star.md +++ b/370/notes/a-star.md @@ -21,7 +21,12 @@ Time: O(VlogV + E) ## Dijkstra's -O(V) +O(V^2 + E) ## A\* -O(V^2 = E) + +Worst case is the same as Dijkstra's time + +O(V^2 + E) + + diff --git a/370/notes/avl-trees.md b/370/notes/avl-trees.md index 53832ac..00ca02b 100644 --- a/370/notes/avl-trees.md +++ b/370/notes/avl-trees.md @@ -7,7 +7,7 @@ _time complexity will be in terms of height_ * impl: _root will typically have the largest height value_ > Balance: - | left_height - right_height | + left_height - right_height we can discard the || if we want negative balance vals but it really shouldn't matter basically: we want the balance for each node to be 1 or 0. diff --git a/370/notes/dynamic.md b/370/notes/dynamic.md new file mode 100644 index 0000000..3338e5f --- /dev/null +++ b/370/notes/dynamic.md @@ -0,0 +1,53 @@ +# """"Dynamic Programming"""" + + +> Take a large problem +> Break it up +> Solve the pieces + + + +# Definitions + +_Recursive dynamic programming_ +: Memoization a.k.a. top-down approach +: Go from big problems and build downward + +_Tabulation_ +: Bottom up approach +: Go from little problems and build up + + +# Recursive compiler tricks + +Normal iterative: +``` +start: +... +jcond start +``` + +Normal recursion(under non-priveleged procs): + +Each "iteration" creates a new frame of whatever size: +hence we approach the hard stack limit + +_Sick guess_: +``` + At compile we should be able to predict an incoming iteration from a + recusive endpoint. + + ? is it just parameterized jumps ? +``` + +_Answer:_ +``` + Tail recusion optimization + + Takes the last statement of function + Assuming its a recursive call, we can replace our current stack frame's arguments + The only state that changes between calls then is just the arguments +``` +In this sense we are turning a recusive functino into an iterative one because the whole state is held in one frame & we only ever jump within our routines address space. + +However, this tail optimization can only happen at the tail of a routine. diff --git a/370/notes/single-source.md b/370/notes/single-source.md new file mode 100644 index 0000000..5ab3abc --- /dev/null +++ b/370/notes/single-source.md @@ -0,0 +1,17 @@ +# Single Source Shortest Path + +# Bellman-ford Algorithm + +Time: O(VE) + +# Floyd-Warshall + +Space: O(V^2) + +That space is because we're using a matrix to store the paths, which of course is going to take up two dimensions + +Main idea: Shortest path between any two nodes in a graph w/ V nodes _will_ go through at most V nodes + +Iterative idea: Path's can visit i intermediary node. Does that many any path shorter? + +Advantages: we can find negative cycles(Cycle where there is a negative edge) diff --git a/370/notes/spanning-tree.md b/370/notes/spanning-tree.md new file mode 100644 index 0000000..364dc50 --- /dev/null +++ b/370/notes/spanning-tree.md @@ -0,0 +1,19 @@ +# Spanning tree + +Graph in a graph where all nodes are connected but there are + +1. no cycles + +2. |V-1| edges + +__Minimum__ +: total edge weight minimized + +Things needed for next two sections: +: _time complexity_ +: _space complexity_ + +## Kruskal + +## Prim + diff --git a/370/past-midterms/2.md b/370/past-midterms/2.md new file mode 100644 index 0000000..49e002a --- /dev/null +++ b/370/past-midterms/2.md @@ -0,0 +1,53 @@ +# Time/space complexity + +For basically everthing, just list it out somewhere on sheet + +# AVL Tree's + +Get some functions for them written out +Insert/Deletion/Lookup Functions + +# No pathfinding code +_mainly cuz we never did any for homework/class_ + +Time/space complexities should be straightforward memorization + +# Tries + + +# Huffman + +Decoding: +: Time - O(n) {n = number of input bits} + +Encoding +: Time O(nlog(n)) +: Where n is the number of unique bits in the string + + +# Pathfinding - Conceptual things + +Admissability: allowed to underestimate but not overestimate. + +> Heuristic? + +* A-star +* Best-first + +> Multiple sources + +* Floyd's Algorithm + +> Multiple destination + +* Floyd's +* Bellman-Ford + +> Negative edges + +* Floyd +* Bellman-Ford + +> Negative Cycles + +None diff --git a/370/past-midterms/2.py b/370/past-midterms/2.py new file mode 100644 index 0000000..0869705 --- /dev/null +++ b/370/past-midterms/2.py @@ -0,0 +1,96 @@ +class HuffmanNode: + # $ will represent a dummy node + # anything else is a regular node + def __init__(self, data, freq): + self.data = data + self.freq = freq + + +class HuffmanTree: + def __init__(self, node): + self.root = node + + def frequencyMap(self, string): + ret = {} + for i in string: + if i not in ret: + ret[i] = Node(i, 1) + else: + ret[i].freq += 1 + + return ret + + + def encode(self, string): + f = self.frequencyMap(string) + +class TrieNode: + def __init__(self): + # 1 ref for each character in the alphabet + self.isleaf = False + self.edges = [0] * 26 + +class TrieTree: + def __init__(self, root): + self.root = root + + # just not going to bother with capitals + def _charIndex(self, char): + return ord(char) - ord('a') + + def insert(self, string): + curr = self.root + for i in string: + alphabetIndex = _charIndex(i) + if curr[alphabetIndex] is None: + curr.edges[alphabetIndex] = Node() + # go to the nexxt thing + curr = curr.edges[alphabetIndex] + else: + # Finally mark the last node as a leaf + curr.isleaf = True + + def lookup(self, string): + curr = self.root + # First we should go straight to the end of the string + # That's why we don't do any checks + for i in string: + alphaIndex = _charIndex(i) + curr = curr.edges[alphaIndex] + + return curr.isleaf + + def remove(self, string): + pass + + def traverse(self, node, preFix): + if node: + if n.isleaf: + print(prefix) + # recursively go through the tree + for i in prefix: + traverse(node.edges[_i], prefix+_charIndex(i)) + +class AVLNode: + def __init__(self, data): + self.data = data + self.height = 0 + self.left = None + self.Right = None + +class AVLTree: + def __init__(self,node): + self.root = node + + def rotateLeft(self, node): + tmp = node.right + node.left = tmp.right + tmp.right = node + + # Set the heights on each node + node.height = 1 + max(node.left.height, node.right.height) + tmp.height = 1 + max(tmp.left.height, tmp.right.height) + return tmp + + def rotateRight(self, node): + pass diff --git a/370/past-midterms/midterm2.pdf b/370/past-midterms/midterm2.pdf new file mode 100644 index 0000000..4c2ad85 Binary files /dev/null and b/370/past-midterms/midterm2.pdf differ diff --git a/370/past-midterms/tmp.py b/370/past-midterms/tmp.py new file mode 100644 index 0000000..0f47417 --- /dev/null +++ b/370/past-midterms/tmp.py @@ -0,0 +1,27 @@ +class Trie: + def __init__(self, *words): + self.root = {} + + for word in words: + self.insert(word) + + def insert(self, word): + curr = self.root + for c in word: + if c not in curr: + curr[c] = {} + else: + curr = curr[c] + + # add a marker to show that we are a leaf + curr['.'] = '.' + self.root = curr + + def remove(self, word): + pass + + def printWord(self, word): + pass + + def all(self): + pass diff --git a/370/past-midterms/trie.py b/370/past-midterms/trie.py new file mode 100644 index 0000000..b6f0b54 --- /dev/null +++ b/370/past-midterms/trie.py @@ -0,0 +1,59 @@ +class Node: + def __init__(self, leaf=False): + # refs list of next valid characters + self.letters = [None] * 26 + self.isLeaf = leaf + + +class Trie: + def __init__(self): + self.root = Node() + + def _charIndex(self, char): + return ord(char) - ord('a') + + def insert(self, string): + curr = self.root + for i in string: + refIndex = self._charIndex() + # create nodes if we have to + if curr.letters[refIndex] is None: + curr.letters[refIndex] = Node() + + curr = curr.letters[refIndex] + # Set the last letter to be a leaf + curr.isLeaf = True + + def remove(self, string): + # Lazy removal + curr = self.root + for i in string: + refIndex = self._charIndex(i) + if curr.letters[refIndex] is None: + break + curr = curr.letters[refIndex] + curr.isLeaf = False + + + # We're also going to be printing things as we go along the thing + def lookup(self, string): + curr = self.root + for i in string: + refIndex = self._charIndex(i) + # Make sure we don't walk into nothing + if curr.letters[refIndex] is None: + return False + curr = curr.letters[refIndex] + print(i, end='') + + return curr.isLeaf + + def all(self, node, word): + if node is None: + return + + if node.isLeaf: + # Print out the word we have so far + self.lookup(word) + +