Sub combinaciones de rendimiento con límite

Estoy trabajando con python 3. La función con la que estoy trabajando es la siguiente:

def sub_combinations(segment): if len(segment) == 1: yield (segment,) else: for j in sub_combinations(segment[1:]): yield ((segment[0],),)+j for k in range(len(j)): yield (((segment[0],)+j[k]),) + (j[:k]) +(j[k+1:]) 

Es una versión de esta función:

Combinando sub combinaciones

La salida es la siguiente para (1,2,3,4,5):

 ((1,), (2,), (3,), (4,), (5,)) ((1, 2), (3,), (4,), (5,)) ((1, 3), (2,), (4,), (5,)) ((1, 4), (2,), (3,), (5,)) * ((1, 5), (2,), (3,), (4,)) * ((1,), (2, 3), (4,), (5,)) ((1, 2, 3), (4,), (5,)) ((1, 4), (2, 3), (5,)) * ((1, 5), (2, 3), (4,)) * ((1,), (2, 4), (3,), (5,)) ((1, 2, 4), (3,), (5,)) ((1, 3), (2, 4), (5,)) ((1, 5), (2, 4), (3,)) * ((1,), (2, 5), (3,), (4,)) * ((1, 2, 5), (3,), (4,)) * ((1, 3), (2, 5), (4,)) * ((1, 4), (2, 5), (3,)) * ((1,), (2,), (3, 4), (5,)) ((1, 2), (3, 4), (5,)) ((1, 3, 4), (2,), (5,)) ((1, 5), (2,), (3, 4)) * ((1,), (2, 3, 4), (5,)) ((1, 2, 3, 4), (5,)) ((1, 5), (2, 3, 4)) * ((1,), (2, 5), (3, 4)) * ((1, 2, 5), (3, 4)) * ((1, 3, 4), (2, 5)) * ((1,), (2,), (3, 5), (4,)) ((1, 2), (3, 5), (4,)) ((1, 3, 5), (2,), (4,)) ((1, 4), (2,), (3, 5)) * ((1,), (2, 3, 5), (4,)) ((1, 2, 3, 5), (4,)) ((1, 4), (2, 3, 5)) * ((1,), (2, 4), (3, 5)) ((1, 2, 4), (3, 5)) ((1, 3, 5), (2, 4)) ((1,), (2,), (3,), (4, 5)) ((1, 2), (3,), (4, 5)) ((1, 3), (2,), (4, 5)) ((1, 4, 5), (2,), (3,)) * ((1,), (2, 3), (4, 5)) ((1, 2, 3), (4, 5)) ((1, 4, 5), (2, 3)) * ((1,), (2, 4, 5), (3,)) ((1, 2, 4, 5), (3,)) ((1, 3), (2, 4, 5)) ((1,), (2,), (3, 4, 5)) ((1, 2), (3, 4, 5)) ((1, 3, 4, 5), (2,)) ((1,), (2, 3, 4, 5)) ((1, 2, 3, 4, 5),) 

El problema es que si trabajo con tuplas más grandes, la función de sub_combinaciones devuelve una gran cantidad de datos y toma mucho tiempo para computarlos. Para solucionar esto, quiero limitar la cantidad de datos devueltos agregando un argumento adicional. Por ejemplo, las combinaciones secundarias ((1,2,3,4,5), 2) deben devolver los datos anteriores pero sin las tuplas marcadas con una estrella. Estos se eliminan porque el desplazamiento entre los valores consecuentes en la tupla es mayor que 2. Por ejemplo, las filas que contienen (1, 4), (1, 5) o (2, 5) y similares (1, 2, 5) etc, se dejan caer.

La línea

 for k in range(len(j)) 

necesita ajustarse para eliminar estas líneas, pero todavía no he descubierto cómo. ¿Alguna sugerencia?

Barry

Creo que el siguiente cambio resulta en la salida que está buscando:

 def sub_combinations(segment, max_offset=None): data = tuple([e] for e in segment) def _sub_combinations(segment): if len(segment) == 1: yield (segment,) else: for j in _sub_combinations(segment[1:]): yield ((segment[0],),)+j for k in range(len(j)): if max_offset and data.index(j[k][0]) - data.index(segment[0]) > max_offset: break yield (((segment[0],)+j[k]),) + (j[:k]) +(j[k+1:]) for combination in _sub_combinations(data): yield tuple(tuple(e[0] for e in t) for t in combination) 

La idea aquí es que se sale del bucle k lugar de producir una tupla que tendría un desplazamiento mayor que max_offset .