Erster Stand

This commit is contained in:
erik detzel committed 2026-10-15 15:23:25 +02:00
commit 397ab45018
10 files changed
+315

No files matched your search

+3
View File
@@ -0,0 +1,3 @@
.venv/
__pycache__/
.env
+8
View File
@@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
+6
View File
@@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.venv" />
</content>
<orderEntry type="jdk" jdkName="Python 3.13 (matrixmania)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.13 (matrixmania)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.13 (matrixmania)" project-jdk-type="Python SDK" />
</project>
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/matrixmania.iml" filepath="$PROJECT_DIR$/.idea/matrixmania.iml" />
</modules>
</component>
</project>
Generated
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
+4
View File
@@ -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`.
+260
View File
@@ -0,0 +1,260 @@
"""Provides matmul, transpose, and rotate functions for 2‑D numeric matrices."""
from __future__ import annotations
import math
from collections.abc import Iterable
from typing import Literal
__all__ = ["matmul", "rot_2d", "rotate", "transpose"]
_NUMERIC_TYPES = (int, float)
def _validate_matrix(
matrix: Iterable[Iterable[object]], name: str
) -> list[list[float]]:
"""Validate that *matrix* is a rectangular list of lists of numeric values.
Returns the matrix converted to ``list[list[float]]`` if valid.
Raises ``TypeError`` for non‑numeric values or if any element is a ``bool``.
Raises ``ValueError`` for empty matrices, empty rows, or ragged matrices.
"""
try:
rows = list(map(list, matrix))
except TypeError as exc:
raise TypeError(f"{name} must be a sequence of sequences") from exc
if not rows:
raise ValueError(f"{name} must not be empty")
if not rows[0]:
raise ValueError(f"{name} must not contain empty rows")
row_len = len(rows[0])
for row in rows:
if len(row) != row_len:
raise ValueError(f"{name} must be rectangular (row lengths differ)")
for value in row:
if isinstance(value, bool):
raise TypeError(f"{name} contains boolean value {value!r}")
if not isinstance(value, _NUMERIC_TYPES):
raise TypeError(f"{name} contains non‑numeric value {value!r}")
return [[float(value) for value in row] for row in rows]
def matmul(a: list[list[float]], b: list[list[float]]) -> list[list[float]]:
"""Multiply two matrices ``a`` and ``b``.
Parameters
----------
a: list[list[float]]
Left operand matrix.
b: list[list[float]]
Right operand matrix.
Returns
-------
list[list[float]]
The product matrix.
Raises
------
ValueError
If matrix dimensions are incompatible or if a matrix is ragged.
TypeError
If inputs are not sequences of numeric values.
"""
a_matrix = _validate_matrix(a, "a")
b_matrix = _validate_matrix(b, "b")
num_rows_a = len(a_matrix)
num_cols_a = len(a_matrix[0])
num_rows_b = len(b_matrix)
num_cols_b = len(b_matrix[0])
if num_cols_a != num_rows_b:
raise ValueError(
f"Incompatible dimensions: a has {num_cols_a} columns; "
f"b has {num_rows_b} rows"
)
result: list[list[float]] = [
[0.0 for _ in range(num_cols_b)] for _ in range(num_rows_a)
]
for i in range(num_rows_a):
for j in range(num_cols_b):
dot_product = 0.0
for k in range(num_cols_a):
dot_product += a_matrix[i][k] * b_matrix[k][j]
result[i][j] = dot_product
return result
def transpose(matrix: list[list[float]]) -> list[list[float]]:
"""Return the transpose of *matrix*.
Parameters
----------
matrix: list[list[float]]
Input matrix as a list of rows.
Returns
-------
list[list[float]]
Transposed matrix.
Raises
------
TypeError, ValueError
Propagated from :func:`_validate_matrix` when the input is not a
rectangular numeric matrix.
"""
m_matrix = _validate_matrix(matrix, "matrix")
rows, cols = len(m_matrix), len(m_matrix[0])
return [[m_matrix[i][j] for i in range(rows)] for j in range(cols)]
def rotate(matrix: list[list[float]]) -> list[list[float]]:
"""Return the matrix rotated 90° clockwise.
Parameters
----------
matrix: list[list[float]]
Input matrix as a list of rows.
Returns
-------
list[list[float]]
Rotated matrix.
Raises
------
TypeError, ValueError
Propagated from :func:`_validate_matrix` when the input is not a
rectangular numeric matrix.
"""
m_matrix = _validate_matrix(matrix, "matrix")
return [list(row) for row in zip(*reversed(m_matrix))]
def rot_2d(angle: float, unit: Literal["deg", "rad"] = "deg") -> list[list[float]]:
"""Return a 2×2 rotation matrix for a given angle.
Parameters
----------
angle : float
Rotation angle.
unit : {"deg", "rad"}, default "deg"
Whether *angle* is given in degrees or radians.
Returns
-------
list[list[float]]
2×2 rotation matrix.
"""
theta = math.radians(angle) if unit == "deg" else angle
c = math.cos(theta)
s = math.sin(theta)
return [[c, -s], [s, c]]
def print_matrix(title: str, matrix: list[list[float]]) -> None:
"""Print a title followed by each matrix row on its own line."""
print(title)
for row in matrix:
print(" ", row)
if __name__ == "__main__":
# Matrix multiplication tests
a1 = [[1, 2, 3], [4, 5, 6]]
b1 = [[7, 8], [9, 10], [11, 12]]
print_matrix("Matrix A:", a1)
print_matrix("Matrix B:", b1)
product = matmul(a1, b1)
print_matrix("A x B:", product)
assert product == [[58, 64], [139, 154]], "matmul first test failed"
print()
a2 = [[1, 2], [3, 4]]
b2 = [[5, 6], [7, 8]]
print_matrix("Matrix A:", a2)
print_matrix("Matrix B:", b2)
product = matmul(a2, b2)
print_matrix("A x B:", product)
assert product == [[19, 22], [43, 50]], "matmul second test failed"
print()
identity = [[1, 0], [0, 1]]
print_matrix("Matrix A:", a2)
print_matrix("Identity matrix:", identity)
product = matmul(a2, identity)
print_matrix("A x Identity:", product)
assert product == a2, "matmul identity test failed"
print()
# Dimension mismatch must raise ValueError
try:
matmul([[1, 2]], [[1, 2]])
except ValueError as error:
print(f"Expected error for mismatched dimensions: {error}")
else:
raise AssertionError("matmul did not raise ValueError")
print()
# Transpose tests
print_matrix("Matrix:", a1)
transposed = transpose(a1)
print_matrix("Transposed:", transposed)
assert transposed == [[1, 4], [2, 5], [3, 6]], "transpose first test failed"
assert transpose(transposed) == a1, "double transpose failed"
print()
column = [[1], [2], [3]]
print_matrix("Matrix:", column)
transposed = transpose(column)
print_matrix("Transposed:", transposed)
assert transposed == [[1, 2, 3]], "transpose column test failed"
print()
# Rotation tests
print_matrix("Matrix:", a1)
rotated = rotate(a1)
print_matrix("Rotated 90 degrees clockwise:", rotated)
assert rotated == [[4, 1], [5, 2], [6, 3]], "rotate 2x3 test failed"
print()
square = [[1, 2], [3, 4]]
print_matrix("Matrix:", square)
rotated = rotate(square)
print_matrix("Rotated 90 degrees clockwise:", rotated)
assert rotated == [[3, 1], [4, 2]], "rotate square test failed"
print()
# Four rotations must return the original matrix
rotated = square
for _ in range(4):
rotated = rotate(rotated)
print_matrix("Square matrix rotated four times:", rotated)
assert rotated == square, "four rotations did not return original"
print()
# 2D rotation matrix tests
rotation_0 = rot_2d(0)
print_matrix("Rotation matrix for 0 degrees:", rotation_0)
assert rotation_0 == [[1.0, -0.0], [0.0, 1.0]], "rot_2d 0 degrees failed"
print()
rotation_90 = rot_2d(90)
print_matrix("Rotation matrix for 90 degrees:", rotation_90)
point = [[1], [0]]
rotated_point = matmul(rotation_90, point)
print_matrix("Point (1, 0) rotated by 90 degrees:", rotated_point)
assert math.isclose(rotated_point[0][0], 0.0, abs_tol=1e-9), "rot_2d x failed"
assert math.isclose(rotated_point[1][0], 1.0, abs_tol=1e-9), "rot_2d y failed"
print()
print("All tests passed.")
+3
View File
@@ -0,0 +1,3 @@
[project]
name = "matrixmania"
version = "0.1.0"