MATH-P7

A fair sample from a stream

Practice 7 of 7Number theory and counting9 tests

The problem

Choose k items fairly from stream, which can be read only once, item by item, and whose length is not known in advance. Use reservoir sampling exactly as lesson 7 describes, with the random function you are given:

  • keep the first k items, in slots 0 to k − 1, in order;
  • for each later item, the one at position i (counting from 0), call rand(i + 1) once to get j from 0 to i; if j < k, put the item in slot j.

Return the list of slots. If the stream has fewer than k items, return all of them. Do not call rand for the first k items.

# rand returns 1, 0, 3, 2 in turn
sample(iter("abcdef"), 2, rand)   # ['d', 'c']
sample(iter([7, 8]), 5, rand)     # [7, 8]

Limits

  • The stream may be a generator: it has no len(), and it can be looped over only once. It has up to 300,000 items.
  • The tests pass fixed “random” answers, so the right sample is known exactly. Two tests try every possible run of answers and check that every set of items is chosen equally often.

Builds on MATH-7 Probability for algorithms.

Continue on a laptop

Practice runs Python in the browser and needs a keyboard and a wider screen. Read the problem and open hints here, then write your solution on a laptop. Progress is saved per browser for now, so hints opened here stay on this device.

Need a hint?0 of 3 opened

  1. Hint 1Nudge
  2. Hint 2Approach Open hint 1 first
  3. Hint 3Pseudocode Open hint 2 first
  4. Worked solutionlast resort Opens after all 3 hints
Python waits for a wider screensolution.py

Ctrl + Enter runs the tests. Tab indents; press Esc, then Tab, to leave the editor.

9 tests, not run yet
Test results
#TestResultReads · time
1The exampleNot run
2Fewer items than kNot run
3k is 0Not run
4Which calls to randNot run
5Every outcome, 5 itemsNot run
6Every outcome, 6 itemsNot run
7A hundred itemsNot run
8A generatorNot run
9300,000 itemsNot run