#
# Handles edge cases:
# - Validates i and j
# - Prevents undefined behavior from shifting by ≥ 64 bits
# - Masks M so only the required bits are copied
#
# Convert integer to binary string without leading zeros
def to_binary(x: int) -> str:
if x == 0:
return "0"
return bin(x)[2:] # strip "0b"
# Copy bits from M into N between bit positions [i, j]
def copy_bits(N: int, M: int, i: int, j: int) -> int:
if i < 0 or j < 0 or i > j or j >= 63:
raise ValueError("Invalid bit range")
length = j - i + 1
# Mask for bits i..j
mask = ((1 << length) - 1) << i
# Clear bits i..j in N
N_cleared = N & ~mask
# Take only the needed bits from M and shift into place
M_shifted = (M & ((1 << length) - 1)) << i
return N_cleared | M_shifted
def main():
#
# N: 100 011111 00
# M: 110011
# Result: 100 110011 00
#
N = 0b10001111100
M = 0b110011
result = copy_bits(N, M, 2, 7)
print("N: ", to_binary(N))
print("M: ", to_binary(M))
print("Result: ", to_binary(result))
if __name__ == "__main__":
main()
"""
OUTPUT:
N: 10001111100
M: 110011
Result: 10011001100
"""