/*
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 unsigned 64‑bit integer to binary string without leading zeros
fun toBinary(x: ULong): String {
if (x == 0UL) return "0"
val sb = StringBuilder()
var n = x
while (n != 0UL) {
sb.insert(0, if ((n and 1UL) == 1UL) '1' else '0')
n = n shr 1
}
return sb.toString()
}
// Copy bits from M into N between bit positions [i, j]
fun copyBits(N: ULong, M: ULong, i: Int, j: Int): ULong {
if (i < 0 || j < 0 || i > j || j >= 63)
throw IllegalArgumentException("Invalid bit range")
val length = j - i + 1
// Mask for bits i..j
val mask = ((1UL shl length) - 1UL) shl i
// Clear bits i..j in N
val Ncleared = N and mask.inv()
// Take only the needed bits from M and shift into place
val Mshifted = (M and ((1UL shl length) - 1UL)) shl i
return Ncleared or Mshifted
}
fun main() {
/*
N: 100 011111 00
M: 110011
Result: 100 110011 00
*/
val N = 0b10001111100UL
val M = 0b110011UL
val result = copyBits(N, M, 2, 7)
println("N: ${toBinary(N)}")
println("M: ${toBinary(M)}")
println("Result: ${toBinary(result)}")
}
/*
OUTPUT:
N: 10001111100
M: 110011
Result: 10011001100
*/