"""Modul zur Matrizenmultiplikation.""" from __future__ import annotations import math from tabulate import tabulate #test Matrix = list[list[float]] def matmul(a: Matrix, b: Matrix) -> Matrix: """Multipliziert zwei Matrizen a * b. Args: a: Erste Matrix der Dimension (m x n). b: Zweite Matrix der Dimension (n x p). Returns: Ergebnismatrix der Dimension (m x p). Raises: ValueError: Wenn die Matrizen leer sind, unregulär sind (ungleiche Zeilenlängen) oder die Innen Dimensionen nicht zusammenpassen (a.Zeilen != b.Spalten). """ if not a or not b: raise ValueError("Matrizen duerfen nicht leer sein.") rows_a = len(a) cols_a = len(a[0]) rows_b = len(b) cols_b = len(b[0]) for row in a: if len(row) != cols_a: raise ValueError("Matrix a ist nicht rechteckig.") for row in b: if len(row) != cols_b: raise ValueError("Matrix b ist nicht rechteckig.") if cols_a != rows_b: raise ValueError( f"Nicht passende Dimensionen: a ist {rows_a}x{cols_a}, " f"b ist {rows_b}x{cols_b} (a.Spalten muss b.Zeilen sein)." ) result: Matrix = [] for i in range(rows_a): new_row: list[float] = [] for j in range(cols_b): new_row.append(sum(a[i][k] * b[k][j] for k in range(cols_a))) result.append(new_row) return result def transpose(m: Matrix) -> Matrix: """Transponiert die gegebene Matrix. Args: m: Matrix von Dimension (rows x cols). Returns: Eine neue Matrix mit umgekehrter Dimension (cols x rows). """ if not m: raise ValueError("Matrix darf nicht leer sein.") rows = len(m) cols = len(m[0]) # überprüfen, ob die Matrix rechteckig ist for row in m: if len(row) != cols: raise ValueError("Matrix ist nicht rechteckig.") # Transponieren return [[m[r][c] for r in range(rows)] for c in range(cols)] def rot_2D(m: Matrix | float) -> Matrix: """Rotiert die Matrix um 90 Grad im Uhrzeigersinn. Falls ``m`` ein Zahlenwert ist, wird die Rotationsmatrix für den Winkel ``m`` (in Bogenmaß) zurückgegeben. Andernfalls wird die Matrix um 90° gedreht. Args: m: Eingabe‑Matrix oder Winkel in Radiant. Returns: Rotierte Matrix bzw. 2×2‑Rotationsmatrix. """ if isinstance(m, (int, float)): theta = float(m) c = math.cos(theta) s = math.sin(theta) return [[c, -s], [s, c]] # Ansonsten normal 90°‑Rotation (wie bisher) if not m: raise ValueError("Matrix darf nicht leer sein.") rows = len(m) cols = len(m[0]) for row in m: if len(row) != cols: raise ValueError("Matrix ist nicht rechteckig.") return [[m[row][col] for row in reversed(range(rows))] for col in range(cols)] if __name__ == "__main__": # Beispiel 1: klassischer Fall 2x3 * 3x2 -> 2x2 print(tabulate(rot_2D(1.0))) a1 = [[1, 2, 3], [4, 5, 6]] b1 = [[7, 8], [9, 10], [11, 12]] expected1 = [[58, 64], [139, 154]] got1 = matmul(a1, b1) assert got1 == expected1, f"Beispiel 1 fehlgeschlagen: {got1}" print("Beispiel 1 ok:", got1) # Beispiel 4: Transponieren einer 3x2 Matrix -> 2x3 m4 = [[1, 2], [3, 4], [5, 6]] expected4 = [[1, 3, 5], [2, 4, 6]] got4 = transpose(m4) assert got4 == expected4, f"Beispiel 4 fehlgeschlagen: {got4}" print("Beispiel 4 ok:", got4) # Beispiel 5: Transponieren einer Einheitsmatrix -> gleich e5 = [[1, 0, 0], [0, 1, 0], [0, 0, 1]] got5 = transpose(e5) assert got5 == e5, f"Beispiel 5 fehlgeschlagen: {got5}" print("Beispiel 5 ok:", got5) # Beispiel 6: Fehlerfall – transponieren leerer Matrix try: transpose([]) except ValueError as err: print("Beispiel 6 ok (Fehler erwartet):", err) m7 = [[1, 2, 3], [4, 5, 6]] expected7 = [[4, 1], [5, 2], [6, 3]]