Доказательство ответа Марка Рэнсома
Давайте использовать цифры, о которых легче думать (по крайней мере, для меня!):
- 10 предметов
- удалить 3 из них
В первый раз в цикле мы будем предполагать, что первые три элемента удаляются - вот как выглядят вероятности:
- первый предмет: 3/10 = 30%
- второй пункт: 2/9 = 22%
- третий пункт: 1/8 = 12%
- четвертый пункт: 0/7 = 0%
- пятый элемент: 0/6 = 0%
- шестой элемент: 0/5 = 0%
- седьмой пункт: 0/4 = 0%
- восьмой пункт: 0/3 = 0%
- девятый пункт: 0/2 = 0%
- десятый элемент: 0/1 = 0%
Как видите, как только он достигает нуля, он остается на нуле. Но что, если ничего не удаляется?
- первый пункт: 3/10 = 30%
- второй пункт: 3/9 = 33%
- третий пункт: 3/8 = 38%
- четвертый пункт: 3/7 = 43%
- пятый пункт: 3/6 = 50%
- шестой предмет: 3/5 = 60%
- седьмой пункт: 3/4 = 75%
- восьмой пункт: 3/3 = 100%
- девятый пункт: 2/2 = 100%
- десятый элемент: 1/1 = 100%
Таким образом, даже если вероятность варьируется в зависимости от строки, в целом вы получаете результаты, которые вы ищете. Я пошел еще дальше и закодировал тест на Python для миллиона итераций в качестве окончательного доказательства для себя - удалите семь элементов из списка 100:
# python 3.2
from __future__ import division
from stats import mean # http://pypi.python.org/pypi/stats
import random
counts = dict()
for i in range(100):
counts[i] = 0
removed_failed = 0
for _ in range(1000000):
to_remove = 7
from_list = list(range(100))
removed = 0
while from_list:
current = from_list.pop()
probability = to_remove / (len(from_list) + 1)
if random.random() < probability:
removed += 1
to_remove -= 1
counts[current] += 1
if removed != 7:
removed_failed += 1
print(counts[0], counts[1], counts[2], '...',
counts[49], counts[50], counts[51], '...',
counts[97], counts[98], counts[99])
print("remove failed: ", removed_failed)
print("min: ", min(counts.values()))
print("max: ", max(counts.values()))
print("mean: ", mean(counts.values()))
и вот результаты одного из нескольких моих тестов (все они были похожи):
70125 69667 70081 ... 70038 70085 70121 ... 70047 70040 70170
remove failed: 0
min: 69332
max: 70599
mean: 70000.0
Последнее замечание: Python's random.random()
равен [0.0, 1.0) (не включает 1.0 как возможность).