diff --git a/schoeffelbe/priorityQueue.py b/schoeffelbe/priorityQueue.py new file mode 100644 index 0000000..7545ad1 --- /dev/null +++ b/schoeffelbe/priorityQueue.py @@ -0,0 +1,224 @@ +from utils.memory_array import MemoryArray +from utils.memory_cell import MemoryCell +from utils.literal import Literal +from utils.constants import MIN_VALUE +from utils.memory_manager import MemoryManager +from utils.memory_range import mrange + +# Impl of MemoryArray says we cant add our own Datatypes beside Literal and List +# BUUUUT we can just wrap our Datatype in a List :-) +class HeapEntry: + def __init__(self, item, priority=1): + self.data = MemoryArray(Literal(2)) + # 0: Content, 1: Prio + self.data[Literal(0)] = Literal(item) + self.data[Literal(1)] = Literal(priority) + + def getItem(self): + return self.data[Literal(0)] + + def getPriority(self): + return self.data[Literal(1)] + + def setPriority(self, priority): + self.data[Literal(1)] = Literal(priority) + + def __lt__(self, other): + if other is None: + return True + if isinstance(other, (int, float)): + return self.getPriority().value > other + return self.getPriority() > other.getPriority() + + def __gt__(self, other): + if other is None: + return False + if isinstance(other, (int, float)): + return self.getPriority().value < other + return self.getPriority() < other.getPriority() + + def __eq__(self, other): + return self.getPriority() == other.getPriority() + + def __str__(self): + return f"({self.getItem()}, prio={self.getPriority()})" + +class PriorityQueue: + def __init__(self, max_size : Literal = Literal(100)): + self.heap = MemoryArray(max_size) + self.size = MemoryCell(0) + + def parent(self, i: Literal) -> Literal: + return MemoryCell(i.pred()) // Literal(2) + + def leftChild(self, i: Literal) -> Literal: + return MemoryCell(MemoryCell(2) * i) + Literal(1) + + def rightChild(self, i: Literal) -> Literal: + return MemoryCell(MemoryCell(2) * i) + Literal(2) + + def swap(self, i: Literal, j: Literal): + tmp_i = self.heap[i].value + tmp_j = self.heap[j].value + self.heap[i].set(tmp_j) + self.heap[j].set(tmp_i) + + def max_heapify(self, i: Literal): + left = self.leftChild(i) + right = self.rightChild(i) + largest = i + + if left < self.size and self.heap[left] > self.heap[largest]: + largest = left + + if right < self.size and self.heap[right] > self.heap[largest]: + largest = right + + if largest != i: + self.swap(i, largest) + self.max_heapify(largest) + + def insert(self, entry : HeapEntry): + if self.size >= self.heap.length(): + raise IndexError("Heap full") + + i = self.size + self.heap[i].set([entry]) + self.size += Literal(1) + + currentNode = self.heap[i] + parentNode : Literal = self.heap[self.parent(i)] + print(currentNode) + print(parentNode) + + while i > Literal(0) and self.heap[self.parent(i)] < self.heap[i]: + self.swap(i, self.parent(i)) + i = self.parent(i) + + def pop(self): + if self.is_empty(): + raise IndexError("Queue is empty!") + + max_item = self.heap[Literal(0)] + + self.heap[Literal(0)] = self.heap[self.size - Literal(1)] + self.size -= Literal(1) + + self.max_heapify(Literal(0)) + + return max_item + + def peek(self): + if self.is_empty(): + raise IndexError("Queue is empty") + return self.heap[Literal(0)] + + def is_empty(self): + return self.size == Literal(0) + + def __len__(self): + """Gibt die Anzahl der Elemente in der Warteschlange zurück.""" + return self.size + +def dummify(method): + match method.lower(): + case "add": + tmp = MemoryCell(1) + Literal(1); + case "cmp": + tmp = MemoryCell(1) > Literal(1); + +# Had to adapt different Approach +# Had to resort to using primite Types as I do not know the language good enough to get my original +# approach working and ran out of time +class PriorityQueue_Primitive: + def __init__(self, max_size=100): + self.heap = [None] * max_size + self.size = 0 + + def parent(self, i): + return (i - 1) // 2 + + def leftChild(self, i): + return 2 * i + 1 + + def rightChild(self, i): + return 2 * i + 2 + + def swap(self, i, j): + self.heap[i], self.heap[j] = self.heap[j], self.heap[i] + + def maxHeapify(self, i): + left = self.leftChild(i) + right = self.rightChild(i) + largest = i + + if left < self.size and self.heap[left] is not None: + if self.heap[largest] is None or self.heap[left] > self.heap[largest]: + largest = left + + if right < self.size and self.heap[right] is not None: + if self.heap[largest] is None or self.heap[right] > self.heap[largest]: + largest = right + + if largest != i: + self.swap(i, largest) + self.maxHeapify(largest) + + def insert(self, entry): + if self.size >= len(self.heap): + raise IndexError("Heap full") + + i = self.size + self.heap[i] = entry + self.size += 1 + + while i > 0: + parent = self.parent(i) + + # Overloaded -> LSP not working quite right, but Interpreter does + if self.heap[parent] is None or self.heap[i] > self.heap[parent]: + self.swap(i, parent) + i = parent + else: + break + + def pop(self): + if self.is_empty(): + raise IndexError("Queue is empty!") + + max_entry = self.heap[0] + + self.heap[0] = self.heap[self.size - 1] + self.heap[self.size - 1] = None + self.size -= 1 + + if not self.is_empty(): + self.maxHeapify(0) + + return max_entry + + def peek(self): + if self.is_empty(): + raise IndexError("Queue is empty") + return self.heap[0] + + def is_empty(self): + return self.size == 0 + + def __len__(self): + return self.size + +if __name__ == '__main__': + pq = PriorityQueue_Primitive() + assert(pq.size == 0 and pq.is_empty()) + test = HeapEntry("A", 2) + print(test) + a = MemoryArray([test]) + print(a) + print(a[Literal(0)]) + pq.insert(HeapEntry("D", 3)); + pq.insert(HeapEntry("A", 4)); + pq.insert(HeapEntry("T", 2)); + print(pq.pop()) + print(pq.pop()) + print(pq.pop())