"""Matrixberechnungen.""" from math import cos, isclose, radians, sin Matrix = list[list[int | float]] def validate_matrix(matrix: Matrix, name: str = "matrix") -> tuple[int, int]: """Prüfe eine Matrix und liefere ihre Zeilen- und Spaltenzahl. Raises: TypeError: Bei falschen Containertypen oder Einträgen, die keine int- oder float-Werte sind, einschließlich bool. ValueError: Bei leeren Matrizen, leeren Zeilen oder unterschiedlich langen Zeilen. """ if not isinstance(matrix, list): raise TypeError(f"{name} muss eine Liste von Listen sein.") if not matrix: raise ValueError(f"{name} darf nicht leer sein.") if any(not isinstance(row, list) for row in matrix): raise TypeError(f"Jede Zeile von {name} muss eine Liste sein.") columns = len(matrix[0]) if columns == 0: raise ValueError(f"{name} darf keine leeren Zeilen enthalten.") if any(len(row) != columns for row in matrix): raise ValueError(f"{name} muss rechteckig sein.") if any( isinstance(value, bool) or not isinstance(value, (int, float)) for row in matrix for value in row ): raise TypeError( f"Alle Einträge von {name} müssen int oder float sein, ohne bool." ) return len(matrix), columns def matmul(left: Matrix, right: Matrix) -> Matrix: """Multipliziere zwei Matrizen mit passenden Dimensionen.""" _, left_columns = validate_matrix(left, "left") right_rows, right_columns = validate_matrix(right, "right") if left_columns != right_rows: raise ValueError( "Die Spaltenzahl von left muss der Zeilenzahl von right entsprechen " f"({left_columns} != {right_rows})." ) return [ [ sum(left_row[index] * right[index][column] for index in range(left_columns)) for column in range(right_columns) ] for left_row in left ] def transpose(matrix: Matrix) -> Matrix: """Vertausche die Zeilen und Spalten einer Matrix.""" _, column_count = validate_matrix(matrix) return [[row[column] for row in matrix] for column in range(column_count)] def rot_2D(angle: float) -> Matrix: """Erzeuge eine zweidimensionale Rotationsmatrix zum Winkel im Bogenmaß.""" return [ [cos(angle), -sin(angle)], [sin(angle), cos(angle)], ] if __name__ == "__main__": integer_product = matmul([[1, 2], [3, 4]], [[5, 6], [7, 8]]) assert integer_product == [[19, 22], [43, 50]] print("Beispiel 1:", integer_product) rectangular_product = matmul( [[1, 2, 3], [4, 5, 6]], [[7, 8], [9, 10], [11, 12]], ) assert rectangular_product == [[58, 64], [139, 154]] print("Beispiel 2:", rectangular_product) float_product = matmul([[0.5, 1.5]], [[2.0], [4.0]]) assert float_product == [[7.0]] print("Beispiel 3:", float_product) transposed_matrix = transpose([[1, 2, 3], [4, 5, 6]]) assert transposed_matrix == [[1, 4], [2, 5], [3, 6]] print("Transponiert:", transposed_matrix) rotated_point = matmul(rot_2D(radians(90)), [[1], [0]]) assert isclose(rotated_point[0][0], 0, abs_tol=1e-9) assert isclose(rotated_point[1][0], 1, abs_tol=1e-9) print("Rotation um 90°:", rotated_point) clockwise_point = matmul(rot_2D(radians(-90)), [[0], [1]]) assert isclose(clockwise_point[0][0], 1, abs_tol=1e-9) assert isclose(clockwise_point[1][0], 0, abs_tol=1e-9) print("Rotation um -90°:", clockwise_point) try: matmul([[1, 2]], [[3, 4]]) except ValueError: print("Nicht passende Dimensionen: ValueError wie erwartet.") else: raise AssertionError("Bei nicht passenden Dimensionen fehlt der ValueError.")