如何提高Python编程能力?不妨试试这个经典的24点问题

1. 问题

暑假期间,办公室里经常会出现因无人看护而不得不跟随爸爸妈妈来上班的小朋友。如果不忙的话,我会陪他们一起玩,他们也都很喜欢和我玩。我们都喜欢玩数字游戏。这不,有位小朋友给我出了一道难题:三个5和一个1,只用加减乘除四则运算,每个数字只能且必须使用一次,如何让结果等于24?

这不就是经典的24点问题吗?这个咱拿手啊,从小就玩,小儿科的游戏岂能难倒老许!可是,对于这道题,我尝试了很久,却仍然找不到答案。

“这个题,是不是无解啊?”我试探着问小朋友。

“不是啦,这个题有答案,而且很简单。”小朋友一脸认真。

“好,再给我5分钟。”我赶紧溜进自己办公室,关上门,打开电脑。不用Python,估计是镇不住场子了。

2. 分析

走投无路的时候,穷举也许是最佳选择。4个数字,4种运算符号,外加括号,如何穷尽全部的算式呢?我们把问题分解一下。

2.1 数字

4个数字,每个数字只能且必须使用一次,这是一个排列问题,共有4×3×2=244\times3\times2=24种排列方案。

Python内置模块itertools提供了排列函数permutations(),可以给出全部的排列方案。如果用ABCD表示4个数字,那么全部的排列如下。

>>> from itertools import permutations
>>> for item in permutations('ABCD'):
		print(item)
	
('A', 'B', 'C', 'D')
('A', 'B', 'D', 'C')
('A', 'C', 'B', 'D')
('A', 'C', 'D', 'B')
('A', 'D', 'B', 'C')
('A', 'D', 'C', 'B')
('B', 'A', 'C', 'D')
('B', 'A', 'D', 'C')
('B', 'C', 'A', 'D')
('B', 'C', 'D', 'A')
('B', 'D', 'A', 'C')
('B', 'D', 'C', 'A')
('C', 'A', 'B', 'D')
('C', 'A', 'D', 'B')
('C', 'B', 'A', 'D')
('C', 'B', 'D', 'A')
('C', 'D', 'A', 'B')
('C', 'D', 'B', 'A')
('D', 'A', 'B', 'C')
('D', 'A', 'C', 'B')
('D', 'B', 'A', 'C')
('D', 'B', 'C', 'A')
('D', 'C', 'A', 'B')
('D', 'C', 'B', 'A')

2.2 运算符号

针对每一种数字排列,我们需要从4种运算符号中允许重复地取出3个,组成一个算式。这个问题幻化成如下描述:有3个篮子,每个篮子里都有4种运算符,从每个篮子里各取1个符号,共有多少种可能?这是一个笛卡尔积的问题,答案是4×4×4=644\times4\times4=64种可能。

Python内置模块itertools提供了笛卡尔积函数product(),可以给出全部的方案。

>>> from itertools import product
>>> for item in product('+-*/', '+-*/', '+-*/'):
		print(item)
	
('+', '+', '+')
('+', '+', '-')
('+', '+', '*')
('+', '+', '/')
('+', '-', '+')
('+', '-', '-')
('+', '-', '*')
('+', '-', '/')
('+', '*', '+')
('+', '*', '-')
('+', '*', '*')
('+', '*', '/')
('+', '/', '+')
('+', '/', '-')
('+', '/', '*')
('+', '/', '/')
('-', '+', '+')
('-', '+', '-')
('-', '+', '*')
('-', '+', '/')
('-', '-', '+')
('-', '-', '-')
('-', '-', '*')
('-', '-', '/')
('-', '*', '+')
('-', '*', '-')
('-', '*', '*')
('-', '*', '/')
('-', '/', '+')
('-', '/', '-')
('-', '/', '*')
('-', '/', '/')
('*', '+', '+')
('*', '+', '-')
('*', '+', '*')
('*', '+', '/')
('*', '-', '+')
('*', '-', '-')
('*', '-', '*')
('*', '-', '/')
('*', '*', '+')
('*', '*', '-')
('*', '*', '*')
('*', '*', '/')
('*', '/', '+')
('*', '/', '-')
('*', '/', '*')
('*', '/', '/')
('/', '+', '+')
('/', '+', '-')
('/', '+', '*')
('/', '+', '/')
('/', '-', '+')
('/', '-', '-')
('/', '-', '*')
('/', '-', '/')
('/', '*', '+')
('/', '*', '-')
('/', '*', '*')
('/', '*', '/')
('/', '/', '+')
('/', '/', '-')
('/', '/', '*')
('/', '/', '/')

2.3 括号

针对一个算式,枚举所有添加括号的可能,似乎没有规律。稍加分析,也很容易找到解决方案。我们用N表示数字,用#表示运算符,可能的情况大概有以下11种类型(其中有些是等价的,为了简单起见,我们不再继续优化了)。

  1. N # N # N # N
  2. (N # N ) # N # N
  3. N # N # (N # N)
  4. N # (N # N) # N
  5. (N # N) # (N # N)
  6. (N # N # N) # N
  7. ((N # N) # N) # N
  8. (N # (N # N)) # N
  9. N # (N # N # N)
  10. N # ((N # N) # N)
  11. N # (N # (N # N))

2.4 计算

数字有24种排列方式,运算符号有64种方案,添加括号有11种可能,则全部可能的算式有24×64×11=1689624\times64\times11=16896个。我们只要将每一个字符串形式的算式(表达式)用eval()函数计算结果,就可以找到结果等于24的算式。当然,有些算式可能无意义,比如除数为0的情况。针对无意义的算式,eval()会抛出异常,我们只需捕捉并忽略异常就可以。

3. 答案

有了上面的分析,写代码就成了水到渠成、轻松愉快的事情了。

>>> from itertools import permutations, product
>>> def game24(n1,n2,n3,n4):
		for a,b,c,d in permutations((n1,n2,n3,n4),4):
			for o1,o2,o3 in product(['+','-','*','/'], repeat=3): # 笛卡尔积的另一种写法
				cases = list()
				cases.append('%d%s%d%s%d%s%d'%(a,o1,b,o2,c,o3,d))
				cases.append('(%d%s%d)%s%d%s%d'%(a,o1,b,o2,c,o3,d))
				cases.append('%d%s%d%s(%d%s%d)'%(a,o1,b,o2,c,o3,d))
				cases.append('%d%s(%d%s%d)%s%d'%(a,o1,b,o2,c,o3,d))
				cases.append('(%d%s%d)%s(%d%s%d)'%(a,o1,b,o2,c,o3,d))
				cases.append('(%d%s%d%s%d)%s%d'%(a,o1,b,o2,c,o3,d))
				cases.append('((%d%s%d)%s%d)%s%d'%(a,o1,b,o2,c,o3,d))
				cases.append('(%d%s(%d%s%d))%s%d'%(a,o1,b,o2,c,o3,d))
				cases.append('%d%s(%d%s%d%s%d)'%(a,o1,b,o2,c,o3,d))
				cases.append('%d%s((%d%s%d)%s%d)'%(a,o1,b,o2,c,o3,d))
				cases.append('%d%s(%d%s(%d%s%d))'%(a,o1,b,o2,c,o3,d))
				for expression in cases:
					try: # 捕获表达式中分母为0的异常
						if eval(expression) == 24:
							print('答案:%s = 24'%expression)
							return
					except:
						pass
		print('无解!')
	
>>> game24(5,5,5,1)
答案:5*(5-1/5) = 24
>>> game24(1,3,4,6)
答案:6/(1-3/4) = 24
>>> game24(10,10,4,4)
答案:(10*10-4)/4 = 24
>>> game24(7,7,3,3)
答案:7*(3/7+3) = 24
>>> game24(1,5,7,10)
答案:(1+7/5)*10 = 24
>>> game24(15,25,37,80)
无解!

穷举所有变化,速度怎么样?加上时间度量,用上面同样的题目测试,最快5毫秒,最慢(全部穷尽算式)146毫秒。

>>> game24(5,5,5,1)
答案:5*(5-1/5) = 24,耗时0.011
>>> game24(1,3,4,6)
答案:6/(1-3/4) = 24,耗时0.117
>>> game24(10,10,4,4)
答案:(10*10-4)/4 = 24,耗时0.005
>>> game24(7,7,3,3)
答案:7*(3/7+3) = 24,耗时0.017
>>> game24(1,5,7,10)
答案:(1+7/5)*10 = 24,耗时0.014
>>> game24(15,25,37,80)
无解!耗时0.146

经过验证,一切都OK了。接下来,就是我在小朋友们面前吹牛的时刻了,你一定能想象得到。哈哈哈。

Python数据挖掘简易入门

03-11
【为什么学习数据挖掘】       人工智能、大数据时代有什么技能是可以运用在各种行业的?数据分析就是。       从海量数据中获得别人看不见的信息,创业者可以通过数据分析来优化产品,营销人员可以通过数据分析改进营销策略,产品经理可以通过数据分析洞察用户习惯,金融从业者可以通过数据分析规避投资风险,程序员可以通过数据分析进一步挖掘出数据价值,它和编程一样,本质上也是一个工具,通过数据来对现实事物进行分析和识别的能力。不管你从事什么行业,掌握了数据分析能力,往往在其岗位上更有竞争力。 【超实用的课程内容】      本课程为Python数据挖掘方向的入门课程,课程主要以真实数据为基础,详细介绍数据挖掘入门的流程和使用Python实现pandas与numpy在数据挖掘方向的运用,并深入学习如何运用scikit-learn调用常用的数据挖掘算法解决数据挖掘问题,为进一步深入学习数据挖掘打下扎实的基础。 本课程分为三大部分: 基础知识篇:主要讲解数据挖掘这项技能的基本工作流程和介绍和入门必须的基本技能Python语言的入门,带领大家了解数据挖掘的常见操作和基础知识。 数据采集篇:学习如何解决数据挖掘的数据来源问题,读取各类型不同的数据包括CSV,excel,MySQL进行数据采集的交互。 数据探索篇:本篇主要解决数据的预处理保证数据的质量并用常见数据挖掘算法进行特征提取,分析数据背后隐含的信息。 【报名须知】 课程采取录播模式,课程永久有效,可无限次观看 课件、课程案例代码完全开放给你,你可以根据所学知识,自行修改、优化 【如何开始学习?】 PC端:报名成功后可以直接进入课程学习 移动端:下载CSDN学院或CSDN
©️2020 CSDN 皮肤主题: 精致技术 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值