#include <iostream> // Thư viện nhập xuất (cout, cin)
#include <bitset> // Dùng để in số ở dạng nhị phân (bit)
#include <cstdint> // Chứa các kiểu số nguyên có kích thước xác định (uint8_t, uint16_t, uint64_t)
#include <iomanip> // Dùng cho setw(), setfill(), hex, dec
using namespace std;
// Hàm 1: Lấy giá trị của 1 bit tại vị trí cho trước
bool lay_bit(uint64_t so, int vi_tri_bit);
// Hàm 2: In ra chuỗi 64 bit của 1 số nguyên 64-bit
void in_day_bit(uint64_t so);
// Hàm 3: Đếm số bit '1' trong một số 64-bit
int dem_bit_1(uint64_t so);
// Hàm 4: Gán giá trị cho 1 bit (0 hoặc 1) tại vị trí cho trước
void gan_bit(uint64_t &so, int vi_tri_bit, bool gia_tri);
// Hàm 5: Hoán đổi giá trị của hai bit trong cùng một số
void hoan_doi_bit(uint64_t &so, int bit_A, int bit_B);
// Hàm 6: Tìm độ dài dãy bit '1' liên tiếp dài nhất
int do_dai_day_1_dai_nhat(uint64_t so);
// Hàm 7: Tìm dãy bit liên tiếp dài nhất có giá trị B (0 hoặc 1)
// Kết quả mã hoá trong 16 bit: [0..5]=độ dài-1, [6..11]=vị trí bắt đầu, [12]=giá trị bit
uint16_t tim_day_bit_dai_nhat(uint64_t so, bool gia_tri_bit_can_tim);
// Hàm 8: Quay trái K bit (bit rơi ra bên trái được đưa lại vào bên phải)
uint64_t quay_trai(uint64_t so, int so_bit);
// Hàm 9: Quay phải K bit (bit rơi ra bên phải được đưa lại vào bên trái)
uint64_t quay_phai(uint64_t so, int so_bit);
// Hàm 10: Đếm số lần thay đổi trạng thái giữa các bit (0→1 hoặc 1→0)
int dem_so_lan_chuyen_trang_thai(uint64_t so);
// Hàm 11: Tìm vị trí cửa sổ (window) gồm W bit liên tiếp gần nhất
// với dãy toàn 0 hoặc toàn 1
int cua_so_gan_nhat(uint64_t so, int tong_so_bit, uint8_t do_rong_cua_so, bool bit_can_tim);
int main() {
uint64_t so;
cout << "Nhap vao mot so nguyen khong am (toi da 64-bit): ";
cin >> so;
cout << "\nSo ban dau (dang nhi phan): ";
in_day_bit(so);
cout << endl;
int lua_chon;
do {
cout << "\n========== MENU CHUC NANG ==========\n";
cout << "1. Lay gia tri cua mot bit\n";
cout << "2. Dem so bit '1'\n";
cout << "3. Gan gia tri cho mot bit (0 hoac 1)\n";
cout << "4. Hoan doi hai bit\n";
cout << "5. Do dai day bit '1' dai nhat\n";
cout << "6. Tim day bit dai nhat theo gia tri (0/1)\n";
cout << "7. Quay trai K bit\n";
cout << "8. Quay phai K bit\n";
cout << "9. Dem so lan chuyen trang thai (0↔1)\n";
cout << "10. Tim cua so gan nhat voi day toan 0/1\n";
cout << "0. Thoat\n";
cout << "===================================\n";
cout << "Chon chuc nang (0-10): ";
cin >> lua_chon;
switch (lua_chon) {
case 1: {
int vi_tri;
cout << "Nhap vi tri bit can lay (0..63): ";
cin >> vi_tri;
cout << "Bit thu " << vi_tri << " = " << lay_bit(so, vi_tri) << endl;
break;
}
case 2: {
cout << "So luong bit '1' = " << dem_bit_1(so) << endl;
break;
}
case 3: {
int vi_tri;
bool gia_tri;
cout << "Nhap vi tri bit can gan (0..63): ";
cin >> vi_tri;
cout << "Nhap gia tri moi (0 hoac 1): ";
cin >> gia_tri;
gan_bit(so, vi_tri, gia_tri);
cout << "Sau khi gan: ";
in_day_bit(so);
break;
}
case 4: {
int a, b;
cout << "Nhap hai vi tri bit can hoan doi: ";
cin >> a >> b;
hoan_doi_bit(so, a, b);
cout << "Sau khi hoan doi: ";
in_day_bit(so);
break;
}
case 5: {
cout << "Do dai day bit '1' dai nhat = " << do_dai_day_1_dai_nhat(so) << endl;
break;
}
case 6: {
bool gia_tri;
cout << "Nhap gia tri bit can tim day (0 hoac 1): ";
cin >> gia_tri;
uint16_t thong_tin = tim_day_bit_dai_nhat(so, gia_tri);
cout << "Thong tin ma hoa = 0x" << hex << setw(4) << setfill('0') << thong_tin << dec << endl;
break;
}
case 7: {
int k;
cout << "Nhap so bit can quay trai: ";
cin >> k;
so = quay_trai(so, k);
cout << "Sau khi quay trai: ";
in_day_bit(so);
break;
}
case 8: {
int k;
cout << "Nhap so bit can quay phai: ";
cin >> k;
so = quay_phai(so, k);
cout << "Sau khi quay phai: ";
in_day_bit(so);
break;
}
case 9: {
cout << "So lan chuyen trang thai (0↔1): " << dem_so_lan_chuyen_trang_thai(so) << endl;
break;
}
case 10: {
int tong_bit = 64;
uint8_t rong;
bool bit_tim;
cout << "Nhap do rong cua so W: ";
cin >> rong;
cout << "Nhap bit can tim (0 hoac 1): ";
cin >> bit_tim;
cout << "Vi tri cua so gan nhat: " << cua_so_gan_nhat(so, tong_bit, rong, bit_tim) << endl;
break;
}
case 0:
cout << "Tam biet!\n";
break;
default:
cout << "Lua chon khong hop le. Thu lai!\n";
}
} while (lua_chon != 0);
return 0;
}
// ==================== ĐỊNH NGHĨA HÀM ====================
bool lay_bit(uint64_t so, int vi_tri_bit) {
return (so >> vi_tri_bit) & 1ULL;
}
void in_day_bit(uint64_t so) {
cout << bitset<64>(so) << endl;
}
int dem_bit_1(uint64_t so) {
int dem = 0;
for (int i = 0; i < 64; ++i)
if ((so >> i) & 1ULL) dem++;
return dem;
}
void gan_bit(uint64_t &so, int vi_tri_bit, bool gia_tri) {
if (gia_tri)
so |= (1ULL << vi_tri_bit); // Bật bit
else
so &= ~(1ULL << vi_tri_bit); // Tắt bit
}
void hoan_doi_bit(uint64_t &so, int bit_A, int bit_B) {
bool gia_tri_A = lay_bit(so, bit_A);
bool gia_tri_B = lay_bit(so, bit_B);
if (gia_tri_A != gia_tri_B) {
so ^= (1ULL << bit_A);
so ^= (1ULL << bit_B);
}
}
int do_dai_day_1_dai_nhat(uint64_t so) {
int lon_nhat = 0, hien_tai = 0;
for (int i = 0; i < 64; ++i) {
if (lay_bit(so, i)) {
hien_tai++;
lon_nhat = max(lon_nhat, hien_tai);
} else hien_tai = 0;
}
return lon_nhat;
}
uint16_t tim_day_bit_dai_nhat(uint64_t so, bool gia_tri_bit_can_tim) {
int lon_nhat = 0, bat_dau_tot = 0, hien_tai = 0, bat_dau_tam = 0;
for (int i = 0; i < 64; ++i) {
if (lay_bit(so, i) == gia_tri_bit_can_tim) {
if (hien_tai == 0) bat_dau_tam = i;
hien_tai++;
if (hien_tai > lon_nhat) {
lon_nhat = hien_tai;
bat_dau_tot = bat_dau_tam;
}
} else hien_tai = 0;
}
uint16_t kq = 0;
kq |= (lon_nhat - 1) & 0x3F; // [0..5]
kq |= (bat_dau_tot & 0x3F) << 6; // [6..11]
kq |= (gia_tri_bit_can_tim ? 1 : 0) << 12; // [12]
return kq;
}
uint64_t quay_trai(uint64_t so, int so_bit) {
return (so << so_bit) | (so >> (64 - so_bit));
}
uint64_t quay_phai(uint64_t so, int so_bit) {
return (so >> so_bit) | (so << (64 - so_bit));
}
int dem_so_lan_chuyen_trang_thai(uint64_t so) {
int dem = 0;
bool truoc = lay_bit(so, 0);
for (int i = 1; i < 64; ++i) {
bool hien_tai = lay_bit(so, i);
if (hien_tai != truoc) dem++;
truoc = hien_tai;
}
return dem;
}
int cua_so_gan_nhat(uint64_t so, int tong_so_bit, uint8_t do_rong_cua_so, bool bit_can_tim) {
int vi_tri_tot = -1, chenh_lech_tot = 65;
for (int vi_tri = 0; vi_tri <= tong_so_bit - do_rong_cua_so; ++vi_tri) {
uint64_t cua_so = (so >> vi_tri) & ((1ULL << do_rong_cua_so) - 1);
int so_bit_1 = dem_bit_1(cua_so);
int chenh_lech = bit_can_tim ? (do_rong_cua_so - so_bit_1) : so_bit_1;
if (chenh_lech < chenh_lech_tot) {
chenh_lech_tot = chenh_lech;
vi_tri_tot = vi_tri;
}
}
return vi_tri_tot;
}