我正在尝试生成由四个字母(正好两个相等,另一个重复的两个相等)和一个数字组成的5个字符的字符串的组合。
正确组合的示例:
1aabb
b1aab
ca3ac
不正确组合的示例:
1aaaa -> incorrect because there are more than 2 equal letters
1aaab -> Same as the previous
1abcd -> No 2 equal letters + 2 equal different letters
这是我正在使用的代码:
from itertools import combinations, permutations, product
LETTERS = 'bcdfghjklmnpqrstvwxz'
DIGITS = '2456789'
def aabb1(letters=LETTERS, digits=DIGITS):
"""Generate the distinct 5-character strings consisting of four
letters (exactly two are equal and another repeat two are equal) and one digit.
"""
combs = []
for (a, b), (i, j), (x, y), d, k in product(
permutations(letters, 2), # Two letters (a repeated).
combinations(range(4), 2), # Positions for the repeated letter.
combinations(range(2), 2), # Positions for the second repeated letter.
digits, # One digit.
range(5)): # Positions for the digit.
result = []
result[i:i] = a,
result[j:j] = a,
result[x:x] = b,
result[y:y] = b,
result[k:k] = d,
combs.append(''.join(result))
print(len(combs))
return combs
它打印出我有79,800个组合,但这是不正确的,因为我正在计算重复的组合:
问题是因为它选择某个字母,例如a
出现两次,然后选择重复的字母(例如f
)出现两次,所以我们会得到类似:a3faf
但稍后,它选择第一个字母作为f
,选择第二个字母作为a
,然后再次得到a3faf
。
在数学中,我可以通过除以2来解决它:
但不确定如何在我的代码中正确执行此操作。
您能在我的代码中建议如何防止它吗?意思是,获得没有重复的组合。
答案 0 :(得分:3)
将permutations(letters, 2)
更改为combinations(letters, 2)
。 permutations()
将交付('a', 'b')
和('b', 'a')
,但是combinations()
将仅交付('a', 'b')
。字母位置的组合可以处理这些字母的所有顺序,因此您无需两次查看它们。
编辑:除了上一个修复程序之外,最后根据第一个字母计算第二个字母的位置也将其修复。因此,如果'a'
位于索引0
和2
,则'b'
必须位于索引1
和4
。
def aabb1(letters=LETTERS, digits=DIGITS):
"""Generate the distinct 5-character strings consisting of four
letters (exactly two are equal and another repeat two are equal) and one digit.
"""
letterdxs = set(range(4))
combs = []
for (a, b), (i, j), d, k in product(
combinations(letters, 2), # Two letters (a repeated).
combinations(range(4), 2), # Positions for the 1st repeated letter.
digits, # One digit.
range(5)): # Positions for the digit.
x, y = letterdxs.difference((i, j))
result = []
result[i:i] = a,
result[j:j] = a,
result[x:x] = b,
result[y:y] = b,
result[k:k] = d,
combs.append(''.join(result))
print(len(combs))
return combs
答案 1 :(得分:1)
您可以编写一个递归函数:
#1aabb
#b1aab
#ca3ac
from collections import Counter
LETTERS = 'bcdfghjklmnpqrstvwxz'
DIGITS = '2456789'
def combinations(d, current = []):
if len(current) == 5:
yield ''.join(current)
else:
for i in d:
_d = Counter(current)
if i.isdigit() and not any(c.isdigit() for c in current):
yield from combinations(d, current+[i])
elif (not current or _d.get(i, 0) == 1 or sum(c.isalpha() for c in current) < 2) and i.isalpha():
yield from combinations(d, current+[i])
result = list(combinations(LETTERS+DIGITS))
输出(前100个结果):
['bcbc2', 'bcbc4', 'bcbc5', 'bcbc6', 'bcbc7', 'bcbc8', 'bcbc9', 'bcb2c', 'bcb4c', 'bcb5c', 'bcb6c', 'bcb7c', 'bcb8c', 'bcb9c', 'bccb2', 'bccb4', 'bccb5', 'bccb6', 'bccb7', 'bccb8', 'bccb9', 'bcc2b', 'bcc4b', 'bcc5b', 'bcc6b', 'bcc7b', 'bcc8b', 'bcc9b', 'bc2bc', 'bc2cb', 'bc4bc', 'bc4cb', 'bc5bc', 'bc5cb', 'bc6bc', 'bc6cb', 'bc7bc', 'bc7cb', 'bc8bc', 'bc8cb', 'bc9bc', 'bc9cb', 'bdbd2', 'bdbd4', 'bdbd5', 'bdbd6', 'bdbd7', 'bdbd8', 'bdbd9', 'bdb2d', 'bdb4d', 'bdb5d', 'bdb6d', 'bdb7d', 'bdb8d', 'bdb9d', 'bddb2', 'bddb4', 'bddb5', 'bddb6', 'bddb7', 'bddb8', 'bddb9', 'bdd2b', 'bdd4b', 'bdd5b', 'bdd6b', 'bdd7b', 'bdd8b', 'bdd9b', 'bd2bd', 'bd2db', 'bd4bd', 'bd4db', 'bd5bd', 'bd5db', 'bd6bd', 'bd6db', 'bd7bd', 'bd7db', 'bd8bd', 'bd8db', 'bd9bd', 'bd9db', 'bfbf2', 'bfbf4', 'bfbf5', 'bfbf6', 'bfbf7', 'bfbf8', 'bfbf9', 'bfb2f', 'bfb4f', 'bfb5f', 'bfb6f', 'bfb7f', 'bfb8f', 'bfb9f', 'bffb2', 'bffb4']
答案 2 :(得分:1)
对于固定长度和格式,此简单的代码可生成39900个组合:
LETTERS = 'bcdfghjklmnpqrstvwxz'
DIGITS = '2456789'
def insdig(s, d):
for i in range(5):
ss = s[:i] + d + s[i:]
print(ss)
def aabb1():
for dig in DIGITS:
for i in range(len(LETTERS)-1):
for j in range(i+1, len(LETTERS)):
a = LETTERS[i]
b = LETTERS[j]
insdig(a+a+b+b, dig)
insdig(a+b+a+b, dig)
insdig(b+a+a+b, dig)
insdig(a+b+b+a, dig)
insdig(b+a+b+a, dig)
insdig(b+b+a+a, dig)
aabb1()