Files

144 lines
3.8 KiB
Python

import math
def _is_rectangular(matrix: list[list[float]]) -> bool:
"""Check whether a matrix is non-empty and rectangular."""
if not matrix:
return False
first_length = len(matrix[0])
return first_length > 0 and all(
len(row) == first_length for row in matrix
)
def matmul(
a: list[list[float]],
b: list[list[float]],
) -> list[list[float]]:
"""Multiply two matrices and return their product.
Raises:
ValueError: If a matrix is invalid or dimensions do not match.
"""
if not _is_rectangular(a) or not _is_rectangular(b):
raise ValueError("Both matrices must be non-empty and rectangular.")
if len(a[0]) != len(b):
raise ValueError("Number of columns in a must equal rows in b.")
result = []
for row in a:
result_row = []
for column_index in range(len(b[0])):
total = sum(
row[k] * b[k][column_index]
for k in range(len(b))
)
result_row.append(total)
result.append(result_row)
return result
def transpose(matrix: list[list[float]]) -> list[list[float]]:
"""Return the transpose of a matrix.
Raises:
ValueError: If the matrix is invalid.
"""
if not _is_rectangular(matrix):
raise ValueError("Matrix must be non-empty and rectangular.")
return [
[matrix[row][column] for row in range(len(matrix))]
for column in range(len(matrix[0]))
]
def rot_2D(theta: float) -> list[list[float]]:
"""Create a 2D rotation matrix for an angle in radians."""
cos_theta = math.cos(theta)
sin_theta = math.sin(theta)
return [
[cos_theta, -sin_theta],
[sin_theta, cos_theta],
]
def rotate(matrix: list[list[float]]) -> list[list[float]]:
"""Rotate a matrix 90 degrees clockwise.
Raises:
ValueError: If the matrix is invalid.
"""
if not _is_rectangular(matrix):
raise ValueError("Matrix must be non-empty and rectangular.")
return [
[
matrix[row][column]
for row in range(len(matrix) - 1, -1, -1)
]
for column in range(len(matrix[0]))
]
if __name__ == "__main__":
# Test 1: Matrix multiplication
a = [[1, 2, 3], [4, 5, 6]]
b = [[7, 8], [9, 10], [11, 12]]
assert matmul(a, b) == [[58, 64], [139, 154]]
print("Matrix multiplication: passed")
print(matmul(a, b))
# Test 2: Matrix multiplication with another example
assert matmul([[1, 2]], [[3], [4]]) == [[11]]
print("Second multiplication test: passed")
# Test 3: Transpose
matrix = [[1, 2, 3], [4, 5, 6]]
assert transpose(matrix) == [[1, 4], [2, 5], [3, 6]]
print("Transpose: passed")
# Test 4: Rotation clockwise
assert rotate(matrix) == [[4, 1], [5, 2], [6, 3]]
print("Rotation: passed")
# Test 5: 2D rotation matrix
rotation = rot_2D(0.01)
assert len(rotation) == 2 and len(rotation[0]) == 2
print("2D rotation matrix: passed")
print(rotation)
# Test 6: Invalid multiplication dimensions
try:
matmul([[1, 2], [3, 4]], [[5, 6, 7]])
except ValueError:
print("Invalid multiplication dimensions: handled")
else:
raise AssertionError("Expected ValueError for matmul")
# Test 7: Invalid matrices
for function in (transpose, rotate):
try:
function([])
except ValueError:
print(f"{function.__name__}: invalid matrix handled")
else:
raise AssertionError(
f"Expected ValueError for {function.__name__}"
)
# Test 8: Non-rectangular matrix
try:
transpose([[1, 2], [3]])
except ValueError:
print("Non-rectangular matrix: handled")
else:
raise AssertionError("Expected ValueError for transpose")
print("All tests passed!")