done exrcises

This commit is contained in:
2023-11-16 19:52:46 +01:00
parent 1b50d31111
commit 736bcb43c2
2 changed files with 161 additions and 4 deletions

View File

@ -40,9 +40,7 @@
## Übungsaufgaben ## Übungsaufgaben
### Annotations ### [Primes](./src/primes.py)
#### [Primes](./src/primes.py)
Schreibe eine Funktion `prime_factorization` die eine Ganzzahl `n` entgegen nimmt und alle Primfaktoren berrechnet und die gegebene Zahl `n` in einen Paar mit den Primfaktoren als Liste zurückgibt. Denkt dabei an die richtigen Type Annotations Schreibe eine Funktion `prime_factorization` die eine Ganzzahl `n` entgegen nimmt und alle Primfaktoren berrechnet und die gegebene Zahl `n` in einen Paar mit den Primfaktoren als Liste zurückgibt. Denkt dabei an die richtigen Type Annotations
@ -51,6 +49,77 @@ def prime_factorization(n):
pass pass
``` ```
#### [Dataclass](./src/data_classes.py) ### [Dataclass](./src/data_classes.py)
Schreiben Sie eine Datenklasse `Fraction` (Bruch), beachten Sie dabei die Type Annotations. Ein Bruch besteht aus einem `divident` und einem `divisor`.
```python
from dataclasses import dataclass
@dataclass
class Fraction:
pass
```
Nun modellieren wir Hilfsmethoden für unsere Datenklassen, die uns später bei der Logik von Brüchen helfen
```python
# the greatest common divisor of two numbers `a`, `b`
def gcd(a, b):
pass
# this shortens a fraction to its most reduced representation
def shorten_fraction(fraction):
pass
```
Abschließend modellieren wir nun auch noch das Verhalten von Brüchen indem wir Methoden direkt in der Datenklasse erstellen. Type Annotations!
```python
# Multiplication of two fractions
# `Fraction(1 / 2) * Fraction(2 / 6) -> Fraction(1, 6)`
# Extra: make it possible to multiply `int` with a fraction
# `Fraction(1 / 2) * 2 -> Fraction(1 / 4)`
def __mul__(self, o):
pass
# The division of two fraction
# `Fraction(1 / 2) / Fraction(2 / 6) -> Fraction(3, 2)`
# Extra: make it possible to divide `int` with a fraction
# `Fraction(1 / 4) / 2 -> Fraction(1 / 2)`
def __truediv__(self, o):
pass
# The negative of a fraction
# `-Fraction(1 / 2) -> Fraction(-1 / 2)`
def __neg__(self):
pass
# The addition of two fractions
# `Fraction(1 / 4) + Fraction(2 / 8) -> Fraction(1 / 2)`
# Extra: make it possible to add `int` with a fraction
# `Fraction(1 / 4) + 1 -> Fraction(5 / 4)`
def __add__(self, o):
pass
# The subtraction of two fractions
# `Fraction(1 / 2) - Fraction(1 / 4) -> Fraction(1 / 4)`
# Extra: make it possible to subtract `int` with a fraction
# `Fraction(5 / 2) - 1 -> Fraction(3 / 2)`
def __sub__(self, o):
pass
# The `equal`-function is == and should only care about reduced fractions
# `Fraction(1 / 2) == Fraction(2 / 4)` is True
def __eq__(self, o):
pass
# The `not equal`-function is != and should only care about reduced fractions exactly as equal
def __neq__(self, o):
pass
# The str function should return this string `(divident / divisor)`
def __str__(self):
pass
```

View File

@ -0,0 +1,88 @@
from dataclasses import dataclass
def gcd(a: int, b: int) -> int:
x = abs(a)
y = abs(b)
while (y):
x, y = y, x % y
return x
def shorten_fraction(fraction: 'Fraction') -> 'Fraction':
g: int = gcd(fraction.divident, fraction.divisor)
return Fraction(fraction.divident // g, fraction.divisor // g)
@dataclass
class Fraction:
divident: int
divisor: int
def __neg__(self: 'Fraction') -> 'Fraction':
return -1 * self
def __mul__(self: 'Fraction', o: 'Fraction | int') -> 'Fraction':
if isinstance(o, int):
o = Fraction(o, 1)
return shorten_fraction(Fraction(self.divident * o.divident,
self.divisor * self.divisor))
def __rmul__(self: 'Fraction', o: 'Fraction | int') -> 'Fraction':
return self * o
def __truediv__(self: 'Fraction', o: 'Fraction | int') -> 'Fraction':
if isinstance(o, int):
o = Fraction(o, 1)
return shorten_fraction(Fraction(self.divident * o.divisor,
self.divisor * o.divident))
def __rtruediv___(self: 'Fraction', o: 'Fraction | int') -> 'Fraction':
return self / o
def __add__(self: 'Fraction', o: 'Fraction | int') -> 'Fraction':
if isinstance(o, int):
o = Fraction(o, 1)
g: int = gcd(self.divisor, o.divisor)
l: int = abs(self.divisor * o.divisor) // g
return shorten_fraction(Fraction(self.divident
* (l // self.divisor)
+ o.divident
* (l // o.divisor), l))
def __radd__(self: 'Fraction', o: 'Fraction | int') -> 'Fraction':
return self + o
def __sub__(self: 'Fraction', o: 'Fraction | int') -> 'Fraction':
if isinstance(o, int):
o = Fraction(o, 1)
return self + -o
def __rsub__(self: 'Fraction', o: 'Fraction | int') -> 'Fraction':
return self - o
def __eq__(self: 'Fraction', o: 'Fraction | int') -> bool:
if isinstance(o, int):
o = Fraction(o, 1)
shorten_self: 'Fraction' = shorten_fraction(self)
shorten_o: 'Fraction' = shorten_fraction(o)
return (shorten_self.divident == shorten_o.divident
and shorten_self.divisor == shorten_o.divisor)
def __neq__(self: 'Fraction', o: 'Fraction | int') -> bool:
return not (self == o)
def __str__(self: 'Fraction'):
return f"({self.divident} / {self.divisor})"
if __name__ == "__main__":
assert Fraction(1, 1) == 1
assert Fraction(1, 2) == (out := Fraction(2, 4) /
Fraction(g := gcd(2, 4), g)), f"!= {out}"
assert (sol := Fraction(9, 20)) == (
res := Fraction(1, 5) + Fraction(1, 4)), f"!= {out}"
assert (sol := Fraction(-9, 20)) == (
res := Fraction(1, -5) + Fraction(-1, 4)), f"!= {out}"
assert (sol := Fraction(-1, 20)) == (
res := Fraction(1, 5) + Fraction(-1, 4)), f"!= {out}"