Giải bài tập SGK: Bài 32: Ôn tập lập trình Python – Tin học 10

Mục lục [Ẩn]

Chọn đến phần học sinh cần nhanh chóng thông qua mục lục bằng cách click đến phần đó

Thực hành các nhiệm vụ trang 153 – 155

Nhiệm vụ 1 trang 153

Đề bài: Viết chương trình nhập họ tên đầy đủ từ bàn phím, ví dụ "Nguyễn Thị Mai Hương", sau đó tách riêng phần tên, họ, đệm và in ra màn hình.

Hướng dẫn thực hành:

Ý tưởng:

  • Tách họ tên thành danh sách các từ bằng split().
  • Phần tử đầu tiênhọ, phần tử cuốitên, các phần tử ở giữađệm.
  • Dùng " ".join(slist[1:n-1]) để ghép phần đệm lại thành xâu.
hoten = input("Nhập họ tên đầy đủ của em: ")
slist = hoten.split()
n = len(slist)
ho = slist[0]
ten = slist[n-1]
dem = " ".join(slist[1:n-1])
print("Tên của em là", ten)
print("Họ của em là", ho)
if n > 2:
    print("Đệm của em là", dem)

Ví dụ khi chạy (nhập "Nguyễn Thị Mai Hương"):

  • slist $= $ ["Nguyễn", "Thị", "Mai", "Hương"], $n = 4$.
  • $\text{ho} = $ "Nguyễn", $\text{ten} = $ "Hương".
  • $\text{dem} = $ " ".join(["Thị", "Mai"]) $= $ "Thị Mai".
Nhập họ tên đầy đủ của em: Nguyễn Thị Mai Hương
Tên của em là Hương
Họ của em là Nguyễn
Đệm của em là Thị Mai

Chú ý: Điều kiện if n > 2 để chỉ in đệm khi họ tên có từ $3$ từ trở lên (nếu chỉ có $2$ từ thì không có đệm).

Nhiệm vụ 2 trang 153 – 154

Đề bài: Trọng lượng của em trên các hành tinh khác. Chương trình yêu cầu nhập trọng lượng của em (theo đơn vị N) trên Trái Đất và tính trọng lượng của em trên một hành tinh khác.

Hướng dẫn thực hành:

Cơ sở vật lí: Công thức trọng lượng:

$$P = m \times g \quad (1)$$

Trong đó $P$ là trọng lượng (N), $m$ là khối lượng (kg), $g$ là gia tốc trọng trường (m/s²). Trên Trái Đất $g = 9.8$ m/s².

Vì khối lượng $m$ không đổi nên từ $(1)$ ta có:

$$P = P_0 \times \dfrac{g}{9.8} \quad (2)$$

Với $P_0$ là trọng lượng trên Trái Đất, $g$ là gia tốc trọng trường của hành tinh khác.

Chương trình:

def string(w):
    s = ""
    for i in range(len(w)):
        s = s + str(i+1) + ". " + w[i] + " "
    return s

planet = ["Mặt Trăng","Hoả tinh","Kim tinh","Mộc tinh","Thổ tinh","Mặt Trời"]
gravities = [1.62, 3.711, 8.83, 24.79, 10.44, 274.0]
P_earth = float(input("Nhập trọng lượng của em, tính theo N: "))
k = int(input("Nhập số thứ tự hành tinh\n" + string(planet) + ": "))
Grp = gravities[k-1]
P = round(P_earth*Grp/9.8, 3)
print("Trọng lượng của em trên", planet[k-1], "là:", P, "N")

Giải thích các phần:

  • Hàm string(w): tạo xâu hiển thị danh sách hành tinh kèm số thứ tự (vd: "1. Mặt Trăng 2. Hoả tinh ...").
  • Danh sách planet: tên các hành tinh.
  • Danh sách gravities: gia tốc $g$ tương ứng (cùng thứ tự).
  • Nhập $P_{\text{earth}}$ và chọn hành tinh thứ $k$.
  • Tính $P$ theo công thức $(2)$, làm tròn $3$ chữ số thập phân bằng round().

Ví dụ khi chạy (nhập $P_{\text{earth}} = 500$, chọn hành tinh số $1$ — Mặt Trăng):

  • $P = 500 \times \dfrac{1.62}{9.8} \approx 82.653$ N. ✓

Nhiệm vụ 3 trang 154 – 155

Đề bài: Kiểm tra tính hợp lệ của ba tham số ngày, tháng, năm. Chương trình yêu cầu nhập ngày, tháng, năm theo khuôn dạng 08-02-2021, sau đó thông báo dữ liệu có hợp lệ hay không.

Hướng dẫn thực hành:

Ý tưởng:

  • Dùng danh sách thang = [31, 28, 31, 30, ..., 31] lưu số ngày của $12$ tháng (mặc định tháng $2$ là $28$).
  • Nếu năm nhuận → tháng $2$ có $29$ ngày → cập nhật thang[1] = 29.
  • Điều kiện hợp lệ: $\text{year} > 0$ và $1 \leq \text{month} \leq 12$ và $1 \leq \text{day} \leq \text{thang}[\text{month}-1]$.

Chương trình:

thang = [31,28,31,30,31,30,31,31,30,31,30,31]

def nhuan(year):
    return year%400 == 0 or (year%4 == 0 and year%100 != 0)

date = input("Nhập thời gian theo dạng ngày - tháng - năm: ")
tg = date.split("-")
day,month,year = int(tg[0]),int(tg[1]),int(tg[2])
if nhuan(year):
    thang[1] = 29
else:
    thang[1] = 28
if year > 0 and 1 <= month <= 12 and 1 <= day <= thang[month-1]:
    print(day,"-",month,"-",year, "là hợp lệ")
else:
    print("Bộ dữ liệu đã nhập không hợp lệ")

Ví dụ khi chạy:

  • Với 29-2-2024 (năm nhuận): hợp lệ ✓
  • Với 31-4-2024: không hợp lệ (tháng $4$ chỉ có $30$ ngày) ✗
  • Với 29-2-2023 (không nhuận): không hợp lệ ✗

Chú ý: Cú pháp 1 <= month <= 12so sánh kép trong Python, tương đương 1 <= month and month <= 12.

Luyện tập trang 155

Luyện tập trang 155

Đề bài: Viết chương trình nhập số $n$, sau đó nhập danh sách tên học sinh với họ, đệm, tên. Sắp xếp tên học sinh trong lớp theo bảng chữ cái. Đưa kết quả ra màn hình.

Lời giải:

Ý tưởng:

  • Nhập $n$ rồi nhập $n$ họ tên đầy đủ, lưu vào danh sách.
  • Dùng lệnh sort() để sắp xếp danh sách theo bảng chữ cái.
n = int(input("Nhập số học sinh: "))
ds = []
for i in range(n):
    s = input("Nhập họ tên học sinh thứ " + str(i+1) + ": ")
    ds.append(s)

ds.sort()
print("Danh sách học sinh sau khi sắp xếp:")
for hoten in ds:
    print(hoten)

Ví dụ khi chạy (nhập $n = 3$):

Nhập số học sinh: 3
Nhập họ tên học sinh thứ 1: Trần Văn An
Nhập họ tên học sinh thứ 2: Lê Thị Bình
Nhập họ tên học sinh thứ 3: Nguyễn Văn Cường
Danh sách học sinh sau khi sắp xếp:
Lê Thị Bình
Nguyễn Văn Cường
Trần Văn An

Chú ý: Lệnh sort() của Python sắp xếp xâu kí tự theo thứ tự bảng chữ cái (Unicode), so sánh từ đầu xâu trở đi.

Vận dụng trang 155

Vận dụng 1 trang 155

Đề bài: Trong các phần mềm bảng tính điện tử, dữ liệu ngày tháng được coi là số ngày tính từ ngày $1$-$1$-$1990$. Viết chương trình:

  • Nhập số tự nhiên $n$ từ bàn phím và tính xem số đó ứng với ngày, tháng, năm nào.
  • Nhập thời gian theo khuôn dạng ngày – tháng – năm (ví dụ $8$-$10$-$2021$), tính số ngày ứng với ngày này.

Lời giải:

Hàm phụ trợ chung:

thang = [31,28,31,30,31,30,31,31,30,31,30,31]

def nhuan(year):
    return year%400 == 0 or (year%4 == 0 and year%100 != 0)

def so_ngay_nam(year):
    if nhuan(year):
        return 366
    else:
        return 365

Phần 1 – Cho số $n$, tìm ngày-tháng-năm:

Ý tưởng: Trừ dần số ngày của mỗi năm (bắt đầu từ $1990$) cho đến khi $n$ nằm trong một năm cụ thể. Sau đó trừ dần số ngày của mỗi tháng.

n = int(input("Nhập số n: "))
n_goc = n
year = 1990
while n > so_ngay_nam(year):
    n = n - so_ngay_nam(year)
    year = year + 1

# Cập nhật tháng 2 cho năm nhuận
if nhuan(year):
    thang[1] = 29
else:
    thang[1] = 28

month = 1
while n > thang[month-1]:
    n = n - thang[month-1]
    month = month + 1

day = n
print("Số", n_goc, "ứng với ngày:", day, "-", month, "-", year)

Phần 2 – Cho ngày-tháng-năm, tìm số $n$:

Ý tưởng: Cộng dồn số ngày của các năm từ $1990$ đến $\text{year} – 1$, sau đó cộng số ngày của các tháng trong năm year (từ tháng $1$ đến month - 1), cuối cùng cộng day.

date = input("Nhập ngày - tháng - năm: ")
tg = date.split("-")
day, month, year = int(tg[0]), int(tg[1]), int(tg[2])

if nhuan(year):
    thang[1] = 29
else:
    thang[1] = 28

n = 0
# Cộng số ngày các năm từ 1990 đến year-1
for y in range(1990, year):
    n = n + so_ngay_nam(y)
# Cộng số ngày các tháng từ 1 đến month-1
for m in range(1, month):
    n = n + thang[m-1]
# Cộng day
n = n + day
print("Số ngày tính từ 1-1-1990:", n)

Chú ý: Đây là bài toán phức tạp, em nên chạy thử với các dữ liệu đơn giản (như ngày $1$-$1$-$1990$ phải ra $n = 1$) để kiểm tra tính đúng đắn.

Vận dụng 2 trang 155

Đề bài: Mở rộng bài tập trong phần luyện tập như sau:

  • Việc sắp xếp thứ tự phải ưu tiên tính theo tên trước, rồi đến họ, rồi đến đệm.
  • Sắp xếp theo thứ tự của bảng chữ cái tiếng Việt.

Chú ý: Bảng chữ cái tiếng Việt được cho trong SGK.

Lời giải:

Ý tưởng:

  • Lưu bảng chữ cái tiếng Việt vào biến ALPHABET.
  • Viết hàm truoc_VN(s1, s2) so sánh hai xâu theo thứ tự bảng chữ cái tiếng Việt.
  • Dùng bubble sort với điều kiện so sánh theo thứ tự ưu tiên: tên → họ → đệm.
ALPHABET = "AÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬBCDĐEÈÉẺẼẸÊỀẾỂỄỆGHIÌÍỈĨỊKLMNOÒÓỎÕỌÔỒỐỔỖỘƠỜỚỞỠỢPQRSTUÙÚỦŨỤƯỪỨỬỮỰVXYỲÝỶỸỴ"

def truoc_VN(s1, s2):
    """Trả về True nếu s1 đứng trước s2 theo bảng chữ cái tiếng Việt."""
    s1 = s1.upper()
    s2 = s2.upper()
    for i in range(min(len(s1), len(s2))):
        p1 = ALPHABET.find(s1[i])
        p2 = ALPHABET.find(s2[i])
        if p1 != p2:
            return p1 < p2
    return len(s1) < len(s2)

n = int(input("Nhập số học sinh: "))
ds = []
for i in range(n):
    s = input("Nhập họ tên học sinh thứ " + str(i+1) + ": ")
    ds.append(s)

# Sắp xếp bubble sort: ưu tiên tên → họ → đệm
for i in range(n-1):
    for j in range(n-1-i):
        s1 = ds[j].split()
        s2 = ds[j+1].split()
        ho1, ten1 = s1[0], s1[-1]
        ho2, ten2 = s2[0], s2[-1]
        dem1 = " ".join(s1[1:-1])
        dem2 = " ".join(s2[1:-1])
        # Kiểm tra xem có cần đổi chỗ không
        doi_cho = False
        if ten1 != ten2:
            if truoc_VN(ten2, ten1):
                doi_cho = True
        else:
            if ho1 != ho2:
                if truoc_VN(ho2, ho1):
                    doi_cho = True
            else:
                if truoc_VN(dem2, dem1):
                    doi_cho = True
        if doi_cho:
            ds[j], ds[j+1] = ds[j+1], ds[j]

print("Danh sách học sinh đã sắp xếp:")
for hoten in ds:
    print(hoten)

Giải thích:

  • Hàm truoc_VN(s1, s2): lấy vị trí của từng kí tự trong ALPHABET rồi so sánh. Vị trí nhỏ hơn nghĩa là đứng trước.
  • Trong vòng sort: so sánh tên trước (ten1 vs ten2). Nếu tên bằng nhau, mới so sánh họ. Nếu họ cũng bằng nhau, mới so sánh đệm.

Chú ý: Đây là bài tương đối phức tạp. Em có thể tham khảo cách viết hàm so sánh tiếng Việt làm bài học cho các tình huống cần sắp xếp tiếng Việt khác.

Vận dụng 3 trang 155

Đề bài: Nếu $n$ là hợp số thì dễ thấy $n$ phải có ước số nguyên tố nhỏ hơn hoặc bằng $\sqrt{n}$. Viết chương trình tối ưu hơn theo cách: để tìm ước số nguyên tố nhỏ nhất chỉ cần tìm trong các số $2, 3, …, \sqrt{n}$. Nếu trong dãy trên không tìm thấy ước của $n$ thì kết luận ngay $n$ là nguyên tố.

Lời giải:

Ý tưởng tối ưu:

  • Thay vì duyệt $k$ từ $2$ đến $n – 1$ (như Bài 26), ta chỉ cần duyệt $k$ từ $2$ sao cho $k^2 \leq n$ (tương đương $k \leq \sqrt{n}$).
  • Điều kiện $k \times k \leq n$ tránh phải tính căn bậc hai.
n = int(input("Nhập số tự nhiên n: "))

if n < 2:
    print(n, "không phải là số nguyên tố.")
else:
    k = 2
    found = False
    while k*k <= n:
        if n % k == 0:
            print("Ước số nguyên tố nhỏ nhất của", n, "là", k)
            print(n, "là hợp số.")
            found = True
            break
        k = k + 1
    if not found:
        print(n, "là số nguyên tố.")

Ví dụ khi chạy:

  • Với $n = 97$: duyệt $k = 2, 3, 4, …, 9$ (vì $9^2 = 81 \leq 97 < 100 = 10^2$). Không tìm thấy ước → $97$ là số nguyên tố.
  • Với $n = 91$: duyệt $k = 2, 3, …, 9$. Tại $k = 7$: $91 \% 7 = 0$ → ước nhỏ nhất là $7$, $91$ là hợp số.

So sánh hiệu quả với cách cũ:

$n$ Cách cũ (duyệt đến $n – 1$) Cách mới (duyệt đến $\sqrt{n}$)
$100$ $98$ lần kiểm tra $\sim 9$ lần kiểm tra
$10000$ $9998$ lần $\sim 99$ lần
$1000000$ $\sim 10^6$ lần $\sim 10^3$ lần

→ Cách mới nhanh hơn rất nhiều khi $n$ lớn.

Lý do toán học: Nếu $n = a \times b$ với $a \leq b$ thì $a \leq \sqrt{n} \leq b$. Vì vậy nếu $n$ có ước, thì phải có ít nhất một ước $\leq \sqrt{n}$. Nếu duyệt đến $\sqrt{n}$ mà không thấy ước nào, có nghĩa là $n$ không có ước thực sự → $n$ là số nguyên tố.

Thầy Phạm Thành Danh

Thầy Phạm Thành Danh

(Người kiểm duyệt, ra đề)

Chức vụ: Trưởng ban biên soạn môn Tin Học THPT

Trình độ: Cử nhân Sư phạm Tin học, Chứng chỉ hạng II, Chứng chỉ Tin học, Ngoại ngữ B1

Kinh nghiệm: 8+ năm kinh nghiệm tại Trường THPT Thuận Hóa