Liceum Klasa III 45 minut PP: I.2b-d | s. 342

Lekcja 16: Algorytmy - powtorzenie (teksty, sortowanie, ciagi)

Powtorka z algorytmow tekstowych, sortowania i ciagow liczbowych

📋 Podstawa programowa: I.2b-d
Fibonaccialgorytmyciagipowtorzeniesortowanieszyfr Cezara
00:00
Wprowadzenie
5 min
00:05
Teoria
15 min
00:20
Cwiczenia
15 min
00:35
Podsumowanie
10 min
📚

Teoria

Powtorzenie algorytmow - przeglad kluczowych zagadnien

Na lekcjach w klasach I i II poznawalismy rozne rodzaje algorytmow. Dzis przypomnimy sobie najwazniejsze z nich: algorytmy na tekstach, algorytmy sortowania oraz algorytmy na ciagach liczbowych.

Pamietaj! Algorytm to skonczony ciag precyzyjnie okreslonych krokow, ktory prowadzi do rozwiazania danego problemu. Dobry algorytm jest: poprawny, jednoznaczny, skonczony i efektywny.

1. Algorytmy na tekstach

Szyfr Cezara to jeden z najprostszych szyfrow podstawieniowych. Kazda litera tekstu jawnego jest zastepowana litera znajdujaca sie o stala liczbe pozycji dalej w alfabecie.

def szyfr_cezara(tekst, klucz):
    wynik = ""
    for znak in tekst:
        if znak.isalpha():
            baza = ord('A') if znak.isupper() else ord('a')
            wynik += chr((ord(znak) - baza + klucz) % 26 + baza)
        else:
            wynik += znak
    return wynik

# Szyfrowanie: przesuniecie o 3
print(szyfr_cezara("HELLO", 3))  # KHOOR
# Deszyfrowanie: przesuniecie o -3
print(szyfr_cezara("KHOOR", -3))  # HELLO

Wyszukiwanie wzorca w tekscie (pattern matching) polega na znalezieniu wszystkich wystapien krotszego ciagu znakow (wzorca) w dluzszym tekscie.

def wyszukaj_wzorzec(tekst, wzorzec):
    pozycje = []
    n = len(tekst)
    m = len(wzorzec)
    for i in range(n - m + 1):
        if tekst[i:i+m] == wzorzec:
            pozycje.append(i)
    return pozycje

print(wyszukaj_wzorzec("ababcababd", "abab"))  # [0, 5]

2. Algorytmy sortowania

Przypomnienie najwazniejszych metod sortowania:

  • Sortowanie babelkowe - porownujemy sasiednie elementy i zamieniamy je miejscami, jesli sa w zlej kolejnosci. Zlozonosc: O(n2)
  • Sortowanie przez wstawianie - kazdy element wstawiamy na odpowiednie miejsce w juz posortowanej czesci. Zlozonosc: O(n2)
  • Sortowanie przez wybieranie - wybieramy minimum z nieposortowanej czesci i wstawiamy na koniec posortowanej. Zlozonosc: O(n2)
# Sortowanie babelkowe
def bubble_sort(lista):
    n = len(lista)
    for i in range(n - 1):
        for j in range(n - 1 - i):
            if lista[j] > lista[j + 1]:
                lista[j], lista[j + 1] = lista[j + 1], lista[j]
    return lista

# Sortowanie przez wstawianie
def insertion_sort(lista):
    for i in range(1, len(lista)):
        klucz = lista[i]
        j = i - 1
        while j >= 0 and lista[j] > klucz:
            lista[j + 1] = lista[j]
            j -= 1
        lista[j + 1] = klucz
    return lista

3. Ciagi liczbowe - Fibonacci i inne

Ciag Fibonacciego: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ... Kazdy kolejny element jest suma dwoch poprzednich.

def fibonacci(n):
    if n <= 0:
        return 0
    elif n == 1:
        return 1
    a, b = 0, 1
    for _ in range(2, n + 1):
        a, b = b, a + b
    return b

# Wypisz pierwsze 10 wyrazow
for i in range(10):
    print(fibonacci(i), end=" ")  # 0 1 1 2 3 5 8 13 21 34
Wersja iteracyjna vs rekurencyjna: Wersja iteracyjna ciagu Fibonacciego ma zlozonosc O(n), natomiast naiwna rekurencja ma zlozonosc wykladnicza O(2n). Dlatego w praktyce stosujemy wersje iteracyjna lub rekurencje z pamietaniem wynikow (memoizacja).
✏️

Zadania

Latwe

Zadanie 1: Szyfr Cezara - szyfrowanie i deszyfrowanie

Napisz program, ktory pobiera od uzytkownika tekst i klucz (liczbe calkowita), a nastepnie szyfruje tekst szyfrem Cezara. Program powinien rowniez oferowac mozliwosc deszyfrowania.

Pokaz przykladowe rozwiazanie
def szyfr_cezara(tekst, klucz):
    wynik = ""
    for znak in tekst:
        if znak.isalpha():
            baza = ord('A') if znak.isupper() else ord('a')
            wynik += chr((ord(znak) - baza + klucz) % 26 + baza)
        else:
            wynik += znak
    return wynik

tekst = input("Podaj tekst: ")
klucz = int(input("Podaj klucz: "))
wybor = input("(S)zyfruj czy (D)eszyfruj? ").upper()

if wybor == "S":
    print("Zaszyfrowany:", szyfr_cezara(tekst, klucz))
else:
    print("Odszyfrowany:", szyfr_cezara(tekst, -klucz))
Srednie

Zadanie 2: Porownanie sortowan

Zaimplementuj trzy algorytmy sortowania (babelkowe, przez wstawianie, przez wybieranie). Zmierz czas sortowania losowej tablicy 1000 elementow kazdym algorytmem. Ktory jest najszybszy w praktyce? Czy wynik jest zgodny z teoria?

Pokaz przykladowe rozwiazanie
import time
import random

def bubble_sort(lst):
    lst = lst[:]
    n = len(lst)
    for i in range(n-1):
        for j in range(n-1-i):
            if lst[j] > lst[j+1]:
                lst[j], lst[j+1] = lst[j+1], lst[j]
    return lst

def insertion_sort(lst):
    lst = lst[:]
    for i in range(1, len(lst)):
        k = lst[i]
        j = i - 1
        while j >= 0 and lst[j] > k:
            lst[j+1] = lst[j]
            j -= 1
        lst[j+1] = k
    return lst

def selection_sort(lst):
    lst = lst[:]
    n = len(lst)
    for i in range(n):
        min_idx = i
        for j in range(i+1, n):
            if lst[j] < lst[min_idx]:
                min_idx = j
        lst[i], lst[min_idx] = lst[min_idx], lst[i]
    return lst

dane = [random.randint(1, 10000) for _ in range(1000)]

for nazwa, funkcja in [("Babelkowe", bubble_sort),
                        ("Wstawianie", insertion_sort),
                        ("Wybieranie", selection_sort)]:
    start = time.time()
    funkcja(dane)
    czas = time.time() - start
    print(f"{nazwa}: {czas:.4f} s")
Srednie

Zadanie 3: Ciag Fibonacciego - wersje

Zaimplementuj ciag Fibonacciego w trzech wersjach: iteracyjnej, rekurencyjnej i rekurencyjnej z memoizacja. Porownaj czas obliczenia F(30) i F(35) kazdym sposobem.

Pokaz przykladowe rozwiazanie
import time
from functools import lru_cache

def fib_iter(n):
    if n <= 1: return n
    a, b = 0, 1
    for _ in range(2, n+1):
        a, b = b, a+b
    return b

def fib_rek(n):
    if n <= 1: return n
    return fib_rek(n-1) + fib_rek(n-2)

@lru_cache(maxsize=None)
def fib_memo(n):
    if n <= 1: return n
    return fib_memo(n-1) + fib_memo(n-2)

for n in [30, 35]:
    print(f"\n--- F({n}) ---")
    for nazwa, f in [("Iteracyjna", fib_iter),
                      ("Rekurencyjna", fib_rek),
                      ("Memoizacja", fib_memo)]:
        start = time.time()
        wynik = f(n)
        czas = time.time() - start
        print(f"{nazwa}: {wynik} ({czas:.4f} s)")
Trudne

Zadanie 4: Lamanie szyfru Cezara

Napisz program, ktory bez znajomosci klucza probuje zlamac szyfr Cezara metoda brute-force. Wypisz wynik deszyfrowania dla wszystkich 25 mozliwych kluczy. Dodaj analiza czestotliwosci liter (najczestsza litera w polskim to 'A', w angielskim 'E').

Pokaz przykladowe rozwiazanie
def deszyfruj(tekst, klucz):
    wynik = ""
    for z in tekst:
        if z.isalpha():
            baza = ord('A') if z.isupper() else ord('a')
            wynik += chr((ord(z) - baza - klucz) % 26 + baza)
        else:
            wynik += z
    return wynik

def analiza_czestotliwosci(tekst):
    freq = {}
    for z in tekst.upper():
        if z.isalpha():
            freq[z] = freq.get(z, 0) + 1
    if not freq:
        return None
    return max(freq, key=freq.get)

szyfr = input("Podaj zaszyfrowany tekst: ")
print("\n--- Brute force (wszystkie klucze) ---")
for k in range(1, 26):
    print(f"Klucz {k:2d}: {deszyfruj(szyfr, k)}")

# Analiza czestotliwosci
naj = analiza_czestotliwosci(szyfr)
if naj:
    klucz_ang = (ord(naj) - ord('E')) % 26
    klucz_pol = (ord(naj) - ord('A')) % 26
    print(f"\nNajczestsza litera: {naj}")
    print(f"Prawdopodobny klucz (ang): {klucz_ang} -> {deszyfruj(szyfr, klucz_ang)}")
    print(f"Prawdopodobny klucz (pol): {klucz_pol} -> {deszyfruj(szyfr, klucz_pol)}")
🎥

Materialy wideo

Liczby, potęgi, ciągi - klasa 8 szkoły podstawowej
Jacek Grotkiewicz
Czym jest algorytm - najważniejsza podstawa programowania
Kreatywny Koder
🎧

Podcasty

✔️

Quiz - sprawdz sie!

📜

Podstawa programowa

← Poprzednia lekcja Lekcja 17: Projekt indywidualny - analiza →