2026-04-28 11:48:59 +02:00

147 lines
3.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from utils.algo_context import AlgoContext
from utils.algo_array import Array
from utils.algo_int import Int
from utils.algo_range import Range
def max_sequence_1(z: Array, ctx: AlgoContext):
"""O(n³) dreifach verschachtelte Schleife."""
n = len(z)
m = Int(float('-inf'), ctx)
s = Int(0, ctx)
l = Int(0, ctx)
r = Int(0, ctx)
for i in Range(n):
for j in Range(int(i), n):
s.set(0)
for k in Range(int(i), int(j)):
s += z[k]
if s > m:
m.set(s)
l.set(Int(int(i), ctx))
r.set(Int(int(j), ctx))
return m, l, r
def max_sequence_2(z: Array, ctx: AlgoContext):
"""O(n²) doppelt verschachtelte Schleife."""
n = len(z)
m = Int(float('-inf'), ctx)
s = Int(0, ctx)
left = Int(0, ctx)
right = Int(0, ctx)
for i in Range(n):
s.set(0)
for j in Range(int(i), n):
s += z[j]
if s > m:
m.set(s)
left.set(Int(int(i), ctx))
right.set(Int(int(j), ctx))
return m, left, right
def _finde_zwischen(z: Array, ctx: AlgoContext, l: int, m: int, r: int):
"""Hilfsfunktion für max_sequence_3: findet die maximale Teilsumme,
die die Mitte m überschreitet (3. Fall von Teile-und-Herrsche)."""
links_max = Int(float('-inf'), ctx)
s = Int(0, ctx)
links = Int(l, ctx)
for i in Range(m, l - 1, -1):
s += z[i]
if s > links_max:
links_max.set(s)
links.set(Int(int(i), ctx))
rechts_max = Int(float('-inf'), ctx)
s.set(0)
rechts = Int(m + 1, ctx)
for i in Range(m + 1, r + 1):
s += z[i]
if s > rechts_max:
rechts_max.set(s)
rechts.set(Int(int(i), ctx))
return links_max + rechts_max, links, rechts
def max_sequence_3(z: Array, ctx: AlgoContext, l: int = None, r: int = None):
"""O(n ld n) Teile-und-Herrsche."""
if l is None:
l = 0
if r is None:
r = len(z) - 1
if l == r:
return z[l], Int(l, ctx), Int(r, ctx)
m = (l + r) // 2
links_max, links_l, links_r = max_sequence_3(z, ctx, l, m)
rechts_max, rechts_l, rechts_r = max_sequence_3(z, ctx, m + 1, r)
zwi_max, zwi_l, zwi_r = _finde_zwischen(z, ctx, l, m, r)
if links_max >= rechts_max and links_max >= zwi_max:
return links_max, links_l, links_r
if rechts_max >= links_max and rechts_max >= zwi_max:
return rechts_max, rechts_l, rechts_r
return zwi_max, zwi_l, zwi_r
def max_sequence_4(z: Array, ctx: AlgoContext):
"""O(n) Kadane's Algorithmus."""
n = len(z)
m = Int(float('-inf'), ctx)
cur_sum = Int(0, ctx)
cur_left = Int(0, ctx)
left = Int(0, ctx)
right = Int(0, ctx)
for i in Range(n):
cur_sum += z[i]
if cur_sum > m:
m.set(cur_sum)
left.set(cur_left)
right.set(Int(int(i), ctx))
if cur_sum < 0:
cur_sum.set(0)
cur_left.set(Int(int(i) + 1, ctx))
return m, left, right
def example(max_sequence_func):
ctx = AlgoContext()
data = [-59, 52, 46, 14, -50, 58, -87, -77, 34, 15]
print(data)
z = Array(data, ctx)
m, l, r = max_sequence_func(z, ctx)
print(m, l, r)
def seq(filename, max_sequence_func):
ctx = AlgoContext()
z = Array.from_file(filename, ctx)
m, l, r = max_sequence_func(z, ctx)
print(m, l, r)
def analyze_complexity(max_sequence_func, sizes):
ctx = AlgoContext()
for size in sizes:
ctx.reset()
z = Array.random(size, -100, 100, ctx)
max_sequence_func(z, ctx)
ctx.save_stats(size)
ctx.plot_stats(["additions"])
if __name__ == '__main__':
example(max_sequence_3)
for filename in ["data/seq0.txt", "data/seq1.txt"]:
print(filename)
seq(filename, max_sequence_3)
analyze_complexity(max_sequence_3, [10, 20, 30, 40, 50, 60, 70, 80, 90, 100])