From 06fa81648c7afd03f4255a193ea5bbc3ad0f3575 Mon Sep 17 00:00:00 2001 From: Oliver Hofmann Date: Tue, 1 Apr 2025 12:38:52 +0200 Subject: [PATCH 1/3] basic sort algorithms --- praktika/01_max_folge/algorithms.py | 83 ++++++++++++++++-- utils/game.py | 53 ++++++++++++ utils/literal.py | 10 +++ utils/memory_array.py | 8 ++ vorlesung/01_grundlagen/euklid.py | 13 +++ .../02_elementares_sortieren/bubble_game.py | 41 +++++++++ .../bubble_sorting.py | 84 +++++++++++++++++++ .../02_elementares_sortieren/insert_game.py | 41 +++++++++ .../insert_sorting.py | 61 ++++++++++++++ .../02_elementares_sortieren/select_game.py | 41 +++++++++ .../select_sorting.py | 58 +++++++++++++ 11 files changed, 488 insertions(+), 5 deletions(-) create mode 100644 utils/game.py create mode 100644 vorlesung/01_grundlagen/euklid.py create mode 100644 vorlesung/02_elementares_sortieren/bubble_game.py create mode 100644 vorlesung/02_elementares_sortieren/bubble_sorting.py create mode 100644 vorlesung/02_elementares_sortieren/insert_game.py create mode 100644 vorlesung/02_elementares_sortieren/insert_sorting.py create mode 100644 vorlesung/02_elementares_sortieren/select_game.py create mode 100644 vorlesung/02_elementares_sortieren/select_sorting.py diff --git a/praktika/01_max_folge/algorithms.py b/praktika/01_max_folge/algorithms.py index aafccf2..ad77305 100644 --- a/praktika/01_max_folge/algorithms.py +++ b/praktika/01_max_folge/algorithms.py @@ -3,6 +3,7 @@ from utils.memory_cell import MemoryCell from utils.constants import MIN_VALUE from utils.memory_manager import MemoryManager from utils.memory_range import mrange +from utils.literal import Literal def max_sequence_1(z: MemoryArray): n = z.length() @@ -21,6 +22,77 @@ def max_sequence_1(z: MemoryArray): r.set(j) return m, l, r +def max_sequence_2(z: MemoryArray): + n = z.length() + m = MemoryCell(MIN_VALUE) + s = MemoryCell() + l = MemoryCell() + r = MemoryCell() + for i in mrange(n): + s.set(0) + for j in mrange(i, n): + s += z[j] + if s > m: + m.set(s) + l.set(i) + r.set(j) + return m, l, r + +def max_sequence_3(z: MemoryArray, l = None, r = None): + if l is None: + l = Literal(0) + if r is None: + r = Literal(len(z)-1) + if l == r: + return z[l], l, r + m = Literal((int(l) + int(r)) // 2) + lm, ll, lr = max_sequence_3(z, l, m) + rm, rl, rr = max_sequence_3(z, Literal(int(m) + 1), r) + zm, zl, zr = find_between(z, l, m, r) + if lm >= rm and lm >= zm: + return lm, ll, lr + if rm >= lm and rm >= zm: + return rm, rl, rr + return zm, zl, zr + +def find_between(z: MemoryArray, l, m, r): + max_sum = MemoryCell(MIN_VALUE) + s = MemoryCell(0) + border = MemoryCell() + for i in mrange(m, int(l)-1, -1): + s += z[i] + if s > max_sum: + max_sum.set(s) + border.set(i) + left_max = Literal(max_sum) + left_border = Literal(border) + max_sum = MemoryCell(MIN_VALUE) + s.set(0) + for i in mrange(int(m) + 1, int(r)+1): + s += z[i] + if s > max_sum: + max_sum.set(s) + border.set(i) + max_sum += left_max + return max_sum, left_border, border + +def max_sequence_4(z: MemoryArray): + n = z.length() + max_sum = MemoryCell(MIN_VALUE) + curr_sum = MemoryCell(0) + curr_left = MemoryCell(0) + r = MemoryCell() + l = MemoryCell() + for i in mrange(n): + curr_sum += z[i] + if curr_sum > max_sum: + max_sum.set(curr_sum) + l.set(curr_left) + r.set(i) + if curr_sum < Literal(0): + curr_sum.set(0) + curr_left.set(int(i) + 1) + return max_sum, l, r def example(max_sequence_func): l = [-59, 52, 46, 14, -50, 58, -87, -77, 34, 15] @@ -53,8 +125,9 @@ def analyze_complexity(max_sequence_func, sizes): if __name__ == '__main__': - example(max_sequence_1) - for filename in ["data/seq0.txt", "data/seq1.txt"]: - print(filename) - seq(filename, max_sequence_1) - analyze_complexity(max_sequence_1, [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]) \ No newline at end of file + for func in [max_sequence_1, max_sequence_2, max_sequence_3, max_sequence_4]: + example(func) + for filename in ["data/seq0.txt", "data/seq1.txt"]: + print(filename) + seq(filename, func) + analyze_complexity(func, [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]) diff --git a/utils/game.py b/utils/game.py new file mode 100644 index 0000000..cdb9dff --- /dev/null +++ b/utils/game.py @@ -0,0 +1,53 @@ +import pygame + +class Game: + + def __init__(self, title, fps=60, size=(640, 400)): + self.title = title + self.fps = fps + self.size = size + self.clock = pygame.time.Clock() + self.dt = 0 + self.screen = None + + def init_game(self): + pygame.init() + pygame.display.set_caption(self.title) + self.screen = pygame.display.set_mode(self.size) + + + def game_loop(self): + while True: + # Berechnung der Zeitdifferenz seit dem letzten Frame + self.dt = self.clock.tick(self.fps) / 1000 + if self.event_handling() == False: + break + if self.update_game() == False: + break + self.draw_game() + + def exit_game(self): + pygame.quit() + + def event_handling(self): # bleibt in der Unterklasse unverändert + for event in pygame.event.get(): + if not self.handle_event(event): + return False + return True + + def handle_event(self, event): # wird in der Unterklasse überschrieben + if event.type == pygame.QUIT: + return False + return True + + def update_game(self): + return True + + def draw_game(self): + pygame.display.flip() + + def run(self): + self.init_game() + self.game_loop() + self.exit_game() + diff --git a/utils/literal.py b/utils/literal.py index 92cd423..ac41a93 100644 --- a/utils/literal.py +++ b/utils/literal.py @@ -71,6 +71,10 @@ class Literal: """Repräsentation des Werts.""" return f"{self.value}" + def __repr__(self): + """Repräsentation des Werts für Debugging-Zwecke.""" + return f"Literal(value={self.value}, reads={self.read_count})" + def get_read_count(self): """Gibt zurück, wie oft der Wert gelesen wurde.""" return self.read_count @@ -80,6 +84,12 @@ class Literal: self.read_count += 1 return int(self.value) + def succ(self): + return Literal(self.value+1) + + def pred(self): + return Literal(self.value-1) + if __name__ == "__main__": l1 = Literal(5) diff --git a/utils/memory_array.py b/utils/memory_array.py index 65f40e9..92ab2ca 100644 --- a/utils/memory_array.py +++ b/utils/memory_array.py @@ -73,6 +73,14 @@ class MemoryArray: a.reset_counters() return a + @staticmethod + def create_sorted_array(count): + """Erzeugt ein sortiertes Speicherarray.""" + a = MemoryArray(list(range(count))) + a.reset_counters() + return a + + @staticmethod def create_array_from_file(filename, limit=None): """Erzeugt ein Speicherarray aus einer Datei.""" diff --git a/vorlesung/01_grundlagen/euklid.py b/vorlesung/01_grundlagen/euklid.py new file mode 100644 index 0000000..ae79752 --- /dev/null +++ b/vorlesung/01_grundlagen/euklid.py @@ -0,0 +1,13 @@ +from utils.memory_cell import MemoryCell +from utils.literal import Literal + +x = MemoryCell(int(input("Erste Zahl: "))) +y = MemoryCell(int(input("Zweite Zahl: "))) + +while x > Literal(0): + if x < y: + x, y = y, x + x -= y +print(y) + +print(f"Insgesamt gab es {x.sub_count + y.sub_count} Subtraktionen.") \ No newline at end of file diff --git a/vorlesung/02_elementares_sortieren/bubble_game.py b/vorlesung/02_elementares_sortieren/bubble_game.py new file mode 100644 index 0000000..11bda67 --- /dev/null +++ b/vorlesung/02_elementares_sortieren/bubble_game.py @@ -0,0 +1,41 @@ +import random +import pygame +from utils.game import Game +from utils.memory_array import MemoryArray +from bubble_sorting import bubble_sort_stepwise + +WHITE = (255, 255, 255) +BLUE = (0, 0, 255) + +class BubbleGame(Game): + + def __init__(self): + super().__init__("Bubble Game", fps=60, size=(400, 400)) + random.seed() + l =list(range(1, 101)) + random.shuffle(l) + self.z = MemoryArray(l) + self.finished = False + self.sort_generator = bubble_sort_stepwise(self.z) + + def update_game(self): + if not self.finished: + try: + next(self.sort_generator) + except StopIteration: + self.finished = True + return True + + def draw_game(self): + self.screen.fill(WHITE) + for i, cell in enumerate(self.z): + x = 50 + i*3 + y = 350 - cell.value * 3 + pygame.draw.rect(self.screen, BLUE, (x, y, 3, 3)) + super().draw_game() + + +if __name__ == "__main__": + b = BubbleGame() + b.run() + diff --git a/vorlesung/02_elementares_sortieren/bubble_sorting.py b/vorlesung/02_elementares_sortieren/bubble_sorting.py new file mode 100644 index 0000000..2ee32b3 --- /dev/null +++ b/vorlesung/02_elementares_sortieren/bubble_sorting.py @@ -0,0 +1,84 @@ +from utils.memory_array import MemoryArray +from utils.memory_cell import MemoryCell +from utils.constants import MIN_VALUE +from utils.memory_manager import MemoryManager +from utils.memory_range import mrange +from utils.literal import Literal + +def bubble_sort_stepwise(z: MemoryArray): + n = z.length() + for i in mrange(n.pred()): + for j in mrange(n.pred(), i, -1): + if z[j.pred()] > z[j]: + swap(z, j, j.pred()) + yield z + + +def bubble_sort2_stepwise(z: MemoryArray): + n = MemoryCell(z.length()) + true = Literal(1) + false = Literal(0) + sortiert = MemoryCell() + while True: + sortiert.set(true) + for i in mrange(n.pred()): + if z[i] > z[i.succ()]: + swap(z, i, i.succ()) + sortiert.set(false) + yield z + n -= Literal(1) + if sortiert == true or n <= Literal(1): + break + + +def bubble_sort(z: MemoryArray): + sort_generator = bubble_sort_stepwise(z) + while True: + try: + next(sort_generator) + except StopIteration: + break + + +def bubble_sort2(z: MemoryArray): + sort_generator = bubble_sort2_stepwise(z) + while True: + try: + next(sort_generator) + except StopIteration: + break + + +def sort_file(filename, sort_func): + z = MemoryArray.create_array_from_file(filename) + sort_func(z) + return z + +def analyze_complexity(sort_func, sizes, presorted=False): + """ + Analysiert die Komplexität einer Sortierfunktion. + + :param sort_func: Die Funktion, die analysiert wird. + :param sizes: Eine Liste von Eingabegrößen für die Analyse. + """ + for size in sizes: + MemoryManager.purge() # Speicher zurücksetzen + if presorted: + random_array = MemoryArray.create_sorted_array(size) + else: + random_array = MemoryArray.create_random_array(size, -100, 100) + sort_func(random_array) + MemoryManager.save_stats(size) + + MemoryManager.plot_stats(["cells", "compares", "writes"]) + +def swap(z: MemoryArray, i: int, j: int): + tmp = z[Literal(i)].value + z[Literal(i)] = z[Literal(j)] + z[Literal(j)].set(tmp) + +if __name__ == '__main__': + analyze_complexity(bubble_sort, [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]) +# analyze_complexity(bubble_sort2, [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]) +# analyze_complexity(bubble_sort, [10, 20, 30, 40, 50, 60, 70, 80, 90, 100], True) +# analyze_complexity(bubble_sort2, [10, 20, 30, 40, 50, 60, 70, 80, 90, 100], True) diff --git a/vorlesung/02_elementares_sortieren/insert_game.py b/vorlesung/02_elementares_sortieren/insert_game.py new file mode 100644 index 0000000..3d17b29 --- /dev/null +++ b/vorlesung/02_elementares_sortieren/insert_game.py @@ -0,0 +1,41 @@ +import random +import pygame +from utils.game import Game +from utils.memory_array import MemoryArray +from insert_sorting import insert_sort_stepwise + +WHITE = (255, 255, 255) +BLUE = (0, 0, 255) + +class InsertGame(Game): + + def __init__(self): + super().__init__("Insert Game", fps=60, size=(400, 400)) + random.seed() + l =list(range(1, 101)) + random.shuffle(l) + self.z = MemoryArray(l) + self.finished = False + self.sort_generator = insert_sort_stepwise(self.z) + + def update_game(self): + if not self.finished: + try: + next(self.sort_generator) + except StopIteration: + self.finished = True + return True + + def draw_game(self): + self.screen.fill(WHITE) + for i, cell in enumerate(self.z): + x = 50 + i*3 + y = 350 - cell.value * 3 + pygame.draw.rect(self.screen, BLUE, (x, y, 3, 3)) + super().draw_game() + + +if __name__ == "__main__": + b = InsertGame() + b.run() + diff --git a/vorlesung/02_elementares_sortieren/insert_sorting.py b/vorlesung/02_elementares_sortieren/insert_sorting.py new file mode 100644 index 0000000..6e526ee --- /dev/null +++ b/vorlesung/02_elementares_sortieren/insert_sorting.py @@ -0,0 +1,61 @@ +from utils.memory_array import MemoryArray +from utils.memory_cell import MemoryCell +from utils.memory_manager import MemoryManager +from utils.memory_range import mrange +from utils.literal import Literal + +def insert_sort_stepwise(z: MemoryArray): + n = z.length() + j = MemoryCell() + elem = MemoryCell() + for i in mrange(n): + elem.set(z[i]) + j.set(i) + while j > Literal(0) and z[j.pred()] > elem: + z[j].set(z[j.pred()]) + j -= Literal(1) + yield z + z[j].set(elem) + yield z + + +def insert_sort(z: MemoryArray): + sort_generator = insert_sort_stepwise(z) + while True: + try: + next(sort_generator) + except StopIteration: + break + +def sort_file(filename, sort_func): + z = MemoryArray.create_array_from_file(filename) + sort_func(z) + return z + + +def analyze_complexity(sort_func, sizes, presorted=False): + """ + Analysiert die Komplexität einer Sortierfunktion. + + :param sort_func: Die Funktion, die analysiert wird. + :param sizes: Eine Liste von Eingabegrößen für die Analyse. + """ + for size in sizes: + MemoryManager.purge() # Speicher zurücksetzen + if presorted: + random_array = MemoryArray.create_sorted_array(size) + else: + random_array = MemoryArray.create_random_array(size, -100, 100) + sort_func(random_array) + MemoryManager.save_stats(size) + + MemoryManager.plot_stats(["cells", "compares", "writes"]) + +def swap(z: MemoryArray, i: int, j: int): + tmp = z[Literal(i)].value + z[Literal(i)] = z[Literal(j)] + z[Literal(j)].set(tmp) + +if __name__ == '__main__': + analyze_complexity(insert_sort, [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]) + analyze_complexity(insert_sort, [10, 20, 30, 40, 50, 60, 70, 80, 90, 100], True) diff --git a/vorlesung/02_elementares_sortieren/select_game.py b/vorlesung/02_elementares_sortieren/select_game.py new file mode 100644 index 0000000..8c65eb3 --- /dev/null +++ b/vorlesung/02_elementares_sortieren/select_game.py @@ -0,0 +1,41 @@ +import random +import pygame +from utils.game import Game +from utils.memory_array import MemoryArray +from select_sorting import select_sort_stepwise + +WHITE = (255, 255, 255) +BLUE = (0, 0, 255) + +class SelectGame(Game): + + def __init__(self): + super().__init__("Select Game", fps=60, size=(400, 400)) + random.seed() + l =list(range(1, 101)) + random.shuffle(l) + self.z = MemoryArray(l) + self.finished = False + self.sort_generator = select_sort_stepwise(self.z) + + def update_game(self): + if not self.finished: + try: + next(self.sort_generator) + except StopIteration: + self.finished = True + return True + + def draw_game(self): + self.screen.fill(WHITE) + for i, cell in enumerate(self.z): + x = 50 + i*3 + y = 350 - cell.value * 3 + pygame.draw.rect(self.screen, BLUE, (x, y, 3, 3)) + super().draw_game() + + +if __name__ == "__main__": + b = SelectGame() + b.run() + diff --git a/vorlesung/02_elementares_sortieren/select_sorting.py b/vorlesung/02_elementares_sortieren/select_sorting.py new file mode 100644 index 0000000..6f80f19 --- /dev/null +++ b/vorlesung/02_elementares_sortieren/select_sorting.py @@ -0,0 +1,58 @@ +from utils.memory_array import MemoryArray +from utils.memory_cell import MemoryCell +from utils.memory_manager import MemoryManager +from utils.memory_range import mrange +from utils.literal import Literal + +def select_sort_stepwise(z: MemoryArray): + n = z.length() + cur_min = MemoryCell() + for i in mrange(n): + cur_min.set(i) + for j in mrange(i.succ(), n): + if z[j] < z[cur_min]: + cur_min.set(j) + swap(z, i, int(cur_min)) + yield z + + +def select_sort(z: MemoryArray): + sort_generator = select_sort_stepwise(z) + while True: + try: + next(sort_generator) + except StopIteration: + break + +def sort_file(filename, sort_func): + z = MemoryArray.create_array_from_file(filename) + sort_func(z) + return z + + +def analyze_complexity(sort_func, sizes, presorted=False): + """ + Analysiert die Komplexität einer Sortierfunktion. + + :param sort_func: Die Funktion, die analysiert wird. + :param sizes: Eine Liste von Eingabegrößen für die Analyse. + """ + for size in sizes: + MemoryManager.purge() # Speicher zurücksetzen + if presorted: + random_array = MemoryArray.create_sorted_array(size) + else: + random_array = MemoryArray.create_random_array(size, -100, 100) + sort_func(random_array) + MemoryManager.save_stats(size) + + MemoryManager.plot_stats(["cells", "compares", "writes"]) + +def swap(z: MemoryArray, i: int, j: int): + tmp = z[Literal(i)].value + z[Literal(i)] = z[Literal(j)] + z[Literal(j)].set(tmp) + +if __name__ == '__main__': + analyze_complexity(select_sort, [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]) +# analyze_complexity(select_sort, [10, 20, 30, 40, 50, 60, 70, 80, 90, 100], True) From 36383991d6cb4876c07cc1fa68df79b30ab18015 Mon Sep 17 00:00:00 2001 From: Oliver Hofmann Date: Tue, 1 Apr 2025 14:55:47 +0200 Subject: [PATCH 2/3] fixed off by one in max seq --- praktika/01_max_folge/algorithms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/praktika/01_max_folge/algorithms.py b/praktika/01_max_folge/algorithms.py index ad77305..5bb3c9d 100644 --- a/praktika/01_max_folge/algorithms.py +++ b/praktika/01_max_folge/algorithms.py @@ -14,7 +14,7 @@ def max_sequence_1(z: MemoryArray): for i in mrange(n): for j in mrange(i, n): s.set(0) - for k in mrange(i, j): + for k in mrange(i, j.succ()): s += z[k] if s > m: m.set(s) From 74f118d11c235ccb7cdece8be7d5df990501bc03 Mon Sep 17 00:00:00 2001 From: Oliver Hofmann Date: Wed, 2 Apr 2025 11:13:30 +0200 Subject: [PATCH 3/3] succ / pred --- .idea/AlgoDatSoSe25.iml | 2 +- praktika/01_max_folge/algorithms.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.idea/AlgoDatSoSe25.iml b/.idea/AlgoDatSoSe25.iml index bf024fa..982282a 100644 --- a/.idea/AlgoDatSoSe25.iml +++ b/.idea/AlgoDatSoSe25.iml @@ -5,7 +5,7 @@ - + \ No newline at end of file diff --git a/praktika/01_max_folge/algorithms.py b/praktika/01_max_folge/algorithms.py index 5bb3c9d..f5f3ab9 100644 --- a/praktika/01_max_folge/algorithms.py +++ b/praktika/01_max_folge/algorithms.py @@ -42,12 +42,12 @@ def max_sequence_3(z: MemoryArray, l = None, r = None): if l is None: l = Literal(0) if r is None: - r = Literal(len(z)-1) + r = z.length().pred() if l == r: return z[l], l, r m = Literal((int(l) + int(r)) // 2) lm, ll, lr = max_sequence_3(z, l, m) - rm, rl, rr = max_sequence_3(z, Literal(int(m) + 1), r) + rm, rl, rr = max_sequence_3(z, m.succ(), r) zm, zl, zr = find_between(z, l, m, r) if lm >= rm and lm >= zm: return lm, ll, lr @@ -59,7 +59,7 @@ def find_between(z: MemoryArray, l, m, r): max_sum = MemoryCell(MIN_VALUE) s = MemoryCell(0) border = MemoryCell() - for i in mrange(m, int(l)-1, -1): + for i in mrange(m, l.pred(), -1): s += z[i] if s > max_sum: max_sum.set(s) @@ -68,7 +68,7 @@ def find_between(z: MemoryArray, l, m, r): left_border = Literal(border) max_sum = MemoryCell(MIN_VALUE) s.set(0) - for i in mrange(int(m) + 1, int(r)+1): + for i in mrange(m.succ(), r.succ()): s += z[i] if s > max_sum: max_sum.set(s) @@ -91,7 +91,7 @@ def max_sequence_4(z: MemoryArray): r.set(i) if curr_sum < Literal(0): curr_sum.set(0) - curr_left.set(int(i) + 1) + curr_left.set(i.succ()) return max_sum, l, r def example(max_sequence_func):