Python解甲乙猜数问题

已知两个1~n之间的不同的数,甲知道两数之和,乙知道两数之积。
甲问乙:“你知道是哪两个数吗?”乙说:“不知道”;
乙问甲:“你知道是哪两个数吗?”甲说:“也不知道”;
于是,乙说:“那我知道了”;
随后甲也说:“那我也知道了”;
这两个数是多少?

思路很暴力,把所有的组合先列出来,两个数且不相同共有29+28+27+...1种可能性也就是435种

然后用字典将结果装起来:a,b为两个数,名称就是元组形式的(a,b),内容为两者之和和两者之积

dic={(a,b):(a+b,a*b) for a in range(1,n+1) for b in range(a+1,n+1)}
#先列出所以可能
#dic的单位是key:(a,b)   value:(a+b,a*b)

甲和乙的对话,建模后可以直接理解为:已知两数之积/和,两数只有单解(对应甲乙说:“那我知道了”)或一定有多解(对应甲乙说:“我不知道”)

而只需要将不符合题意的组合删除,就能得到最终的解。

并定义一个函数,专门用来删除不符合题意的解

def pop(dic,is_product,is_single):
    #用来剔除多解或单解
    #参数二:是积还是和
    #参数三:是单解还是多解
    lis,lis2=list(zip(*dic.values()))[is_product],[]
    for j in lis:
        if (lis.count(j) == 1)==is_single:lis2.append(j)
            #如果总数为1,及没有多解
            #如果总是不为1,及有多解
            #然后把不符条件的放入lis2,准备删除
    dic={k:v for k,v in dic.items() if v[is_product] in lis2}
    #删除多解或删除单解
    return dic

分析题目:


#乙不知道是哪两个数,也就是有多解
#如果没有多解,乙肯定知道是哪两个
#所以删除积的单解
dic=pop(dic,True,False)
    
#甲:"我也不知道"说明和有多解
#删除和的单解
dic=pop(dic,False,False)

#乙说:"那我知道了"说明积只有一解
#删除积的多解
dic=pop(dic,True,True)
    
#甲说:"那我也知道了"说明和只有一解
#删除和的多解
dic=pop(dic,False,True)

最终代码:

def pop(dic,is_product,is_single):
    lis,lis2=list(zip(*dic.values()))[is_product],[]
    for j in lis:
        if (lis.count(j) == 1)==is_single:lis2.append(j)
    dic={k:v for k,v in dic.items() if v[is_product] in lis2}
    return dic
n=30
dic={(a,b):(a+b,a*b) for a in range(1,n+1) for b in range(a+1,n+1)}
dic=pop(dic,True,False)
dic=pop(dic,False,False)
dic=pop(dic,True,True)
dic=pop(dic,False,True)
print(*dic.keys())

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值