Search code examples
pythonpython-3.xdequecollatzperiodic-task

Python: How to do something every 'n' iterations but only with the previous 'm' values?


I'm attempting to collect statistics from the Collatz Conjecture. Currently, my script gets the length of the Collatz sequence of every number starting from 2 to a large, preset number and saves that length into an ever-growing array. Every 100 iterations it collects several statistics from the all the previous data and saves them to a dictionary like this:

    result = []
    data = {}
    for count, v in enumerate(range(2, 10000000), 1):
        if count % 100 == 0:
            result.append(len(collatz_concise(count))-1)
            Max = round(max(result), 2)
            Min = round(min(result), 2)
            Mean = round(sum(result) / len(result))
            Median = round(statistics.median(result))
            Range = round(Max - Min, 2)
            Trim_Mean = round(stats.trim_mean(result, 0.1), 2)
            stat = np.array(result)
            Q1 = round(np.percentile(stat, 25), 2)
            Q3 = round(np.percentile(stat, 75), 2)
            data[count] = [Min, Q1, Median, Mean, Trim_Mean, Q3, Max]

I would like for the statistics to be collected every 100 times but only on the previous 100 values of the list. I've looked around for a while but couldn't find a suitable answer.

Be gentle, I'm fairly new at this and StackOverflow as well.


Solution

  • Periodic actions

    The way to perform an action of every n steps is to take the count modulo n and check to see if it is zero.

    Tracking recent values

    The easiest way to track m most recent values is with collections.deque() with the maxlen parameter set to m.

    Overview of approach

    Here's some code to get you started:

    >>> n = 15
    >>> m = 20
    >>> result = deque(maxlen=m)
    >>> for i in range(100):
            c = collatz(i)
            result.append(c)
            if i % n == 0:
                print(i, '-->', result)
    

    Here's the output:

    0 --> deque([0], maxlen=20)
    15 --> deque([0, 4, 1, 10, 2, 16, 3, 22, 4, 28, 5, 34, 6, 40, 7, 46], maxlen=20)
    30 --> deque([34, 6, 40, 7, 46, 8, 52, 9, 58, 10, 64, 11, 70, 12, 76, 13, 82, 14, 88, 15], maxlen=20)
    45 --> deque([13, 82, 14, 88, 15, 94, 16, 100, 17, 106, 18, 112, 19, 118, 20, 124, 21, 130, 22, 136], maxlen=20)
    60 --> deque([124, 21, 130, 22, 136, 23, 142, 24, 148, 25, 154, 26, 160, 27, 166, 28, 172, 29, 178, 30], maxlen=20)
    75 --> deque([28, 172, 29, 178, 30, 184, 31, 190, 32, 196, 33, 202, 34, 208, 35, 214, 36, 220, 37, 226], maxlen=20)
    90 --> deque([214, 36, 220, 37, 226, 38, 232, 39, 238, 40, 244, 41, 250, 42, 256, 43, 262, 44, 268, 45], maxlen=20)