build-a-bloom-filter / lesson-17.md
Lesson 17 · The Count-Min sketch

Estimate is the minimum

To read a frequency back, look at the item's counter in each row and take the smallest. Because collisions only ever add to a counter, the minimum is the tightest over-estimate available and never reads low. Today you implement Estimate.

The goal

Estimate an item's frequency as the minimum of its mapped counters across all rows.

Start here - the target
TO DO
Scenario: The estimate is the minimum across rows
Giventhe sketch after adding "cat" three times, "dog" twice, and "the" five times
Wheneach item is estimated
ThenEstimate("cat") is 3, Estimate("dog") is 2, and Estimate("the") is 5
AndEstimate("fox"), never added, is 0 - the estimate never reads below the true count
Background

Reading a count back is where the name earns itself. Every one of an item’s row counters holds at least its true frequency, because counters only ever get added to - the item’s own additions are always in there, plus whatever collisions piled on. So each row gives an over-estimate, and the tightest one is the minimum across rows. That min is the Count-Min estimate.

The one-sided error is the guarantee to hold onto: the estimate can be too high when collisions inflate every row, but it can never be too low, because no row can hold less than the item’s real count. Here each item happens to have a collision-free row, so the min lands exactly on the truth, and "fox" - never added - estimates 0. When rows do collide, taking the minimum is what rescues the answer, as the next lesson shows.

Make it work
func (c *CountMin) Estimate(data []byte) uint64 {
// take the minimum of the item's counter across all rows
}
CheckpointDONE
Your sketch estimates frequencies by taking the row minimum. Commit and stop here.