python 比赛 组合问题

比赛 组合问题

简述:已知有两支乒乓球队要进行比赛,每队各出三人;
甲队为a,b,c三人,乙队为x,y,z三人;
已抽签决定比赛名单。

问题:有人向队员打听比赛的名单。a说他不和x比,c说他不和x,z比,请编程序找出三队赛手的名单。

li1 = ['a','b','c']
li2  = ['x','y','z']
# 全排列 有九种
allMatchs = [m+n for m in li1 for n in li2]
print(allMatchs)
['ax', 'ay', 'az', 'bx', 'by', 'bz', 'cx', 'cy', 'cz']

如果只是解决这个问题,肯定有简单点的办法,根据条件 a说他不和x比,c说他不和x,z比 去生成可能的结果
现在 我想找找看 '田忌赛马' 两两捉对厮杀的 共有多少种组合

先确定 结果的形式: [{'a':'x','b':'y','c':'z'},{...}...]

#  结果集合 操作的行 列索引 
def nextProp(res,rIndex,cIndex,li1,li2):
    v = li2[cIndex]
    keys = []
   ## 
    for e in li1:
        if not res[rIndex].get(e):
           keys.append(e)
    newRows = []
    for kIndex in range(len(keys)):
        if kIndex==0:
           res[rIndex][keys[kIndex]] =v
           continue
        else:
            newRow = res[rIndex].copy()
            newRow.pop(keys[kIndex-1]) ##  把前面 kIndex==0 时候赋的值也copy过来了 去掉
            newRow[keys[kIndex]] = v
            newRows.append(newRow) ## 循环内部先使用新的list 不要影响循环
    res+=newRows
                 

def getAllOptions(li1,li2,res=None):
    if not res: # 为空,第一次 初始化res
        res = []
        for e in li1:
            row = {e:li2[0]}
            res.append(row)
    for cIndex in range(1,len(li2)):
        for rIndex in range(len(res)):
            nextProp(res,rIndex,cIndex,li1,li2) # 填下一个属性
    return res
                
opts = getAllOptions(li1,li2)
for e in opts:
    print(e)
{'a': 'x', 'b': 'y', 'c': 'z'}
{'b': 'x', 'a': 'y', 'c': 'z'}
{'c': 'x', 'a': 'y', 'b': 'z'}
{'a': 'x', 'c': 'y', 'b': 'z'}
{'b': 'x', 'c': 'y', 'a': 'z'}
{'c': 'x', 'b': 'y', 'a': 'z'}

a说他不和x比,c说他不和x,z比, 现在就可以据此排除了,将刷选条件写成 回调函数

def filterOptions(opts,*fns):
    res = []
    for e in opts:
        flag = True
        for fn in fns:
            if not fn(e):
                flag = False
                break
        if flag:
            res.append(e) # 没有因为不符合条件break 到这里就可以加进结果集了
    return res

def f1(e):
    return e.get('a') !='x'
def f2(e):
    return e.get('c')!='x' and e.get('c')!='z'

res = filterOptions(opts,f1,f2)
print(res)
[{'b': 'x', 'c': 'y', 'a': 'z'}]

python中对list dict中的查询遍历操作等全靠循环,一时间想不起来了....
到时新技能get:

arr = [2,45,50,24,35]
for i in arr:
    if i>50:
        break
else:
        print('arr里没有比50大的数!')
arr里没有比50大的数!

for 和 else 类似于 if和else,当for里没有break的时候,就会进去else

for i in arr:
   pass
else:
        print('arr里没有比50大的数!')
arr里没有比50大的数!

for 里if不是关键, 关键看break, 有break没else,没break有else

可以在 for里用if exp :break 筛除, 剩下的进入else中处理

import math #
l = [2, 3]
for i in range(5, 101): #第一层循环,从5到100
    for j in range(2, int(math.sqrt(i))+1): #一个数的最大因数是它的平方根
        if i%j == 0: #如果出现整除说明有因子
            break 
    else:
        l.append(i) #for正常执行(包括contine)完会执行else,break不会执行else
print(" ".join(map(str, l))) #先将列表中的元素变为字符串再用空格连接输出
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

猜你喜欢

转载自www.cnblogs.com/ShawSpring/p/10818889.html