Bỏ qua

THỰC HÀNH TỔNG HỢP 2 - CẤU TRÚC ĐIỀU KHIỂN

I. Mục tiêu buổi học

Mục tiêu chính

Buổi học này nhằm củng cố và thực hành kiến thức từ Buổi 6-10, tập trung vào:

  • List và Tuple - Cấu trúc dữ liệu tập hợp
  • Cấu trúc rẽ nhánh - if, elif, else
  • Vòng lặp - for và while
  • Kết hợp điều kiện và vòng lặp để giải bài toán phức tạp

Kỹ năng đạt được

Sau buổi học, học viên sẽ có khả năng:

  • Thành thạo cấu trúc điều khiển trong Python
  • Xử lý dữ liệu với List và Tuple hiệu quả
  • Áp dụng thuật toán cơ bản vào bài toán thực tế
  • Tư duy logic để giải quyết bài toán phức tạp

II. Cấu trúc buổi học (90 phút)

Hoạt động Thời gian Nội dung
Ôn tập nhanh 15 phút Review kiến thức cốt lõi
Thực hành thuật toán cơ bản 40 phút 4 bài thuật toán quan trọng
Thực hành dự án nhỏ 25 phút 1 dự án tích hợp kiến thức
Thảo luận và tối ưu 10 phút Code review và best practices

III. Ôn tập kiến thức (15 phút)

Checklist kiến thức cần nhớ

✅ List và Tuple:

# List - có thể thay đổi
numbers = [1, 2, 3, 4, 5]
numbers.append(6)        # Thêm phần tử
numbers.remove(3)        # Xóa phần tử
numbers[0] = 10         # Sửa phần tử

# Tuple - không thể thay đổi
point = (10, 20)
x, y = point            # Unpacking

✅ Cấu trúc rẽ nhánh:

if condition1:
    # Code block 1
elif condition2:
    # Code block 2
else:
    # Code block 3

✅ Vòng lặp:

# For loop với range
for i in range(1, 6):    # 1, 2, 3, 4, 5
    print(i)

# For loop với list
for item in my_list:
    print(item)

# While loop
count = 0
while count < 5:
    print(count)
    count += 1

IV. Thực hành thuật toán cơ bản (40 phút)

Bài 1: Tìm số nguyên tố (10 phút)

Đề bài: Viết hàm kiểm tra số nguyên tố và tìm tất cả số nguyên tố từ 1 đến n.

Phân tích đề

Khái niệm số nguyên tố: - Số nguyên tố là số tự nhiên lớn hơn 1 chỉ chia hết cho 1 và chính nó - Ví dụ: 2, 3, 5, 7, 11, 13, 17, 19, 23...

Thuật toán kiểm tra: 1. Nếu số < 2 → không phải số nguyên tố 2. Kiểm tra chia hết từ 2 đến √n 3. Nếu không chia hết cho số nào → là số nguyên tố

Input/Output mẫu:

Input Quá trình kiểm tra Output
n = 10 Kiểm tra 2,3,4,5,6,7,8,9,10 [2, 3, 5, 7]
n = 20 Kiểm tra 2→20 [2, 3, 5, 7, 11, 13, 17, 19]
Gợi ý code
def is_prime(num):
    """Kiểm tra số nguyên tố"""
    if num < 2:
        return False

    for i in range(2, int(num ** 0.5) + 1):
        if num % i == 0:
            return False
    return True

def find_primes(n):
    """Tìm tất cả số nguyên tố từ 1 đến n"""
    primes = []
    for num in range(2, n + 1):
        if is_prime(num):
            primes.append(num)
    return primes

# Test
n = int(input("Nhập n: "))
prime_list = find_primes(n)
print(f"Các số nguyên tố từ 1 đến {n}: {prime_list}")
print(f"Tổng cộng có {len(prime_list)} số nguyên tố")

Bài 2: Sắp xếp danh sách (10 phút)

Đề bài: Implement thuật toán sắp xếp nổi bọt (Bubble Sort).

Phân tích đề

Thuật toán Bubble Sort: 1. So sánh 2 phần tử liền kề 2. Nếu phần tử trước > phần tử sau → hoán đổi 3. Lặp lại cho đến khi không còn hoán đổi nào

Ví dụ với [64, 34, 25]: - Lần 1: [34, 25, 64] (64 "nổi" lên cuối) - Lần 2: [25, 34, 64] (34 "nổi" lên vị trí 2) - Kết quả: [25, 34, 64]

Input/Output mẫu:

Input Các bước sắp xếp Output
[64, 34, 25, 12] Bước 1: [34, 25, 12, 64] [12, 25, 34, 64]
Bước 2: [25, 12, 34, 64]
Bước 3: [12, 25, 34, 64]
Gợi ý code
def bubble_sort(arr):
    """Sắp xếp mảng bằng thuật toán nổi bọt"""
    n = len(arr)

    for i in range(n):
        # Flag để tối ưu hóa
        swapped = False

        for j in range(0, n - i - 1):
            if arr[j] > arr[j + 1]:
                # Hoán đổi
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
                swapped = True

        # Nếu không có hoán đổi nào, mảng đã sắp xếp
        if not swapped:
            break

    return arr

# Test
numbers = [64, 34, 25, 12, 22, 11, 90]
print("Mảng gốc:", numbers)

sorted_numbers = bubble_sort(numbers.copy())
print("Mảng đã sắp xếp:", sorted_numbers)

Bài 3: Tìm kiếm trong danh sách (10 phút)

Đề bài: Tìm kiếm tuyến tính và tìm kiếm nhị phân.

Phân tích đề

So sánh 2 thuật toán:

Thuật toán Điều kiện Độ phức tạp Ưu điểm
Linear Search Mảng bất kỳ O(n) Đơn giản, không cần sắp xếp
Binary Search Mảng đã sắp xếp O(log n) Nhanh với mảng lớn

Binary Search hoạt động: 1. Tìm phần tử giữa mảng 2. So sánh với target 3. Loại bỏ một nửa mảng 4. Lặp lại cho đến khi tìm thấy

Ví dụ tìm 7 trong [1,3,5,7,9,11,13,15]: - Bước 1: mid=7 (index 3) → target=7 → tìm thấy!

Gợi ý code
def linear_search(arr, target):
    """Tìm kiếm tuyến tính"""
    for i in range(len(arr)):
        if arr[i] == target:
            return i
    return -1

def binary_search(arr, target):
    """Tìm kiếm nhị phân (mảng đã sắp xếp)"""
    left, right = 0, len(arr) - 1

    while left <= right:
        mid = (left + right) // 2

        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1

    return -1

# Test
numbers = [1, 3, 5, 7, 9, 11, 13, 15]
target = 7

# Tìm kiếm tuyến tính
linear_result = linear_search(numbers, target)
print(f"Tìm kiếm tuyến tính: Vị trí của {target}{linear_result}")

# Tìm kiếm nhị phân
binary_result = binary_search(numbers, target)
print(f"Tìm kiếm nhị phân: Vị trí của {target}{binary_result}")

Bài 4: Phân tích dữ liệu (10 phút)

Đề bài: Tính toán thống kê cơ bản cho một danh sách số.

Phân tích đề

Các chỉ số cần tính:

Chỉ số Công thức Ý nghĩa
Tổng sum(numbers) Tổng tất cả phần tử
Trung bình tổng / số lượng Giá trị trung bình
Median Giá trị giữa (sau sắp xếp) Giá trị trung vị
Min/Max Nhỏ nhất / Lớn nhất Khoảng giá trị

Tính Median: - Nếu n lẻ: median = arr[n//2] - Nếu n chẵn: median = (arr[n//2-1] + arr[n//2])/2

Input/Output mẫu:

Input Tính toán Output
[12,7,3,15,8] Tổng: 45, TB: 9.0 Trung bình: 9.0
Sắp xếp: [3,7,8,12,15] Median: 8
Chẵn: 1, Lẻ: 4 Số chẵn: 1
Gợi ý code
def analyze_data(numbers):
    """Phân tích thống kê cơ bản"""
    if not numbers:
        return None

    # Tính các giá trị cơ bản
    total = sum(numbers)
    count = len(numbers)
    average = total / count

    # Tìm min, max
    minimum = min(numbers)
    maximum = max(numbers)

    # Tìm median
    sorted_nums = sorted(numbers)
    n = len(sorted_nums)
    if n % 2 == 0:
        median = (sorted_nums[n//2 - 1] + sorted_nums[n//2]) / 2
    else:
        median = sorted_nums[n//2]

    # Đếm số chẵn, lẻ
    even_count = sum(1 for x in numbers if x % 2 == 0)
    odd_count = count - even_count

    return {
        'count': count,
        'sum': total,
        'average': round(average, 2),
        'min': minimum,
        'max': maximum,
        'median': median,
        'even_count': even_count,
        'odd_count': odd_count
    }

# Test
data = [12, 7, 3, 15, 8, 9, 11, 6, 14, 10]
stats = analyze_data(data)

print("PHÂN TÍCH DỮ LIỆU")
print("="*30)
print(f"Dữ liệu: {data}")
print(f"Số lượng: {stats['count']}")
print(f"Tổng: {stats['sum']}")
print(f"Trung bình: {stats['average']}")
print(f"Min: {stats['min']}")
print(f"Max: {stats['max']}")
print(f"Median: {stats['median']}")
print(f"Số chẵn: {stats['even_count']}")
print(f"Số lẻ: {stats['odd_count']}")

V. Dự án nhỏ: Quản lý điểm học sinh (25 phút)

Đề bài: Tạo chương trình quản lý điểm học sinh đơn giản.

Yêu cầu chức năng

  1. Nhập danh sách học sinh và điểm
  2. Hiển thị danh sách điểm
  3. Tính thống kê lớp học
  4. Tìm kiếm học sinh theo tên
  5. Sắp xếp theo điểm

Code mẫu

class StudentManager:
    def __init__(self):
        self.students = []  # List of tuples (name, score)

    def add_student(self, name, score):
        """Thêm học sinh"""
        self.students.append((name, score))

    def display_students(self):
        """Hiển thị danh sách học sinh"""
        if not self.students:
            print("Chưa có học sinh nào!")
            return

        print("\nDANH SÁCH HỌC SINH")
        print("="*40)
        print(f"{'STT':<5}{'Tên':<20}{'Điểm':<10}")
        print("-"*40)

        for i, (name, score) in enumerate(self.students, 1):
            print(f"{i:<5}{name:<20}{score:<10}")

    def calculate_stats(self):
        """Tính thống kê lớp"""
        if not self.students:
            return None

        scores = [score for name, score in self.students]
        return analyze_data(scores)

    def find_student(self, search_name):
        """Tìm học sinh theo tên"""
        results = []
        for name, score in self.students:
            if search_name.lower() in name.lower():
                results.append((name, score))
        return results

    def sort_by_score(self, ascending=True):
        """Sắp xếp theo điểm"""
        self.students.sort(key=lambda x: x[1], reverse=not ascending)

def main():
    manager = StudentManager()

    while True:
        print("\n" + "="*50)
        print("QUẢN LÝ ĐIỂM HỌC SINH")
        print("="*50)
        print("1. Thêm học sinh")
        print("2. Hiển thị danh sách")
        print("3. Thống kê lớp")
        print("4. Tìm kiếm học sinh")
        print("5. Sắp xếp theo điểm")
        print("0. Thoát")

        choice = input("\nChọn chức năng (0-5): ")

        if choice == '1':
            name = input("Nhập tên học sinh: ").strip()
            try:
                score = float(input("Nhập điểm: "))
                if 0 <= score <= 10:
                    manager.add_student(name, score)
                    print("✅ Đã thêm học sinh!")
                else:
                    print("❌ Điểm phải từ 0-10!")
            except ValueError:
                print("❌ Điểm phải là số!")

        elif choice == '2':
            manager.display_students()

        elif choice == '3':
            stats = manager.calculate_stats()
            if stats:
                print("\nTHỐNG KÊ LỚP HỌC")
                print("="*30)
                print(f"Số học sinh: {stats['count']}")
                print(f"Điểm trung bình: {stats['average']}")
                print(f"Điểm cao nhất: {stats['max']}")
                print(f"Điểm thấp nhất: {stats['min']}")
            else:
                print("Chưa có dữ liệu!")

        elif choice == '4':
            search_name = input("Nhập tên cần tìm: ")
            results = manager.find_student(search_name)
            if results:
                print(f"\nTìm thấy {len(results)} kết quả:")
                for name, score in results:
                    print(f"- {name}: {score} điểm")
            else:
                print("Không tìm thấy!")

        elif choice == '5':
            order = input("Sắp xếp tăng dần (t) hay giảm dần (g)? ").lower()
            ascending = order == 't'
            manager.sort_by_score(ascending)
            print("✅ Đã sắp xếp!")
            manager.display_students()

        elif choice == '0':
            print("Tạm biệt!")
            break

        else:
            print("Lựa chọn không hợp lệ!")

if __name__ == "__main__":
    main()

VI. Code Review và Best Practices (10 phút)

Các pattern quan trọng đã học

1. Xử lý danh sách:

# Tạo list từ input
numbers = [int(x) for x in input("Nhập các số: ").split()]

# Lọc dữ liệu
even_numbers = [x for x in numbers if x % 2 == 0]

# Tìm max/min với điều kiện
max_even = max([x for x in numbers if x % 2 == 0], default=0)

2. Vòng lặp hiệu quả:

# Enumerate để có index
for i, value in enumerate(my_list):
    print(f"Vị trí {i}: {value}")

# Zip để ghép 2 list
names = ["An", "Bình", "Cường"]
scores = [8, 9, 7]
for name, score in zip(names, scores):
    print(f"{name}: {score}")

3. Error handling:

try:
    number = int(input("Nhập số: "))
    result = 10 / number
except ValueError:
    print("Vui lòng nhập số!")
except ZeroDivisionError:
    print("Không thể chia cho 0!")

VII. Bài tập về nhà

Bài 1: Trò chơi đoán số nâng cao

Yêu cầu:

  • Máy tính random số từ 1-100
  • Người chơi có tối đa 7 lần đoán
  • Hiển thị lịch sử các lần đoán
  • Tính điểm dựa trên số lần đoán
  • Lưu high score

Bài 2: Phân tích văn bản

Yêu cầu:

  • Đọc một đoạn văn từ file hoặc input
  • Đếm frequency của từng từ
  • Tìm từ xuất hiện nhiều nhất
  • Tìm các từ dài nhất/ngắn nhất
  • Export kết quả ra file

Bài 3: Máy tính ma trận

Yêu cầu:

  • Nhập 2 ma trận 2D (dùng list of lists)
  • Thực hiện phép cộng ma trận
  • Thực hiện phép nhân ma trận
  • Tính ma trận chuyển vị
  • Hiển thị kết quả đẹp

VIII. Chuẩn bị cho buổi sau

Buổi tiếp theo sẽ học về Set (Tập hợp) - cấu trúc dữ liệu đặc biệt không chứa phần tử trùng lặp. Hãy ôn lại:

  • Khái niệm tập hợp trong toán học
  • Các phép toán tập hợp: hợp, giao, hiệu
  • List và cách loại bỏ phần tử trùng lặp

💡 Tip học tập: Thuật toán là linh hồn của lập trình. Hãy thường xuyên luyện tập với các bài toán logic để nâng cao tư duy!