How to Actually Solve the Locker Problem Without Overcomplicating It
The classic version runs like this: 1000 lockers, all closed. Student 1 opens every locker. Student 2 closes every second locker. Student 3 toggles every third locker. Student 4 toggles every fourth, and so on through all 1000 students. The question everyone asks is which lockers stay open at the end. Most people try to simulate it on paper or write a script that iterates through each student and each locker. That works fine for 100 lockers. With 1000, it's still manageable on a modern machine, but you end up doing 500,500 toggle operations and learning nothing about the actual structure. The brute force approach is what got me to look closer at the pattern. Here is what happens when you think about it properly. A locker gets toggled once for every one of its divisors. Locker 12, for example, gets touched by student 1, student 2, student 3, student 4, student 6, and student 12. That is six toggles. Six is even, so the locker ends up closed. The lockers that stay open are the ones with an odd number of divisors. And here is the part nobody tells you until they have already wasted two days debugging a simulation: only perfect squares have an odd number of divisors. This is because divisors normally come in pairs. For 12, you have 1 times 12, 2 times 6, and 3 times 4. But for a perfect square like 36, you get 1 times 36, 2 times 18, 3 times 12, 4 times 9, and then 6 times 6. The 6 repeats. That is the only divisor without a pair. So 36 gets an odd count.
The Locker Problem 1000 Lockers Answer
The lockers that remain open are the perfect squares from 1 through 961. The 31st perfect square is 961. The next one would be 32 squared, which is 1024, and that exceeds 1000. So there are exactly 31 lockers open, and their numbers are 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529, 576, 625, 676, 729, 784, 841, 900, and 961. I wrote a quick Python script to verify this because I did not trust the math on first glance. The divisor-counting method is cleaner than simulating the whole toggle process, but both give the same result. The direct formula approach takes microseconds. The full simulation with nested loops took about 8 milliseconds on my machine, which sounds fast but becomes noticeable if you ever scale this to 100,000 lockers. At that scale, the simulation runs for roughly 5 seconds while the mathematical answer is still instant. One edge case I ran into that is easy to miss: people sometimes forget that student 1 toggles every single locker, starting from the first. If you accidentally start your divisor logic from 2 instead of 1, you will get the wrong answer because you are skipping the initial toggle that determines whether the lockers are closed or open at the very beginning. I caught this when my simulation output was exactly one locker different from the formula. The difference was locker 1. It took me about ten minutes to realize I had started my inner loop at divisor 2 in the simulation instead of divisor 1.
There is another thing worth noting that most tutorials skip. The problem only works cleanly because we assume each student toggles their multiples in sequence. If the rules change even slightly, like if student 3 only toggles multiples of 3 that are greater than 9, the entire divisor-based reasoning breaks down. I saw a variant of this problem where student n only starts toggling at locker n², which sounds clever but completely destroys the elegant divisor pairing argument. In those cases, you are stuck with simulation. For the standard version with 1000 lockers and 1000 students, the answer is straightforward once you see the perfect square connection. The code is trivial too. Here is a minimal implementation you can use as a reference point. For the direct mathematical answer, the code is just a range of squared integers. That is the version you should use unless you are specifically teaching someone how to write a nested loop.
Get the Full Details

I usually recommend the mathematical approach for any real application, not just this puzzle. The simulation is useful for understanding the mechanics, but it hides the actual structure of the problem. Once you recognize that divisor parity determines the final state, you stop thinking about lockers and students and start seeing it as a number theory problem, which it actually is.