一个24点游戏的算法,帮你深刻理解python中的匿名函数

首先简单地介绍一下24点游戏:将一副扑克牌去除大小王,AK分别代表113。任意抽出4张,任意使用加减乘除四则运算,使得这四个数运算的结果等于24。要求这四个数必须也只能使用一次。

听上去很简单吧,下面我们就要运用python中的匿名函数来实现这个算法,要求这个算法满足:任意输入4个数(例如:2,2,11,11),能够返回一个四则运算等式(就像这样:((2/11)+2)*11=24),如果不能算出,就告诉我们算不出来。

好啦,废话不多说了,直接上代码。( 注释应该很详细了吧 ^_* )

# coding=utf-8
#!/usr/bin/python

class Numbers(object):
    def __init__(self, numbers):
        #初始化一个数组对象,这个对象包含四个待处理的数
        self.numbers=numbers

    #获取输入元素的所有组合
    def combine(self,array,length):
        arr=[]
        if length==4:
            for i in array:
                for j in array:
                    for k in array:
                        for l in array:
                            arr.append([str(i),str(j),str(k),str(l)])
        elif length==3:
            for i in array:
                for j in array:
                    for k in array:
                        arr.append([str(i),str(j),str(k)])
        return(arr)

    #调用judge函数去除不符合要求的组合,
    #比如:原数组是2 2 3 4,那么要求生成的数组满足:
    #存在两个2,一个3和一个4,不能多也不能少
    def decrease(self,array):
        arr=[]
        for i in range(len(array)):
            if self.judge(array[i]):
                arr.append(array[i])
        return(arr)

    #对生成的数组进行排序,判定是否和原数组相等,
    def judge(self,array):
        tmp=sorted(array)
        if self.numbers==tmp:
            return(1)
        return(0)

    #根据加减乘除的符号返回对应的运算函数
    #在python中,函数也能作为返回值
    #这里使用了lambda来定义匿名函数
    def fun(self,measure):
        if measure=='+':
            f=lambda x,y : x+y
        elif measure=='-':
            f=lambda x,y : x-y
        elif measure=='*':
            f=lambda x,y : x*y
        elif measure=='/':
            f=lambda x,y : x/y
        else:
            raise ValueError
        return(f)

    #结合数组中的四个数字和运算法则,进行运算,判定结果是否等于24
    def figure(self,numbers,measures):
        #这是一个三层递归调用,每一层的fun函数返回的函数都可能不一样,
        #具体是什么取决于运算符号measure
        out=self.fun(measures[2])(
                self.fun(measures[1])(
                    self.fun(measures[0])(
                        float(numbers[0])
                        ,float(numbers[1]))
                    ,float(numbers[2]))
                ,float(numbers[3]))
        if out==24:
            return(1)
        else:
            return(0)

    #过滤掉数组中重复的部分
    def screen(self,array):
        #将array中重复的元素置空
        for i in range(len(array)):
            s=list(array)
            s[i]=''
            if(array[i] in s):
                array[i]=''
        #定义一个临时数组tmp,放入array中非空的元素
        tmp=[]
        for arr in array:
            if arr!='':
                tmp.append(arr)
        return(tmp)

if __name__ == '__main__':
    #获取输入的四个数
    numbers=input('''
        Please input 4 numbers to calculate,
        these numbers are split by space ',' ';' and '-',
        which just looks like "1 2 3 4" .\n''')
    
    #支持的分割符都在这个数组里
    char=[',',';','-','\n']
    #对char里的字符进行替换,以空格来分割numbers,
    #得到包含所输4个数字的数组numbers
    #(这里似乎可以换个名字,不过本人习惯这么写了)
    for c in char:
        numbers=numbers.replace(c,' ')
    numbers=(numbers.split(' '))

    #对输入的数进行排序
    numbers.sort()
    #给出一个Numbers对象的实例num并初始化
    num=Numbers(numbers)
    #先得到四个数字的所有排列组合,再筛除那些不符合judge函数要求的组合
    subnumbers=num.decrease(num.combine(numbers,4))

    #定义包含加减乘除四个运算符的数组measures
    measures=['+','-','*','/']
    #由于四则运算可以有重复的运算,所以不需要调用decrease函数来进行judge筛选
    submeasures=num.combine(measures,3)

    #定义一个数组arr来存放运算结果等于24的数字和运算符的组合
    arr=[]
    for i in range(len(subnumbers)):
        for j in range(len(submeasures)):
            #如果数字组合和四则运算符号组合的运算结果等于24,
            #则把这两对组合存放到arr数组中
            if num.figure(subnumbers[i],submeasures[j]):
                arr.append('Pass: ((%s%s%s)%s%s)%s%s=24' % (
                    subnumbers[i][0], submeasures[j][0], subnumbers[i][1], 
                    submeasures[j][1], subnumbers[i][2], submeasures[j][2], 
                    subnumbers[i][3]))
    #舍弃arr中重复的元素
    arr=num.screen(arr)

    #将非空的组合打印到终端,否则提示不能计算出
    if arr!=[]:
        for a in arr:
            print(a)
    else:
        print('Sorry, this combination cannot be figured out.')
    # 终于结束了,有收获就点个赞吧 ^_^
    print('Finished')
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容