From 2019d5897c2b52e710b1370df70c4d8e2861a313 Mon Sep 17 00:00:00 2001 From: Ziemowit Skowronek Date: Wed, 21 Oct 2026 11:04:39 +0200 Subject: [PATCH] Erster Stand: Matrixberechnungen und Projektstruktur --- .gitignore | 4 ++ AGENTS.md | 4 ++ compute.py | 109 +++++++++++++++++++++++++++++++++++++++++++++++++ pyproject.toml | 7 ++++ 4 files changed, 124 insertions(+) create mode 100644 .gitignore create mode 100644 AGENTS.md create mode 100644 compute.py create mode 100644 pyproject.toml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5860384 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.venv/ +__pycache__/ +.env +.ruff_cache/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..7256709 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,4 @@ +# Regeln für dieses Projekt +- Code nach PEP 8, Zeilenlänge maximal 88 Zeichen. +- Jede Funktion und Methode hat einen Docstring und Type Hints. +- Vor jedem Commit: `ruff check` und `ruff format`. diff --git a/compute.py b/compute.py new file mode 100644 index 0000000..807ca01 --- /dev/null +++ b/compute.py @@ -0,0 +1,109 @@ +"""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.") diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..0371289 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,7 @@ +[project] +name = "matrixmania" +version = "0.1.0" +requires-python = ">=3.10" + +[tool.ruff] +line-length = 88