Декартово произведение в порядке Грея с itertools? - PullRequest
1 голос
/ 11 апреля 2020

Есть ли что-то вроде Python itertools.product(), обеспечивающее итерацию по декартовому произведению набора множеств в Порядке кода Грея ? Например, если предположить, что такой гипотетический генератор существует и он называется gray_code_product(), то gray_code_product(['a','b','c'], [0,1], ['x','y']) сгенерирует в следующем порядке:

('a',0,'x')
('a',0,'y')
('a',1,'y')
('a',1,'x')
('b',1,'x')
('b',1,'y')
('b',0,'y')
('b',0,'x')
('c',0,'x')
('c',0,'y')
('c',1,'y')
('c',1,'x')

1 Ответ

1 голос
/ 11 апреля 2020

Согласно документации из itertools.product, функция эквивалентна следующему коду Python:

def product(*args, repeat=1):
    pools = [tuple(pool) for pool in args] * repeat
    result = [[]]
    for pool in pools:
        result = [x+[y] for x in result for y in pool]
    for prod in result:
        yield tuple(prod)

Поскольку продукт с серым кодом имеет дело с обращением порядка В предыдущей последовательности для каждого пула вы можете использовать enumerate в предыдущем списке result, перебирая его, чтобы определить, является ли индекс нечетным или четным, и инвертировать последовательность пула, если он нечетный:

def gray_code_product(*args, repeat=1):
    pools = [tuple(pool) for pool in args] * repeat
    result = [[]]
    for pool in pools:
        result = [x+[y] for i, x in enumerate(result) for y in (
            reversed(pool) if i % 2 else pool)]
    for prod in result:
        yield tuple(prod)

, так что:

for p in gray_code_product(['a','b','c'], [0,1], ['x','y']):
    print(p)

выходы:

('a', 0, 'x')
('a', 0, 'y')
('a', 1, 'y')
('a', 1, 'x')
('b', 1, 'x')
('b', 1, 'y')
('b', 0, 'y')
('b', 0, 'x')
('c', 0, 'x')
('c', 0, 'y')
('c', 1, 'y')
('c', 1, 'x')
...