Chèn bit¶
Đề bài¶
Cho hai số nguyên 32 bit \(n\) và \(m\), cùng hai vị trí bit \(start\) và \(end\), với \(start \ge end\).
Yêu cầu:
Chèn toàn bộ các bit của \(m\) vô trong \(n\) sao cho \(m\) nằm từ vị trí bit \(start\) đến vị trí bit \(end\).
Input:
\(n, m, start, end\).
Output:
\(n\) mới sau khi chèn vô.
Giải thích:
Các bit của \(n\) tại vị trí từ 2 đến 6 được thay thế bằng các bit của \(m = 10011\).
Điều kiện:
Đoạn bit từ \(start\) đến \(end\) luôn có đủ chỗ để chứa trọn vẹn \(m\).
Bài giải đề xuất¶
Ý tưởng chính¶
Ta cần dịch chuyển các bit của m sang trái để khớp với các vị trí cần chèn vô là start và end.
Để có thể chèn vô vị trí start và end trong n, ta cần "xóa" đoạn bit này của n, tức là chuyển các bit từ start đến end thành bit 0.
Để làm điều này, ta dùng toán tử & đối với n và mask:
Trong đó, mask là mặt nạ dùng để che các bit bên trái của start và các bit bên phải của end, đồng thời để hở các bit nằm giữa start và end (để chèn m vô).
mask có dạng: 1..1 00000 11.
Để tạo mask, ta cần tạo hai chuỗi:
leftlà chuỗi các bit1nằm bên trái củastart.rightlà chuỗi các bit1nằm bên phải củaend.
Để tạo left, ta tạo một chuỗi toàn bit 1 bằng lệnh ~0. Sau đó, dịch trái chuỗi này start + 1 bước.
Để tạo right, ta dịch chuyển các bit của số nguyên 1 sang trái end bước, rồi thực hiện trừ đi 1 để các bit từ vị trí 0 đến i - 1 trở thành bit 1 và các bit cao hơn trở thành bit 0.
Kết hợp left và right bằng toán tử | để tạo thành mask.
Như vậy,
Cuối cùng, ta chèn m_shifted vô n_cleared bằng toán tử |:
Hình sau đây minh họa lại các bước vừa trình bày:
Viết chương trình¶
Mã nguồn¶
Code đầy đủ được đặt tại GitHub.
