利用初等数学解决python求24点的算法
24点游戏可以说家喻户晓,陪伴了很多人的童年,游戏玩法通常会使用一副扑克牌,然后从中抽取4张,J代表11,Q代表12,K代表13,然后算出24点。也就是说给定4个整数,数字范围在1-13之间,任意使用+、-、*、/、(),构造出一个代数式,其结果为24(含幂运算,指、对等复杂运算先不考虑),这就是常见的24点游戏,例如:(1+2+3)*4=24。当然每个地区可能会略有区别。
网上有很多24点的题目和答案,也有一些小程序帮助我们计算,那么我们就从高中数学出发,讲解一下计算机的解法,很多地区的小初高课程都加入了python的学习,我们用数学建模之后也利用一些最基础的python语句实现这个要求。
算法分析:
先实现4个数字的排列组合,这样等于已经实现了括号的功能,然后使用四则运算符进行组合计算,这么说找出所有的解法并不难,难就难在如何合适的加括号和去除等价的重复表达式上。我们的目标大概清楚了,是给定任意N个正整数,(N>1),找到这N个数通过四则运算计算得出24的全部表达式,并且只在必要的时候加上括号以及去除等价表达式。
(1)去除括号
首先我们要明确一个问题:什么是合适的括号呢?就是指在不影响计算结果的前提下,能不加括号尽量不加括号,比如:(15+8)+7-6=24应写作15+8+7-6=24。
其次还需要明白一个问题,什么是等价的重复表达式呢?就是完全相同的表达式,或者是在加法交换率和乘法交换率的作用下,完全等价的表达式。比如:10+12+7-5=24等价于10-5+7+12=24,15*8/(1+4)=24等价于15/(4+1)*8=24
(2)求全部解算法
我们采用的算法是降低维度的算法,即把4个数字运算的四维问题降低到二维来解决。比如,给定4个数字[1,2,3,4],这是一个四维问题,我们首先要将其转换为二维问题。具体的办法是,先将4个数字其中的2个数字取出,然后将2个数字转化为所能组成的全部表达式。我们首先取出[1,2],考虑到加法交换率和乘法交换率的前提下,共有6种可能的不等价表达式,即1+2,1-2,1*2,1/2,2-1,2/1,则四维问题就可以转化为多组三维问题,即[‘1+2’,3,4],[‘1-2’,3,4],['1*2',3,4],['1/2',3,4], [‘2-1’,3,4],['2/1',3,4]。
然后我们枚举每一种取出两个数的组合,使用排列组合公式即C(4,2),所以将四维问题转化为三维问题,共有C(4,2)*6=36种组合。
下一步是重复这一过程,将三维问题继续转化为二维问题。同理,每一个三维问题都可以转化为等价的二维问题,共有C(3,2)*6=18种组合。
所以,四维问题可转化为36*18=648种二维问题,每个二维问题又有6种组合方式,所以,全部的表达式个数为648*6=3888个。
(3)加括号算法
每当将二维问题组合成新表达式的时候,根据原有的两个表达式的各自运算符号和两个表达式之间的运算符号的关系来判断是否需要添加括号。举个例子,假设a、b两个表达式要组成新的表达式,总共会有如下4种情形:
●如果是a+b,则完全不需要加括号。
●如果是a*b或者a/b,若a、b自身的运算符号是加号或减号,则应加括号,如a=a1+a2,b为数字,则a*b=(a1+a2)*b。
●如果是a-b,若b为加号或减号,则b应加括号,如b=b1-b2,a=a1+b2,则a-b=a1+a2-(b1-b2),但值得注意的是,a1+a2-(b1-b2)其实等价于a1+a2-b1+b2,这种情况在其他的组合中其实已经存在。因此可以不再考虑括号问题。
●如果是a/b,若b的符号是乘号或除号,原本理应也要加括号,但其实这种情况与上一种情况类似,我们出于计算简便考虑,可以不再考虑括号问题。
(4)去除等价表达式
对于一个运算表达式来说,a+b-c+d与以下三种运算表达式的计算结果均是等价的:
●a+d+b-c
●b+a+d-c
●b-c+a+d
我们可以在任何一个表达式前加一个加号,然后使用python的切片或正则表达式进行切割:
[‘+a’,’+b’,’-c’,’+d’]
然后对其进行排序后再组合成字符串得到a+b+d-c,当然如果对于高中生结合python讲数学,我们也可以将上述列表直接转化为集合的形式,利用唯一性和无序性等集合的性质判断等价。
python具体实现代码:略