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())