Zestawy zadań z poprzednich sesji. Praktyka pod warunki egzaminu INF.04.
Egzamin praktyczny INF.04 trwa 150 minut. Zdający otrzymuje zadanie do wykonania na komputerze — zazwyczaj jedno większe lub kilka mniejszych powiązanych.
# Obszar 1: Przetwarzanie danych z pliku
# - Wczytaj dane z pliku CSV/TXT
# - Oblicz statystyki (min, max, średnia)
# - Posortuj i wypisz wyniki
# - Zapisz przetworzone dane do nowego pliku
# Obszar 2: Algorytmy
# - Implementacja algorytmu sortowania
# - Wyszukiwanie (liniowe lub binarne)
# - NWD, NWW, liczby pierwsze
# - Rekurencja (silnia, Fibonacci)
# Obszar 3: Aplikacja konsolowa
# - Menu z pętlą while
# - Walidacja danych wejściowych
# - Operacje na listach/słownikach
# - Formatowanie wyjścia w tabeli
# Obszar 4: Aplikacja webowa (Flask)
# - Prosta strona z formularzem
# - Wyświetlanie danych z listy/słownika
# - Podstawowy CRUD
# - Szablony Jinja2
Plik uczniowie.txt zawiera dane uczniów — każda linia to: imię, nazwisko i trzy oceny oddzielone przecinkami. Wczytaj plik, oblicz średnią każdego ucznia. Wypisz na ekran uczniów z wyróżnieniem najlepszego. Zapisz do pliku wyniki.txt posortowaną listę: miejsce, imię i nazwisko, średnia.
def wczytaj_uczniow(nazwa_pliku):
uczniowie = []
try:
with open(nazwa_pliku, "r",
encoding="utf-8") as f:
for linia in f:
linia = linia.strip()
if not linia:
continue
czesci = linia.split(",")
imie = czesci[0].strip()
nazwisko = czesci[1].strip()
oceny = [int(x.strip())
for x in czesci[2:]]
srednia = sum(oceny) / len(oceny)
uczniowie.append({
"imie": imie,
"nazwisko": nazwisko,
"oceny": oceny,
"srednia": round(srednia, 2)
})
except FileNotFoundError:
print(f"Błąd: brak pliku {nazwa_pliku}")
return uczniowie
def zapisz_wyniki(uczniowie, nazwa_pliku):
posortowani = sorted(uczniowie,
key=lambda u: u["srednia"],
reverse=True)
with open(nazwa_pliku, "w",
encoding="utf-8") as f:
f.write(f"{'Msc':<5} {'Imię i nazwisko':<25}"
f" {'Średnia':>8}\n")
f.write("-" * 40 + "\n")
for i, u in enumerate(posortowani, 1):
pelne = f"{u['imie']} {u['nazwisko']}"
f.write(f"{i:<5} {pelne:<25}"
f" {u['srednia']:>8.2f}\n")
return posortowani
# Generuj przykładowy plik
with open("uczniowie.txt", "w",
encoding="utf-8") as f:
f.write("Kasia, Nowak, 5, 4, 5\n")
f.write("Marek, Kowal, 3, 4, 3\n")
f.write("Zofia, Wiśniewska, 5, 5, 4\n")
f.write("Piotr, Zając, 2, 3, 4\n")
uczniowie = wczytaj_uczniow("uczniowie.txt")
posortowani = zapisz_wyniki(uczniowie, "wyniki.txt")
print(f"{'Msc':<5} {'Imię i nazwisko':<25} {'Śr':>6}")
print("-" * 38)
for i, u in enumerate(posortowani, 1):
pelne = f"{u['imie']} {u['nazwisko']}"
marker = " ← NAJLEPSZY" if i == 1 else ""
print(f"{i:<5} {pelne:<25} "
f"{u['srednia']:>6.2f}{marker}")
linia.split(",") dzieli po przecinku. Pierwsze dwa pola to imię i nazwisko, reszta to oceny — czesci[2:] pobiera wszystkie od trzeciego elementu. List comprehension z int(x.strip()) konwertuje każdą.
if i == 1 po posortowaniu — pierwszy element to najlepszy uczeń. Prosty warunek, duże wrażenie przy wypisywaniu.
Na podstawie tych samych danych wypisz: średnią klasy, medianę średnich, odchylenie standardowe, ile uczniów ma średnią powyżej średniej klasy, jaka to wartość procentowa.
import math
def statystyki_klasy(uczniowie):
if not uczniowie:
return
srednie = [u["srednia"] for u in uczniowie]
n = len(srednie)
# Średnia klasy
sr_klasy = sum(srednie) / n
# Mediana
posort = sorted(srednie)
if n % 2 == 0:
mediana = (posort[n//2-1] + posort[n//2]) / 2
else:
mediana = posort[n//2]
# Odchylenie standardowe
wariancja = sum((x - sr_klasy)**2
for x in srednie) / n
odch_std = math.sqrt(wariancja)
# Powyżej średniej
pow_sr = [u for u in uczniowie
if u["srednia"] > sr_klasy]
print("\n=== STATYSTYKI KLASY ===")
print(f"Liczba uczniów: {n}")
print(f"Średnia klasy: {sr_klasy:.2f}")
print(f"Mediana: {mediana:.2f}")
print(f"Odchylenie std: {odch_std:.2f}")
print(f"Powyżej średniej: "
f"{len(pow_sr)} "
f"({len(pow_sr)/n*100:.1f}%)")
statystyki_klasy(uczniowie)
sum() oblicza każdy składnik. math.sqrt() pierwiastkuje wynik. Nie potrzebujemy importu statistics.
sorted()) żeby nie modyfikować oryginału.
len(pow_sr)/n*100:.1f — ręczne obliczenie procenta z jednym miejscem po przecinku. Alternatywa: :.1% ale wtedy nie mnożymy przez 100.
Napisz program który: (a) znajdzie wszystkie liczby doskonałe do 10000, (b) sprawdzi czy dwie wczytane liczby są zaprzyjaźnione (suma dzielników właściwych pierwszej = druga i odwrotnie). Wypisz wyniki w czytelnym formacie.
def suma_dzielnikow(n):
"""Suma dzielników właściwych n (bez n)."""
if n <= 1:
return 0
suma = 1
i = 2
while i * i <= n:
if n % i == 0:
suma += i
if i != n // i:
suma += n // i
i += 1
return suma
def czy_doskonala(n):
return n > 1 and suma_dzielnikow(n) == n
def czy_zaprzyjaznione(a, b):
return (a != b and
suma_dzielnikow(a) == b and
suma_dzielnikow(b) == a)
# Liczby doskonałe do 10000
print("Liczby doskonałe do 10000:")
for n in range(2, 10001):
if czy_doskonala(n):
dziel = [i for i in range(1, n)
if n % i == 0]
print(f" {n} = {' + '.join(map(str,dziel))}")
# Liczby zaprzyjaźnione
print("\nSprawdzanie zaprzyjaźnienia:")
a = int(input("Pierwsza liczba: "))
b = int(input("Druga liczba: "))
if czy_zaprzyjaznione(a, b):
print(f"{a} i {b} są zaprzyjaźnione!")
print(f" Suma dzielników {a}: "
f"{suma_dzielnikow(a)}")
print(f" Suma dzielników {b}: "
f"{suma_dzielnikow(b)}")
else:
print(f"{a} i {b} NIE są zaprzyjaźnione.")
print(f" σ({a}) = {suma_dzielnikow(a)}")
print(f" σ({b}) = {suma_dzielnikow(b)}")
√n — jeśli i dzieli n, to n/i też jest dzielnikiem. Dodajemy oba jednocześnie. Warunek i != n//i zapobiega podwójnemu liczeniu dzielnika równego √n.
czy_doskonala i czy_zaprzyjaznione to eleganckie jednowierszowe funkcje. Warunek a != b wyklucza przypadek gdy obie liczby są równe.
join() łączy je znakiem + . Wynik: 6 = 1 + 2 + 3.
Wczytaj n. Wypełnij macierz n×n liczbami od 1 do n² spiralnie (od lewego górnego rogu, w prawo, potem w dół, w lewo, w górę...). Wypisz macierz w czytelnym formacie.
def spirala(n):
# Pusta macierz n×n
m = [[0] * n for _ in range(n)]
# Kierunki: prawo, dół, lewo, góra
dr = [0, 1, 0, -1]
dc = [1, 0, -1, 0]
r = c = kierunek = 0
for liczba in range(1, n*n + 1):
m[r][c] = liczba
# Następna pozycja
nr = r + dr[kierunek]
nc = c + dc[kierunek]
# Zmień kierunek jeśli wyjście poza macierz
# lub komórka już wypełniona
if (nr < 0 or nr >= n or
nc < 0 or nc >= n or
m[nr][nc] != 0):
kierunek = (kierunek + 1) % 4
nr = r + dr[kierunek]
nc = c + dc[kierunek]
r, c = nr, nc
return m
n = int(input("Rozmiar spirali n: "))
m = spirala(n)
# Wypisanie
szerokosc = len(str(n * n))
for wiersz in m:
print(" ".join(f"{x:{szerokosc}}"
for x in wiersz))
(kierunek+1) % 4.
szerokosc = len(str(n*n)) — dla n=4 największa liczba to 16 (2 cyfry). Formatowanie f"{x:{szerokosc}}" wyrównuje wszystkie liczby do tej samej szerokości.
Napisz program z menu: (1) dodaj książkę (tytuł, autor, rok), (2) wyświetl wszystkie posortowane po autorze, (3) wyszukaj po tytule lub autorze (częściowe dopasowanie), (4) usuń książkę po ID, (5) zapisz do pliku, (6) wczytaj z pliku, (0) wyjście.
import csv, os
biblioteka = []
next_id = 1
def dodaj(tytul, autor, rok):
global next_id
biblioteka.append({
"id": next_id,
"tytul": tytul,
"autor": autor,
"rok": rok
})
next_id += 1
print(f"Dodano: '{tytul}'")
def wyswietl():
if not biblioteka:
print("Biblioteka jest pusta.")
return
posort = sorted(biblioteka,
key=lambda k: k["autor"])
print(f"\n{'ID':<5} {'Autor':<20} "
f"{'Tytuł':<25} {'Rok':>5}")
print("-" * 57)
for k in posort:
print(f"{k['id']:<5} {k['autor']:<20} "
f"{k['tytul']:<25} {k['rok']:>5}")
def szukaj(fraza):
fraza = fraza.lower()
wyniki = [k for k in biblioteka
if fraza in k["tytul"].lower()
or fraza in k["autor"].lower()]
if wyniki:
print(f"Znaleziono {len(wyniki)} wyników:")
for k in wyniki:
print(f" [{k['id']}] {k['autor']} "
f"— {k['tytul']} ({k['rok']})")
else:
print("Brak wyników.")
def usun(book_id):
global biblioteka
przed = len(biblioteka)
biblioteka = [k for k in biblioteka
if k["id"] != book_id]
if len(biblioteka) < przed:
print(f"Usunięto książkę ID={book_id}")
else:
print(f"Brak książki o ID={book_id}")
def zapisz(plik="biblioteka.csv"):
with open(plik, "w", newline="",
encoding="utf-8") as f:
writer = csv.DictWriter(
f, fieldnames=["id","tytul",
"autor","rok"])
writer.writeheader()
writer.writerows(biblioteka)
print(f"Zapisano {len(biblioteka)} książek.")
def wczytaj(plik="biblioteka.csv"):
global biblioteka, next_id
if not os.path.exists(plik):
print("Brak pliku."); return
with open(plik, "r", newline="",
encoding="utf-8") as f:
reader = csv.DictReader(f)
biblioteka = [{
"id": int(r["id"]),
"tytul": r["tytul"],
"autor": r["autor"],
"rok": int(r["rok"])
} for r in reader]
if biblioteka:
next_id = max(k["id"]
for k in biblioteka) + 1
print(f"Wczytano {len(biblioteka)} książek.")
# Menu główne
while True:
print("\n=== BIBLIOTEKA ===")
print("1. Dodaj książkę")
print("2. Wyświetl wszystkie")
print("3. Wyszukaj")
print("4. Usuń książkę")
print("5. Zapisz do pliku")
print("6. Wczytaj z pliku")
print("0. Wyjście")
wybor = input("Wybór: ").strip()
if wybor == "1":
t = input("Tytuł: ").strip()
a = input("Autor: ").strip()
r = int(input("Rok: "))
dodaj(t, a, r)
elif wybor == "2":
wyswietl()
elif wybor == "3":
szukaj(input("Szukaj: "))
elif wybor == "4":
usun(int(input("ID do usunięcia: ")))
elif wybor == "5":
zapisz()
elif wybor == "6":
wczytaj()
elif wybor == "0":
print("Do widzenia!"); break
else:
print("Nieznana opcja.")
fraza in k["tytul"].lower() — operator in sprawdza czy fraza jest podciągiem. .lower() zapewnia wyszukiwanie bez rozróżniania wielkości liter.
next_id = max(k["id"] for k in biblioteka) + 1 — nowe ID musi być większe od wszystkich istniejących. Bez tego po wczytaniu z pliku ID mogłyby się powtarzać.
fieldnames definiuje kolejność kolumn w pliku CSV.
Każde zadanie poniżej to pełnoprawne zadanie egzaminacyjne. Rozwiązuj je w warunkach zbliżonych do egzaminu — ustaw timer na 30–45 minut i nie zaglądaj do notatek.
Sklep — zestawienie sprzedaży
Plik CSV: produkt, kategoria, cena, ilość. Wczytaj, oblicz przychód dla każdego produktu i każdej kategorii. Wypisz top 3 produktów i najlepszą kategorię. Zapisz raport do TXT.
Kalkulator ONP
Zaimplementuj kalkulator działający w Odwrotnej Notacji Polskiej (np. "3 4 + 2 *" = 14). Używaj stosu (lista). Obsłuż błędy: dzielenie przez 0, za mało operandów.
Harmonogram zajęć
Przechowuj plan lekcji jako słownik {dzień: [lista przedmiotów]}. Zaimplementuj: dodaj/usuń przedmiot, wypisz plan na dany dzień, znajdź w którym dniu jest dany przedmiot.
Szyfrowanie XOR
Zaimplementuj szyfrowanie XOR: każdy znak tekstu XORuj z odpowiadającym znakiem klucza (klucz powtarzaj). Zaszyfruj i odszyfruj tekst. Wypisz hex każdego bajtu.
ord(), ^ operator XOR, chr(), klucz: klucz[i % len(klucz)]Generator sudoku — walidator
Wczytaj planszę sudoku 9×9 (0 = puste pole). Sprawdź poprawność: czy każdy wiersz, kolumna i kwadrat 3×3 zawiera cyfry 1–9 bez powtórzeń (ignoruj zera). Wypisz które reguły są naruszone.
Aplikacja Flask — ankieta
Aplikacja webowa: strona z ankietą (3–5 pytań wielokrotnego wyboru), zbieranie odpowiedzi, wyświetlanie statystyk (ile % wybrało każdą opcję) na osobnej stronie wyników.