Skip to content

Instantly share code, notes, and snippets.

@SimonBrandner
Last active November 17, 2024 09:38
Show Gist options
  • Save SimonBrandner/7f0fc9513e185ac7083169fd2345dd4d to your computer and use it in GitHub Desktop.
Save SimonBrandner/7f0fc9513e185ac7083169fd2345dd4d to your computer and use it in GitHub Desktop.
GEM
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("")
@SimonBrandner
Copy link
Author

Something I quickly put together to check one's steps during GEM are correct

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment