周末隔壁老王和媳妇玩24点,我忍不住用 Python...

点击上方“ 俊林 ”,马上关注,每天早上 8:50 准时推送 真爱,请置顶或星标 周末闲来无事,看到隔壁家的老王在和隔壁家的媳妇玩24点,就进屋看了看。 发现老王是真不行啊,那不行,这也不行。
就连个24点都玩不过他媳妇,给他媳妇气的,啥都不能满足,这不能,那也不能。
640?wx_fmt=gif 我坐下来和他媳妇玩了两把,那都是无出其右,把把赢!
我要走的时候,他媳妇还挽留我多玩几把,有意思。 为了能让老王在他媳妇面前抬起头来,我决定帮他一把……就用python写了个算24点的玩意,老王对我感激涕零。
640?wx_fmt=jpeg
什么是24点
我们先来约定下老王和他媳妇玩的24点规则:给定4个任意数字(0-9),然后通过`+,-,*,/`,将这4个数字计算出24。 小时候玩的都是这个规则,长大了才有根号,才有各种莫名其妙的高级算法,不好玩了,因为我不会。 可能有人会觉得很简单,但是真的简单吗?


比如: * 8,3,3,3 * 7,3,3,3


你能一眼看出来答案吗?好像真的可以……


大致思路 这样想,将四个数字进行全排列,在他们之间添加运算符号。 运算符我们需要进行排列组合,因为只有四个数字,所以只需要三个运算符,而且算法符可能会重复,比如三个都是`+`。 再遍历四个数字的全排列,对每一组数字而言,遍历所有组合的操作符。最后将数字和操作符进行拼接运算,就可以得到最终结果了。


演示环境 操作系统: windows10 python版本: python 3.7 代码编辑器: pycharm 2018.2 使用模块: math,itertools, collections.abc


具体代码 1、首先我们对所有数字进行去全排列,这里我们使用 itertools.permutations 来帮助我们完成。


iertools.permutations 用法演示
 
 


结果显示
 
 


permutations 第一个参数是接收一个课迭代的对象,第二个参数指定每次排列时从课迭代对象中选着几个字符进行排列。 也可以不传入第二个参数,那么默认就是可迭代对象的长度。 并且返回一个生成器。


所以我们需要对所有数字进行全排列,就可以像下面这样写:
 
 


2、然后我们需要拿到所有的操作运算符的所有组合方式。 这里我们就会使用 `itertools.product` 函数了。


itertools.product 用法演示
 
 
结果显示
 
  
 
`itertools.product`,返回传入所有序列中笛卡尔积的元祖,repeat参数表示传入序列的重复次数。 返回的是一个生成器。 那么获取所有的操作运算符就可以通过这个函数来获取了
 
  
 
3、现在我们已经拿到了所有可能组合的操作符和数字了,接下来就需要对他们进行拼接了。 然后执行运算。
这一步操作我们会用到 `itertools.zip_longest()` 和 `itertools.chain.form_iterable()` 函数。


itertools.zip_longest() 用法演示
 
 
结果显示
 
 
zip_longest() 其实和 python 内置的 zip() 函数用法差不多,只是 zip_longest 是以最长的一个序列为基准,缺失值就使用 `fillvalue` 参数的值进行填充


itertools.chain.form_iterable() 用法演示
 
 


结果显示
 
  
 这里的data是什么样的大家知道了吧,然后我们将data传入 chain.form_iterable() 中,它就能将里面的值依次拿出来。 
 


了解了这两个函数之后,那么我们就可以开始拼接数字和操作运算符了。
 
 


代码分析 1、eval() 函数,接受一个字符串,能让这个字符串当成 python 代码运行,返回运行的结果。
2、math.isclose(): 为什么这里需要使用 math.isclose() ,而不是直接使用`==`运算符呢? 这是因为最后算出来的表达式可能有精度问题,例如23.9...或者24.0...等数字,所以我们就需要使用math.isclose()函数来帮助我们判断两个数字是否相等了,这个函数就有一个精度范围。 这样出现上面情况的时候,我们也能匹配得到条件了。 我们运行代码,然后测试代码是否能达到我们的需求。 首先我们测试1,2,3,4四个数字, 程序出来了结果 `1*2*3*4` 24 看来好像我们写的代码是正确的


我们再来测试一组数据8,8,3,3. 嗯? 我们并没有得到结果? 这四个数字不能运算出24吗? `8 / ( 3 - 8 / 3 )` 这样组合可以吧,为什么没有算出来这种结果呢?


这是因为我们没有考虑括号的原因。 括号是可以改变运算优先级的。 所以我们得把括号考虑进去。


那么想一下括号最多可以有几个呢? 怎样给我们的表达式添加括号呢?


在4个数字的运算中,括号最多只能有三个。 并且,在这里,我们使用一种简单的方法添加括号,我们把所有可能出现括号的情况全部罗列出来,然后在将得到的运算表达式拼接进去。 可能大家会觉得罗列出所有括号出现的情况不现实,因为有很多情况 其实不然,当我们去罗列的时候,你就会发现,只有11种情况。


然后我们对得到的表达式在进行遍历拼接,然后我们再运算表达式。 这样我们就能得出正确的结果了 代码写完了,终于可以开始和媳妇,哦不,老王家的媳妇玩起来了 更多爬虫,关注公号,后台回复:24点,获取全套代码。

640?wx_fmt=jpeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值