A Full Cycle Generator in Python

Suppose you set n = 10 and you want to generate the ten numbers 0 through 9 in a scrambled way. The technique I usually use is to create an array with 10 cells, initialized to the values 0 to 9, then scramble the contents of the array using the Fisher Yates mini-algorithm, and then you can walk through the array contents. This approach gives you a random sequence something like (4, 0, 9, 2, 3, 8, 1, 7, 5, 6).

An alternative approach is to generate a full cycle. Suppose you determine an increment that is a prime number, like 7. If start at 0 and add 7 you get 7. Then you add 7 and get 14 but since that’s more than 10 you wrap around to 4. Then you add 7 and get 11 which wraps to 1. Then you add 7 and get 8. And so on. You get a full cycle of (7, 4, 1, 8, 5, 2, 9, 6, 3, 0). This sequence of numbers isn’t at all random, but it is somewhat scrambled.

I decided to implement a full cycle generator in Python just for fun and to keep my coding skills sharp. The key part of the code is determining a suitable prime number increment. It must be more than n / 3 and prime and not divide n evenly. For n = 10 that means the prime increment must be greater than 3. The first prime greater than 3 is 5 but that divides n = 10 evenly. The next prime is 7 which is a good one for the increment.

Good fun! I enjoy creating algorithms and implementing algorithms in code. The process is challenging and it’s creative in the sense that something is produced. With the basic building blocks of a programming language keywords, you can construct an infinite number of different programs.


“Tales of the Cocktail” is an annual liquor industry trade event. It’s been held since 2003. Creating an interesting new type of cocktail is difficult because you have a limited set of components (rum, vodka, orange juice, etc.). I like these posters from the event — art is also a creative endeavor.


# full_cycle_demo.py
# Python 3.7

import math  # for square root

class FullCycle:
  def __init__(self, n, seed):
    self.n = n
    self.p = self.compute_p(n)  # the inc
    self.curr = seed % n

  def next_int(self):
    self.curr = (self.curr + self.p) % self.n
    return self.curr

  def compute_p(self, n):
    p = (n // 3) + 1
    while p less-than n:
      if self.is_prime(p) and (n % p) != 0:
        return p
      p += 1
    return -1  # error

  def is_prime(self, n):
    divisor = 2
    max_divisor = (int)(math.sqrt(n) + 1)
    while divisor less-than max_divisor:
      if n % divisor == 0:
        return False
      divisor += 1
    return True

def main():
  print("\nBegin full cycle demo for n=10 \n")
 
  fc = FullCycle(10, seed= 0)
  for i in range(10):
    j = fc.next_int()
    print(str(j) + "  ", end="")
  print("")

  print("\nEnd demo \n")

if __name__ == "__main__":
  main()
This entry was posted in Miscellaneous. Bookmark the permalink.