在python中生成特定的排列模式

在python中生成特定的排列模式,python,permutation,combinatorics,Python,Permutation,Combinatorics,我试图建立一个概率系统的模型。我正在使用的系统包含三个元素——称它们为“X”、“Y”和“Z”。这些元素以特定类型的交替模式形成字符串,其中X必须与Y或Z交替(即,禁止使用XX、YY、ZZ、YZ和ZY连接)。我想为不同的字符串长度排列所有可能序列的列表 我最初的尝试是生成这三个字符的所有可能排列,并过滤掉任何被禁止的模式。不幸的是,对于长序列长度,排列的伸缩性非常差。我通过生成每个序列,一次生成一个字符,并检查序列构建时设置的条件来解决这个问题。这可以防止在很早的时候生成非生产性序列,并大大减少正

我试图建立一个概率系统的模型。我正在使用的系统包含三个元素——称它们为“X”、“Y”和“Z”。这些元素以特定类型的交替模式形成字符串,其中X必须与Y或Z交替(即,禁止使用XX、YY、ZZ、YZ和ZY连接)。我想为不同的字符串长度排列所有可能序列的列表

我最初的尝试是生成这三个字符的所有可能排列,并过滤掉任何被禁止的模式。不幸的是,对于长序列长度,排列的伸缩性非常差。我通过生成每个序列,一次生成一个字符,并检查序列构建时设置的条件来解决这个问题。这可以防止在很早的时候生成非生产性序列,并大大减少正在生成的排列的数量。问题是我不是一个很好的程序员,为了达到这个目标,我不得不硬编码一堆嵌套for循环。下面显示的代码的字符串长度为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)
输出:

['XYXYX', 'XYXZX', 'XZXYX', 'XZXZX', 'YXYXY', 'YXYXZ', 'YXZXY', 'YXZXZ', 'ZXYXY', 'ZXYXZ', 'ZXZXY', 'ZXZXZ']
['XYXYX', 'XYXYZ', 'XYXZX', 'XYXZY', 'XYZXY', 'XYZXZ', 'XYZYX', 'XYZYZ', 'XZXYX', 'XZXYZ', 'XZXZX', 'XZXZY', 'XZYXY', 'XZYXZ', 'XZYZX', 'XZYZY']

我的问题是,如何将这种类型的算法推广到一个函数,该函数只需要输入“长度”(即字符串中的字符数)并在列表中生成我的所有序列模式?

您可以使用带递归的生成器:

def combinations(d, _len, current = []):
  if len(current) == _len:
     yield current
  else:
     for i in d:
       if not current or ('X' in current and current[-1] != i):
         yield from combinations(d, _len, current+[i])


results = list(map(''.join, combinations(['X','Y','Z'], 5)))
final_results = [a for i, a in enumerate(results) if a not in results[:i]]
输出:

['XYXYX', 'XYXZX', 'XZXYX', 'XZXZX', 'YXYXY', 'YXYXZ', 'YXZXY', 'YXZXZ', 'ZXYXY', 'ZXYXZ', 'ZXZXY', 'ZXZXZ']
['XYXYX', 'XYXYZ', 'XYXZX', 'XYXZY', 'XYZXY', 'XYZXZ', 'XYZYX', 'XYZYZ', 'XZXYX', 'XZXYZ', 'XZXZX', 'XZXZY', 'XZYXY', 'XZYXZ', 'XZYZX', 'XZYZY']

对于
['X','Y','Z']
可以创建9对。但禁止配对
XX、YY、ZZ、YZ、ZY
。所以它仍然是XY,XZ,YX,ZX。将其分为两个单元(
units1
units2
),以避免排列中出现
XX
。如果
长度
为偶数,则只需使用itertools产品对每个单元进行排列(请参见:)。它将生成可以连接到字符串的元组列表(请参阅:)。附加这两个列表

对于奇数情况,单元1的组合将产生前缀为
X
的任何组合,因此将“X”附加到每个字符串的最后一个,并将
Y,Z
附加到开头。对于2号机组组合,则执行相反的操作。它不会生成唯一的列表,因此对
集合进行强制转换仅用于使其唯一

import itertools

def combine(length):
    units1 = ['XY','XZ']
    units2 = ['YX','ZX']

    combine1 = ["".join(map(str,p)) for p in itertools.product(units1,repeat=int(length/2))]
    combine2 = ["".join(map(str,p)) for p in itertools.product(units2,repeat=int(length/2))]

    if (length%2 == 1):
        combine1_odd = [item + 'X' for item in combine1] + ['Y' + item for item in combine1] + ['Z' + item for item in combine1]
        combine2_odd = ['X' + item for item in combine2] + [item + 'Y' for item in combine2] + [item + 'Z' for item in combine2]
        return list(set(combine1_odd + combine2_odd))

    return list(set(combine1 + combine2))

print(combine(5))

接近我需要的,但ZY和YZ序列是禁止的。