Представьте себе создание сетки комбинаций, где каждая строка представляет блокировку, а значение каждого столбца - возможную комбинацию для этой блокировки.Например, предположим, что есть 10 блокировок и только 5 возможных комбинаций на блокировку.Вы можете генерировать их все в случайном порядке, например:
In [42]: np.random.seed(2018) # to make the example reproducible
In [43]: grid = np.random.random((10,5)).argsort(axis=1); grid
Out[43]:
array([[1, 3, 4, 0, 2],
[4, 0, 2, 3, 1],
[3, 4, 2, 0, 1],
[2, 1, 3, 4, 0],
[1, 3, 0, 4, 2],
[1, 0, 4, 3, 2],
[2, 0, 1, 3, 4],
[2, 0, 3, 4, 1],
[2, 3, 1, 0, 4],
[2, 4, 0, 3, 1]])
Далее, давайте выберем случайную комбинацию для каждого из 10 замков:
In [48]: combo = np.random.choice(5, size=10, replace=True); combo
Out[48]: array([3, 2, 3, 3, 4, 4, 4, 3, 2, 3])
Мы можем думатьgrid
как указание порядка, в котором используются комбинации для каждой блокировки.И мы можем взять combo
в качестве фактической комбинации для каждого замка.
Мы также можем визуализировать расположение матчей, используя:
plt.imshow((grid == combo[:, None])[::-1], origin='upper')
![enter image description here](https://i.stack.imgur.com/S4yN2.png)
и мы можем найти местоположение каждого успешного совпадения в нашей сетке, используя argmax
:
In [73]: (grid == combo[:, None]).argmax(axis=1)
Out[73]: array([1, 2, 0, 2, 3, 2, 4, 2, 0, 3])
argmax
возвращает индекс (местоположение) совпадениядля каждого ряда.Эти индексы также указывают количество попыток, необходимых для поиска каждого совпадения.Ну, почти.Поскольку Python основан на 0 индексах, argmax
вернет 0, если совпадение произойдет с первой попытки.Поэтому нам нужно добавить 1 к (grid == combo[:, None]).argmax(axis=1)
, чтобы получить истинное количество попыток.
Итак, мы ищем распределение (grid == combo[:,
None]).argmax(axis=1) + 1
.Теперь, когда мы разработали вычисления для 10 блокировок и 5 комбинаций, легко увеличить это, скажем, до 10000 блокировок и 1000 комбинаций:
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(2018)
num_locks = 10000
num_combos = 1000
grid = np.random.random((num_locks, num_combos)).argsort(axis=1)
combo = np.random.choice(num_combos, size=num_locks, replace=True)
attempts = (grid == combo[:, None]).argmax(axis=1) + 1
plt.hist(attempts, density=True)
plt.show()
![enter image description here](https://i.stack.imgur.com/TLd00.png)
Этот метод выбора случайного местоположения в сетке проясняет, что распределение должно быть равномерным - столь же вероятно, что правильная комбинация происходит в начале, как в конце, или в любом месте вмежду ними.