forked from hofmannol/AlgoDatSoSe25
116 lines
4.3 KiB
Python
116 lines
4.3 KiB
Python
import logging
|
|
logger = logging.getLogger(__name__)
|
|
# logging.basicConfig(level=logging.DEBUG)
|
|
|
|
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
|
|
|
|
def example():
|
|
initial = [6, 5, 3, 8, 1, 7, 2, 4]
|
|
# initial = [-6, -5, -3, -8, 1, 7, 2, 4]
|
|
toSort = MemoryArray(initial)
|
|
# init_from_size not accessible?
|
|
sorted = MemoryArray([-1] * len(initial))
|
|
mergeSort(toSort, sorted)
|
|
logger.debug(f"sorted {sorted} vs initial {initial}")
|
|
assert all(sorted[Literal(i)] == Literal(i+1) for i in range(len(initial))), "Array not sorted correctly"
|
|
|
|
analyze_complexity(mergeSort, [10, 20, 30, 40, 50, 60, 70, 80, 90, 100])
|
|
|
|
def merge(left: MemoryArray, right: MemoryArray, sort: MemoryArray):
|
|
pointerLeft = MemoryCell(0)
|
|
pointerRight = MemoryCell(0)
|
|
pointerSort = MemoryCell(0)
|
|
|
|
compare = lambda x, y: x <= y
|
|
|
|
logger.debug(f"Merging left {left} with right {right} in sort {sort}")
|
|
|
|
while pointerLeft < left.length() and pointerRight < right.length():
|
|
if compare(left[pointerLeft], right[pointerRight]):
|
|
sort[pointerSort] = left[pointerLeft]
|
|
pointerLeft += Literal(1)
|
|
else:
|
|
sort[pointerSort] = right[pointerRight]
|
|
pointerRight += Literal(1)
|
|
|
|
logger.debug(f"Now are at sort {sort} with {pointerLeft} (l) and {pointerRight} (r)")
|
|
pointerSort += Literal(1)
|
|
|
|
# Consume remaining elements
|
|
while pointerLeft < left.length():
|
|
logger.debug(f"Consuming left {left} from {pointerSort} at {pointerLeft}")
|
|
sort[pointerSort] = left[pointerLeft]
|
|
pointerLeft += Literal(1)
|
|
pointerSort += Literal(1)
|
|
|
|
while pointerRight < right.length():
|
|
logger.debug(f"Consuming right {right} from {pointerSort} at {pointerRight}")
|
|
sort[pointerSort] = right[pointerRight]
|
|
pointerRight += Literal(1)
|
|
pointerSort += Literal(1)
|
|
|
|
# Sort the array passed as "toSort" and place the result in array "sort"
|
|
# Does not change the original Array
|
|
def mergeSort(toSort: MemoryArray, sort: MemoryArray):
|
|
logger.debug(toSort)
|
|
toSortLength = MemoryCell(toSort.length())
|
|
|
|
# Splitting
|
|
# Rec-Term -> Reached single Element. Single Element is already sorted so we place it!
|
|
if toSortLength <= Literal(1):
|
|
# still working for empty array
|
|
if toSortLength == Literal(1):
|
|
sort[Literal(0)] = toSort[Literal(0)]
|
|
return
|
|
|
|
# TODO - Use a global var or a reference to an array passed as argument for this
|
|
# TODO - Tried non-temp-array approach with alternating Work-Arrays passed to the function, but made code really unreadable. Decided not worth it for now
|
|
# Temporary Arrays to hold the split arrays
|
|
mid : Literal = toSortLength // Literal(2)
|
|
left : MemoryArray = MemoryArray([toSort[i] for i in mrange(mid)])
|
|
right : MemoryArray = MemoryArray([toSort[i] for i in mrange(mid, toSortLength)])
|
|
|
|
# Temporary arrays for sorted halves
|
|
leftSort = MemoryArray([-1] * mid.get())
|
|
rightSort = MemoryArray([-1] * (toSortLength - mid).get())
|
|
|
|
# Split further
|
|
mergeSort(left, leftSort)
|
|
mergeSort(right, rightSort)
|
|
|
|
# Recreate the array from the seperated parts
|
|
merge(leftSort, rightSort, sort)
|
|
|
|
def analyze_complexity(fn, sizes):
|
|
"""
|
|
Analysiert die Komplexität einer maximalen Teilfolgenfunktion.
|
|
|
|
:param max_sequence_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
|
|
random_array = MemoryArray.create_random_array(size, -100, 100)
|
|
other_array = MemoryArray([-1] * size)
|
|
fn(random_array, other_array)
|
|
MemoryManager.save_stats(size)
|
|
|
|
MemoryManager.plot_stats(["cells", "adds", "compares"])
|
|
|
|
|
|
if __name__ == '__main__':
|
|
# For debug, assert if working and complexity-analysis
|
|
# example()
|
|
|
|
for filename in ["data/seq0.txt", "data/seq1.txt", "data/seq2.txt", "data/seq3.txt"]:
|
|
print(filename)
|
|
toSort = MemoryArray.create_array_from_file(filename)
|
|
sorted = MemoryArray([-1] * toSort.length().get())
|
|
mergeSort(toSort, sorted)
|
|
print(sorted)
|