#Katzenaufgabe: 1. funktionierender Stand war committed. #2. in compute.py und pyproject.toml absichtlich Änderungen/Quatsch gemacht. #3. Diese Änderungen nicht committed. #4. ↩ Git → Uncommitted Changes → Rollback ausgeführt. #5. Danach waren die Katzen-Änderungen wieder verschwunden und die Dateien wieder wie vorher. #Dann: Katze erledigt. # Matrixfunktionen für das Projekt MatrixMania #Was die Aufgabe war: #opencode verwenden und python code generieren lassen #den generierten code auf funktionalität und clean code prüfen #in compute.py sollten wir eine matrixmultiplikation anwenden #und das modul danach um eine Transposition und 2d rotationmatrix erweitern #gefordert: type hints, docstrings und fehlerbehandlung mit valueerror #auf kurz: #Agent generiert code #wir prüfen ihn selbst #pep 8 beachten #verständlicher name #type hints #docstrings #fehler sinnvoll behandeln #mindestens einen verbesserungspunkt am Agentencode erkennen """Matrix-Operationen ohne externe Bibliotheken (reine Python-Listen).""" import math from math import cos, sin from tabulate import tabulate #from typing import List #da wir eine aktuelle python version verwenden wäre eingebaute schreibweise mit list[float] beser Matrix = list[list[float]] #Matrix ist hier ein typ alias für eine verschachtelte liste aus zahlen dadurch werden die type hints lesbarer #Funktion matmul: zwei matrizen multiplizieren def matmul(matrix_a: Matrix, matrix_b: Matrix) -> Matrix: #jetzt kommt mein docstring hier dokumentiert open code: #was macht die funktion? #wleche parameter bekommt sie? (args) #was gibt sie zurück?(returns) #welche fehler können auftreten?(raises) """Multipliziere zwei Matrizen ``A * B``. # Args: matrix_a: Linke Matrix der Form ``(m, n)``. matrix_b: Rechte Matrix der Form ``(n, p)``. Returns: Die Produktmatrix der Form ``(m, p)``. Raises: ValueError: Wenn ``matrix_a`` weniger Spalten hat, als ``matrix_b`` Zeilen hat, oder wenn eine der Matrizen leer ist. """ if not matrix_a or not matrix_b: #sicherheitsprüfung wenn matrix a leer oder matrix b leer ist, breche ab raise ValueError("Matrizen dürfen nicht leer sein.") #fehler wird absichtlich ausgeführt #die größe wird bestimmt rows_a = len(matrix_a) cols_a = len(matrix_a[0]) rows_b = len(matrix_b) cols_b = len(matrix_b[0]) #Dimensionsprüfung #hier ist auch mein zweiter verbesserungspunkt siehe ausführlich unten if cols_a != rows_b: raise ValueError( "Breite der ersten Matrix muss der Höhe der zweiten entsprechen." ) result: Matrix = [] for i in range(rows_a): #i steht für die zeile von a result_row: list[float] = [] for j in range(cols_b): #j steht für die spalte von b total = 0 for k in range(cols_a): #k läuft durch die einszlnen werte die miteinander multipliziert und addiert werden total += matrix_a[i][k] * matrix_b[k][j] #"nimm einen wert aus der aktuellen zeile von a multipliziere ihn mit den passenden wert aus der aktuellen spalte von b und addiere das ergebnis zu total result_row.append(total) #fügt die fertige zeile zur ergebnismatrix hinzu result.append(result_row) return result #Zeilen und Spalten einer Matrix vertauschen def transpose(matrix: Matrix) -> Matrix: """Transponiere eine Matrix (Zeilen werden zu Spalten). Args: matrix: Nicht leere, rechteckige Matrix. Returns: Die transponierte Matrix. Raises: ValueError: Wenn die Matrix leer ist oder die Zeilen unterschiedlich viele Spalten enthalten. """ if not matrix or not matrix[0]: raise ValueError("Die Matrix darf nicht leer sein.") num_cols = len(matrix[0]) if any(len(row) != num_cols for row in matrix): raise ValueError("Alle Zeilen müssen gleich viele Spalten haben.") return [[matrix[row][col] for row in range(len(matrix))] for col in range(num_cols)] #Rotationsmatrix für einen Winkel erzeugen def rot_2D(theta: float) -> Matrix: """Erzeuge die 2D-Rotationsmatrix für einen Winkel ``theta``. Args: theta: Rotationswinkel im Bogenmaß. Returns: Die Rotationsmatrix ``[[cos(theta), -sin(theta)], [sin(theta), cos(theta)]]``. """ cosine = math.cos(theta) sine = math.sin(theta) return [[cosine, -sine], [sine, cosine]] def rot_3D(angle: float, axis: str) -> list[list[float]]: """Erzeugt eine Rotationsmatrix für eine Drehung im 3D-Raum. Args: angle: Drehwinkel im Bogenmaß. axis: Drehachse "x", "y" oder "z". Returns: Die zur Achse passende 3x3-Rotationsmatrix. Raises: ValueError: Wenn axis weder "x", "y" noch "z" ist. Formeln mit c = cos(angle) und s = sin(angle): Rotation um die x-Achse: [1, 0, 0] [0, c, -s] [0, s, c] Rotation um die y-Achse: [ c, 0, s] [ 0, 1, 0] [-s, 0, c] Rotation um die z-Achse: [c, -s, 0] [s, c, 0] [0, 0, 1] """ c = cos(angle) s = sin(angle) if axis == "x": return [ [1.0, 0.0, 0.0], [0.0, c, -s], [0.0, s, c], ] if axis == "y": return [ [c, 0.0, s], [0.0, 1.0, 0.0], [-s, 0.0, c], ] if axis == "z": return [ [c, -s, 0.0], [s, c, 0.0], [0.0, 0.0, 1.0], ] raise ValueError("axis muss 'x', 'y' oder 'z' sein.") def project_ortho( point: tuple[float, float, float], scale: float = 1, ) -> tuple[float, float]: """Projiziert einen 3D-Punkt auf die xy-Ebene und skaliert ihn.""" # Die ersten beiden Koordinaten des Punktes auslesen. # Python beginnt beim Zählen mit 0. x = point[0] y = point[1] # Die dritte Koordinate point[2] ist z. # Für diese Projektion brauchen wir sie nicht. # x und y skalieren und als Tupel zurückgeben. return (x * scale, y * scale) def project_perspective( point: tuple[float, float, float], focal_length: float = 1.0, scale: float = 1.0, camera_distance: float = 4.0, ) -> tuple[float, float]: """Projiziert einen 3D-Punkt perspektivisch auf eine 2D-Ebene.""" # Wir verteilen die drei Koordinaten auf einzelne Variablen. x, y, z = point # Die Tiefe des Punktes wird um den Kameraabstand verschoben. depth = z + camera_distance # Durch 0 darf nicht geteilt werden. # Ein Punkt auf der Kameraebene kann so nicht projiziert werden. if depth == 0: raise ValueError( "Der Punkt darf nicht auf der Kameraebene liegen." ) # Wir berechnen die horizontalen und vertikalen Bildschirmkoordinaten. projected_x = x * focal_length / depth * scale projected_y = y * focal_length / depth * scale # Aus dem 3D-Punkt wird ein 2D-Punkt. return projected_x, projected_y if __name__ == "__main__": #führe den testcode nur aus wenn compute.py direkt gestartet wird matrix_a = [ [3, 4, -1, 4], [-2, 2, 5, 1], ] matrix_b = [ [1, 3, -2], [2, 5, 1], [-1, 4, -4], [2, 3, 6], ] matrix_c = matmul(matrix_a, matrix_b) print("Ergebnis C = A * B:") for row in matrix_c: print(row) matrix = [ [1, 2, 3], [4, 5, 6], ] print("\nTransponierte Matrix:") for row in transpose(matrix): print(row) print("\nRotationsmatrix für 90 Grad (pi / 2):") for row in rot_2D(math.pi / 2): print(row) print(tabulate(rot_2D(1.0))) #Code Beurteilung durch opencode generiert #1. Der matmul-DocString sagt "weniger Spalten", obwohl der Code allgemein auf != prüft #Das sollte präziser dokumentiert werden weil zb 4 != 3 ist True aber ValueError #der Code prüft nicht weniger sondern generell nicht gleich #2.opencode verwendet noch typing.list obwohl meine python version schon die #moderne Schreibweise mit list[...] möglich ist und sogar im skript verwendet wird