Một bản ghi trên một dòng
Thực hành dùng dữ liệu **giả định**, không cần thu thập thông tin của người thật. Mỗi dòng chứa tên mẫu và chiều cao tính bằng mét; trường cuối là số dùng dấu chấm thập phân:
```text
Mẫu A 1.62
Mẫu B 1.48
Mẫu C 1.75
Mẫu D 1.48
Mẫu E 1.75
```
Dùng split() để tách dòng theo khoảng trắng. Trường cuối được đổi sang float; các trường trước ghép lại thành tên. Không chỉ lấy trường đầu làm tên vì tên mẫu có thể gồm nhiều từ.
```python
parts = 'Mẫu B 1.48'.split()
ten = ' '.join(parts[:-1])
h = float(parts[-1])
print(ten, h)
```
Đoạn này in `Mẫu B 1.48`. Sau khi đọc, DS giữ tên và CC giữ chiều cao theo cùng thứ tự; DS[i] phải thuộc đúng bản ghi của CC[i]. Tệp tải về bỏ qua dòng trắng, báo lỗi nếu thiếu trường số, số không dương hoặc không hữu hạn; tệp không có bản ghi cũng được báo trước khi gọi minmax.
Từ giá trị min/max tới bản ghi tương ứng
Với bộ dữ liệu trên, minmax(CC,len(CC)−1) cho (1.48,1.75). Dùng CC.index(1.48) được chỉ số 1; CC.index(1.75) được chỉ số 2. **index chọn lần xuất hiện đầu tiên**, nên kết quả lấy Mẫu B và Mẫu C dù Mẫu D/Mẫu E có cùng giá trị tương ứng.
Tệp kết quả ghi dòng có chiều cao nhỏ nhất trước, lớn nhất sau:
```text
Mẫu B 1.48
Mẫu C 1.75
```
Mẫu ghi hai chữ số sau dấu chấm để thống nhất cách trình bày dữ liệu. Đây là phép tổng kết các giá trị, không đưa ra nhận xét sức khỏe. Nếu chỉ có một bản ghi, cả hai dòng kết quả cùng là bản ghi ấy.
Chạy và đối chiếu cả ba nhiệm vụ
Tải mã Python và tệp dữ liệu; đặt trong cùng một thư mục làm việc. Đổi tên tệp dữ liệu tải về thành `chieucao.inp`. Mở terminal tại thư mục đó và chạy bằng Python3; nếu máy dùng lệnh `python` để gọi Python3 thì dùng tên lệnh tương ứng:
```text
python3 g11-cs-thuc-hanh-de-quy.py nhi-phan 10101
python3 g11-cs-thuc-hanh-de-quy.py ucln 84 30
python3 g11-cs-thuc-hanh-de-quy.py chieu-cao chieucao.inp ketqua.out
```
Hai lệnh đầu cần in 21 và 6. Lệnh cuối đọc tệp đầu vào, tạo hoặc ghi lại `ketqua.out` ở thư mục đang làm việc; mở tệp và đối chiếu đúng hai dòng với bản tham chiếu. Mã mở tệp bằng UTF-8 để giữ tên tiếng Việt. Tệp kết quả phải khác tệp đầu vào; không dùng đường dẫn của tài liệu cần giữ để thử ghi.
Thử thêm xâu `'0'` và xâu có chữ số 2; cặp (0,6) và (0,0); tệp một bản ghi và tệp rỗng. Các đầu vào hợp lệ cho 0, 6 và hai dòng cùng bản ghi; các đầu vào không hợp lệ phải báo lỗi. Mẫu đệ quy trực tiếp dùng bộ thử nhỏ, không tăng giới hạn đệ quy để ép xử lí tệp lớn.
Bài luyện
Đọc dòng 'Mẫu B 1.48' bằng cách trong bài, cặp (tên, chiều cao) nào đúng?
Dấu chấm thập phân không được bỏ.
Các trường trước ghép thành tên; trường cuối đổi sang float.
Cách đó làm mất phần B của tên.
Chiều cao cần là số để so sánh, chưa phải xâu.
Lời giải
split() cho ['Mẫu','B','1.48']. Ghép hai trường đầu được 'Mẫu B'; float('1.48') được số 1.48, giữ đúng dữ liệu của dòng.
Bài luyện
Với năm dòng mẫu trong bài, vì sao tệp kết quả chọn Mẫu B và Mẫu C?
Cả năm dòng đều được đọc; chỉ quy tắc chọn bản ghi khác.
Dòng đầu có 1.62, chưa phải max 1.75.
CC.index trả vị trí đầu tiên có giá trị cần tìm.
index không có quy tắc chọn vị trí cuối.
Lời giải
Min=1.48 xuất hiện trước ở chỉ số 1 ứng với Mẫu B; max=1.75 xuất hiện trước ở chỉ số 2 ứng với Mẫu C. index lấy các vị trí đó, nên Mẫu D/Mẫu E không được ghi trong hai dòng kết quả.
Bài luyện
Tệp đầu vào không có bản ghi. Cách xử lí nào phù hợp với chương trình thực hành?
Hàm minmax chưa định nghĩa kết quả cho dãy rỗng.
Đó là thêm dữ liệu không có trong tệp.
CC rỗng không có phần tử chỉ số 0.
Chưa có phần tử để xác định min/max.
Lời giải
Sau bước đọc, CC rỗng nên phải báo chưa có bản ghi. Không gọi hàm yêu cầu dãy không rỗng, không đọc CC[0] và không tự thêm giá trị 0 để thay dữ liệu.
Đang học