times = [...]
first_cluster, second_cluster = [min(times)], [max(times)]
for t in times:
if abs(mean(first_cluster) - t) <= abs(mean(second_cluster) - t):
first_cluster.append(t)
else:
second_cluster.append(t)
import functools
def make_help_tables(arr):
sizes = [len(s) for s in arr]
dividers = [1]
for size in sizes:
dividers.append(dividers[-1] * size)
return sizes, dividers
def product(arr):
if not arr:
return
arr_size = len(arr)
sizes, dividers = make_help_tables(arr)
total_variants = functools.reduce(lambda x, y: x * y, sizes)
for variant in range(total_variants):
indexes = [(variant // dividers[i]) % sizes[i] for i in range(arr_size)]
yield indexes, [arr[i][idx] for i, idx in enumerate(indexes)]
m = [['A', 'B'], [1, 2, 3], ['Привет!']]
for indexes, combination in product(m):
print('{} -> {}'.format(indexes, combination))
[0, 0, 0] -> ['A', 1, 'Привет!']
[1, 0, 0] -> ['B', 1, 'Привет!']
[0, 1, 0] -> ['A', 2, 'Привет!']
[1, 1, 0] -> ['B', 2, 'Привет!']
[0, 2, 0] -> ['A', 3, 'Привет!']
[1, 2, 0] -> ['B', 3, 'Привет!']
Для начала попробуем реализовать схему "переполнения разрядов", как в системе счисления, но с учётом разной "ёмкости" разрядов.
Массивы [[1, 2], [а, б, в]]
Всего вариантов 2 * 3 = 6
Варианты (индексы):
1) [0, 0] (0 // 3) % 2 = 0; (0 // 1) % 3 = 0
2) [0, 1] (1 // 3) % 2 = 0; (1 // 1) % 3 = 1
3) [0, 2] <-- переполнение последнего разряда (2 // 3) % 2 = 0; (2 // 1) % 3 = 2
4) [1, 0] <-- перенос в старший разряд (3 // 3) % 2 = 1; (3 // 1) % 3 = 0
5) [1, 1] (4 // 3) % 2 = 1; (4 // 1) % 3 = 1
6) [1, 2] (5 // 3) % 2 = 1; (5 // 1) % 3 = 2
Что нам нужно для подсчёта?
1) Размеры массивов (для вычетов по модулю)
2) Список произведений размеров массивов (в обратном порядке)
Попробуем теперь разобраться как перейти к прямому порядку переполнения вместо обратного.
Массивы [[1, 2], [3, 4, 5], [6]]
Всего вариантов 2 * 3 * 1 = 6
Варианты (индексы):
1) [0, 0, 0] (0 // 1) % 2 = 0; (0 // (1 * 2)) % 3 = 0; (0 // 1 * 2 * 3) % 1 = 0
2) [1, 0, 0] (1 // 1) % 2 = 1; (1 // (1 * 2)) % 3 = 0; (1 // 1 * 2 * 3) % 1 = 0
3) [0, 1, 0] (2 // 1) % 2 = 0; (2 // (1 * 2)) % 3 = 1; (2 // 1 * 2 * 3) % 1 = 0
4) [1, 1, 0] (3 // 1) % 2 = 1; (3 // (1 * 2)) % 3 = 1; (3 // 1 * 2 * 3) % 1 = 0
5) [0, 2, 0] (4 // 1) % 2 = 0; (4 // (1 * 2)) % 3 = 2; (4 // 1 * 2 * 3) % 1 = 0
6) [1, 2, 0] (5 // 1) % 2 = 1; (5 // (1 * 2)) % 3 = 2; (5 // 1 * 2 * 3) % 1 = 0
В итоге таблица делителей формируется следующим образом:
1 для первого массива
1 * 2 для второго (поскольку размер первого равен 1)
1 * 2 * 3 для первого (размер второго, умноженный на накопленный делитель)
def product(pools):
result = [[]]
for pool in pools:
result = [x + [y] for x in result for y in pool]
for prod in result:
yield prod
Вот разве что симпатичный гайд: www.jezzamon.com/fourier