Last active
November 17, 2024 09:38
-
-
Save SimonBrandner/7f0fc9513e185ac7083169fd2345dd4d to your computer and use it in GitHub Desktop.
GEM
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from typing import List, Self, Union | |
import math | |
import copy | |
class Ratio: | |
numerator: int | |
denominator: int | |
def __init__(self, numerator: int, denominator=1): | |
self.numerator = numerator | |
self.denominator = denominator | |
def __mul__(self, other) -> Self: | |
other = Ratio.from_other_type(other) | |
new_numerator = self.numerator * other.numerator | |
new_denominator = self.denominator * other.denominator | |
new_ratio = type(self)(new_numerator, new_denominator) | |
new_ratio.shorten() | |
return new_ratio | |
def __add__(self, other: Self) -> Self: | |
new_denominator = math.lcm(self.denominator, other.denominator) | |
new_numerator = int( | |
(new_denominator / self.denominator) * self.numerator | |
+ (new_denominator / other.denominator) * other.numerator | |
) | |
new_ratio = type(self)(new_numerator, new_denominator) | |
new_ratio.shorten() | |
return new_ratio | |
def __str__(self): | |
if self.denominator == 1: | |
return str(self.numerator) | |
else: | |
return f"{self.numerator}/{self.denominator}" | |
def __ge__(self, other: Union[Self, int]): | |
new_other = type(self).from_other_type(other) | |
return ( | |
self.numerator / self.denominator | |
>= new_other.numerator / new_other.denominator | |
) | |
def shorten(self): | |
gcd = math.gcd(self.numerator, self.denominator) | |
self.numerator = int(self.numerator / gcd) | |
self.denominator = int(self.denominator / gcd) | |
if self.denominator < 0: | |
self.numerator = -1 * self.numerator | |
self.denominator = -1 * self.denominator | |
@staticmethod | |
def from_other_type(value): | |
match value: | |
case Ratio(): | |
new_value = value | |
case int(): | |
new_value = Ratio(value) | |
case _: | |
raise Exception(f"Unknown type {type(value)}") | |
return new_value | |
class AugmentedMatrix: | |
data: List[List[Ratio]] | |
number_of_columns: int | |
def __init__(self, data: List[List]) -> None: | |
number_of_columns = None | |
for row in data: | |
if number_of_columns is None: | |
number_of_columns = len(row) | |
else: | |
assert number_of_columns == len(row) | |
if number_of_columns is None: | |
raise Exception("Bad matrix") | |
new_data = [] | |
for row in data: | |
new_row = [] | |
for column in row: | |
new_row.append(Ratio.from_other_type(column)) | |
new_data.append(new_row) | |
self.number_of_columns = number_of_columns | |
self.data = new_data | |
pass | |
def add_row_multiple( | |
self, to_row_index: int, from_row_index: int, scalar: Union[Ratio, int] | |
): | |
scalar_part = f"+{scalar}" if scalar >= 0 else f"-{scalar * (-1)}" | |
print(f"R{to_row_index}=R{to_row_index}{scalar_part}⋅R{from_row_index}") | |
scalar = Ratio.from_other_type(scalar) | |
to_row_index -= 1 | |
from_row_index -= 1 | |
self.data[to_row_index] = [ | |
scalar * self.data[from_row_index][i] + self.data[to_row_index][i] | |
for i in range(self.number_of_columns) | |
] | |
def swap_rows(self, row_index: int, other_row_index: int): | |
print(f"R{row_index}↔R{other_row_index}") | |
row_index -= 1 | |
other_row_index -= 1 | |
temporary = copy.deepcopy(self.data[row_index]) | |
self.data[row_index] = copy.deepcopy(self.data[other_row_index]) | |
self.data[other_row_index] = temporary | |
def multiply_row(self, row_index: int, scalar: Union[Ratio, int]): | |
print(f"R{row_index}={scalar}⋅R{row_index}") | |
scalar = Ratio.from_other_type(scalar) | |
row_index -= 1 | |
self.data[row_index] = [ | |
scalar * self.data[row_index][i] for i in range(self.number_of_columns) | |
] | |
def print(self): | |
print("Matrix after performing the beforehand operations:") | |
max_column_width = 0 | |
for row in self.data: | |
for column in row: | |
length = len(str(column)) | |
if length > max_column_width: | |
max_column_width = length | |
for row in self.data: | |
for column in row: | |
str_column = str(column) | |
print( | |
(max_column_width - len(str_column)) * " " + str_column + " ", | |
end="", | |
) | |
print("") | |
print("") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Something I quickly put together to check one's steps during GEM are correct