解24点游戏

24点游戏相信大家比较清楚规则了:给出四个数,运用加减乘除四则运算如何使结果等于24?
1、求解思路
霸王硬上弓,用穷举法。穷举法是最直接暴力的解决方案:已知给出的四个数(如a,b,c,d),搭配任意的三个运算符(如+,*,/)以及两组括号,穷举出所有不同的排列组合方式(如(a/b)+(c*d)),再逐个计算结果是否等于24。
2、具体实现
第一步:产生4个数的所有排列,结果存放在 self.nums 中;
第二步:产生3个运算符的所有组合,随后排列;
operators_combination 存放三个运算符的所有组合(运算符可以重复)。然后对三个运算符的组合进行排列,例如三个运算符分别为(+,-,*),那么对这个组合进行排列后(有顺序先后)的结果有六种:(+,-,*)、(+,*,-)、(-,+,*)(-,*,+)、(*,+,-)、(*,-,+);
由三个运算符组成的所有的排列组合放在 self.operators_arrangement中。
3、将数字的排列和运算符的排列组合连接起来,组成运算表达式;
这里注意,由4个数字与3个运算符组成的所有表达式都可以在其间穿插两组括号,表示人为设置运算符的优先级,具体的穿插方式有以下五种。当括号也穿插完毕后就可以暴力搜索了,计算结果是否为24。
4、将每一个表达式计算过程中的结果记录下来,便于表达式去重。(其实这里是我瞎捉摸的,对去重有一定效果,但没有完全达到预期效果)
例如表达式(8+4)+(2*6)、(4+8)+(2*6)、(8+4)+(6*2)、(4+8)+(6*2)这四个表达式的计算方法都一样,而我们不希望看到重复的。故思考将每一个表达式的计算过程记录下来,如(8+4)+(2*6)的计算过程用元组(12,12,24)记录,最后根据计算过程是否重复去掉相似的表达式。

import itertools

class Twenty_four_point:
    def __init__(self,four_nums_list):
        self.nums = map(str,four_nums_list)
        self.operators = ['+','-','*','/']
        self.result_step = []
        
    def Combinations_and_arrangements(self):
        self.nums_arrangement = itertools.permutations(self.nums)
        
        operators_combination = itertools.combinations_with_replacement(self.operators, 3)
        operators_arrangement = list()
        for item in operators_combination:
            for item1 in itertools.permutations(item):
                operators_arrangement.append(item1)
        self.operators_arrangement= list(set(operators_arrangement))
        
        self.expressions_lst = list()
        for nums in self.nums_arrangement:
            for operators in self.operators_arrangement:
                combination1 = '(' + nums[0] + operators[0] + nums[1] + ')' + operators[1] + '(' + nums[2] + operators[2] + nums[3] + ')'
                combination2 = '((' + nums[0] + operators[0] + nums[1] + ')' + operators[1] + nums[2] + ')' + operators[2] + nums[3] 
                combination3 = '(' + nums[0] + operators[0] + '(' + nums[1] + operators[1] + nums[2] + '))' + operators[2] + nums[3]
                combination4 = nums[0] + operators[0] + '((' + nums[1] + operators[1] + nums[2] + ')' + operators[2] + nums[3] + ')'
                combination5= nums[0] + operators[0] + '(' + nums[1] + operators[1] + '(' + nums[2] + operators[2] + nums[3] + '))'
                self.expressions_lst.extend([combination1,combination2,combination3,combination4,combination5])
          
    def Calculate_result(self,expression):
        brackets_index = [i for (i,j) in enumerate(expression) if j in ['(',')']]
        try:
            if brackets_index == [0, 4, 6, 10]:
                self.result_step.append((expression,(eval(expression[1:4]),eval(expression[7:10]),eval(expression))))
            elif brackets_index == [0, 1, 5, 8]:
                self.result_step.append((expression,(eval(expression[2:5]),eval(expression[0:9]),eval(expression))))
            elif brackets_index == [0, 3, 7, 8]:
                self.result_step.append((expression,(eval(expression[4:7]),eval(expression[0:9]),eval(expression))))
            elif brackets_index == [2, 3, 7, 10]:
                self.result_step.append((expression,(eval(expression[4:7]),eval(expression[3:10]),eval(expression))))
            elif brackets_index == [2, 5, 9, 10]:
                self.result_step.append((expression,(eval(expression[6:9]),eval(expression[3:10]),eval(expression))))
        except ZeroDivisionError:
            pass
    
    def Filtrate_results(self):
        self.valid_result = [(i,j) for i,j in self.result_step if round(j[2],1) == 24.0]
        self.filtrated_result = []
        temp_lst = []
        for (i,j) in self.valid_result:
            if j not in temp_lst:
                temp_lst.append(j)
                self.filtrated_result.append(i)
        else:
            print('')
                     
if __name__ == '__main__':
    input_nums = [1,4,5,6]
    problem = Twenty_four_point(input_nums)
    problem.Combinations_and_arrangements()
    
    for item in problem.expressions_lst:
        problem.Calculate_result(item)
    
    problem.Filtrate_results()

    if len(problem.filtrated_result) == 0:
        print('Sorry,this problem has no solution!')
    else:
        print('='*30)
        print('The four input numbers are:{}'.format(input_nums))
        print('Solutions can be:')
        for solution in problem.filtrated_result: 
            print('   ' + solution[:])
        print('='*30)
        print('')

5、运行结果

==============================
The four input numbers are:[1, 4, 5, 6]
Solutions can be:
   4/(1-(5/6))
   6/((5/4)-1)
==============================

以上就是整个代码,由于水平确实有限,就不花精力简化代码和优化结果了。自娱自乐一下就好,哈哈O(∩_∩)O~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值