用Python算24点

简介:

215c8eed1961083df1118ffa330b7c7c92344f4e

小外甥女的课后作业是算24点,看了一下题目,发现都挺难的,像下面这些:
7 7 3 3
8 8 3 3
5 5 5 1
1 5 7 10
2 5 5 10
只能用加减乘除,算出24点。
发现心算不容易,于是突发奇想,用Python写了一个程序来算。
基本思路

枚举4个数字可以组成的所有的算式,找到其中等于24的式子。
对于每一个算式,我们用一棵二叉树来存取。根节点保存运算符(+,-,*,/),左子树保存运算符左侧的子算式,右子树保存运算符右侧的子算式,运算结果也存在根节点中。如下图

d518196ba25df5e072b03eaa1dea32b574e794ec

这棵二叉树对应的算式就是 (4 + 10) + (2 * 5) 。非常简单直观。
有了二叉树后,对于给定的一组数字,我们就可以递归地列出这组数字组成的所有可能的算式。
具体实现

首先定义二叉树。对于树中的每一个节点,我们用一个Node类来保存

 

class Node (object):
def __init__ (self, result=None):
self._left = None
self._right = None
self._operator = None
self._result = result

def set_expression (self, left_node, right_node, operator):
self._left = left_node
self._right = right_node
self._operator = operator
expression = "{} {} {}" .format(left_node._result, operator, right_node._result)
self._result = eval(expression)

def __repr__ (self):
if self._operator:
return '<Node operator="{}">' .format(self._operator)
else :
return '<Node value="{}">' .format(self._result)

Node类中,如果 _operator 是None,则 _result 就是数字本身,如果 _operator 不为None,则 _result 表示的是左右两棵子树运算的结果。

对于一组给定顺序的数字,我们用递归的方式获取所有可能的算式

 

def build_all_trees (array):
if len(array) == 1 :
tree = Node(array[ 0 ])
return [tree]

treelist = []
for i in range( 1 , len(array)):
left_array = array[:i]
right_array = array[i:]
left_trees = build_all_trees(left_array)
right_trees = build_all_trees(right_array)
for left_tree in left_trees:
for right_tree in right_trees:
combined_trees = build_tree(left_tree, right_tree)
treelist.extend(combined_trees)
return treelist

上面函数的输入是一组数字,第一层for循环中将这组数字,拆成左右两部分,分别对应左右两棵子树的部分,输出的 treelist 是所有可能的算式。
对于给定的左子树和右子树,build_tree 函数用加减乘除把它们连接在一起,组成新的二叉树。build_tree 函数如下

 

def build_tree (left_tree, right_tree):
treelist = []
tree1 = Node()
tree1.set_expression(left_tree, right_tree, "+" )
treelist.append(tree1)
tree2 = Node()
tree2.set_expression(left_tree, right_tree, "-" )
treelist.append(tree2)
tree4 = Node()
tree4.set_expression(left_tree, right_tree, "*" )
treelist.append(tree4)
if right_tree._result != 0 :
tree5 = Node()
tree5.set_expression(left_tree, right_tree, "/" )
treelist.append(tree5)
return treelist

build_tree 中会枚举所有的运算方式,组成新的二叉树并返回所有可能的组合。
这里需要注意的是,如果运算方式是除法,除数也就是右侧子算式的结果不能为0。

罗列出所有的算式后,我们就来找一找有没有算式的结果是24。

 

def find_24 (array):
perms = itertools.permutations(array)
found = False
for perm in perms:
treelist = build_all_trees(perm)
for tree in treelist:
if math.isclose(tree._result, 24 , rel_tol= 1e-10 ):
expression = get_expression(tree)
print( "{} - {}" .format(perm, expression))
found = True
break
if found:
break

以上就实现了我们的算法。

测试

下面是令人兴奋的时刻。我们用文章开始的几个例子来测一下我们的算法。
运行结果如下

 

( 7 , 7 , 3 , 3 ) - ( 7 * (( 3 / 7 ) + 3 ))
( 8 , 8 , 3 , 3 ) - ( 8 / ( 3 - ( 8 / 3 )))
( 5 , 5 , 5 , 1 ) - (( 5 - ( 1 / 5 )) * 5 )
( 1 , 5 , 7 , 10 ) - (( 1 + ( 7 / 5 )) * 10 )
( 2 , 5 , 5 , 10 ) - (( 5 - ( 2 / 10 )) * 5 )

哈哈,都用到了小数运算,怪不得心算这么难呢~ 是不是很有趣?


原文发布时间为:2018-11-16

本文作者:shenzhongqiang

本文来自云栖社区合作伙伴“Python爱好者社区”,了解相关信息可以关注“Python爱好者社区”。

相关文章
|
资源调度 算法 JavaScript
Python基础专题 - 超级详细的 Random(随机)原理解析与编程实践
Python基础专题 - 超级详细的 Random(随机)原理解析与编程实践
1917 0
|
安全 Linux Shell
Read-only file system 问题分析与解决
Read-only file system 问题分析与解决
Read-only file system 问题分析与解决
|
计算机视觉 Python
解决pycharm调用plt.show()后无图片显示问题
解决pycharm调用plt.show()后无图片显示问题
2454 0
|
8月前
|
JavaScript 索引
Vue.js中el-table组件实现数据行删除功能,包含行索引处理
注意:当从列表中移除项目时,默认情况下列表会重新渲染,并且每一项会获得新 的 索引值。如果你依赖于特定 索引值进行其他计算或者逻辑处理,请确保更新那些依赖于旧 索引值得逻辑代码段。
574 16
|
编解码 Linux 开发者
初探FFplay:多媒体播放器的快速入门指南
【10月更文挑战第15天】FFplay是一个由FFmpeg项目提供的轻量级多媒体播放器,它使用FFmpeg库来解码和播放音频/视频流。FFplay非常适合那些想要深入了解多媒体编解码技术和音视频播放流程的开发者或爱好者。本文将介绍FFplay的基本功能、安装配置步骤以及如何使用命令行参数来播放多媒体文件。
2475 0
|
9月前
|
机器学习/深度学习 监控 安全
Jailbreak 36计————向天再借500分
本内容由IT老兵“老李”倾情奉献,结合《三十六计》智慧,深入剖析大语言模型越狱攻击的36种策略。每计包含思路、详解、案例、防御与点评,内容详实,实战性强,助你在“大模型安全挑战者计划”中脱颖而出。
1506 8
|
前端开发 Java 关系型数据库
基于ssm的台球厅管理系统,附源码+数据库+论文
本项目为新锐台球厅管理系统,支持管理员和会员两种角色。管理员可进行会员管理、台球桌管理、订单管理等;会员可查看台球桌、预约、购买商品等。技术框架基于Java,采用B/S架构,前端使用Vue+HTML+JavaScript+CSS+LayUI,后端使用SSM框架,数据库为MySQL。运行环境为Windows,JDK8+MySQL5.7+Tomcat8.5。提供演示视频及详细文档截图。
|
SQL 存储 关系型数据库
计算效率提升 30 倍、存储资源节省 90%,雨润集团基于 Apache Doris 的统一实时数据仓库建设实践
数字化转型的浪潮中,高效准确的数据分析能够帮助雨润集团快速洞察市场动态、优化供应链管理、提高生产效率。雨润集团引入了 Apache Doris 构建了统一实时数据仓库,实现了计算效率提升 30 倍、存储资源节省 90%、成本降低超 100 万、人员效率提升 3 倍,为智能化、高效化转型指明了方向。
513 1
计算效率提升 30 倍、存储资源节省 90%,雨润集团基于 Apache Doris 的统一实时数据仓库建设实践
|
Web App开发 安全 Linux
FFmpeg开发笔记(二十六)Linux环境安装ZLMediaKit实现视频推流
《FFmpeg开发实战》书中介绍轻量级流媒体服务器MediaMTX,但其功能有限,不适合生产环境。推荐使用国产开源的ZLMediaKit,它支持多种流媒体协议和音视频编码标准。以下是华为欧拉系统下编译安装ZLMediaKit和FFmpeg的步骤,包括更新依赖、下载源码、配置、编译、安装以及启动MediaServer服务。此外,还提供了通过FFmpeg进行RTSP和RTMP推流,并使用VLC播放器拉流的示例。
2769 3
FFmpeg开发笔记(二十六)Linux环境安装ZLMediaKit实现视频推流
|
SQL 数据挖掘 数据处理
R语言数据操作:使用dplyr进行数据处理的深度探索
【8月更文挑战第27天】`dplyr`包以其简洁、强大的数据处理能力,在R语言的数据分析领域占据了重要地位。通过`select()`、`filter()`、`arrange()`、`mutate()`和`summarise()`等核心函数,结合管道操作符`%>%`,我们可以轻松地完成数据筛选、排序、变换和汇总等操作。掌握`dplyr`的使用,将极大地提高我们在R语言中进行

热门文章

最新文章