A No-Repeat Random Draw Looks Trivial Until Round 70
Drawing numbers without repeats sounds like a beginner exercise. It is also a place where a lot of shipped code has a real defect. The version most people write function drawNaive ( called : number []): number { let n : number ; do { n = Math . floor ( Math . random () * 75 ) + 1 ; } while ( called . includes ( n )); return n ; } This is rejection sampling. It is correct in the sense that it…
A seemingly simple task of drawing numbers without repetition turns out to be a complex one in practice. A common naive approach involves rejection sampling, where a random number is generated and checked against the already drawn numbers. However, this method has two significant issues. First, as the pool of available numbers shrinks, the expected number of iterations per draw increases, making the code inefficient.
Second, the time complexity of the check operation (called.includes(n)) is O(n), which can lead to unbounded loop iterations near the end of the draw process. To fix these issues, it is recommended to directly select numbers from the remaining set instead of using a loop to filter out the used numbers. This approach ensures constant time complexity and eliminates the risk of looping indefinitely when the deck is empty.
Additionally, it is suggested to make the random number generator (RNG) injectable, which allows for easier testing and more reliable results. By implementing these changes, developers can create a more efficient and reliable random draw system.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.