用 itertools 实现 组合、排列、组合(放回)、笛卡尔积

之所以想起来itertools,是看到了这么一个题目

题目是英文的,里面废话有点多,简单而言就是:
假设有一组只由01构成字符串,你可以随便猜3次,每次告诉你猜对了多少位。
然后问题来了,你要结合你这三次猜测结果,说说满足这个条件的字符串最多存在几个。

试着用python3写了一下解法:

# 载入数据
x = '6 3'
length,trytimes = [int(i) for i in x.split(' ')]
print(length,trytimes )
y = '''
000000 2
010100 4
111100 2
'''
r = [j.split(' ') for j in [i for i in y.strip().split('\n')]]
print(r)

# 比较两个字符串,返回相同位置上,字符一致的个数。
def match(a,b):
    count = 0
    if len(a)==len(b):
        for i in range(len(a)):
            if a[i]==b[i]:
                count+=1
    else:
        print('ERROR:',a,b)
    return str(count)

# 开始解题,构造字符串迭代器,遍历所有字符串,返回符合条件的字符串个数
import itertools
total = 0
z = itertools.product('01', repeat=length)
for i in z:
    g = ''.join(i)
    for j in range(trytimes):
        if match(r[j][0],g)!=r[j][1]:
            break
    else:
        total+=1

# 符合条件的
print(total)

因为昨天刚刚说完关于迭代器的特征,这里itertools实际上就是通过迭代器的方式,相当高效且节省内存。

将itertools中的排列组合,拿出来专门记录一下:

函数 名称 说明
combinations 组合 4个中抽取2个(不分先后) C 4 2
permutations 排列 4个中抽取2个(分先后) A 4 2
combinations_with_replacement 组合(放回) 4个中抽取2个,每次抽完放回去(不分先后)
product 笛卡尔积 4个中抽取2个,每次抽完放回去(分先后)
>>> for i in itertools.combinations('ABCD', 2):print(''.join(i),end=' ')
>>> for i in itertools.permutations('ABCD', 2):print(''.join(i),end=' ')
>>> for i in itertools.combinations_with_replacement('ABCD', 2):print(''.join(i),end=' ')
>>> for i in itertools.product('ABCD', repeat = 2):print(''.join(i),end=' ')
AB AC AD BC BD CD 
AB AC AD BA BC BD CA CB CD DA DB DC 
AA AB AC AD BB BC BD CC CD DD 
AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD 

上面例子中的最后一项,字符串的笛卡尔积。就其结果而言,等同于for循环嵌套。

>>> for i in 'ABCD':
>>>     for j in 'ABCD':
>>>         print(i+j,end=' ')
AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD 

猜你喜欢

转载自blog.csdn.net/watfe/article/details/80108774