XOR-fold solved the whole-array problem — annihilating duplicates to find a unique element. But that technique treats numbers as indivisible atoms. You XOR entire values together and the algebra handles the rest. What if you need finer control?
Real-world bit manipulation rarely operates on whole numbers. Feature flags, permission masks, hardware registers, network protocol headers — they all pack multiple independent fields into a single integer, and you need to read, set, clear, or flip one specific bit without disturbing any of its neighbors. Think of it as the difference between repainting an entire wall and retouching a single pixel.
That requires a different set of tools — and a fundamentally different way of thinking about bitwise operations. Instead of combining entire numbers, you'll learn to construct masks that isolate individual positions, then pair those masks with the operators you already know to perform precision surgery. The difference is like using a sledgehammer versus a scalpel, and by the end of this module you'll have five distinct scalpel techniques in your toolkit.
Before you appreciate the scalpel, you need to feel the sledgehammer. Every whole-number arithmetic operation you know — complement (~n), addition (n + 1), subtraction (n - 1) — changes multiple bits simultaneously, because these operations don't respect bit-position independence.
Complement flips every bit: ~0b001100 becomes 0b110011. Six positions, six changes — no way to target just one. Addition is subtler but equally destructive: 0b001111 + 1 triggers a carry chain that ripples through four consecutive positions, turning 1111 into 10000.
Subtraction propagates borrows in the same cascading fashion — 0b010000 - 1 borrows across every zero below the leading 1, flipping four bits to produce 0b001111. These ripple effects mean that even when you think you're making a small change, the binary representation shifts in ways that are hard to predict and impossible to contain.
Try to flip just bit 3 of a 6-bit number using these arithmetic tools, and watch how many other bits get caught in the blast.
101101. Try a whole-number operation.Every attempt changed too many bits. That's the fundamental limitation of arithmetic operations: they don't respect bit boundaries. Carries and borrows ripple across positions, turning a targeted operation into collateral damage. To touch exactly one bit, you need a different approach entirely.
The tool you need is a mask — a number with exactly one bit set at the position you want to target. 1 << k creates a mask for position k: a single 1 surrounded by zeros.
Combined with the right operator, this mask lets you perform four distinct surgeries on any bit: CHECK it (is it ON or OFF?), SET it (force it ON), CLEAR it (force it OFF), or TOGGLE it (flip it to the opposite). Build the mask first, then perform each surgery and predict the outcome.
Four surgeries, four operators. CHECK uses & to isolate the target bit. SET uses | to force it ON. CLEAR uses & ~mask to force it OFF. TOGGLE uses ^ to flip it. Each surgery targets exactly one position and leaves every other bit untouched — that's the precision the sledgehammer couldn't provide.
Subtracting 1 from a number does something precise and useful to its binary representation — but the mechanics are easy to miss if you only think in decimal. Consider n = 12, which is 1100 in binary. What does n - 1 look like?
In decimal, 12 - 1 = 11. Unremarkable. But in binary, 1100 - 1 = 1011. Something interesting happened to the bit pattern — but what, exactly? Which bits changed, and which stayed the same? Is there a predictable rule, or does it depend on the specific number?
Subtracting 1 creates a cascade effect in the binary representation. The pattern is consistent, but you need to see it across several different numbers before the rule becomes clear. Watch the cascade happen below and try to predict the result before each subtraction completes.
101100 (44). What happens when you subtract 1?Will the borrow from subtracting 1 affect bits ABOVE position 2?
The borrow propagation pattern is predictable: n - 1 flips the lowest set bit OFF and flips every 0 below it to 1. The critical insight is what happens when you AND the original number with the result: n & (n - 1) clears the lowest set bit and preserves everything above it. That's not an accident — it's a direct consequence of the borrow pattern you just observed.
You just saw n & (n - 1) clear the lowest set bit in a single operation. What if you applied the same trick again to the result? And then again? How many times can you do it before you run out of set bits entirely?
That question — “how many iterations until the number reaches zero?” — is more interesting than it sounds. Think about what the answer depends on. Is it the magnitude of the number? The number of digits? Something else?
Watch each step below and predict when the number hits zero. Count the iterations carefully — do you see a relationship between the starting number and the number of steps?
The loop ran exactly as many times as there were set bits — no more, no less. That's dramatically better than the naive approach of checking every bit position individually (which always takes 32 or 64 iterations regardless of how many bits are set). Kernighan's trick is O(k) where k is the number of set bits, and the entire loop body is just n = n & (n - 1).
Five bit-surgery functions, each a single return expression — except countSetBits, which needs a three-line loop. The first three (checkBit, setBit, toggleBit) are straightforward operator-to-surgery mappings you've already performed. The interesting two are clearBit — the only one requiring the inverted mask ~(1 << k) — and countSetBits with the Kernighan loop body. Match the operators to surgeries, then fill in the tricky expressions.
Five functions, five tools. checkBit reads without modifying. setBit forces ON. clearBit forces OFF. toggleBit flips. countSetBits destroys set bits one by one and counts the iterations. These five operations are the complete vocabulary of single-bit manipulation — every bit trick in competitive programming is built from some combination of them.
whole-number operations that broke multiple bits at once. The sledgehammer showed you WHY surgical precision matters.
Then you built a single-bit mask from its decimal value, not from a hint. You had to reason: weight 8 lives at position 3. That's 1 << 3.
Four surgeries followed — CHECK, SET, CLEAR, TOGGLE — each with a different operator. CLEAR was the tricky one: the inverted mask ~(1<<k) is unique to clearing.
The borrow cascade showed you the engine behind n & (n-1): subtract 1 flips bits in a cascade that stops at the lowest set bit.
Finally, Kernighan's loop. You FELT the cost of manual clearing — 6 real operations for 2 bits — then watched the loop do it in 3 iterations. One per set bit.Five surgeries, five one-liners
function checkBit(n: number, k: number) { return (n & (1 << k)) !== 0}function setBit(n: number, k: number) { return n | (1 << k)}function clearBit(n: number, k: number) { return n & ~(1 << k)}function toggleBit(n: number, k: number) { return n ^ (1 << k)}function countSetBits(n: number) { let count = 0 while (n > 0) { n = n & (n - 1) count++ } return count}When to reach for each