How to remove the mirror reflects the values โ€‹โ€‹of the function itertools.product?

I create a Cartesian product using the function itertools.product:

from itertools import product

a = list(map(list, itertools.product(list(range(2)), repeat=3)))

Conclusion:

[[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]]

Then I get rid of mirror reflections as follows:

b = [] 
for k, v in enumerate(a):
    if v[::-1] not in a[:k]:
       b.append(v[::-1])

Output:

[[0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0], [1, 0, 1], [1, 1, 1]]

But can I get the same effect step by step without saving all the results itertools.productin the list? For example, with the usual approach to the for loop:

for i in list(map(list, itertools.product(list(range(2)), repeat=3))):
    # blah blah blah

Because in the end, I will use large Cartesian products, at least repeat = 18. And so I have to abandon the approach on the lists. Is there any other way to do this? I will be grateful for any advice.

+4
source share
2 answers
import itertools

l = (list(i) for i in itertools.product(tuple(range(2)), repeat=3) if tuple(reversed(i)) >= tuple(i))
print list(l)

Conclusion:

[[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 1], [1, 1, 1]]
+3
source

( ):

def noReflections(n, k, current=None, idx=0, symmetric=True):
    # n: number of distinct elements
    # k: sequences length
    # current: sequence being generated
    # idx: current generated index
    # symmetric: true if the chosen elements up to now are symmetric
    assert n >= 0 and k >= 0
    if n == 0 or k == 0:
        return
    if idx == 0:
        current = k * [0]
    if idx < k // 2:
        # Choose the value for current position (idx) and symmetric (idx2)
        idx2 = k - idx - 1
        for i in range(n):
            # Value for current position
            current[idx] = i
            # If all previously selected values were symmetric,
            # the symmetric position must have a value equal or greater 
            # than the current; otherwise it can take any value.
            first = i if symmetric else 0
            for j in range(first, n):
                # Value for symmetric position
                current[idx2] = j
                # Recursive call
                # Only keep symmetric flag if previously selected values
                # and the ones selected now are symmetric.
                yield from noReflections(n, k, current, idx + 1, symmetric and (i == j))
    elif idx == k // 2 and (k % 2 == 1):
        # In middle position of odd-length sequence
        # Make one sequence with each possible value
        for i in range(n):
            current[idx] = i
            yield tuple(current)
    else:
        # Even-length sequence completed
        yield tuple(current)

print(list(noReflections(2, 3)))
>>> [(0, 0, 0), (0, 1, 0), (0, 0, 1), (0, 1, 1), (1, 0, 1), (1, 1, 1)]

, , , - .. ( ).

+1

Source: https://habr.com/ru/post/1691974/


All Articles