1Kalkulator paragonu – zmienne, typy, instrukcje warunkowe

Cel zadania (~20 min)

Napisz program, który działając jak kasa fiskalna, oblicza wartość koszyka zakupów z uwzględnieniem rabatu oraz podatku VAT. Program ma pobierać dane od użytkownika, przechowywać produkty w liście słowników i wyświetlić sformatowany paragon.

Wymagania szczegółowe:
  • Zdefiniuj funkcję oblicz_kwote_netto(wartosc_netto, stawka_vat) – dodaje podatek VAT do kwoty netto.
  • Zdefiniuj funkcję oblicz_rabat(kwota): rabat 20% dla kwoty ≥500 zł, 10% dla ≥200 zł, 5% dla ≥100 zł, 0% poniżej.
  • Program pyta o liczbę produktów, a następnie w pętli zbiera nazwę, ilość i cenę każdego.
  • Wyświetl sformatowany paragon: kolumny Nazwa | Ilość | Cena | Wartość, sumę netto, rabat, VAT i kwotę do zapłaty.
  • Obsłuż przypadek pustego koszyka (0 produktów).

Wskazówki

Użyj pętli for i in range(n) do zbierania danych. Produkty przechowuj jako listę słowników: {"nazwa": str, "ilosc": int, "cena": float}. Do formatowania kolumn użyj f-string z wyrównaniem: {nazwa:<15}. Operator sum(wartości) zlicza sumę z listy składanej.

def oblicz_kwote_netto(wartosc_netto, stawka_vat):
    vat = wartosc_netto * stawka_vat / 100
    return wartosc_netto + vat

def oblicz_rabat(kwota):
    if kwota >= 500:
        return kwota * 0.2
    elif kwota >= 200:
        return kwota * 0.1
    elif kwota >= 100:
        return kwota * 0.05
    else:
        return 0

n = int(input("Liczba produktow: "))
if n == 0:
    print("Pusty koszyk.")
else:
    produkty = []
    for i in range(n):
        nazwa = input(f"Nazwa produktu {i+1}: ")
        ilosc = int(input("Ilosc: "))
        cena = float(input("Cena za szt.: "))
        produkty.append({"nazwa": nazwa, "ilosc": ilosc, "cena": cena})

    suma_netto = sum(p["cena"] * p["ilosc"] for p in produkty)
    rabat = oblicz_rabat(suma_netto)
    po_rabacie = suma_netto - rabat
    vat_23 = oblicz_kwote_netto(po_rabacie, 23) - po_rabacie
    do_zaplaty = po_rabacie + vat_23

    print("\n" + "=" * 45)
    print(f"{'PARAGON FISKALNY':^45}")
    print("=" * 45)
    print(f"{'Nazwa':<15} {'Ilosc':<8} {'Cena':<8} {'Wartosc':<10}")
    print("-" * 45)
    for p in produkty:
        wart = p["cena"] * p["ilosc"]
        print(f"{p['nazwa']:<15} {p['ilosc']:<8} {p['cena']:<8.2f} {wart:<10.2f}")
    print("-" * 45)
    print(f"{'Suma netto:':<33} {suma_netto:>8.2f}")
    print(f"{'Rabat:':<33} -{rabat:>7.2f}")
    print(f"{'Po rabacie:':<33} {po_rabacie:>8.2f}")
    print(f"{'VAT 23%:':<33} {vat_23:>8.2f}")
    print("=" * 45)
    print(f"{'DO ZAPLATY:':<33} {do_zaplaty:>8.2f}")
    print("=" * 45)
PRZYKLADOWY EKRAN WYNIKOWY:

Liczba produktow: 4
Nazwa produktu 1: Mleko
Ilosc: 2
Cena za szt.: 3.50
Nazwa produktu 2: Chleb
Ilosc: 1
Cena za szt.: 4.20
Nazwa produktu 3: Maslo
Ilosc: 3
Cena za szt.: 6.00
Nazwa produktu 4: Ser
Ilosc: 1
Cena za szt.: 12.50

=============================================
              PARAGON FISKALNY
=============================================
Nazwa           Ilosc    Cena     Wartosc
---------------------------------------------
Mleko           2        3.50     7.00
Chleb           1        4.20     4.20
Maslo           3        6.00     18.00
Ser             1        12.50    12.50
---------------------------------------------
Suma netto:                       41.70
Rabat:                         -   0.00
Po rabacie:                       41.70
VAT 23%:                           9.59
=============================================
DO ZAPLATY:                       51.29
=============================================
2Analizator tekstu – stringi, indeksowanie, palindromy

Cel zadania (~20 min)

Napisz program do wszechstronnej analizy tekstu wprowadzonego przez użytkownika. Program ma zliczać znaki, słowa i zdania, znajdować najdłuższe słowo, wykrywać palindromy oraz odwracać kolejność słów.

Wymagania szczegółowe:
  • Funkcja analizuj_tekst(tekst) zwraca słownik z: liczbą znaków, znaków bez spacji, słów, zdań.
  • Znajdź najdłuższe słowo (usuń znaki interpunkcyjne przed pomiarem).
  • Policz samogłoski i spółgłoski w tekście.
  • Sprawdź czy cały tekst (po usunięciu znaków niealfabetycznych) jest palindromem.
  • Znajdź wszystkie wyrazy, które same są palindromami (np. ala, kajak).
  • Wyświetl tekst z odwróconą kolejnością słów.

Wskazówki

Użyj re.split(r'[.!?]+', tekst) do dzielenia na zdania. re.sub(r'[^a-ząćęłńóśśźź]', '', tekst.lower()) usuwa wszystkie znaki niebędące literami. Sprawdzenie palindromu: s == s[::-1]. Wyrazy podziel przez tekst.split().

import re

def analizuj_tekst(tekst):
    znaki = len(tekst)
    znaki_bs = len(re.sub(r'\s', '', tekst))
    slowa = [s for s in tekst.split() if s]
    liczba_slow = len(slowa)
    zdania = [z for z in re.split(r'[.!?]+', tekst) if z.strip()]
    liczba_zdan = len(zdania)

    najdluzsze = max(
        (re.sub(r'[^a-zA-Z]', '', s) for s in slowa),
        key=len
    ) if slowa else ""

    samogloski = sum(1 for z in tekst.lower()
                     if z in "aeiouyaeou")
    spolgloski = sum(1 for z in tekst.lower()
                     if z.isalpha() and z not in "aeiouyaeou")

    czysty = re.sub(r'[^a-z]', '', tekst.lower())
    czy_palindrom = (czysty == czysty[::-1] and len(czysty) > 0)

    wyrazy_pal = [s for s in slowa
                  if len(s) > 1 and s.lower() == s.lower()[::-1]]

    return {
        "znaki": znaki, "znaki_bs": znaki_bs,
        "slowa": liczba_slow, "zdania": liczba_zdan,
        "najdluzsze": najdluzsze,
        "samogloski": samogloski, "spolgloski": spolgloski,
        "palindrom": czy_palindrom,
        "wyrazy_pal": wyrazy_pal,
        "odwrocone": " ".join(slowa[::-1]),
    }

tekst = input("Wprowadz tekst: ")
w = analizuj_tekst(tekst)
print(f"\n=== ANALIZA TEKSTU ===")
print(f"Znaki: {w['znaki']} (bez spacji: {w['znaki_bs']})")
print(f"Slowa: {w['slowa']}, Zdania: {w['zdania']}")
print(f"Najdluzsze slowo: \"{w['najdluzsze']}\"")
print(f"Samogloski: {w['samogloski']}, Spolgloski: {w['spolgloski']}")
print(f"Palindrom: {'TAK' if w['palindrom'] else 'NIE'}")
if w['wyrazy_pal']:
    print(f"Palindromy w tekscie: {w['wyrazy_pal']}")
print(f"Odwrocone: {w['odwrocone']}")
PRZYKLADOWY EKRAN WYNIKOWY:

Wprowadz tekst: Ala ma kota. Kot ma Ale? Nie, to nie tak!

=== ANALIZA TEKSTU ===
Znaki: 41 (bez spacji: 32)
Slowa: 10, Zdania: 3
Najdluzsze slowo: "kota"
Samogloski: 15, Spolgloski: 13
Palindrom: NIE
Palindromy w tekscie: ['Ala']
Odwrocone: tak! nie to Nie, Ale? ma Kot kota. ma Ala
3Statystyki ocen – listy, comprehensions, funkcje wbudowane

Cel zadania (~20 min)

Napisz program obliczający zaawansowane statystyki dla zestawu ocen (w skali 0–100). Program pobiera oceny od użytkownika, oblicza średnią, medianę, modę, odchylenie standardowe, klasyfikuje według oceny literowej i rysuje histogram ASCII.

Wymagania szczegółowe:
  • Funkcja srednia(liczby) – suma / liczba.
  • Funkcja mediana(liczby) – wartość środkowa w posortowanej liŚcie (dla parzystej liczby – średnia dwóch środkowych).
  • Funkcja moda(liczby) – wartość występująca najczęściej (zwraca listę, gdy kilka wartości ma tę samą częstotliwość).
  • Funkcja odchylenie_std(liczby) – pierwiastek z wariancji (wzór dla próbki: dzielenie przez n–1).
  • Funkcja klasyfikuj(ocena) – zamienia liczbę na ocenę literową: ≥90 → 5.0, ≥75 → 4.0, ≥60 → 3.0, ≥50 → 2.0, poniżej → 1.0.
  • Użyj list składanych do filtrowania ocen zdanych/niezdanych (próg 50%).
  • Narysuj histogram ASCII: 75.0: ### (3).

Wskazówki

Mediana: sorted(liczby)[n//2] dla nieparzystej długości. Modę znajdziesz zliczając czest[l] = czest.get(l, 0) + 1. Odchylenie standardowe: math.sqrt(sum((x - sr)**2 for x in liczby) / (n-1)). Lista składana: [o for o in oceny if o >= 50].

import math

def srednia(liczby):
    return sum(liczby) / len(liczby) if liczby else 0

def mediana(liczby):
    s = sorted(liczby)
    n = len(s)
    if n % 2 == 1:
        return s[n // 2]
    return (s[n // 2 - 1] + s[n // 2]) / 2

def moda(liczby):
    czest = {}
    for l in liczby:
        czest[l] = czest.get(l, 0) + 1
    max_cz = max(czest.values())
    return sorted([k for k, v in czest.items() if v == max_cz])

def odchylenie_std(liczby):
    if len(liczby) < 2:
        return 0
    sr = srednia(liczby)
    war = sum((x - sr) ** 2 for x in liczby) / (len(liczby) - 1)
    return math.sqrt(war)

def klasyfikuj(ocena):
    if ocena >= 90: return "5.0 (bdb)"
    elif ocena >= 75: return "4.0 (db)"
    elif ocena >= 60: return "3.0 (dst)"
    elif ocena >= 50: return "2.0 (dop)"
    else: return "1.0 (ndst)"

n = int(input("Liczba ocen: "))
oceny = []
for i in range(n):
    o = float(input(f"Ocena {i+1} (0-100): "))
    oceny.append(o)

print(f"\nOceny: {oceny}")
print(f"Posortowane: {sorted(oceny)}")
print(f"Srednia: {srednia(oceny):.2f} -> {klasyfikuj(srednia(oceny))}")
print(f"Mediana: {mediana(oceny)}")
print(f"Moda: {moda(oceny)}")
print(f"Odch. std: {odchylenie_std(oceny):.2f}")
print(f"Min: {min(oceny)}, Max: {max(oceny)}")
zdane = [o for o in oceny if o >= 50]
niezdane = [o for o in oceny if o < 50]
print(f"Zdalo: {len(zdane)} ({len(zdane)/len(oceny)*100:.0f}%)")
print(f"Nie zdalo: {len(niezdane)} ({len(niezdane)/len(oceny)*100:.0f}%)")

print("\nHistogram ocen:")
czest = {}
for l in oceny:
    czest[l] = czest.get(l, 0) + 1
for v in sorted(czest):
    print(f"  {v:>5}: {'#' * czest[v]} ({czest[v]})")
PRZYKLADOWY EKRAN WYNIKOWY:

Liczba ocen: 6
Ocena 1 (0-100): 45
Ocena 2 (0-100): 78
Ocena 3 (0-100): 92
Ocena 4 (0-100): 55
Ocena 5 (0-100): 63
Ocena 6 (0-100): 30

Oceny: [45.0, 78.0, 92.0, 55.0, 63.0, 30.0]
Posortowane: [30.0, 45.0, 55.0, 63.0, 78.0, 92.0]
Srednia: 60.50 -> 3.0 (dst)
Mediana: 59.0
Moda: [30.0, 45.0, 55.0, 63.0, 78.0, 92.0]
Odch. std: 22.39
Min: 30.0, Max: 92.0
Zdalo: 4 (67%)
Nie zdalo: 2 (33%)

Histogram ocen:
   30.0: # (1)
   45.0: # (1)
   55.0: # (1)
   63.0: # (1)
   78.0: # (1)
   92.0: # (1)
4Słownik angielsko-polski – słowniki, zbiory, JSON

Cel zadania (~20 min)

Zaimplementuj interaktywny słownik angielsko-polski. Program przechowuje tłumaczenia w pliku JSON, umożliwia dodawanie, usuwanie, wyszukiwanie oraz naukęsłówek w trybie quizu.

Wymagania szczegółowe:
  • Słownik przechowuj jako słownik Python: {"cat": "kot", "dog": "pies"}.
  • Funkcje wczytaj() i zapisz(slownik) – trwałe przechowywanie w pliku JSON.
  • Funkcja dodaj(slownik) – dodaje nową parę (angielski, polski).
  • Funkcja usun(slownik) – usuwa słowo po angielsku.
  • Funkcja szukaj(slownik) – wyszukuje tłumaczenie.
  • Funkcja quiz(slownik) – losuje 5 słówek, pyta o tłumaczenie, wyświetla wynik punktowy.
  • Menu: 1-Dodaj, 2-Usuń, 3-Szukaj, 4-Wyświetl wszystkie, 5-Quiz, 6-Koniec.

Wskazówki

Moduł json: json.dump(slownik, f, indent=2, ensure_ascii=False) zapisuje ładnie słownik. random.sample(list(slownik.items()), 5) losuje 5 par. sorted(slownik.items()) wyświetla słownik w kolejności alfabetycznej. Sprawdzaj czy plik istnieje przed wczytaniem: os.path.exists(plik).

import json, os, random

PLIK = "slownik.json"

def wczytaj():
    if os.path.exists(PLIK):
        with open(PLIK, "r", encoding="utf-8") as f:
            return json.load(f)
    return {}

def zapisz(slownik):
    with open(PLIK, "w", encoding="utf-8") as f:
        json.dump(slownik, f, indent=2, ensure_ascii=False)

def dodaj(slownik):
    ang = input("Slowo po angielsku: ").strip().lower()
    pl = input("Tlumaczenie: ").strip().lower()
    if ang in slownik:
        print("Slowo juz istnieje!")
        return
    slownik[ang] = pl; zapisz(slownik); print("Dodano!")

def usun(slownik):
    ang = input("Slowo do usuniecia: ").strip().lower()
    if ang in slownik:
        del slownik[ang]; zapisz(slownik); print("Usunieto!")
    else:
        print("Nie znaleziono!")

def szukaj(slownik):
    ang = input("Szukane slowo: ").strip().lower()
    if ang in slownik:
        print(f"{ang} -> {slownik[ang]}")
    else:
        print("Nie znaleziono!")

def quiz(slownik):
    if len(slownik) < 3:
        print("Za malo slow (min. 3)"); return
    pytania = random.sample(list(slownik.items()),
                            min(5, len(slownik)))
    punkty = 0
    for ang, pl in pytania:
        odp = input(f"Jak jest po polsku '{ang}'? ").strip().lower()
        if odp == pl:
            print("Poprawnie!"); punkty += 1
        else:
            print(f"Blad! Poprawna: {pl}")
    print(f"Wynik: {punkty}/{len(pytania)}")

slownik = wczytaj()
while True:
    print(f"\n=== SLOWNIK ({len(slownik)} slow) ===")
    print("1-Dodaj 2-Usun 3-Szukaj 4-Wyswietl 5-Quiz 6-Koniec")
    op = input("Wybor: ")
    if op == "1": dodaj(slownik)
    elif op == "2": usun(slownik)
    elif op == "3": szukaj(slownik)
    elif op == "4":
        for ang, pl in sorted(slownik.items()):
            print(f"  {ang} -> {pl}")
    elif op == "5": quiz(slownik)
    elif op == "6": break
PRZYKLADOWY EKRAN WYNIKOWY:

=== SLOWNIK (0 slow) ===
1-Dodaj 2-Usun 3-Szukaj 4-Wyswietl 5-Quiz 6-Koniec
Wybor: 1
Slowo po angielsku: cat
Tlumaczenie: kot
Dodano!

Wybor: 1
Slowo po angielsku: dog
Tlumaczenie: pies
Dodano!

Wybor: 4
  cat -> kot
  dog -> pies

Wybor: 5
Jak jest po polsku 'cat'? kot
Poprawnie!
Jak jest po polsku 'dog'? pies
Poprawnie!
Wynik: 2/2

Wybor: 6
5Generator haseł z walidacją – moduł random, string, funkcje

Cel zadania (~20 min)

Napisz program do generowania bezpiecznych haseł i oceny ich siły. Program umożliwia konfigurację długości hasła oraz zestawu użytych znaków (wielkie litery, cyfry, znaki specjalne), a następnie ocenia wygenerowane hasła według punktacji.

Wymagania szczegółowe:
  • Funkcja generuj_haslo(dlugosc=12, uzyj_wielkich=True, uzyj_cyfr=True, uzyj_specjalnych=True) – losuje znaki z odpowiedniego zestawu.
  • Funkcja ocen_sile(haslo) – przyznaje punkty: +1 za długość ≥8, +1 za ≥12, +1 za ≥16, +1 za wielką literę, +1 za małą literę, +1 za cyfrę, +1 za znak specjalny. Klasyfikacja: 0–2 „Słabe”, 3–4 „Średnie”, 5–6 „Mocne”, 7 „Bardzo mocne”.
  • Wygeneruj 5 losowych haseł domyślnych i 3 hasła 16-znakowe bez znaków specjalnych – każde z oceną siły.
  • Pozwól użytkownikowi na własne hasło i wyświetl jego ocenę z listą brakujących elementów.

Wskazówki

Moduł string zawiera ascii_lowercase, ascii_uppercase, digits. random.choice(znaki) losuje pojedynczy znak. any(c.isupper() for c in haslo) sprawdza czy jest choć jedna wielka litera. Połącz zestawy znaków: znaki = string.ascii_lowercase + string.ascii_uppercase.

import random, string

def generuj_haslo(dlugosc=12, uzyj_wielkich=True,
                  uzyj_cyfr=True, uzyj_specjalnych=True):
    znaki = string.ascii_lowercase
    if uzyj_wielkich:
        znaki += string.ascii_uppercase
    if uzyj_cyfr:
        znaki += string.digits
    if uzyj_specjalnych:
        znaki += "!@#$%^&*()"
    return "".join(random.choice(znaki) for _ in range(dlugosc))

def ocen_sile(haslo):
    p = 0
    if len(haslo) >= 8: p += 1
    if len(haslo) >= 12: p += 1
    if len(haslo) >= 16: p += 1
    if any(c.isupper() for c in haslo): p += 1
    if any(c.islower() for c in haslo): p += 1
    if any(c.isdigit() for c in haslo): p += 1
    if any(c in "!@#$%^&*()" for c in haslo): p += 1
    if p <= 2: return "Slabe"
    elif p <= 4: return "Srednie"
    elif p <= 6: return "Mocne"
    else: return "Bardzo mocne"

print("=== GENERATOR HASEL ===")
print("\nGenerowanie 5 losowych hasel:")
for i in range(5):
    h = generuj_haslo()
    print(f"  {i+1}. {h}  (sila: {ocen_sile(h)})")

print("\nHasla 16-znakowe bez znakow specjalnych:")
for i in range(3):
    h = generuj_haslo(16, True, True, False)
    print(f"  {i+1}. {h}  (sila: {ocen_sile(h)})")

print("\n=== WALIDACJA HASLA ===")
haslo = input("Podaj haslo do oceny: ")
print(f"Sila hasla: {ocen_sile(haslo)}")
if len(haslo) < 8:
    print("  - haslo za krotkie (min 8)")
if not any(c.isupper() for c in haslo):
    print("  - brak wielkiej litery")
if not any(c.islower() for c in haslo):
    print("  - brak malej litery")
if not any(c.isdigit() for c in haslo):
    print("  - brak cyfry")
if not any(c in "!@#$%^&*()" for c in haslo):
    print("  - brak znaku specjalnego")
PRZYKLADOWY EKRAN WYNIKOWY:

=== GENERATOR HASEL ===

Generowanie 5 losowych hasel:
  1. joua7wHDmkWu  (sila: Mocne)
  2. DiU1Be2YEffV  (sila: Mocne)
  3. tDhOn3fY2$Iq  (sila: Mocne)
  4. @ykzFN@tyNqb  (sila: Mocne)
  5. E8y%!gIijSs&  (sila: Mocne)

Hasla 16-znakowe bez znakow specjalnych:
  1. ZI0Mz4I9rqlQlwBY  (sila: Mocne)
  2. bqCJUQoPKdTG3fJn  (sila: Mocne)
  3. p0TA6gk25XsLbxWA  (sila: Mocne)

=== WALIDACJA HASLA ===
Podaj haslo do oceny: Test123!
Sila hasla: Mocne
6Analizator pliku CSV studentów – csv, wyjątki, file I/O

Cel zadania (~20 min)

Napisz program, który wczytuje dane studentów z pliku CSV (imie,nazwisko,wiek,ocena), oblicza statystyki grupy, wyświetla ranking najlepszych oraz obsługuje błędy (brak pliku, błędne dane). Program ma również generować przykładowy plik CSV, gdy go nie ma.

Wymagania szczegółowe:
  • Funkcja generuj_przykladowy_csv() – tworzy plik studenci.csv z nagłówkami i 6 przykładowymi wierszami.
  • Funkcja wczytaj_studentow(nazwa_pliku) – odczytuje CSV przez csv.DictReader, zwraca listę słowników. W razie błędu (brak pliku, złe dane) zgłasza wyjątek.
  • Funkcja statystyki(studenci) – zwraca słownik z: liczba studentów, średnia ocen, max/min ocena, średni wiek, liczba zdanych/niezdanych (próg 50).
  • Funkcja najlepsi(studenci, n=3) – zwraca n studentów z najwyższą oceną (sortowanie lambda).
  • Użyj bloku try/except do obsługi błędów wejścia/wyjścia.

Wskazówki

csv.DictReader(f) czyta wiersze jako słowniki z nagłówkami jako kluczami. sorted(lista, key=lambda s: -s["ocena"]) sortuje malejąco po ocenie. try: ... except FileNotFoundError: ... obsługuje brak pliku. Do konwersji typów użyj int() i float() wewnątrz try/except Value Error.

import csv, os

PLIK = "studenci.csv"

def generuj_przykladowy_csv():
    dane = [
        ["Imie", "Nazwisko", "Wiek", "Ocena"],
        ["Anna", "Kowalska", "22", "85"],
        ["Jan", "Nowak", "23", "72"],
        ["Piotr", "Wisniewski", "21", "91"],
        ["Kasia", "Zielinska", "24", "45"],
        ["Tomasz", "Adamczyk", "22", "68"],
        ["Marta", "Lewandowska", "23", "78"],
    ]
    with open(PLIK, "w", newline="", encoding="utf-8") as f:
        w = csv.writer(f)
        w.writerows(dane)

def wczytaj_studentow(nazwa_pliku):
    if not os.path.exists(nazwa_pliku):
        raise FileNotFoundError(f"Plik '{nazwa_pliku}' nie istnieje!")
    studenci = []
    with open(nazwa_pliku, "r", encoding="utf-8") as f:
        reader = csv.DictReader(f)
        for i, row in enumerate(reader, 1):
            try:
                studenci.append({
                    "imie": row["Imie"].strip(),
                    "nazwisko": row["Nazwisko"].strip(),
                    "wiek": int(row["Wiek"]),
                    "ocena": float(row["Ocena"]),
                })
            except (ValueError, KeyError) as e:
                print(f"Blad w wierszu {i+1}: {e}")
    return studenci

def statystyki(studenci):
    oceny = [s["ocena"] for s in studenci]
    wiek = [s["wiek"] for s in studenci]
    return {
        "liczba": len(studenci),
        "srednia_ocen": sum(oceny) / len(oceny),
        "max_ocena": max(oceny), "min_ocena": min(oceny),
        "sredni_wiek": sum(wiek) / len(wiek),
        "zdali": sum(1 for o in oceny if o >= 50),
        "nie_zdali": sum(1 for o in oceny if o < 50),
    }

def najlepsi(studenci, n=3):
    return sorted(studenci, key=lambda s: -s["ocena"])[:n]

if not os.path.exists(PLIK):
    generuj_przykladowy_csv()

try:
    studenci = wczytaj_studentow(PLIK)
    for s in studenci:
        print(f"{s['imie']:10} {s['nazwisko']:12} "
              f"wiek: {s['wiek']:2} ocena: {s['ocena']}")

    stat = statystyki(studenci)
    print(f"\n=== STATYSTYKI ===")
    print(f"Liczba: {stat['liczba']}")
    print(f"Srednia ocen: {stat['srednia_ocen']:.2f}")
    print(f"Najwyzsza: {stat['max_ocena']}, "
          f"Najnizsza: {stat['min_ocena']}")
    print(f"Sredni wiek: {stat['sredni_wiek']:.1f}")
    print(f"Zdalo: {stat['zdali']}, "
          f"Nie zdalo: {stat['nie_zdali']}")

    print("\n=== TOP 3 ===")
    for i, s in enumerate(najlepsi(studenci), 1):
        print(f"  {i}. {s['imie']} {s['nazwisko']} - {s['ocena']}")

except FileNotFoundError as e:
    print(f"BLAD: {e}")
except Exception as e:
    print(f"Nieoczekiwany blad: {e}")
PRZYKLADOWY EKRAN WYNIKOWY:

Anna       Kowalska     wiek: 22 ocena: 85.0
Jan        Nowak        wiek: 23 ocena: 72.0
Piotr      Wisniewski   wiek: 21 ocena: 91.0
Kasia      Zielinska    wiek: 24 ocena: 45.0
Tomasz     Adamczyk     wiek: 22 ocena: 68.0
Marta      Lewandowska  wiek: 23 ocena: 78.0

=== STATYSTYKI ===
Liczba: 6
Srednia ocen: 73.17
Najwyzsza: 91.0, Najnizsza: 45.0
Sredni wiek: 22.5
Zdalo: 5, Nie zdalo: 1

=== TOP 3 ===
  1. Piotr Wisniewski - 91.0
  2. Anna Kowalska - 85.0
  3. Marta Lewandowska - 78.0
7Menedżer zadań – funkcje, słowniki, datetime, filtrowanie

Cel zadania (~20 min)

Stwórz system zarządzania zadaniami („To-Do List”), który przechowuje zadania z tytułem, opisem, priorytetem (wysoki/średni/niski) i terminem. Program umożliwia dodawanie, oznaczanie wykonania, filtrowanie i sortowanie zadań oraz trwałe przechowywanie w pliku JSON.

Wymagania szczegółowe:
  • Każde zadanie to słownik: {"tytul": str, "opis": str, "priorytet": str, "termin": str, "wykonane": bool, "utworzono": str}.
  • Funkcja dodaj(zadania) – dodaje nowe zadanie z bieżącą datą utworzenia.
  • Funkcja oznacz(zadania) – przełącza status wykonania (done/not done).
  • Funkcja pokaz(zadania) – wyświetla zadania z opcjami filtrowania (wszystkie/aktywne/wykonane) i sortowania (kolejność/priorytet/termin).
  • Funkcja usun(zadania) – usuwa zadanie po numerze.
  • Zapis/odczyt do pliku JSON przy każdej modyfikacji.

Wskazówki

datetime.now().strftime("%Y-%m-%d %H:%M") daje bieżącą datę. Sortowanie po priorytecie: zdefiniuj kolejność {"wysoki": 0, "sredni": 1, "niski": 2} i użyj key=lambda z: kolejnosc[z["priorytet"]]. Sortowanie po terminie: key=lambda z: z["termin"]. Filtrowanie: lista składana z warunkiem if not z["wykonane"].

import json, os
from datetime import datetime

PLIK = "zadania.json"

def wczytaj():
    if os.path.exists(PLIK):
        with open(PLIK, "r", encoding="utf-8") as f:
            return json.load(f)
    return []

def zapisz(zadania):
    with open(PLIK, "w", encoding="utf-8") as f:
        json.dump(zadania, f, indent=2, ensure_ascii=False)

def dodaj(zadania):
    tytul = input("Tytul: ")
    opis = input("Opis: ")
    priorytet = input("Priorytet (wysoki/sredni/niski): ").lower()
    if priorytet not in ("wysoki", "sredni", "niski"):
        priorytet = "sredni"
    termin = input("Termin (RRRR-MM-DD): ")
    zadania.append({
        "tytul": tytul, "opis": opis,
        "priorytet": priorytet, "termin": termin,
        "wykonane": False,
        "utworzono": datetime.now().strftime("%Y-%m-%d %H:%M"),
    })
    zapisz(zadania); print("Dodano!")

def oznacz(zadania):
    for i, z in enumerate(zadania, 1):
        s = "[X]" if z["wykonane"] else "[ ]"
        print(f"  {i}. {s} {z['tytul']}")
    nr = int(input("Nr do oznaczenia: ")) - 1
    if 0 <= nr < len(zadania):
        zadania[nr]["wykonane"] = not zadania[nr]["wykonane"]
        zapisz(zadania); print("Zmieniono!")
    else:
        print("Nieprawidlowy numer!")

def pokaz(zadania):
    f = input("Filtruj (wszystkie/aktywne/wykonane): ").lower()
    s = input("Sortuj (kolejnosc/priorytet/termin): ").lower()
    if f == "aktywne":
        zad = [z for z in zadania if not z["wykonane"]]
    elif f == "wykonane":
        zad = [z for z in zadania if z["wykonane"]]
    else:
        zad = list(zadania)
    if s == "priorytet":
        kol = {"wysoki": 0, "sredni": 1, "niski": 2}
        zad.sort(key=lambda z: kol.get(z["priorytet"], 3))
    elif s == "termin":
        zad.sort(key=lambda z: z["termin"])
    print(f"\nZadania ({len(zad)}):")
    print("-" * 60)
    for i, z in enumerate(zad, 1):
        st = "OK" if z["wykonane"] else "..."
        print(f"  {i:2}. [{st}] {z['tytul']}")
        print(f"       Priorytet: {z['priorytet']} | "
              f"Termin: {z['termin']}")

def usun(zadania):
    for i, z in enumerate(zadania, 1):
        print(f"  {i}. {z['tytul']}")
    nr = int(input("Nr do usuniecia: ")) - 1
    if 0 <= nr < len(zadania):
        zadania.pop(nr); zapisz(zadania); print("Usunieto!")
    else:
        print("Nieprawidlowy numer!")

zadania = wczytaj()
while True:
    print(f"\n=== ZADANIA ({len(zadania)}) ===")
    print("1-Dodaj 2-Oznacz 3-Pokaz 4-Usun 5-Koniec")
    op = input("Wybor: ")
    if op == "1": dodaj(zadania)
    elif op == "2": oznacz(zadania)
    elif op == "3": pokaz(zadania)
    elif op == "4": usun(zadania)
    elif op == "5": break
PRZYKLADOWY EKRAN WYNIKOWY:

=== ZADANIA (0) ===
1-Dodaj 2-Oznacz 3-Pokaz 4-Usun 5-Koniec
Wybor: 1
Tytul: Nauczyc sie Pythona
Opis: Przerobic wszystkie zadania z listy
Priorytet (wysoki/sredni/niski): wysoki
Termin (RRRR-MM-DD): 2026-07-15
Dodano!

Wybor: 3
Filtruj (wszystkie/aktywne/wykonane): wszystkie
Sortuj (kolejnosc/priorytet/termin): priorytet

Zadania (1):
------------------------------------------------------------
   1. [...] Nauczyc sie Pythona
       Priorytet: wysoki | Termin: 2026-07-15

Wybor: 5
8Konwerter jednostek – funkcje, lambda, map, sys.argv

Cel zadania (~20 min)

Stwórz uniwersalny konwerter jednostek i walut. Program działa w trybie interaktywnym, oferując konwersje temperatury, długości, masy i walut. Zaimplementuj konwersję zbiorczą z użyciem map() i lambda, a także obsługę argumentów linii poleceń przez sys.argv.

Wymagania szczegółowe:
  • Słownik KONWERSJE przechowuje funkcje konwertujące jako lambda: np. "c_f": ("Celsjusz", "Fahrenheit", lambda c: c * 9/5 + 32).
  • Funkcja konwertuj(typ, wartosc) – wywołuje odpowiednią lambdę ze słownika.
  • Funkcja konwertuj_wiele(typ, wartosci) – używa map() do zbiorczej konwersji listy wartości.
  • Menu z wyborem konwersji, obsługa trybu pojedynczej wartości i listy.
  • Program wyświetla przykład użycia map() i lambda do konwersji zbiorczej temperatury.
  • Obsługa sys.argv —help wyświetla instrukcję.

Wskazówki

lambda c: c * 9/5 + 32 to funkcja anonimowa. map(funkcja, lista) stosuje funkcję do każdego elementu listy. sys.argv[0] to nazwa skryptu, sys.argv[1:] to argumenty. list(map(lambda x: konwertuj(typ, x)[2], wartosci)) wykonuje konwersję zbiorczą.

import sys

KONWERSJE = {
    "c_f": ("Celsjusz", "Fahrenheit", lambda c: c * 9/5 + 32),
    "f_c": ("Fahrenheit", "Celsjusz", lambda f: (f-32) * 5/9),
    "m_km": ("Metry", "Kilometry", lambda m: m / 1000),
    "km_m": ("Kilometry", "Metry", lambda km: km * 1000),
    "kg_g": ("Kilogramy", "Gramy", lambda kg: kg * 1000),
    "g_kg": ("Gramy", "Kilogramy", lambda g: g / 1000),
    "usd_pln": ("USD", "PLN", lambda usd: usd * 4.05),
    "pln_usd": ("PLN", "USD", lambda pln: pln / 4.05),
    "eur_pln": ("EUR", "PLN", lambda eur: eur * 4.35),
    "pln_eur": ("PLN", "EUR", lambda pln: pln / 4.35),
}

def konwertuj(typ, wartosc):
    z, na, func = KONWERSJE[typ]
    return z, na, func(wartosc)

def konwertuj_wiele(typ, wartosci):
    z, na, _ = konwertuj(typ, 0)
    wyniki = list(map(lambda w: konwertuj(typ, w)[2], wartosci))
    return z, na, wyniki

if "--help" in sys.argv:
    print("Konwerter jednostek. Uzyj bez argumentow dla trybu "
          "interaktywnego.")
    sys.exit(0)

print("=== KONWERTER JEDNOSTEK ===")
print("\nDostepne konwersje:")
opcje = list(sorted(KONWERSJE.keys()))
for i, k in enumerate(opcje, 1):
    z, na, _ = KONWERSJE[k]
    print(f"  {i}. {z} -> {na}")

wybor = int(input(f"\nWybierz (1-{len(opcje)}): ")) - 1
typ = opcje[wybor]
tryb = input("Tryb (1=poj, 2=lista): ")

if tryb == "2":
    dane = input("Wartosci oddzielone spacjami: ")
    w = list(map(float, dane.split()))
    z, na, wyniki = konwertuj_wiele(typ, w)
    print(f"\nKonwersja {z} -> {na}:")
    for v, wynik in zip(w, wyniki):
        print(f"  {v} {z} = {wynik:.2f} {na}")
else:
    w = float(input("Podaj wartosc: "))
    z, na, wynik = konwertuj(typ, w)
    print(f"{w} {z} = {wynik:.2f} {na}")

print("\n=== PRZYKLAD map() i lambda ===")
temp_c = [0, 10, 20, 30, 100]
temp_f = list(map(lambda c: c * 9/5 + 32, temp_c))
print(f"Celsjusze: {temp_c}")
print(f"Fahrenheity: {temp_f}")
PRZYKLADOWY EKRAN WYNIKOWY:

=== KONWERTER JEDNOSTEK ===

Dostepne konwersje:
  1. Celsjusz -> Fahrenheit
  2. EUR -> PLN
  3. Fahrenheit -> Celsjusz
  4. Gramy -> Kilogramy
  5. Kilogramy -> Gramy
  6. Kilometry -> Metry
  7. Metry -> Kilometry
  8. PLN -> EUR
  9. PLN -> USD
  10. USD -> PLN

Wybierz (1-10): 1
Tryb (1=poj, 2=lista): 1
Podaj wartosc: 25
25.0 Celsjusz = 77.00 Fahrenheit

=== PRZYKLAD map() i lambda ===
Celsjusze: [0, 10, 20, 30, 100]
Fahrenheity: [32.0, 50.0, 68.0, 86.0, 212.0]
9Rejestr pomiarów meteorologicznych – datetime, pliki CSV, wykres ASCII

Cel zadania (~20 min)

Stwórz system do rejestracji dziennych pomiarów meteorologicznych (temperatura min/max, wilgotność, ciśnienie). Program generuje przykładowe dane, oblicza statystyki, rysuje wykres temperatury ASCII i wykrywa fale upałów (3+ kolejnych dni >30°C).

Wymagania szczegółowe:
  • Funkcja generuj_dane_przykladowe() – tworzy 30 dni losowych pomiarów i zapisuje do pomiary.csv.
  • Funkcje zapisz(pomiary) i wczytaj() – obsługa pliku CSV własnym kodem (bez csv.DictReader, dla ćwiczenia operacji na stringach).
  • Funkcja statystyki(pomiary) – oblicza średnie, minima, maksima dla wszystkich wielkości.
  • Funkcja rysuj_wykres_temp(pomiary) – rysuje wykres ASCII dla ostatnich 10 dni: 2026-06-22 3.3 34.7 [#|#################]
  • Wykryj fale upałów (3+ kolejnych dni z temp. max >30°C).
  • Pozwól na dodanie nowego pomiaru z klawiatury.

Wskazówki

datetime.now() - timedelta(days=30) oblicza datę sprzed 30 dni. random.uniform(-5, 10) losuje liczbę zmiennoprzecinkową. Wykres ASCII: "#" * int(temp / 2). Wykrywanie fali upałów: pętla zliczająca kolejne dni spełniające warunek, zapis długości gdy przerwany ciąg.

import os, random
from datetime import datetime, timedelta

PLIK = "pomiary.csv"

def generuj_dane():
    pomiary = []
    start = datetime.now() - timedelta(days=30)
    for i in range(30):
        d = (start + timedelta(days=i)).strftime("%Y-%m-%d")
        pomiary.append({
            "data": d,
            "temp_min": round(random.uniform(-5, 10), 1),
            "temp_max": round(random.uniform(10, 35), 1),
            "wilgotnosc": random.randint(30, 95),
            "cisnienie": random.randint(980, 1040),
        })
    return pomiary

def zapisz(pomiary):
    with open(PLIK, "w", encoding="utf-8") as f:
        f.write("data,temp_min,temp_max,wilgotnosc,cisnienie\n")
        for p in pomiary:
            f.write(f"{p['data']},{p['temp_min']},"
                    f"{p['temp_max']},{p['wilgotnosc']},"
                    f"{p['cisnienie']}\n")

def wczytaj():
    if not os.path.exists(PLIK):
        return []
    pomiary = []
    with open(PLIK, "r", encoding="utf-8") as f:
        lines = f.readlines()
    for line in lines[1:]:
        line = line.strip()
        if not line: continue
        parts = line.split(",")
        if len(parts) >= 5:
            pomiary.append({
                "data": parts[0],
                "temp_min": float(parts[1]),
                "temp_max": float(parts[2]),
                "wilgotnosc": int(parts[3]),
                "cisnienie": int(parts[4]),
            })
    return pomiary

def statystyki(pomiary):
    tmin = [p["temp_min"] for p in pomiary]
    tmax = [p["temp_max"] for p in pomiary]
    wilg = [p["wilgotnosc"] for p in pomiary]
    cis = [p["cisnienie"] for p in pomiary]
    return {
        "dni": len(pomiary),
        "tmin_sr": sum(tmin)/len(tmin),
        "tmax_sr": sum(tmax)/len(tmax),
        "tmin_abs": min(tmin), "tmax_abs": max(tmax),
        "wilg_sr": sum(wilg)/len(wilg),
        "cis_sr": sum(cis)/len(cis),
    }

def wykres(pomiary):
    print(f"\nWykres temperatur (ostatnie 10 dni):")
    print(f"{'Data':<12} {'Min':<6} {'Max':<6} Wykres")
    print("-" * 65)
    for p in pomiary[-10:]:
        sl_min = "#" * max(1, int(abs(p["temp_min"]) / 2))
        sl_max = "#" * max(1, int(p["temp_max"] / 2))
        print(f"{p['data']:<12} {p['temp_min']:<6} "
              f"{p['temp_max']:<6} "
              f"[{sl_min}|{sl_max}]")

if not os.path.exists(PLIK):
    pomiary = generuj_dane()
    zapisz(pomiary)
else:
    pomiary = wczytaj()

stat = statystyki(pomiary)
print(f"Okres: {pomiary[0]['data']} - {pomiary[-1]['data']}")
print(f"Srednia temp. min: {stat['tmin_sr']:.1f} C")
print(f"Srednia temp. max: {stat['tmax_sr']:.1f} C")
print(f"Abs. minimum: {stat['tmin_abs']:.1f} C")
print(f"Abs. maksimum: {stat['tmax_abs']:.1f} C")
print(f"Srednia wilgotnosc: {stat['wilg_sr']:.0f}%")
print(f"Srednie cisnienie: {stat['cis_sr']:.0f} hPa")

wykres(pomiary)

ciag = 0
fale = []
for i, p in enumerate(pomiary):
    if p["temp_max"] > 30:
        ciag += 1
    else:
        if ciag >= 3:
            fale.append((i-ciag, i-1, ciag))
        ciag = 0
if ciag >= 3:
    fale.append((len(pomiary)-ciag, len(pomiary)-1, ciag))

if fale:
    print(f"\nFale upalow (>30 C przez >=3 dni):")
    for s, e, d in fale:
        print(f"  {pomiary[s]['data']} - {pomiary[e]['data']} ({d} dni)")
else:
    print("\nBrak fal upalow.")

if input("\nDodac pomiar? (t/n): ").lower() == "t":
    dzis = datetime.now().strftime("%Y-%m-%d")
    tmin = float(input(f"Tmin ({dzis}): "))
    tmax = float(input(f"Tmax ({dzis}): "))
    wilg = int(input("Wilgotnosc (%): "))
    cis = int(input("Cisnienie (hPa): "))
    pomiary.append({"data": dzis, "temp_min": tmin,
                    "temp_max": tmax, "wilgotnosc": wilg,
                    "cisnienie": cis})
    zapisz(pomiary); print("Zapisano!")
PRZYKLADOWY EKRAN WYNIKOWY:

Okres: 2026-05-28 - 2026-06-26
Srednia temp. min: 2.1 C
Srednia temp. max: 21.9 C
Abs. minimum: -3.9 C
Abs. maksimum: 34.8 C
Srednia wilgotnosc: 59%
Srednie cisnienie: 1008 hPa

Wykres temperatur (ostatnie 10 dni):
Data         Min    Max    Wykres
-----------------------------------------------------------------
2026-06-17  -1.4   11.7   [#|#####]
2026-06-18  1.7    27.9   [#|#############]
2026-06-19  -2.5   28.9   [#|##############]
2026-06-20  9.3    26.8   [####|#############]
2026-06-21  0.8    27.1   [#|#############]
2026-06-22  3.3    34.7   [#|#################]
2026-06-23  6.4    11.7   [###|#####]
2026-06-24  7.4    13.1   [###|######]
2026-06-25  1.9    22.3   [#|###########]
2026-06-26  -1.3   34.8   [#|#################]

Brak fal upalow.

Dodac pomiar? (t/n): n
10Wyszukiwarka plików i tekstu – os.walk, fnmatch, re, sys

Cel zadania (~20 min)

Napisz narzędzie do przeszukiwania dysku: znajduje pliki według wzorca nazwy (np. *.py), a następnie może przeszukać ich zawartość pod kątem wyrażenia regularnego. Program działa interaktywnie, wyświetla listę plików z rozmiarami oraz podsumowanie trafień.

Wymagania szczegółowe:
  • Funkcja szukaj_plikow(katalog, wzorzec, recursive=True) – używa os.walk() i fnmatch.fnmatch() do znajdowania plików pasujących do wzorca.
  • Funkcja szukaj_w_plikach(pliki, wyrazenie) – otwiera każdy plik, szuka linii pasujących do wzorca regex (re.search()), zwraca słownik z plikami i trafieniami.
  • Funkcja podsumowanie(znalezione) – wyświetla liczbę plików z trafieniami, dla każdego pliku pokazuje do 5 pierwszych linii z trafieniami.
  • Program pyta o katalog, wzorzec pliku, tekst do znalezienia i czy szukać rekurencyjnie.
  • Obsłuż błędy odczytu plików (try/except).

Wskazówki

os.walk(katalog) zwraca (root, dirs, files) dla każdego podkatalogu. fnmatch.fnmatch(nazwa, "*.py") sprawdza czy nazwa pasuje do wzorca. re.search(wzorzec, linia, re.IGNORECASE) szuka wzorca w linii. os.path.getsize(path) podaje rozmiar pliku. os.path.relpath(path) daje ścieżkę względną.

import os, re, sys, fnmatch

def szukaj_plikow(katalog, wzorzec, recursive=True):
    znalezione = []
    katalog = os.path.abspath(katalog)
    if recursive:
        for root, dirs, files in os.walk(katalog):
            for f in files:
                if fnmatch.fnmatch(f, wzorzec):
                    znalezione.append(os.path.join(root, f))
    else:
        for f in os.listdir(katalog):
            path = os.path.join(katalog, f)
            if os.path.isfile(path) and fnmatch.fnmatch(f, wzorzec):
                znalezione.append(path)
    return znalezione

def szukaj_w_plikach(pliki, wyrazenie):
    znalezione = {}
    for plik in pliki:
        try:
            with open(plik, "r", encoding="utf-8",
                      errors="ignore") as f:
                linie = f.readlines()
            trafienia = []
            for i, linia in enumerate(linie, 1):
                if re.search(wyrazenie, linia, re.IGNORECASE):
                    trafienia.append((i, linia.rstrip()))
            if trafienia:
                znalezione[plik] = trafienia
        except Exception as e:
            print(f"Blad odczytu {plik}: {e}")
    return znalezione

def podsumowanie(znalezione):
    if not znalezione:
        print("Brak wynikow."); return
    print(f"Trafienia w {len(znalezione)} plikach:")
    for plik, trafienia in sorted(znalezione.items()):
        rel = os.path.relpath(plik)
        print(f"\n  {rel} ({len(trafienia)} trafien):")
        for nr, linia in trafienia[:5]:
            print(f"    linia {nr}: {linia.strip()[:80]}")
        if len(trafienia) > 5:
            print(f"    ... i {len(trafienia)-5} wiecej")

print("=== WYSZUKIWARKA ===")
kat = input("Katalog (ENTER=biezacy): ").strip() or "."
if not os.path.isdir(kat):
    print(f"Blad: '{kat}' nie jest katalogiem!"); sys.exit(1)

wz = input("Wzorzec pliku (np. *.py): ").strip() or "*"
tekst = input("Szukany tekst (ENTER=pomin): ").strip()
rek = input("Rekurencyjnie? (t/n): ").strip().lower() == "t"

pliki = szukaj_plikow(kat, wz, rek)
print(f"\nZnaleziono {len(pliki)} plikow.")

if pliki:
    print(f"\nLista plikow:")
    for p in sorted(pliki):
        roz = os.path.getsize(p)
        print(f"  {os.path.relpath(p)} ({roz} bajtow)")

if tekst and pliki:
    wyniki = szukaj_w_plikach(pliki, tekst)
    podsumowanie(wyniki)
else:
    print("Pominieto wyszukiwanie tekstu.")
PRZYKLADOWY EKRAN WYNIKOWY:

=== WYSZUKIWARKA ===
Katalog (ENTER=biezacy):
Wzorzec pliku (np. *.py): *.py
Szukany tekst (ENTER=pomin):
Rekurencyjnie? (t/n): n

Znaleziono 11 plikow.

Lista plikow:
  SJP_PYTHON_OK.html (175600 bajtow)
  test_z01.py (1503 bajtow)
  test_z02.py (1738 bajtow)
  test_z03.py (1804 bajtow)
  test_z04.py (2082 bajtow)
  test_z05.py (1808 bajtow)
  test_z06.py (2791 bajtow)
  test_z07.py (3220 bajtow)
  test_z08.py (2643 bajtow)
  test_z09.py (4323 bajtow)
  test_z10.py (2747 bajtow)
Pominieto wyszukiwanie tekstu.