Klasa Ułamek

Zadanie 9 z 11 · rozdział 18Trudność: 2 z 3classoperatoryNWDsortowanie

Treść zadania

Zaprojektuj klasę Ulamek opisującą ułamek zwykły $\frac{a}{b}$:

  • Konstruktor __init__(self, licznik, mianownik=1) od razu normalizuje ułamek:
    • skraca go przez $\text{NWD}(|a|, |b|)$ (funkcja math.gcd),
    • przenosi znak do licznika — mianownik jest zawsze dodatni (np. $\frac{3}{-6}$ zapisujemy jako $-\frac{1}{2}$),
    • zero zapisujemy jako $\frac{0}{1}$.
  • Operatory +, -, *, / (metody __add__, __sub__, __mul__, __truediv__) zwracają nowy, znormalizowany ułamek (dzielnik w / jest różny od zera):
    $\frac{a}{b} + \frac{c}{d} = \frac{ad + cb}{bd}$, $\frac{a}{b} \cdot \frac{c}{d} = \frac{ac}{bd}$, $\frac{a}{b} : \frac{c}{d} = \frac{ad}{bc}$.
  • Porównania == (__eq__) i < (__lt__): $\frac{a}{b} < \frac{c}{d}$ wtedy i tylko wtedy, gdy $ad < cb$ (mianowniki są dodatnie).
  • Metoda __str__() zwraca a/b, np. -3/4, a gdy mianownik jest równy 1 — samą liczbę całkowitą, np. 3, -2, 0.

Program wczytuje listę ułamków i wypisuje:

  1. ułamki posortowane rosnąco (sorted() porównuje elementy operatorem <, czyli Twoją metodą __lt__),
  2. ich sumę,
  3. ich iloczyn,
  4. ich średnią arytmetyczną (sumę podzieloną przez Ulamek(n)),
  5. różnicę między największym a najmniejszym ułamkiem,
  6. liczbę różnych wartości (operator in porównuje elementy operatorem ==, czyli Twoją metodą __eq__).

Dane wejściowe

  • 1. linia: liczba ułamków $n$
  • 2. linia: $n$ ułamków w postaci a/b oddzielonych spacjami ($a$, $b$ — liczby całkowite, $b \ne 0$, mogą być ujemne)

Dane wyjściowe

Sześć linii:

Posortowane: <ułamki oddzielone spacjami>
Suma: <suma>
Iloczyn: <iloczyn>
Średnia: <średnia>
Największy - najmniejszy: <różnica>
Liczba różnych wartości: <liczba>

Wszystkie ułamki wypisz w postaci znormalizowanej (jak w metodzie __str__).

Ograniczenia

  • $1 \le n \le 10$
  • $-100 \le a, b \le 100$, $b \ne 0$

Uwagi

  • math.gcd(a, b) zwraca NWD wartości bezwzględnych argumentów, np. math.gcd(-6, 9) == 3, math.gcd(0, 5) == 5.
  • Używaj dzielenia całkowitego // — licznik i mianownik mają pozostać liczbami całkowitymi.

Przykład

Wejście
5
1/2 3/4 -2/8 6/4 2/4
Wyjście
Posortowane: -1/4 1/2 1/2 3/4 3/2
Suma: 3
Iloczyn: -9/128
Średnia: 3/5
Największy - najmniejszy: 7/4
Liczba różnych wartości: 4

Po normalizacji ułamki to $\frac{1}{2}, \frac{3}{4}, -\frac{1}{4}, \frac{3}{2}, \frac{1}{2}$. Ich suma to $3$, a średnia $\frac{3}{5}$. Ułamki $\frac{1}{2}$ i $\frac{2}{4}$ są równe, więc różnych wartości są 4.

Zasady obowiązujące w rozdziale 18

Zadania w tym rozdziale uczą projektowania klas: konstruktora __init__, atrybutów, metod, metod statycznych (@staticmethod) oraz metod specjalnych, dzięki którym obiekty można wypisywać (__str__), porównywać (__eq__) i łączyć operatorami (__add__, __sub__, __mul__, …). Ostatnie zadania wprowadzają też wyjątki (raise, try/except), klasy danych (@dataclass) i generatory (yield).

Konwencje wspólne:

  • Każde zadanie to osobny program: czyta standardowe wejście i wypisuje wynik na standardowe wyjście.
  • W każdym zadaniu dostajesz kod startowy ze szkieletem klasy, a zwykle także z gotowym wczytywaniem danych i wypisywaniem wyników. Twoim zadaniem jest przede wszystkim uzupełnienie metod klasy — wynik programu zależy od tego, jak działa Twoja klasa.
  • Nazwy klas i metod podane w treści są obowiązkowe (kod startowy z nich korzysta). Nazwy w kodzie piszemy bez polskich znaków, np. Kolo, Prostokat.
  • „Z dokładnością do 2 miejsc po przecinku” oznacza dokładnie dwie cyfry po kropce, np. f"{x:.2f}" (3.00, -0.50).
  • Program nie wypisuje komunikatów typu „Podaj liczbę:”.

Zadanie pochodzi z otwartego zbioru Nauka-Programowania (z rozwiązaniami wzorcowymi). Zgłoś błąd w treści lub testach.

Python uruchomi się w przeglądarce przy pierwszym teście.

Kod zapisuje się automatycznie w tej przeglądarce. Tab wstawia wcięcie; aby opuścić edytor klawiaturą, naciśnij Esc, a potem Tab.

Testy

Program dostaje „Wejście” przez input() i musi wypisać „Oczekiwane wyjście”. Liczby porównywane są z tolerancją 0,01, a tekst podany w input("…") nie jest sprawdzany.

Test 1

Nie uruchomiono
Wejście
1
4/8
Oczekiwane wyjście
Posortowane: 1/2
Suma: 1/2
Iloczyn: 1/2
Średnia: 1/2
Największy - najmniejszy: 0
Liczba różnych wartości: 1

Test 2

Nie uruchomiono
Wejście
2
3/-6 0/5
Oczekiwane wyjście
Posortowane: -1/2 0
Suma: -1/2
Iloczyn: 0
Średnia: -1/4
Największy - najmniejszy: 1/2
Liczba różnych wartości: 2

Test 3

Nie uruchomiono
Wejście
3
2/3 4/6 -6/-9
Oczekiwane wyjście
Posortowane: 2/3 2/3 2/3
Suma: 2
Iloczyn: 8/27
Średnia: 2/3
Największy - najmniejszy: 0
Liczba różnych wartości: 1

Test 4

Nie uruchomiono
Wejście
4
7/1 -5/2 1/3 -1/6
Oczekiwane wyjście
Posortowane: -5/2 -1/6 1/3 7
Suma: 14/3
Iloczyn: 35/36
Średnia: 7/6
Największy - najmniejszy: 19/2
Liczba różnych wartości: 4

Test 5

Nie uruchomiono
Wejście
6
1/2 1/3 1/6 -1/2 -1/3 -1/6
Oczekiwane wyjście
Posortowane: -1/2 -1/3 -1/6 1/6 1/3 1/2
Suma: 0
Iloczyn: -1/1296
Średnia: 0
Największy - najmniejszy: 1
Liczba różnych wartości: 6
Uruchom z własnymi danymi