An unbounded height could build a tower taller than the head sentinel and run off the end of its pointers. Today you cap the height at the maximum level, and move the generator inside the list so the list owns its own reproducible source of randomness.
Bound randomLevel at MaxLevel and wire a seeded generator into the skip list itself.
A tower must never be taller than the head sentinel, because the head only has
MaxLevel forward pointers to link into. An unbounded coin-flip height could, on a
long lucky streak, ask for a level the head does not have. So the generator gets a
cap: stop climbing once the height reaches MaxLevel, even if the coin would
keep saying heads. With seed 698 the coin comes up heads three times in a row, which
uncapped would reach 7, but the cap holds it at 4 - it stops the loop before flipping
a fourth time.
The second move is organizational: the generator belongs inside the list. Up to
now rng was a free-standing helper; now NewSkipList builds one from the seed it
was handed back in lesson 2 and stores it, and the list exposes a small
randomLevel that calls it with the cap. From here on, the list is a self-contained,
seeded machine: hand it a seed and every tower height it will ever choose is fixed.
The next lesson finally connects this to insertion.
// Stop climbing at MaxLevel so a tower never exceeds the head's height.func (r *rng) level(max int) int {lvl := 1for lvl < max && r.coin() { lvl++ }return lvl}// NewSkipList now builds the generator from the seed:// s.rng = newRNG(seed)// and s.randomLevel() calls s.rng.level(MaxLevel).