I'm trying to model a probabilistic system. The system I am working with involves three elements - call them 'X', 'Y' and 'Z'. These elements form strings in a specific type of alternating pattern, where X must be alternating with either Y or Z (i.e. XX, YY, ZZ, YZ and ZY connections are forbidden). I would like to permute lists of all possible sequences for different string lengths.
My initial attempt at this was to generate all possible permutations of these three characters, and filter out any patterns that are forbidden. Unfortunately permutations scale very poorly for long sequence lengths. I solved this problem by generating each sequence, one character at a time, and checking the conditions I set forth as the sequence is being constructed. This prevents the generation of unproductive sequences very early on and drastically decreases the number of permutations being generated. The problem is that I'm not much of a coder, and I had to hardcode a bunch of nested for-loops in order to achieve this goal. The code below is shown for a string length of 5.
Length = 5
Units = ['X','Y','Z']
Sequences = []
#aij is the j'th character in the sequence
for i1 in range(len(Units)):
ai1 = n[i1]
for i2 in range(len(Units)):
ai2 = Units[i2]
#If the two most recent sequential units are identical OR (Y and Z) OR (Z and Y), pass
if ai2 == ai1 or ai2==Units[1] and ai1==Units[2] or ai2==Units[2] and ai1==Units[1]:
pass
else:
#repeat for the other characters in the sequence until the final character is reached
for i3 in range(len(Units)):
ai3 = Units[i3]
if ai3 == ai2 or ai3==Units[1] and ai2==Units[2] or ai3==Units[2] and ai2==Units[1]:
pass
else:
for i4 in range(len(Units)):
ai4 = Units[i4]
if ai4 == ai3 or ai4==Units[1] and ai3==Units[2] or ai4==Units[2] and ai3==Units[1]:
pass
else:
for i5 in range(len(Units)):
ai5 = Units[i5]
if ai5 == ai4 or ai5==Units[1] and ai4==Units[2] or ai5==Units[2] and ai4==Units[1]:
pass
else:
#Append the valid sequence to my list of Sequences
a = ai1 + ai2 + ai3 + ai4 + ai5
Sequences.append(a)
print(Sequences)
Output:
['XYXYX', 'XYXZX', 'XZXYX', 'XZXZX', 'YXYXY', 'YXYXZ', 'YXZXY', 'YXZXZ', 'ZXYXY', 'ZXYXZ', 'ZXZXY', 'ZXZXZ']
My question is, how can i generalize this type of algorithm to a function that simply takes the input "Length" (i.e. number of characters in the string) and generates all of my sequence patterns in a list?