2

Here is a ugly code to find all the possibilities to cut a period in 5 parts. Is there a possibility to create a function which makes it look better, with the number of cut as a parameter ?

I am only abble to write each for loop :

part_list = pd.DataFrame(columns=['period_array'])
for i in range(1, period_size):
    for j in range(1, period_size - i):
        for h in range(1, period_size - (i + j)):
            for g in range(1, period_size - (i + j + h)):
                part_list = part_list.append({'period_array':
                                                  np.array([[0, i],
                                                            [i, i + j],
                                                            [i + j, i + j + h],
                                                            [i + j + h, i + j + h + g],
                                                            [i + j + h + g, period_size]])},
                                             ignore_index=True)
Shanki
  • 21
  • 4
  • 1
    Have a look at [module itertools](https://docs.python.org/3/library/itertools.html) and in particular, function `combinations` – Stef Dec 07 '22 at 16:18

2 Answers2

3

Using function combinations from module itertools to generate all combinations of cutting points:

from itertools import combinations, chain, pairwise

def all_cuts(seq, n):
    for comb in combinations(range(1,len(seq)), n-1):
        yield tuple(seq[i:j] for i,j in pairwise(chain((0,), comb, (len(seq),))))

print( list(all_cuts('Hello, World!', 3)) )
# [('H', 'e', 'llo, World!'), ('H', 'el', 'lo, World!'),
#  ('H', 'ell', 'o, World!'), ('H', 'ello', ', World!'),
#  ('H', 'ello,', ' World!'), ...
#                        ..., ('Hello, Wor', 'l', 'd!'),
#  ('Hello, Wor', 'ld', '!'), ('Hello, Worl', 'd', '!')]
Stef
  • 13,242
  • 2
  • 17
  • 28
0

I modified the code to have a shorter running time with a dataframe and the apply method (the 'for loop' isn't efficient with long sequences).

For 3 period in a list of 52, I reduce the time from 14.6s to 0.2s.

Here is my final code ! Many thanks @Stef :)

    COMBINATION_VECTOR = 'combination vector'
    PERIOD_ARRAY = 'period array'
    
    def get_partition_table(period_resolution: int, number_of_changes: int):
        """
        This function creates a dataframe of all the possible combination of date of change over a year
        :param period_resolution: resolution (month : 12, week: 52 or days: 365)
        :param number_of_changes
        :return: dataframe of each period table
        """
    
        scale_factor = 365 // period_resolution
    
        def from_combinations_to_period_array(comb):
            """
            This returns the period array of the specific combination : [[0, d1], [d1, d2] ... [dn, 365]]
            :param comb: combinations of dates to create the period array
            :return: period array
            """
            return np.array([[i, j] for i, j in pairwise(it.chain((0,), comb, (period_resolution,)))])
    
        part_list = pd.DataFrame(
            {COMBINATION_VECTOR: list(it.combinations(range(1, period_resolution), number_of_changes))})
    
        part_list[PERIOD_ARRAY] = part_list.apply(
            lambda x: from_combinations_to_period_array(x[COMBINATION_VECTOR]), axis=1)
        
        part_list.drop(COMBINATION_VECTOR, axis=1)
    
        return part_list * scale_factor
Shanki
  • 21
  • 4