diff --git a/praktika/02_merge_sort/merge_game.py b/praktika/02_merge_sort/merge_game.py new file mode 100644 index 0000000..60270ad --- /dev/null +++ b/praktika/02_merge_sort/merge_game.py @@ -0,0 +1,42 @@ +import random +import pygame +from utils.algo_game import Game +from utils.algo_context import AlgoContext +from utils.algo_array import Array +from merge_sorting import merge_sort_stepwise + +WHITE = (255, 255, 255) +BLUE = (0, 0, 255) + +class MergeGame(Game): + + def __init__(self): + super().__init__("Merge Game", fps=10, size=(400, 400)) + random.seed() + l = list(range(1, 101)) + random.shuffle(l) + self.ctx = AlgoContext() + self.z = Array(l, self.ctx) + self.finished = False + self.sort_generator = merge_sort_stepwise(self.z, self.ctx) + + 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__": + s = MergeGame() + s.run() diff --git a/praktika/02_merge_sort/merge_sorting.py b/praktika/02_merge_sort/merge_sorting.py new file mode 100644 index 0000000..57f6c25 --- /dev/null +++ b/praktika/02_merge_sort/merge_sorting.py @@ -0,0 +1,71 @@ +from utils.algo_array import Array +from utils.algo_context import AlgoContext +from utils.algo_range import Range +from time import perf_counter as pfc + + +def merge_sort_stepwise(z: Array, ctx: AlgoContext, l=None, r=None, buffer=None): + if l is None: + l = 0 + if r is None: + r = len(z) - 1 + if buffer is None: + buffer = Array([0] * len(z), ctx) + if l < r: + m = (l + r) // 2 + yield from merge_sort_stepwise(z, ctx, l, m, buffer) + yield from merge_sort_stepwise(z, ctx, m + 1, r, buffer) + yield from merge(z, ctx, l, m, r, buffer) + +def merge(z: Array, ctx: AlgoContext, l: int, m: int, r: int, buffer: Array): + i, j, k = l, m + 1, l + while i <= m and j <= r: + if z[i] <= z[j]: + buffer[k] = z[i] + i += 1 + else: + buffer[k] = z[j] + j += 1 + k += 1 + while i <= m: + buffer[k] = z[i] + i += 1 + k += 1 + while j <= r: + buffer[k] = z[j] + j += 1 + k += 1 + for k in Range(l, r + 1): + z[k] = buffer[k] + yield z + +def merge_sort(z: Array, ctx: AlgoContext): + for _ in merge_sort_stepwise(z, ctx): + pass + +def sort_file(filename, sort_func): + ctx = AlgoContext() + z = Array.from_file(filename, ctx) + sort_func(z, ctx) + return z + +def analyze_complexity(sort_func, sizes, presorted=False): + ctx = AlgoContext() + for size in sizes: + ctx.reset() + if presorted: + z = Array.sorted(size, ctx) + else: + z = Array.random(size, -100, 100, ctx) + sort_func(z, ctx) + ctx.save_stats(size) + + ctx.plot_stats(["comparisons", "writes"]) + +if __name__ == '__main__': + analyze_complexity(merge_sort, [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]) + for filename in ["data/seq0.txt", "data/seq1.txt", "data/seq2.txt", "data/seq3.txt"]: + print(filename) + start = pfc() + print(sort_file(filename, merge_sort)) + print(f"Dauer: {pfc() - start:.4f}s")