Chương 0·Bài 0.1

Python

Bài 1Sửa notebook

Một bạn ghi điểm các lần chạy thử model vào notebook broken.ipynb (có trong bộ kit). Lúc làm, bạn ấy chạy các ô lộn xộn nên mọi thứ vẫn có vẻ ổn. Đến khi bấm Restart & Run All, notebook báo lỗi ngay.

Notebook có bốn ô:

max = 10
best = max(scores)
scores = ["9", "10", "2"]
print(best)

Có ba chỗ sai. scores được dùng trước khi gán. Tên max bị lấy làm tên biến, nên hàm max của Python bị che mất. Còn điểm thì đang là chuỗi, mà so chuỗi thì "9" lại lớn hơn "10".

Hãy sửa notebook cho chạy được từ đầu đến cuối. Sau đó viết hàm solve nhận danh sách điểm dạng chuỗi và trả về điểm lớn nhất theo giá trị số.

Dữ liệu vào

Một đối tượng JSON có trường scores, là danh sách chuỗi số thập phân, ví dụ "9", "-74.5".

Kết quả

Điểm lớn nhất, dưới dạng một số.

Giới hạn

  • Có từ 11 đến 100100 điểm, mỗi điểm trong đoạn [−1000,1000][-1000, 1000].

Chấm điểm

Có 20 test, mỗi test 5 điểm. Số thực được chấm với sai số khoảng 10−710^{-7}.

Ví dụ

Input mẫu

{"scores": ["9", "10", "2"]}

Output mẫu

10.0

Bài 2Đếm từ

Trước khi đưa văn bản vào model, người ta hay đếm xem mỗi từ xuất hiện bao nhiêu lần. Bài này làm đúng việc ấy.

Tách văn bản thành từ bằng text.split(), nên dấu cách, tab hay xuống dòng đều là chỗ ngắt. Mỗi từ đưa về chữ thường bằng lower(), để Mèo, mèo và MÈO được tính là một. Rồi đếm.

Từ nào xuất hiện nhiều hơn đứng trước. Hai từ cùng số lần thì xếp theo thứ tự chuỗi của Python.

Dữ liệu vào

Một đối tượng JSON có trường text, là đoạn văn bản, có thể có chữ có dấu.

Kết quả

Danh sách các cặp [từ, số_lần]. Văn bản không có từ nào thì trả về [].

Giới hạn

  • Văn bản dài không quá 50005000 ký tự.

Chấm điểm

Có 20 test, mỗi test 5 điểm.

Ví dụ

Input mẫu

{"text": "Mèo chó mèo Gà mèo chó"}

Output mẫu

[["mèo", 3], ["chó", 2], ["gà", 1]]

Bài 3Robot vòng

Một con robot chạy trên đường vòng có size ô, đánh số từ 00 đến size−1\text{size}-1, ô cuối nối liền ô 00. Robot xuất phát ở ô start rồi đi lần lượt từng bước trong steps. Bước dương đi theo chiều số ô tăng, bước âm đi ngược lại. Có bước rất dài, robot đi hết vòng này sang vòng khác.

Hãy ghi lại hành trình, gồm vị trí ban đầu và vị trí sau mỗi bước.

Gợi ý: với số chia dương, phép % của Python luôn cho kết quả từ 00 đến số chia trừ 11, kể cả khi số bị chia âm.

Dữ liệu vào

Một đối tượng JSON gồm size, start và danh sách steps.

Kết quả

Danh sách vị trí, bắt đầu bằng start, rồi lần lượt vị trí sau từng bước.

Giới hạn

  • 1≤size≤201\le\text{size}\le20 và 0≤start<size0\le\text{start}<\text{size}.
  • Có không quá 100100 bước, mỗi bước dài không quá 10610^6 ô.

Chấm điểm

Có 20 test, mỗi test 5 điểm.

Ví dụ

Input mẫu

{"size": 8, "start": 6, "steps": [3, -10, 1]}

Output mẫu

[6, 1, 7, 0]

Bài 4Avatar

Một xưởng vẽ avatar pixel có mẫu chung template, là một lưới số, mỗi số là một màu từ 00 đến 44. Từ mẫu ấy, xưởng vẽ hai avatar. Avatar thứ nhất là mẫu được tô thêm theo edits_a, avatar thứ hai là mẫu được tô thêm theo edits_b.

Mỗi lần tô là một bộ [hàng, cột, màu], hàng và cột đánh số từ 00. Ô bị tô nhiều lần thì giữ màu cuối cùng.

Tô avatar này không được làm đổi avatar kia, cũng không được làm đổi mẫu. Cẩn thận với template.copy(). Lệnh này chỉ chép danh sách các hàng, còn các hàng bên trong vẫn dùng chung.

Dữ liệu vào

Một đối tượng JSON gồm template, edits_a, edits_b.

Kết quả

Danh sách hai lưới [avatar_thứ_nhất, avatar_thứ_hai].

Giới hạn

  • Lưới có từ 11 đến 1212 hàng, các hàng dài bằng nhau, từ 11 đến 1212 ô.
  • Mỗi danh sách tô có không quá 5050 lần tô, mọi ô đều nằm trong lưới.

Chấm điểm

Có 20 test, mỗi test 5 điểm.

Ví dụ

Input mẫu

{
  "template": [
    [0, 0, 0, 0, 0],
    [0, 1, 0, 1, 0],
    [0, 0, 0, 0, 0],
    [0, 1, 1, 1, 0],
    [0, 0, 0, 0, 0]
  ],
  "edits_a": [[1, 1, 3], [1, 3, 3]],
  "edits_b": [[3, 1, 2], [3, 2, 2], [3, 3, 2]]
}

Output mẫu

[
  [
    [0, 0, 0, 0, 0],
    [0, 3, 0, 3, 0],
    [0, 0, 0, 0, 0],
    [0, 1, 1, 1, 0],
    [0, 0, 0, 0, 0]
  ],
  [
    [0, 0, 0, 0, 0],
    [0, 1, 0, 1, 0],
    [0, 0, 0, 0, 0],
    [0, 2, 2, 2, 0],
    [0, 0, 0, 0, 0]
  ]
]

Bài 5Làm sạch

Dữ liệu thật hiếm khi sạch. Có ô trống, có ô ghi bậy, có mã bị nhập hai lần. Cho danh sách bản ghi, mỗi bản ghi có mã id và giá trị value dạng chuỗi. Hãy làm sạch bảng.

Một giá trị dùng được khi nó khác null, đọc được bằng float(value), là số hữu hạn và nằm trong đoạn [−104,104][-10^4, 10^4]. float đọc được cả "NaN" hay "inf", nhưng đó không phải số hữu hạn; hàm math.isfinite kiểm được việc này.

Mã giữ nguyên là chuỗi, "001" vẫn là "001". Khi một mã có nhiều bản ghi dùng được, giữ bản sau cùng. Bản ghi hỏng không thay được bản tốt đứng trước nó.

Bảng sạch xếp theo id tăng dần, theo thứ tự chuỗi của Python.

Dữ liệu vào

Một đối tượng JSON có trường records, là danh sách {"id": ..., "value": ...}. value là chuỗi hoặc null.

Kết quả

Một đối tượng JSON gồm ba trường:

  • rows: bảng sạch, mỗi dòng {"id": ..., "value": ...} với value là số.
  • rejected: chỉ số các bản ghi bị loại vì giá trị không dùng được.
  • superseded: chỉ số các bản ghi dùng được nhưng bị một bản cùng mã đến sau thay thế.

Chỉ số đánh từ 00, xếp tăng dần.

Giới hạn

  • Có không quá 20002000 bản ghi. Mã và chuỗi giá trị dài không quá 6464 ký tự.

Chấm điểm

Có 20 test, mỗi test 5 điểm. Số thực được chấm với sai số khoảng 10−710^{-7}.

Ví dụ

Input mẫu

{
  "records": [
    {"id": "001", "value": " 7.5 "},
    {"id": "B", "value": null},
    {"id": "001", "value": "8"},
    {"id": "001", "value": "NaN"},
    {"id": "A", "value": "-2"}
  ]
}

Output mẫu

{
  "rows": [{"id": "001", "value": 8.0}, {"id": "A", "value": -2.0}],
  "rejected": [1, 3],
  "superseded": [0]
}

Bài 6Tệp dự đoán

Bài thi AI nào cũng kết thúc bằng một tệp dự đoán. Model tốt đến đâu mà tệp sai định dạng, hay ghép nhầm mã với dự đoán, thì vẫn mất điểm.

Ta đã chạy vài thử nghiệm. Mỗi thử nghiệm có một lỗi validation và một bộ dự đoán cho mọi mẫu, nhưng các dự đoán nằm lộn xộn. Hãy chọn thử nghiệm có lỗi validation nhỏ nhất, rồi ghi tệp CSV gồm mã mẫu và dự đoán của thử nghiệm ấy, theo đúng thứ tự sample_ids. Nếu nhiều thử nghiệm cùng lỗi nhỏ nhất, lấy thử nghiệm có run_id nhỏ nhất theo thứ tự chuỗi.

Mã mẫu có thể chứa dấu phẩy, ví dụ A,B. Ghép tay bằng ",".join(...) sẽ tách nhầm một mã thành hai ô. Module csv tự đặt ngoặc kép khi cần, hãy dùng csv.writer.

Dữ liệu vào

Một đối tượng JSON gồm:

  • sample_ids: danh sách mã mẫu, theo thứ tự cần ghi.
  • runs: danh sách thử nghiệm, mỗi thử nghiệm có run_id, validation_error và predictions. predictions là danh sách {"id": ..., "prediction": ...}, mỗi mã đúng một lần.

Kết quả

Nội dung tệp CSV, dòng đầu là id,prediction. Hàm solve trả về cả nội dung ấy dưới dạng một chuỗi, starter.py sẽ in ra.

Giới hạn

  • Có từ 11 đến 500500 mẫu và từ 11 đến 1010 thử nghiệm.
  • Mã và run_id dài từ 11 đến 6464 ký tự, không chứa ký tự xuống dòng.
  • Lỗi validation từ 00 đến 10410^4, dự đoán có trị tuyệt đối không quá 10410^4.

Chấm điểm

Có 20 test, mỗi test 5 điểm. Dòng đầu, các mã và thứ tự phải đúng hoàn toàn. Dự đoán được chấm với sai số khoảng 10−710^{-7}.

Ví dụ

Input mẫu

{
  "sample_ids": ["001", "A,B"],
  "runs": [
    {
      "run_id": "r2",
      "validation_error": 2,
      "predictions": [{"id": "001", "prediction": 9}, {"id": "A,B", "prediction": 8}]
    },
    {
      "run_id": "r1",
      "validation_error": 1,
      "predictions": [{"id": "A,B", "prediction": 7}, {"id": "001", "prediction": 3}]
    }
  ]
}

Output mẫu

id,prediction
001,3
"A,B",7

Bài 7Làm mới list

Viết hàm refreshList(L) nhận một list số nguyên và sửa ngay trên list ấy. Hàm bỏ mọi số nhỏ hơn hoặc bằng 00, và ngay sau mỗi số dương nn còn lại thì chèn nn chuỗi "A". Các số còn lại giữ nguyên thứ tự.

Ví dụ, L = [2, 0, -3, 4] trở thành [2, "A", "A", 4, "A", "A", "A", "A"].

Hàm không cần trả về gì. Điều quan trọng là chỗ gọi hàm phải thấy chính list của mình đã đổi. Trong starter.py, hàm solve gọi refreshList(data) rồi in data ra.

Bẫy hay gặp là dựng list mới rồi gán L = moi. Lệnh ấy chỉ dời cái tên L sang list mới, list của chỗ gọi vẫn y nguyên. Muốn đổi nội dung list cũ, có thể dùng L.clear() rồi L.extend(moi).

Dữ liệu vào

Một list số nguyên.

Kết quả

List ấy sau khi gọi refreshList.

Giới hạn

  • List có không quá 100100 phần tử, mỗi phần tử trong đoạn [−20,20][-20, 20].

Chấm điểm

Có 20 test, mỗi test 5 điểm.

Ví dụ

Input mẫu

[2, 0, -3, 4]

Output mẫu

[2, "A", "A", 4, "A", "A", "A", "A"]

Input mẫu

[0, -2, -1]

Output mẫu

[]

Bài 8Đọc chéo

Cho một bảng vuông MM cỡ N×NN\times N. Hãy đọc bảng theo các đường chéo ngược. Đường chéo thứ dd gồm các ô (r,c)(r, c) có r+c=dr+c=d. Đọc lần lượt d=0,1,…,2N−2d = 0, 1, \dots, 2N-2, trong mỗi đường chéo thì đi từ hàng trên xuống hàng dưới.

Được một dãy N2N^2 số. Xếp dãy ấy vào một bảng mới N×NN\times N, điền lần lượt từng hàng từ trái sang phải.

Ví dụ, bảng [[1, 2, 3], [4, 5, 6], [7, 8, 9]] đọc ra dãy 1,2,4,3,5,7,6,8,91, 2, 4, 3, 5, 7, 6, 8, 9, nên bảng mới là [[1, 2, 4], [3, 5, 7], [6, 8, 9]].

Đầu vào có khi không phải bảng vuông hợp lệ. Bảng hợp lệ là một list khác rỗng gồm NN list con, mỗi list con có đúng NN phần tử, và mọi phần tử đều là số nguyên. true, false hay chuỗi "2" không được tính là số nguyên. Gặp đầu vào không hợp lệ thì trả về [].

Hàm không được làm đổi bảng gốc.

Dữ liệu vào

Một giá trị JSON MM.

Kết quả

Bảng mới, hoặc [].

Giới hạn

  • MM có không quá 1212 phần tử, mỗi list con không quá 1212 phần tử, các số có trị tuyệt đối không quá 100100.

Chấm điểm

Có 20 test, mỗi test 5 điểm.

Ví dụ

Input mẫu

[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

Output mẫu

[[1, 2, 4], [3, 5, 7], [6, 8, 9]]

Input mẫu

[[1, 2], [3]]

Output mẫu

[]