Comment

Comment by nerdo

There's a better way to do this, you use inverse CDF to avoid all the RNG calls. Generate a random number, then skip items until you reach that number:

selectRandomFromIteratorOptimized(iterator) { if (!iterator.moveNext()) { return null; }

    var winner = iterator.current();
    var count = 1;

    while (true) {
        var u = random_float_open(0.0, 1.0);
        var skip = (int)Math.Floor(Math.Log(u) / Math.Log(1.0 - (1.0 / (count + 1))));

        for (var i = 0; i < skip; ++i) {
            if (!iterator.moveNext()) {
                return winner;
            }
            ++count;
        }

        if (!iterator.moveNext()) {
            return winner;
        }

        ++count;
        winner = iterator.current();
    }
}
parent nerdo 1 month ago

Discussion

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton