You have a number. You XOR it with something. The bits flip — some turn ON, others turn OFF. The original value is gone, replaced by something new.
But here's the question that separates XOR from every other operator: can you get the original back?
Think about what AND and OR leave behind. If you AND a number with a mask and a bit becomes 0, was that bit originally 0 or was it 1 that got forced down? You can't tell — the information is destroyed. OR has the same problem in reverse: once a bit is forced to 1, its original state is gone.
Both operators are one-way streets. They flatten information into a result that can't be unwound.
XOR is different. It has a property that neither AND nor OR possess — a property that makes it the foundation of swap tricks, encryption, error detection, and some of the most elegant algorithms in computer science. The truth table will show you exactly what that property is, and the rest of this module will show you why it matters.
AND destroys information — once a & mask forces a bit to 0, you can't tell whether that bit was originally 0 or 1. The mask ate the evidence. OR does the same in reverse: once a | mask forces a bit to 1, the original state is equally unrecoverable. Both operators are lossy. They compress two distinct inputs into one output, and the mapping isn't invertible.
But what if there were an operator that could undo itself? An operator where applying it twice — (a ^ b) ^ b — returned you to the original a, with no information lost?
That would mean the operator preserves enough structure in its output that the transformation is fully reversible. It sounds like a strange requirement, but it's exactly what makes XOR the foundation of swap tricks, encryption schemes, error-correcting codes, and the single-number algorithm you'll build in the next module.
The truth table will show you exactly why XOR has this property and AND/OR don't. For every combination of inputs (0,0), (0,1), (1,0), (1,1), predict the XOR output. Pay special attention to what happens when both inputs are identical — that's the row that unlocks everything that follows.
Which operator is its own inverse? (Applying it twice gets you back)
The critical row is a ^ a = 0. When both inputs are the same, every bit pair matches, and XOR zeros them all out. Combined with a ^ 0 = a (XOR with zero changes nothing), you get a complete undo mechanism: (a ^ b) ^ b = a ^ (b ^ b) = a ^ 0 = a. XOR is its own inverse.
You've seen that a ^ a = 0 — any number XOR'd with itself vanishes. But what happens when you XOR a sequence of numbers together, one after another? If the sequence contains pairs, what do you think the final result will be?
Six numbers sit below: [5, 3, 5, 3, 7, 7]. Three pairs. Fold them with XOR and predict what happens at each step. Pay attention to the accumulator — does it behave the way you expect?
After XOR-ing 5 with 3, will the result have MORE, FEWER, or SAME number of set bits as 5?
Every matched pair cancelled to zero, and XOR with zero is identity. The fold consumed six numbers and produced nothing — 0. This isn't coincidence; it's the algebraic consequence of self-inverse applied repeatedly. Any array where every value appears an even number of times will XOR-fold to zero.
Here's the subtle thing: the order you folded in didn't matter. The 5 and 3 that cancelled weren't adjacent — other values sat between them. Yet the cancellation still worked, because XOR doesn't care about sequence. That property has a name — commutativity — and you'll prove it next.
The same six numbers are back, but shuffled into a completely different sequence: [7, 5, 3, 3, 7, 5]. Last time the fold went 5, 3, 5, 3, 7, 7 and produced 0. Does the order of XOR operations matter?
Intuitively, if the same pairs exist, they should still cancel — but does the math guarantee it? Commit to a prediction before the fold runs, then watch whether the result matches.
Same numbers, different order. Same result?
Order doesn't matter because XOR obeys two algebraic laws: commutativity (a ^ b = b ^ a) and associativity ((a ^ b) ^ c = a ^ (b ^ c)). Together, these let you rearrange any XOR-fold into whatever order is convenient — the result is always the same. This is what makes XOR-fold so robust in algorithms: you don't need to sort the input or process it in any particular sequence.
You've seen three laws in action across the last three screens — self-inverse (a ^ a = 0) in the truth table, identity (a ^ 0 = a) in the annihilation chamber, and commutativity (a ^ b = b ^ a) in the shuffled fold. Each one appeared as an empirical observation: you watched it happen, you verified it held. But observations aren't tools until you name them and write them down as equations.
Three properties, three equations. The formalization matters because it gives you a calculus — a way to simplify XOR expressions without tracing individual bits. When you see a ^ b ^ a in code, you won't need to mentally evaluate it for specific values of a and b. Instead, you'll rearrange using commutativity (a ^ a ^ b), cancel using self-inverse (0 ^ b), and simplify using identity (b). Three steps, no bit-tracing. That mechanical simplification is exactly how you'll reason about XOR-fold algorithms, the swap trick (a ^= b; b ^= a; a ^= b), and the duplicate-cancellation pattern in later modules.
Assemble the three laws from their component parts below.
Three laws, fully assembled. Self-inverse lets pairs cancel. Identity means XOR with 0 is free. Commutativity means order is irrelevant. These three properties are the complete toolkit for reasoning about XOR — every XOR-based algorithm relies on some combination of them.
The fold operation you've been performing by hand has a direct TypeScript translation. A reduce call with ^ as the accumulator does exactly what the visual fold did — processes each element in sequence, XOR-ing it into a running total. The missing-number variant extends the same idea by XOR-ing against the expected range. Fill in the blanks and see how terse the code is compared to the understanding it requires.
Two functions, two lines of core logic. The conceptual weight of self-inverse, identity, and commutativity collapses into acc ^ x inside a fold. That's the payoff of understanding the algebra: the code is trivially short, but knowing why it works requires everything you built in this module.
One final test: simplify a ^ b ^ a using the three laws. This expression appears constantly in XOR-based algorithms — it's the algebraic core of “the duplicate cancels, leaving the unique.” Apply commutativity to rearrange, self-inverse to cancel, and identity to clean up.
If you can simplify this expression on sight, you own the XOR algebra completely.
3 ^ 3 vanish to 0 inside the fold -- the annihilation moment that makes the whole algorithm possible.
You proved order doesn't matter by shuffling the same six numbers and getting the same result. Commutativity means you never need to sort.
Three laws assembled from fragments, three blanks filled in singleNumber, and a domino proof that reduced a ^ b ^ a down to just b.
That proof IS the algorithm: every duplicate pair cancels, and the unique survivor is the answer.singleNumber — three laws, four lines
let result = 0Identity: a ^ 0 = afor (const n of nums)Walk every element once result ^= nPairs annihilate: a ^ a = 0return resultThe unique element survivesWhen to reach for XOR