{
  "description": "Dữ liệu đầu vào và đầu ra để đối chiếu 20 bài regex. Không chứa lời giải mẫu hoặc công cụ chấm bài.",
  "source": "https://github.com/uet-iai-course/programming-for-data-processing/blob/main/2627-1/notebooks/lab-07-regex.ipynb",
  "license": "CC BY-NC-SA 4.0",
  "exercises": [
    {
      "exercise": 1,
      "cases": [
        {
          "input": "abc123xyz",
          "expected": "123",
          "expectedType": "str"
        },
        {
          "input": "define \"123\"",
          "expected": "123",
          "expectedType": "str"
        },
        {
          "input": "var g = 123;",
          "expected": "123",
          "expectedType": "str"
        },
        {
          "input": "P007 / P12",
          "expected": "007",
          "expectedType": "str"
        },
        {
          "input": "không có mã",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": null,
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "42",
          "expected": "42",
          "expectedType": "str"
        },
        {
          "input": "mã 0",
          "expected": "0",
          "expectedType": "str"
        },
        {
          "input": "１２３",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "A8B9",
          "expected": "8",
          "expectedType": "str"
        },
        {
          "input": "١٢٣",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "A١٢B34",
          "expected": "34",
          "expectedType": "str"
        }
      ],
      "passage": "Trong báo cáo nhập dữ liệu, trợ giảng ghi lại các mô tả có mã số mà nhóm đã gặp trong nhiều tệp khác nhau. Bản ghi đầu tiên là «abc123xyz»; người tiếp theo đưa vào «define \"123\"»; ở phần rà soát có «var g = 123;»; sau đó nhóm ghi thêm «P007 / P12»; một mục khác được lưu là «không có mã». Một ô khác bị thiếu dữ liệu và được lưu là None. Mục tiêu là nhận dãy số xuất hiện đầu tiên trong từng mô tả, giữ nguyên hình thức ban đầu để còn đối chiếu với mã gốc.",
      "selected": [
        [
          "abc123xyz",
          "123"
        ],
        [
          "define \"123\"",
          "123"
        ],
        [
          "var g = 123;",
          "123"
        ],
        [
          "P007 / P12",
          "007"
        ]
      ]
    },
    {
      "exercise": 2,
      "cases": [
        {
          "input": "cat.",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "896.",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "?=+.",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "abc1",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "ab.",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "abcd.",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "   .",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "...",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "....",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "ab\n.",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "cat.\n",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": null,
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "ab\r.",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "A🦊B.",
          "expected": true,
          "expectedType": "bool"
        }
      ],
      "passage": "Một nhóm đang rà soát các nhãn ngắn được gửi từ biểu mẫu và cần nhận đúng kiểu nhãn có dấu chấm cuối. Bản ghi đầu tiên là «cat.»; người tiếp theo đưa vào «896.»; ở phần rà soát có «?=+.»; sau đó nhóm ghi thêm «abc1»; một mục khác được lưu là «ab.»; và mục cuối trong lượt này là «abcd.». Những nhãn nhìn gần giống nhau cũng được giữ trong bản ghi, để nhóm kiểm chứng rằng ký tự cuối và độ dài đều được xét.",
      "selected": [
        [
          "cat.",
          true
        ],
        [
          "896.",
          true
        ],
        [
          "?=+.",
          true
        ]
      ]
    },
    {
      "exercise": 3,
      "cases": [
        {
          "input": "can",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "man",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "fan",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "dan",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "ran",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "pan",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "Can",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": " can",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "cann",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "xcan",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": null,
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "can\n",
          "expected": false,
          "expectedType": "bool"
        }
      ],
      "passage": "Trong một trò chơi nhận diện từ, người quản lý gom các mục từ nhiều phiếu trả lời vào cùng một ghi chú. Bản ghi đầu tiên là «can»; người tiếp theo đưa vào «man»; ở phần rà soát có «fan»; sau đó nhóm ghi thêm «dan»; một mục khác được lưu là «ran»; và mục cuối trong lượt này là «pan». Hệ thống chỉ chọn mục đúng cấu trúc đã nêu, dù nhiều mục gây nhiễu có cùng phần kết thúc.",
      "selected": [
        [
          "can",
          true
        ],
        [
          "man",
          true
        ],
        [
          "fan",
          true
        ]
      ]
    },
    {
      "exercise": 4,
      "cases": [
        {
          "input": "Ana",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "Bob",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "Cpc",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "aax",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "bby",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "ccz",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "Apa",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "Cnc",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "Dna",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "Amc",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "Bpd",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": null,
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "Ana\n",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "Boc",
          "expected": true,
          "expectedType": "bool"
        }
      ],
      "passage": "Bộ phận dữ liệu nhận một danh sách mã ba ký tự do nhiều người nhập và muốn kiểm tra từng vị trí của mã. Bản ghi đầu tiên là «Ana»; người tiếp theo đưa vào «Bob»; ở phần rà soát có «Cpc»; sau đó nhóm ghi thêm «aax»; một mục khác được lưu là «bby»; và mục cuối trong lượt này là «ccz». Người rà soát cần phân biệt chữ hoa với chữ thường và giữ lại cả các mã sai để xác nhận mẫu không chọn quá rộng.",
      "selected": [
        [
          "Ana",
          true
        ],
        [
          "Bob",
          true
        ],
        [
          "Cpc",
          true
        ]
      ]
    },
    {
      "exercise": 5,
      "cases": [
        {
          "input": "wazzzup",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "wazzzzup",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "wazzzzzup",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "wazup",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "wazzup",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "wazzzzzzup",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "wazzzup!",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "Wazzzup",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "waup",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": null,
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "wazzzup\n",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "wazzzzzzzup",
          "expected": false,
          "expectedType": "bool"
        }
      ],
      "passage": "Một ứng dụng thử nghiệm lưu các cách người dùng kéo dài âm trong tin nhắn để nhóm kiểm tra quy tắc số lần lặp. Bản ghi đầu tiên là «wazzzup»; người tiếp theo đưa vào «wazzzzup»; ở phần rà soát có «wazzzzzup»; sau đó nhóm ghi thêm «wazup»; một mục khác được lưu là «wazzup»; và mục cuối trong lượt này là «wazzzzzzup». Nhóm cần chọn cách viết nằm đúng trong giới hạn, thay vì nhận tất cả chuỗi có chữ z.",
      "selected": [
        [
          "wazzzup",
          true
        ],
        [
          "wazzzzup",
          true
        ],
        [
          "wazzzzzup",
          true
        ]
      ]
    },
    {
      "exercise": 6,
      "cases": [
        {
          "input": "aaaabcc",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "aabbbbc",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "aacc",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "a",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "abc",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "aabb",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "aac",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "aaaaaabbbbbccccc",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "aabca",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "aa",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": null,
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "aaaaaacccc",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "aaacbb",
          "expected": false,
          "expectedType": "bool"
        }
      ],
      "passage": "Phòng thực hành đang thử bộ sinh chuỗi với các nhóm ký tự a, b và c, rồi ghi mọi kết quả vào một đoạn nhật ký. Bản ghi đầu tiên là «aaaabcc»; người tiếp theo đưa vào «aabbbbc»; ở phần rà soát có «aacc»; sau đó nhóm ghi thêm «a»; một mục khác được lưu là «abc»; và mục cuối trong lượt này là «aabb». Người kiểm tra chọn chuỗi có đủ các phần bắt buộc và đúng thứ tự, kể cả khi nhóm b hoàn toàn vắng mặt.",
      "selected": [
        [
          "aaaabcc",
          true
        ],
        [
          "aabbbbc",
          true
        ],
        [
          "aacc",
          true
        ]
      ]
    },
    {
      "exercise": 7,
      "cases": [
        {
          "input": "1 file found?",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "2 files found?",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "24 files found?",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "No files found.",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "0 files found?",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "2 files found.",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "2 file found?",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "01 file found?",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "1 file found",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "1  file found?",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "1 File found?",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": null,
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "1 files found?",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "1 file found?\n",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "１２ files found?",
          "expected": false,
          "expectedType": "bool"
        }
      ],
      "passage": "Sau một đợt tìm kiếm tệp, nhân viên hỗ trợ chép các thông báo từ màn hình vào báo cáo bàn giao. Bản ghi đầu tiên là «1 file found?»; người tiếp theo đưa vào «2 files found?»; ở phần rà soát có «24 files found?»; sau đó nhóm ghi thêm «No files found.»; một mục khác được lưu là «0 files found?»; và mục cuối trong lượt này là «2 files found.». Các thông báo có hình thức gần nhau được giữ cạnh nhau, để phân biệt dấu hỏi thực sự với ký hiệu tùy chọn của mẫu.",
      "selected": [
        [
          "1 file found?",
          true
        ],
        [
          "2 files found?",
          true
        ],
        [
          "24 files found?",
          true
        ]
      ]
    },
    {
      "exercise": 8,
      "cases": [
        {
          "input": "1.   abc",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "2.\tabc",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "3.           abc",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "4.abc",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "12. abc",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "1x abc",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "1.\nabc",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "1.\rabc",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "1. ABC",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "1. abc ",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": null,
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "1. abc",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "1.\u000babc",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "1. abc",
          "expected": true,
          "expectedType": "bool"
        }
      ],
      "passage": "Người biên tập nhận các mục đánh số được sao chép từ nhiều ứng dụng, có mục dùng dấu cách và có mục dùng tab. Bản ghi đầu tiên là «1.   abc»; người tiếp theo đưa vào «2.\tabc»; ở phần rà soát có «3.           abc»; sau đó nhóm ghi thêm «4.abc»; một mục khác được lưu là «12. abc»; và mục cuối trong lượt này là «1x abc». Bản ghi giữ nguyên ký tự phân cách để kiểm tra xem mẫu có nhận đủ loại ký tự trắng và loại mục viết dính hay không.",
      "selected": [
        [
          "1.   abc",
          true
        ],
        [
          "2.\tabc",
          true
        ],
        [
          "3.           abc",
          true
        ],
        [
          "12. abc",
          true
        ]
      ]
    },
    {
      "exercise": 9,
      "cases": [
        {
          "input": "file_record_transcript.pdf",
          "expected": "file_record_transcript",
          "expectedType": "str"
        },
        {
          "input": "file_07241999.pdf",
          "expected": "file_07241999",
          "expectedType": "str"
        },
        {
          "input": "fileA1.pdf",
          "expected": "fileA1",
          "expectedType": "str"
        },
        {
          "input": "testfile_fake.pdf.tmp",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "fileA.pdf.tmp",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "fileA.txt",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "file.pdf",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "fileA.PDF",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "folder/fileA.pdf",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "file-A.pdf",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": null,
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "file_.pdf",
          "expected": "file_",
          "expectedType": "str"
        },
        {
          "input": "fileA.pdf\n",
          "expected": null,
          "expectedType": "NoneType"
        }
      ],
      "passage": "Một nhóm quản lý hồ sơ đang chọn tệp PDF từ danh sách tên được chuyển sang dạng văn bản. Bản ghi đầu tiên là «file_record_transcript.pdf»; người tiếp theo đưa vào «file_07241999.pdf»; ở phần rà soát có «fileA1.pdf»; sau đó nhóm ghi thêm «testfile_fake.pdf.tmp»; một mục khác được lưu là «fileA.pdf.tmp»; và mục cuối trong lượt này là «fileA.txt». Bản ghi cũng giữ các tệp có phần mở rộng khác và các bản tạm, để người xử lý chỉ lấy đúng phần tên cần thiết.",
      "selected": [
        [
          "file_record_transcript.pdf",
          "file_record_transcript"
        ],
        [
          "file_07241999.pdf",
          "file_07241999"
        ],
        [
          "fileA1.pdf",
          "fileA1"
        ]
      ]
    },
    {
      "exercise": 10,
      "cases": [
        {
          "input": "Modern 1BR Oasis",
          "expected": "1",
          "expectedType": "str"
        },
        {
          "input": "Casa 3 bedrooms",
          "expected": "3",
          "expectedType": "str"
        },
        {
          "input": "Studio 2 br centro",
          "expected": "2",
          "expectedType": "str"
        },
        {
          "input": "12bravo centro",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "Modern 2BR2BA",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "Torre 2024",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "2 bedroom",
          "expected": "2",
          "expectedType": "str"
        },
        {
          "input": "2 BEDROOMS",
          "expected": "2",
          "expectedType": "str"
        },
        {
          "input": "Room 2 bedrooms and 1BR",
          "expected": "2",
          "expectedType": "str"
        },
        {
          "input": "x2BR",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "2 bedroomss",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": null,
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "A 0BR",
          "expected": "0",
          "expectedType": "str"
        },
        {
          "input": "2BR_apt",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "1 bedroom; 3BR",
          "expected": "1",
          "expectedType": "str"
        }
      ],
      "passage": "Người phân tích đang đọc các tên chỗ ở do chủ nhà tự nhập và muốn tìm thông tin số phòng được ghi trong tên. Bản ghi đầu tiên là «Modern 1BR Oasis»; người tiếp theo đưa vào «Casa 3 bedrooms»; ở phần rà soát có «Studio 2 br centro»; sau đó nhóm ghi thêm «12bravo centro»; một mục khác được lưu là «Modern 2BR2BA»; và mục cuối trong lượt này là «Torre 2024». Các tên có chữ hoặc con số dễ gây nhầm đều được đưa vào bản ghi để kiểm tra ranh giới của cụm cần lấy.",
      "selected": [
        [
          "Modern 1BR Oasis",
          "1"
        ],
        [
          "Casa 3 bedrooms",
          "3"
        ],
        [
          "Studio 2 br centro",
          "2"
        ]
      ]
    },
    {
      "exercise": 11,
      "cases": [
        {
          "input": "3.14529",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "-255.34",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "128",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "720p",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": ".5",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "5.",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "-0",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "001.50",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "+12",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "1,000",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "1e3",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": " 12",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "12\n",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": null,
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "0.0",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "-",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "１２",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "12x5",
          "expected": false,
          "expectedType": "bool"
        }
      ],
      "passage": "Trong quá trình nhập số đo từ một biểu mẫu, nhóm hỗ trợ giữ nguyên các ô dạng chuỗi để rà soát định dạng. Bản ghi đầu tiên là «3.14529»; người tiếp theo đưa vào «-255.34»; ở phần rà soát có «128»; sau đó nhóm ghi thêm «720p»; một mục khác được lưu là «.5»; và mục cuối trong lượt này là «5.». Người xử lý cần chọn đúng số theo miền đã cho trước khi chuyển kiểu, thay vì chỉ nhận một đoạn số nằm trong ô sai.",
      "selected": [
        [
          "3.14529",
          true
        ],
        [
          "-255.34",
          true
        ],
        [
          "128",
          true
        ]
      ]
    },
    {
      "exercise": 12,
      "cases": [
        {
          "input": "1.9e10",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "123,340.00",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "+1E-3",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "12,34.00",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "1,000e+2",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "720p",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "128",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "-255.34",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "1,234,567.89",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "1234,567",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "1,,000",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "1e",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "1e+",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "1.2.3",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": ".5",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "12\n",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": null,
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "128e2",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "1,000,000",
          "expected": true,
          "expectedType": "bool"
        },
        {
          "input": "1,00e2",
          "expected": false,
          "expectedType": "bool"
        },
        {
          "input": "1.0e-2",
          "expected": true,
          "expectedType": "bool"
        }
      ],
      "passage": "Một báo cáo kỹ thuật gom số liệu từ các phần mềm có thể ghi số theo dạng thường, nhóm hàng nghìn hoặc dạng số mũ. Bản ghi đầu tiên là «1.9e10»; người tiếp theo đưa vào «123,340.00»; ở phần rà soát có «+1E-3»; sau đó nhóm ghi thêm «12,34.00»; một mục khác được lưu là «1,000e+2»; và mục cuối trong lượt này là «720p». Nhóm cần chọn mục hợp lệ theo cùng một bộ quy tắc, đặc biệt kiểm tra các dấu phẩy và các thành phần bị thiếu.",
      "selected": [
        [
          "1.9e10",
          true
        ],
        [
          "123,340.00",
          true
        ],
        [
          "+1E-3",
          true
        ],
        [
          "1,000e+2",
          true
        ]
      ]
    },
    {
      "exercise": 13,
      "cases": [
        {
          "input": "415-555-1234",
          "expected": "415",
          "expectedType": "str"
        },
        {
          "input": "(416)555-3456",
          "expected": "416",
          "expectedType": "str"
        },
        {
          "input": "202 555 4567",
          "expected": "202",
          "expectedType": "str"
        },
        {
          "input": "4035555678",
          "expected": "403",
          "expectedType": "str"
        },
        {
          "input": "1 416 555 9292",
          "expected": "416",
          "expectedType": "str"
        },
        {
          "input": "(416555-3456",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "650-555-2345",
          "expected": "650",
          "expectedType": "str"
        },
        {
          "input": "1-416-555-9292",
          "expected": "416",
          "expectedType": "str"
        },
        {
          "input": "14165559292",
          "expected": "416",
          "expectedType": "str"
        },
        {
          "input": "416)5553456",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "+1 416 555 9292",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "416.555.3456",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "416-555-345",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": " 4165553456",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": null,
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "(416)-555-3456",
          "expected": "416",
          "expectedType": "str"
        },
        {
          "input": "1 (416) 555 3456",
          "expected": "416",
          "expectedType": "str"
        },
        {
          "input": "416--555-3456",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "416\t5553456",
          "expected": null,
          "expectedType": "NoneType"
        }
      ],
      "passage": "Bộ phận liên hệ khách hàng sao chép các số điện thoại từ nhiều biểu mẫu vào ghi chú chung. Bản ghi đầu tiên là «415-555-1234»; người tiếp theo đưa vào «(416)555-3456»; ở phần rà soát có «202 555 4567»; sau đó nhóm ghi thêm «4035555678»; một mục khác được lưu là «1 416 555 9292»; và mục cuối trong lượt này là «(416555-3456». Người xử lý phải kiểm cả số trước khi lấy mã vùng, vì một số dòng có hình thức gần đúng nhưng thiếu dấu ngoặc hoặc thiếu chữ số.",
      "selected": [
        [
          "415-555-1234",
          "415"
        ],
        [
          "(416)555-3456",
          "416"
        ],
        [
          "202 555 4567",
          "202"
        ],
        [
          "4035555678",
          "403"
        ],
        [
          "1 416 555 9292",
          "416"
        ]
      ]
    },
    {
      "exercise": 14,
      "cases": [
        {
          "input": "tom@hogwarts.com",
          "expected": "tom",
          "expectedType": "str"
        },
        {
          "input": "tom.riddle@hogwarts.com",
          "expected": "tom.riddle",
          "expectedType": "str"
        },
        {
          "input": "tom.riddle+regexone@hogwarts.com",
          "expected": "tom.riddle",
          "expectedType": "str"
        },
        {
          "input": "tom@hogwarts.eu.com",
          "expected": "tom",
          "expectedType": "str"
        },
        {
          "input": "hermione+regexone@hogwarts.com",
          "expected": "hermione",
          "expectedType": "str"
        },
        {
          "input": "tom..riddle@hogwarts.com",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "an_01+lab@data-lab.edu.vn",
          "expected": "an_01",
          "expectedType": "str"
        },
        {
          "input": "tom+@hogwarts.com",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "@hogwarts.com",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "tom@localhost",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "tom@-host.com",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "tom@host-.com",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "tom@@host.com",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": " tom@host.com",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": null,
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "Tom.Riddle+LAB@EXAMPLE.COM",
          "expected": "Tom.Riddle",
          "expectedType": "str"
        },
        {
          "input": ".tom@host.com",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "tom.@host.com",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "tom@host.c",
          "expected": null,
          "expectedType": "NoneType"
        }
      ],
      "passage": "Nhóm hỗ trợ khóa học đang gom các địa chỉ email được dùng để nhận tài liệu, trong đó có địa chỉ gắn bộ lọc. Bản ghi đầu tiên là «tom@hogwarts.com»; người tiếp theo đưa vào «tom.riddle@hogwarts.com»; ở phần rà soát có «tom.riddle+regexone@hogwarts.com»; sau đó nhóm ghi thêm «tom@hogwarts.eu.com»; một mục khác được lưu là «hermione+regexone@hogwarts.com»; và mục cuối trong lượt này là «tom..riddle@hogwarts.com». Người xử lý chỉ trả tên tài khoản gốc sau khi địa chỉ đáp ứng miền quy tắc, còn các mục viết sai vẫn được giữ để thử mẫu.",
      "selected": [
        [
          "tom@hogwarts.com",
          "tom"
        ],
        [
          "tom.riddle@hogwarts.com",
          "tom.riddle"
        ],
        [
          "tom.riddle+regexone@hogwarts.com",
          "tom.riddle"
        ],
        [
          "tom@hogwarts.eu.com",
          "tom"
        ],
        [
          "hermione+regexone@hogwarts.com",
          "hermione"
        ]
      ]
    },
    {
      "exercise": 15,
      "cases": [
        {
          "input": "<a>Liên kết</a>",
          "expected": "a",
          "expectedType": "str"
        },
        {
          "input": "<a href='https://regexone.com'>Mở</a>",
          "expected": "a",
          "expectedType": "str"
        },
        {
          "input": "<div class='test_style'>Nội dung</div>",
          "expected": "div",
          "expectedType": "str"
        },
        {
          "input": "<div>Chào <span>lớp</span></div>",
          "expected": "div",
          "expectedType": "str"
        },
        {
          "input": "</div>",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "văn bản thuần",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "<h2>Tiêu đề</h2>",
          "expected": "h2",
          "expectedType": "str"
        },
        {
          "input": "<my-card>Thẻ</my-card>",
          "expected": "my-card",
          "expectedType": "str"
        },
        {
          "input": "<DIV>ABC</DIV>",
          "expected": "DIV",
          "expectedType": "str"
        },
        {
          "input": "<123>abc</123>",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "<!-- ghi chú -->",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "<a",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": null,
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "<!-- <div>ẩn</div> -->",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "<!-- <div>ẩn</div> --><p>Hiện</p>",
          "expected": "p",
          "expectedType": "str"
        },
        {
          "input": "<!-- <a>ẩn</a> --><!-- <b>ẩn</b> --><section>Hiện</section>",
          "expected": "section",
          "expectedType": "str"
        },
        {
          "input": "<a>Hiện</a><!-- <div>ẩn</div> -->",
          "expected": "a",
          "expectedType": "str"
        },
        {
          "input": "<br/>",
          "expected": "br",
          "expectedType": "str"
        },
        {
          "input": "<img src='x'/>",
          "expected": "img",
          "expectedType": "str"
        },
        {
          "input": "<my-card/>",
          "expected": "my-card",
          "expectedType": "str"
        }
      ],
      "passage": "Trong lúc rà soát các đoạn HTML nhỏ đã được xác nhận từ một nguồn kiểm soát được, người biên tập ghi lại một số đoạn và cả văn bản thuần. Bản ghi đầu tiên là «<a>Liên kết</a>»; người tiếp theo đưa vào «<a href='https://regexone.com'>Mở</a>»; ở phần rà soát có «<div class='test_style'>Nội dung</div>»; sau đó nhóm ghi thêm «<div>Chào <span>lớp</span></div>»; một mục khác được lưu là «</div>»; và mục cuối trong lượt này là «văn bản thuần». Nhóm chỉ cần nhận tên thẻ mở đầu tiên để phân loại nhanh từng đoạn, kể cả đoạn có thẻ con ở bên trong.",
      "selected": [
        [
          "<a>Liên kết</a>",
          "a"
        ],
        [
          "<a href='https://regexone.com'>Mở</a>",
          "a"
        ],
        [
          "<div class='test_style'>Nội dung</div>",
          "div"
        ],
        [
          "<div>Chào <span>lớp</span></div>",
          "div"
        ]
      ]
    },
    {
      "exercise": 16,
      "cases": [
        {
          "input": "img0912.jpg",
          "expected": [
            "img0912",
            "jpg"
          ],
          "expectedType": "tuple"
        },
        {
          "input": "updated_img0912.png",
          "expected": [
            "updated_img0912",
            "png"
          ],
          "expectedType": "tuple"
        },
        {
          "input": "favicon.gif",
          "expected": [
            "favicon",
            "gif"
          ],
          "expectedType": "tuple"
        },
        {
          "input": ".bash_profile",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "workspace.doc",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "img0912.jpg.tmp",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "anh-phong.01.png",
          "expected": [
            "anh-phong.01",
            "png"
          ],
          "expectedType": "tuple"
        },
        {
          "input": "a.jpg.jpg",
          "expected": [
            "a.jpg",
            "jpg"
          ],
          "expectedType": "tuple"
        },
        {
          "input": ".jpg",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "a..jpg",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "a.JPG",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "folder/a.jpg",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "a b.png",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": null,
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "a.pngx",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "photo-01.jpg",
          "expected": [
            "photo-01",
            "jpg"
          ],
          "expectedType": "tuple"
        }
      ],
      "passage": "Nhân viên quản lý tài nguyên chép tên các tệp nhận được trong ngày vào một đoạn báo cáo để chọn ảnh. Bản ghi đầu tiên là «img0912.jpg»; người tiếp theo đưa vào «updated_img0912.png»; ở phần rà soát có «favicon.gif»; sau đó nhóm ghi thêm «.bash_profile»; một mục khác được lưu là «workspace.doc»; và mục cuối trong lượt này là «img0912.jpg.tmp». Các tệp tài liệu, tệp ẩn và tệp tạm được giữ trong danh sách làm đối chứng, giúp kiểm tra đúng phần mở rộng ở cuối toàn tên.",
      "selected": [
        [
          "img0912.jpg",
          [
            "img0912",
            "jpg"
          ]
        ],
        [
          "updated_img0912.png",
          [
            "updated_img0912",
            "png"
          ]
        ],
        [
          "favicon.gif",
          [
            "favicon",
            "gif"
          ]
        ]
      ]
    },
    {
      "exercise": 17,
      "cases": [
        {
          "input": "  Chào lớp  ",
          "expected": "Chào lớp",
          "expectedType": "str"
        },
        {
          "input": "\tPhân tích dữ liệu\t",
          "expected": "Phân tích dữ liệu",
          "expectedType": "str"
        },
        {
          "input": "  A  B  ",
          "expected": "A  B",
          "expectedType": "str"
        },
        {
          "input": "   ",
          "expected": "",
          "expectedType": "str"
        },
        {
          "input": "",
          "expected": "",
          "expectedType": "str"
        },
        {
          "input": null,
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "A",
          "expected": "A",
          "expectedType": "str"
        },
        {
          "input": " A ",
          "expected": "A",
          "expectedType": "str"
        },
        {
          "input": "\t \t",
          "expected": "",
          "expectedType": "str"
        },
        {
          "input": "  0  ",
          "expected": "0",
          "expectedType": "str"
        },
        {
          "input": "A\t B",
          "expected": "A\t B",
          "expectedType": "str"
        },
        {
          "input": "Ñuñoa  ",
          "expected": "Ñuñoa",
          "expectedType": "str"
        },
        {
          "input": " A ",
          "expected": " A ",
          "expectedType": "str"
        },
        {
          "input": "  A \t",
          "expected": " A ",
          "expectedType": "str"
        },
        {
          "input": "\u000bA\f",
          "expected": "\u000bA\f",
          "expectedType": "str"
        },
        {
          "input": " ",
          "expected": " ",
          "expectedType": "str"
        }
      ],
      "passage": "Trong báo cáo nhập văn bản, nhóm gặp các mục có dấu cách hoặc tab thừa ở hai đầu và muốn chuẩn hóa chúng. Bản ghi đầu tiên là «  Chào lớp  »; người tiếp theo đưa vào «\tPhân tích dữ liệu\t»; ở phần rà soát có «  A  B  »; sau đó nhóm ghi thêm «   »; một mục khác được lưu là «». Một ô khác bị thiếu dữ liệu và được lưu là None. Bản ghi vẫn giữ cả mục toàn khoảng trắng, mục rỗng và dữ liệu thiếu, để người xử lý thấy rõ các trường hợp này khác nhau.",
      "selected": [
        [
          "  Chào lớp  ",
          "Chào lớp"
        ],
        [
          "\tPhân tích dữ liệu\t",
          "Phân tích dữ liệu"
        ],
        [
          "  A  B  ",
          "A  B"
        ],
        [
          "   ",
          ""
        ],
        [
          "",
          ""
        ]
      ]
    },
    {
      "exercise": 18,
      "cases": [
        {
          "input": "E/( 1553): at widget.List.makeView(ListView.java:1727)",
          "expected": [
            "makeView",
            "ListView.java",
            1727
          ],
          "expectedType": "tuple"
        },
        {
          "input": "E/( 1553): at widget.List.fillDown(ListView.java:652)",
          "expected": [
            "fillDown",
            "ListView.java",
            652
          ],
          "expectedType": "tuple"
        },
        {
          "input": "E/( 1553): at widget.List.fillFrom(ListView.java:709)",
          "expected": [
            "fillFrom",
            "ListView.java",
            709
          ],
          "expectedType": "tuple"
        },
        {
          "input": "W/dalvikvm: uncaught exception",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "E/: FATAL EXCEPTION: main",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "at widget.List.run(ListView.java:abc)",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "at app.Main.run(Main.java:0)",
          "expected": [
            "run",
            "Main.java",
            0
          ],
          "expectedType": "tuple"
        },
        {
          "input": "at app.Main.run(Main.java:-1)",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "at app.Main.run(Unknown Source)",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "at app.Main.run(Main.java:12",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "at app.Main.run(Main.txt:12)",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "method(Main.java:12)",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": null,
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "sat app.Main.run(Main.java:2)",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "at app.Main.run(Main.java:007)",
          "expected": [
            "run",
            "Main.java",
            7
          ],
          "expectedType": "tuple"
        },
        {
          "input": "E/: at pkg.sub.Main.run(Main.java:5)",
          "expected": [
            "run",
            "Main.java",
            5
          ],
          "expectedType": "tuple"
        }
      ],
      "passage": "Một nhân viên hỗ trợ ứng dụng gom các dòng thông báo và dòng ngăn xếp lỗi vào cùng một đoạn nhật ký bàn giao. Bản ghi đầu tiên là «E/( 1553): at widget.List.makeView(ListView.java:1727)»; người tiếp theo đưa vào «E/( 1553): at widget.List.fillDown(ListView.java:652)»; ở phần rà soát có «E/( 1553): at widget.List.fillFrom(ListView.java:709)»; sau đó nhóm ghi thêm «W/dalvikvm: uncaught exception»; một mục khác được lưu là «E/: FATAL EXCEPTION: main»; và mục cuối trong lượt này là «at widget.List.run(ListView.java:abc)». Nhóm phân tích cần chọn những dòng có đủ cụm phương thức, tệp nguồn và số dòng, sau đó chuyển số dòng sang kiểu số nguyên.",
      "selected": [
        [
          "E/( 1553): at widget.List.makeView(ListView.java:1727)",
          [
            "makeView",
            "ListView.java",
            1727
          ]
        ],
        [
          "E/( 1553): at widget.List.fillDown(ListView.java:652)",
          [
            "fillDown",
            "ListView.java",
            652
          ]
        ],
        [
          "E/( 1553): at widget.List.fillFrom(ListView.java:709)",
          [
            "fillFrom",
            "ListView.java",
            709
          ]
        ]
      ]
    },
    {
      "exercise": 19,
      "cases": [
        {
          "input": "ftp://file_server.com:21/top_secret/a.pdf",
          "expected": [
            "ftp",
            "file_server.com",
            "21"
          ],
          "expectedType": "tuple"
        },
        {
          "input": "https://regexone.com/lesson/introduction#section",
          "expected": [
            "https",
            "regexone.com",
            null
          ],
          "expectedType": "tuple"
        },
        {
          "input": "file://localhost:4040/zip_file",
          "expected": [
            "file",
            "localhost",
            "4040"
          ],
          "expectedType": "tuple"
        },
        {
          "input": "https://s3cur3-server.com:9999/",
          "expected": [
            "https",
            "s3cur3-server.com",
            "9999"
          ],
          "expectedType": "tuple"
        },
        {
          "input": "market://search/angry%20birds",
          "expected": [
            "market",
            "search",
            null
          ],
          "expectedType": "tuple"
        },
        {
          "input": "https://host:abc/a",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "http://localhost",
          "expected": [
            "http",
            "localhost",
            null
          ],
          "expectedType": "tuple"
        },
        {
          "input": "git+ssh://git.example.com:0022/x",
          "expected": [
            "git+ssh",
            "git.example.com",
            "0022"
          ],
          "expectedType": "tuple"
        },
        {
          "input": "1http://host/a",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "https://host:/a",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "https:///a",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "https://a..com/x",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "https://host/a b",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "https://host:80x/a",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": null,
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "HTTPS://host/",
          "expected": [
            "HTTPS",
            "host",
            null
          ],
          "expectedType": "tuple"
        },
        {
          "input": "https://host:",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "https://host:999999/",
          "expected": [
            "https",
            "host",
            "999999"
          ],
          "expectedType": "tuple"
        }
      ],
      "passage": "Nhóm hạ tầng đang rà soát địa chỉ tài nguyên do nhiều dịch vụ gửi tới, với giao thức, máy chủ và cổng có thể khác nhau. Bản ghi đầu tiên là «ftp://file_server.com:21/top_secret/a.pdf»; người tiếp theo đưa vào «https://regexone.com/lesson/introduction#section»; ở phần rà soát có «file://localhost:4040/zip_file»; sau đó nhóm ghi thêm «https://s3cur3-server.com:9999/»; một mục khác được lưu là «market://search/angry%20birds»; và mục cuối trong lượt này là «https://host:abc/a». Người xử lý cần giữ nguyên ba trường có thật trong địa chỉ, đồng thời loại mục có cổng sai thay vì chỉ lấy một tiền tố hợp lệ.",
      "selected": [
        [
          "ftp://file_server.com:21/top_secret/a.pdf",
          [
            "ftp",
            "file_server.com",
            "21"
          ]
        ],
        [
          "https://regexone.com/lesson/introduction#section",
          [
            "https",
            "regexone.com",
            null
          ]
        ],
        [
          "file://localhost:4040/zip_file",
          [
            "file",
            "localhost",
            "4040"
          ]
        ],
        [
          "https://s3cur3-server.com:9999/",
          [
            "https",
            "s3cur3-server.com",
            "9999"
          ]
        ],
        [
          "market://search/angry%20birds",
          [
            "market",
            "search",
            null
          ]
        ]
      ]
    },
    {
      "exercise": 20,
      "cases": [
        {
          "input": "https://example.com/data.csv?year=2026#top",
          "expected": "/data.csv",
          "expectedType": "str"
        },
        {
          "input": "http://localhost:8080/a/b",
          "expected": "/a/b",
          "expectedType": "str"
        },
        {
          "input": "https://example.com",
          "expected": "/",
          "expectedType": "str"
        },
        {
          "input": "https://example.com/?q=x",
          "expected": "/",
          "expectedType": "str"
        },
        {
          "input": "https://example.com/angry%20birds#info",
          "expected": "/angry%20birds",
          "expectedType": "str"
        },
        {
          "input": "ftp://example.com/a",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "https://example.com?q=x",
          "expected": "/",
          "expectedType": "str"
        },
        {
          "input": "https://example.com#top",
          "expected": "/",
          "expectedType": "str"
        },
        {
          "input": "https://example.com/a?x=1?y=2#z",
          "expected": "/a",
          "expectedType": "str"
        },
        {
          "input": "https://example.com/a#x?y=1",
          "expected": "/a",
          "expectedType": "str"
        },
        {
          "input": "https://example.com:abc/a",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "https://example.com/a b",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "https:///a",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "HTTP://example.com/a",
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": null,
          "expected": null,
          "expectedType": "NoneType"
        },
        {
          "input": "https://host:0",
          "expected": "/",
          "expectedType": "str"
        },
        {
          "input": "https://host/?#",
          "expected": "/",
          "expectedType": "str"
        },
        {
          "input": "https://host/a%2Fb?q=x",
          "expected": "/a%2Fb",
          "expectedType": "str"
        }
      ],
      "passage": "Trong một báo cáo truy cập, nhân viên ghi các địa chỉ trang có đường dẫn, tham số truy vấn hoặc đoạn neo để nhóm xử lý. Bản ghi đầu tiên là «https://example.com/data.csv?year=2026#top»; người tiếp theo đưa vào «http://localhost:8080/a/b»; ở phần rà soát có «https://example.com»; sau đó nhóm ghi thêm «https://example.com/?q=x»; một mục khác được lưu là «https://example.com/angry%20birds#info»; và mục cuối trong lượt này là «ftp://example.com/a». Mục tiêu là lấy riêng đường dẫn của các URL đúng miền đã nêu, giữ nguyên phần mã hóa và trả đường dẫn gốc khi địa chỉ không ghi đường dẫn.",
      "selected": [
        [
          "https://example.com/data.csv?year=2026#top",
          "/data.csv"
        ],
        [
          "http://localhost:8080/a/b",
          "/a/b"
        ],
        [
          "https://example.com",
          "/"
        ],
        [
          "https://example.com/?q=x",
          "/"
        ],
        [
          "https://example.com/angry%20birds#info",
          "/angry%20birds"
        ]
      ]
    }
  ]
}
