← Strona główna

13 — Zadania z konsoli

Typowe zadania egzaminacyjne — Python w trybie tekstowym, input/output, przetwarzanie danych.

Przetwarzanie i algorytmy

1. Jak wygląda zadanie z konsoli na egzaminie INF.04?

Zadanie konsolowe to program który: wczytuje dane od użytkownika lub z pliku, przetwarza je według opisu, i wypisuje wynik w określonym formacie.

  • Zawsze czytaj uważnie co i w jakiej kolejności wczytać
  • Zwróć uwagę na format wyjścia — egzaminator sprawdza dokładnie
  • Waliduj dane wejściowe gdy treść tego wymaga
  • Używaj funkcji — nie pisz wszystkiego w jednym bloku
  • Testuj na przykładach z treści zadania
Schemat rozwiązania 1. Wczytaj dane (input + konwersja typów)
2. Przetwórz (algorytm, obliczenia, pętle)
3. Wypisz wynik (print z formatowaniem)
4. Sprawdź na przykładach z treści
Schemat — typowa struktura rozwiązania
# ── WCZYTANIE DANYCH ─────────────────────────
n = int(input("Ile liczb: "))
liczby = []
for i in range(n):
    x = float(input(f"Liczba {i+1}: "))
    liczby.append(x)

# ── PRZETWARZANIE ─────────────────────────────
suma    = sum(liczby)
srednia = suma / len(liczby)
minimum = min(liczby)
maksimum = max(liczby)

# ── WYPISANIE WYNIKU ──────────────────────────
print(f"Suma:    {suma:.2f}")
print(f"Średnia: {srednia:.2f}")
print(f"Min:     {minimum:.2f}")
print(f"Max:     {maksimum:.2f}")

# ── DOBRA PRAKTYKA: funkcje ───────────────────
def wczytaj_liczby(n):
    return [float(input(f"Liczba {i+1}: "))
            for i in range(n)]

def statystyki(dane):
    return {
        "suma":    sum(dane),
        "srednia": sum(dane) / len(dane),
        "min":     min(dane),
        "max":     max(dane)
    }

2. Wzorce wczytywania danych

Egzamin INF.04 testuje różne sposoby wczytywania danych. Poniżej najczęstsze wzorce — zapamiętaj je.

ScenariuszWzorzec
Jedna liczban = int(input())
n liczb w osobnych liniachpętla for + append
Liczby w jednej liniilist(map(int, input().split()))
Wczytuj aż do wartości sentinelwhile True + sprawdzenie
Dane tabelarycznepętla po liniach + split()
Pary klucz–wartośćsplit + słownik
split() i map() list(map(int, input().split())) to skrócony sposób wczytania kilku liczb z jednej linii oddzielonych spacjami. Np. dla wejścia "3 7 2 9" dostaniesz listę [3, 7, 2, 9].
Przykłady — wzorce wczytywania
# Wczytanie n liczb z osobnych linii
n      = int(input("n: "))
liczby = [int(input()) for _ in range(n)]

# Wczytanie z jednej linii (np. "3 7 2 9")
liczby = list(map(int, input("Liczby: ").split()))

# Wczytanie float z jednej linii
floaty = list(map(float, input().split()))

# Wczytywanie do sentinel (0 lub "koniec")
dane = []
while True:
    x = input("Wartość (0=koniec): ")
    if x == "0" or x.lower() == "koniec":
        break
    dane.append(int(x))

# Wczytywanie par "imie wynik"
wyniki = {}
n = int(input("Ile wpisów: "))
for _ in range(n):
    linia = input().split()
    imie, wynik = linia[0], int(linia[1])
    wyniki[imie] = wynik

# Wczytywanie tabeli n×m
n, m = map(int, input("n m: ").split())
tabela = []
for _ in range(n):
    wiersz = list(map(int, input().split()))
    tabela.append(wiersz)

3. Formatowanie wyjścia

Egzaminator sprawdza wynik automatycznie lub ręcznie — format musi być dokładnie taki jak w treści zadania. Błąd w formatowaniu = utrata punktów.

CelKodWynik
2 miejsca po przecinkuf"{x:.2f}"3.14
Całkowita bez .0f"{x:.0f}"42
Pole szerokości 8f"{x:8}"    3.14
Do lewej, sz. 10f"{s:<10}"tekst     
Separator tysiąc.f"{x:,}"1,234,567
Procentf"{x:.1%}"73.5%
Lista jako tekst", ".join(map(str, l))1, 2, 3
Nie drukuj listy bezpośrednio print([1, 2, 3]) wypisze [1, 2, 3] z nawiasami. Jeśli wymagany format to "1 2 3" — użyj print(*lista) lub print(" ".join(map(str, lista))).
Przykłady — formatowanie wyjścia
liczby = [3.14159, 2.71828, 1.41421]
wyniki = [87, 92, 74, 88]
imiona = ["Kasia", "Marek", "Zofia"]

# Liczby z 2 miejscami po przecinku
for x in liczby:
    print(f"{x:.2f}")
# 3.14 / 2.72 / 1.41

# Tabela z wyrównaniem
print(f"{'Imię':<10} {'Wynik':>6} {'Ocena':>6}")
print("-" * 24)
for imie, wynik in zip(imiona, wyniki):
    ocena = "bdb" if wynik >= 90 else "db"
    print(f"{imie:<10} {wynik:>6} {ocena:>6}")

# Lista bez nawiasów
print(*wyniki)                        # 87 92 74 88
print(*wyniki, sep=", ")              # 87, 92, 74, 88
print(", ".join(map(str, wyniki)))    # 87, 92, 74, 88

# Procent
srednia = sum(wyniki) / len(wyniki)
print(f"Średnia: {srednia:.1f} ({srednia/100:.1%})")
# Średnia: 85.2 (85.2%)

# Separator tysięcy
duza = 1234567
print(f"{duza:,}")     # 1,234,567
print(f"{duza:_}")     # 1_234_567

4. Typowe kategorie zadań egzaminacyjnych

Obliczenia numeryczne
  • BMI, temperatura, przeliczniki
  • Progi podatkowe
  • Obliczenia geometryczne
  • Procentowe — rabaty, odsetki
  • Statystyki — min, max, średnia, mediana
Przetwarzanie list
  • Filtrowanie według warunków
  • Sortowanie i ranking
  • Zliczanie wystąpień
  • Znajdowanie min/max bez wbudowanych
  • Operacje na macierzach 2D
Tekst i algorytmy
  • Palindromy, anagramy
  • Zliczanie liter/słów
  • Szyfry (Cezar, ROT13)
  • Walidacja danych
  • NWD, NWW, liczby pierwsze

Zadania przykładowe z omówieniem

Zadanie 1 Sklep — paragon i rabat łatwe

Wczytaj liczbę produktów n. Następnie wczytaj n par: nazwa produktu i cena. Jeśli suma przekracza 100 zł — zastosuj rabat 10%. Wypisz paragon: każdy produkt z ceną, linię podsumowania z sumą przed i po rabacie.

Rozwiązanie
n = int(input("Liczba produktów: "))
produkty = []

for i in range(n):
    nazwa = input(f"Produkt {i+1} — nazwa: ")
    cena  = float(input(f"Produkt {i+1} — cena: "))
    produkty.append((nazwa, cena))

suma = sum(cena for _, cena in produkty)
prog_rabatu = 100.0
rabat_proc  = 0.10

print("\n" + "=" * 35)
print(f"{'PARAGON':^35}")
print("=" * 35)

for nazwa, cena in produkty:
    print(f"{nazwa:<22} {cena:>8.2f} zł")

print("-" * 35)
print(f"{'Suma:':<22} {suma:>8.2f} zł")

if suma > prog_rabatu:
    rabat   = suma * rabat_proc
    do_zap  = suma - rabat
    print(f"{'Rabat 10%:':<22} {-rabat:>8.2f} zł")
    print("-" * 35)
    print(f"{'DO ZAPŁATY:':<22} {do_zap:>8.2f} zł")
else:
    print(f"{'DO ZAPŁATY:':<22} {suma:>8.2f} zł")

print("=" * 35)
Omówienie krok po kroku
  1. Lista krotek (nazwa, cena)
    Każdy produkt to para — przechowujemy w liście krotek. Przy wypisywaniu rozpakowujemy przez for nazwa, cena in produkty.
  2. Generator w sum()
    sum(cena for _, cena in produkty) — generator expression wewnątrz sum(). Podkreślnik _ to konwencja dla zmiennej której nie używamy (tu: nazwy).
  3. Wyrównanie paragonu
    :<22 — nazwa do lewej w polu 22 znaków. :>8.2f — cena do prawej, 8 znaków, 2 miejsca po przecinku. Kolumny są równe niezależnie od długości nazwy.
  4. Rabat jako ujemna wartość
    {-rabat:>8.2f} — wypisujemy rabat ze znakiem minus aby paragon był czytelny. Alternatywnie można pisać oddzielną etykietę "Oszczędzasz:".
Zadanie 2 Klasyfikacja trójkąta łatwe

Wczytaj trzy boki trójkąta (a, b, c). Sprawdź czy tworzą trójkąt (nierówność trójkąta). Jeśli tak — określ czy jest równoboczny, równoramienny czy różnoboczny, a także czy prostokątny. Oblicz pole i obwód.

Rozwiązanie
import math

a, b, c = map(float, input("Boki a b c: ").split())

# Sprawdzenie nierówności trójkąta
if a + b <= c or a + c <= b or b + c <= a:
    print("To nie jest trójkąt!")
else:
    # Typ według boków
    if a == b == c:
        typ = "równoboczny"
    elif a == b or b == c or a == c:
        typ = "równoramienny"
    else:
        typ = "różnoboczny"

    # Czy prostokątny (twierdzenie Pitagorasa)
    boki = sorted([a, b, c])
    prosto = math.isclose(boki[0]**2 + boki[1]**2,
                          boki[2]**2, rel_tol=1e-9)

    # Pole — wzór Herona
    s    = (a + b + c) / 2
    pole = math.sqrt(s * (s-a) * (s-b) * (s-c))
    obwod = a + b + c

    print(f"Typ:        {typ}")
    print(f"Prostokątny: {'tak' if prosto else 'nie'}")
    print(f"Obwód:      {obwod:.2f}")
    print(f"Pole:       {pole:.2f}")
Omówienie krok po kroku
  1. map() dla trzech wartości naraz
    a, b, c = map(float, input().split()) — wczytujemy jedną linię, dzielimy po spacjach, zamieniamy każdy element na float i od razu rozpakowujemy do trzech zmiennych.
  2. Nierówność trójkąta
    Suma dowolnych dwóch boków musi być większa od trzeciego. Sprawdzamy wszystkie trzy kombinacje — jeśli choć jedna nie jest spełniona, to nie jest trójkąt.
  3. math.isclose() zamiast ==
    Porównywanie liczb zmiennoprzecinkowych przez == może zawieść przez błędy zaokrągleń. isclose() sprawdza czy wartości są wystarczająco blisko siebie.
  4. Wzór Herona
    s = (a+b+c)/2 — połowa obwodu (semiperimeter). pole = √(s(s-a)(s-b)(s-c)) — wzór Herona, działa dla dowolnego trójkąta znając tylko boki.
Zadanie 3 Ranking uczniów z kategoryzacją średnie

Wczytaj dane n uczniów (imię i wynik 0–100). Posortuj malejąco według wyniku. Wypisz ranking z miejscem, imieniem i wynikiem. Dodaj kategorię: 90–100 = celujący, 75–89 = bardzo dobry, 60–74 = dobry, 50–59 = dostateczny, poniżej 50 = niedostateczny. Na końcu wypisz ilu uczniów w każdej kategorii.

Rozwiązanie
def kategoria(wynik):
    if wynik >= 90: return "celujący"
    if wynik >= 75: return "bardzo dobry"
    if wynik >= 60: return "dobry"
    if wynik >= 50: return "dostateczny"
    return "niedostateczny"

n       = int(input("Liczba uczniów: "))
uczniowie = []
for i in range(n):
    imie  = input(f"Uczeń {i+1} — imię: ")
    wynik = int(input(f"Uczeń {i+1} — wynik: "))
    uczniowie.append({"imie": imie, "wynik": wynik})

uczniowie.sort(key=lambda u: u["wynik"], reverse=True)

print(f"\n{'Msc':<5} {'Imię':<15} {'Wynik':>6} {'Kategoria':<15}")
print("-" * 44)

liczniki = {}
for i, u in enumerate(uczniowie, 1):
    kat = kategoria(u["wynik"])
    liczniki[kat] = liczniki.get(kat, 0) + 1
    print(f"{i:<5} {u['imie']:<15} "
          f"{u['wynik']:>6} {kat:<15}")

print("\nPodsumowanie kategorii:")
kolejnosc = ["celujący","bardzo dobry","dobry",
             "dostateczny","niedostateczny"]
for kat in kolejnosc:
    ile = liczniki.get(kat, 0)
    if ile > 0:
        print(f"  {kat:<16}: {ile}")
Omówienie krok po kroku
  1. Funkcja kategoria()
    Seria if bez elif z wczesnym return — czytelniejsza niż długi łańcuch elif. Sprawdzamy od najwyższego progu w dół.
  2. Lista słowników jako baza danych
    Każdy uczeń to słownik. Sortujemy listę słowników po wartości klucza "wynik". Łatwo rozszerzyć o nowe pola (klasa, data) bez zmiany reszty kodu.
  3. Zliczanie kategorii podczas wypisywania
    Obliczamy kategorię tylko raz — przy wypisywaniu. Wynik trafia do słownika liczników (get(kat, 0) + 1). Nie potrzebujemy osobnej pętli.
  4. Stała kolejność kategorii
    Słownik nie ma gwarantowanej kolejności wstawiania dla starszych Pythonów. Definiujemy jawnie listę kolejnosc żeby wypisać kategorie od najlepszej do najgorszej.
Zadanie 4 Szyfrowanie i deszyfrowanie tekstu średnie

Napisz program szyfrujący i deszyfrujący tekst szyfrem Cezara. Wczytaj tekst i przesunięcie. Zaszyfruj tekst (litery przesuwaj, resztę znaków pozostaw). Następnie odszyfruj i sprawdź czy wynik jest taki sam jak oryginał.

Rozwiązanie
def cezar(tekst, przesuniecie):
    wynik = []
    for znak in tekst:
        if znak.isalpha():
            baza  = ord('A') if znak.isupper() else ord('a')
            nowy  = (ord(znak) - baza + przesuniecie) % 26
            wynik.append(chr(nowy + baza))
        else:
            wynik.append(znak)   # spacje, cyfry, znaki spec.
    return "".join(wynik)

tekst      = input("Tekst do zaszyfrowania: ")
przesuniecie = int(input("Przesunięcie (1-25): "))

zaszyfrowany   = cezar(tekst, przesuniecie)
odszyfrowany   = cezar(zaszyfrowany, -przesuniecie)
zgodnosc       = tekst == odszyfrowany

print(f"\nOryginalny:    {tekst}")
print(f"Zaszyfrowany:  {zaszyfrowany}")
print(f"Odszyfrowany:  {odszyfrowany}")
print(f"Weryfikacja:   {'✓ OK' if zgodnosc else '✗ BŁĄD'}")
Omówienie krok po kroku
  1. Obsługa wielkich i małych liter oddzielnie
    baza = ord('A') if znak.isupper() else ord('a') — dla wielkiej litery bazujemy na 65 (A), dla małej na 97 (a). Dzięki temu szyfr zachowuje wielkość liter.
  2. Modulo 26 — zawijanie alfabetu
    % 26 zapewnia że po 'Z' wraca do 'A'. Działa też dla ujemnego przesunięcia (deszyfrowanie) — Python poprawnie obsługuje modulo dla liczb ujemnych.
  3. join() dla wydajności
    Budowanie stringa przez + w pętli jest nieefektywne (tworzy nowe obiekty). Lista + "".join() na końcu to standardowy wzorzec dla wydajnego budowania stringów.
  4. Deszyfrowanie = szyfrowanie z -k
    Szyfr Cezara jest symetryczny — odszyfrowanie to zaszyfrowanie z ujemnym przesunięciem. Jedna funkcja obsługuje oba kierunki.

Zadania do samodzielnego rozwiązania

Wszystkie zadania są w stylu egzaminacyjnym. Pisz funkcje, dbaj o format wyjścia i testuj na przykładach z treści.

1★☆☆

Przelicznik walut

Wczytaj kwotę w PLN i kod waluty (USD, EUR, GBP). Przelicz według stałych kursów. Wypisz wynik z 2 miejscami po przecinku i symbolem waluty.

Wskazówka: słownik kursów, walidacja kodu waluty, format :.2f
2★☆☆

Kalkulator czasu pracy

Wczytaj godziny wejścia i wyjścia (HH:MM). Oblicz przepracowany czas. Jeśli powyżej 8h — oblicz nadgodziny. Wypisz w formacie "Xh Ymin".

Wskazówka: zamień na minuty, odejmij, przelicz z powrotem; split(":")
3★★☆

Macierz — podstawowe operacje

Wczytaj macierz n×n. Wypisz: sumę każdego wiersza, sumę każdej kolumny, sumę przekątnej głównej i czy macierz jest symetryczna (M[i][j] == M[j][i]).

Wskazówka: wczytaj przez map(int, input().split()), przekątna: sum(m[i][i])
4★★☆

Dziennik ocen z raportem

Wczytaj dane uczniów (imię, 5 ocen). Wypisz raport: dla każdego ucznia średnią i czy zdał (średnia ≥ 2.75). Wypisz średnią klasy i odsetek zdanych.

Wskazówka: lista słowników, sum(oceny)/len(oceny), zlicz zdanych
5★★☆

Walidator PESEL

Wczytaj numer PESEL (11 cyfr). Sprawdź sumę kontrolną, wyciągnij datę urodzenia i płeć. Wypisz czy PESEL jest poprawny i odczytane dane.

Wskazówka: wagi [1,3,7,9,1,3,7,9,1,3], suma mod 10, cyfra 10 = płeć
6★★★

Symulator banku

Zaimplementuj prosty rachunek bankowy: saldo, wpłata, wypłata (waliduj czy nie więcej niż saldo), historia operacji, wyciąg. Wszystko przez menu w pętli.

Wskazówka: słownik konta, lista historii, while True z menu, funkcje dla każdej operacji