24点扑克游戏详细解析附代码

题目要求:
52张牌里面选4张,可以重复,任意使用±/*和括号,使得最后运算结果为24.

多少种排列组合:
有131313*13种排列,但是这些排列的牌会有重复的,比如(1,1,2,3)和(1,3,2,1)就算是重复,把不重复的叫做一个组合,那么实际上有1820种组合。

成功的组合:
这1820种组合里面有1362种组合是成功解的。

成功的概率:
但是因为每个组合出现的概率不一样,不能使用1362/1820来做成功概率。比如组合123包含排列123,132,213,231,312,321.而组合221只包含排列122,212,221.所以最后的成功概率是要加权计算的,最后的成功概率为80.0%左右

优化求概率算法:
实际上,推广到广义更多牌(非4张),更多点数(非13点),可能使用完全逐一验证排列的算法会很耗时。例如变形为从无数副扑克里面挑10张牌出来算24点,复杂度变为13的10次方,如果使用逐一验证每个排列是否有解,会很耗性能。另外一种思路是随机抽样调查,随机产生适当数量的排列,验证是否有解,然后统计概率。

代码:
本算法的get_math_probability是逐个验证解,get_sim_probability是模拟统计解,对于一种组合,使用遍历换位,括号,运算符的方式来生成表达式。使用eval函数来计算表达式。

算法的坑:
对于(3,3,8,8)组合,有解"8/(3-8/3)"=24,但是如果直接计算会得到23.99999999999.所以解决方案是把eval(expr)==24改为abs(eval(expr)-24)<0.000001。限制精确度范围。

为什么是24:
因为24有1,2,3,4,6,8,12,24。总共8乘法个因子,并且24/4=6,6这个数字在[1,13]点里面是中间位置。所以24无论是乘除法,还是加减法都比较容易拼凑,使用其它数字会降低成功概率。

源代码:

#怎么模拟排列组合
import itertools as it
import random#permutations('ABCD', 2)排列 A42
#combinations('ABCD', 2)组合 C42def get_tu_res(tu):''':param tu: 整数元组:return: 能成功做出24点的字符串的集合'''situation = it.permutations(tu, 4)res=set()for si in situation:a,b,c,d=sifor o1 in "+-*/":for o2 in "+-*/":for o3 in "+-*/":# 那么三个符号根据运算顺序有6种顺序123,132,213,231,321,例如123是先算o1,再o2,再o3,其中312和132重复了e1=f"(({a}{o1}{b}){o2}{c}){o3}{d}"e2= f"({a}{o1}{b}){o2}({c}{o3}{d})"e3= f"({a}{o1}({b}{o2}{c})){o3}{d}"e4 = f"{a}{o1}(({b}{o2}{c}){o3}{d})"e5 = f"{a}{o1}({b}{o2}({c}{o3}{d}))"for expr in (e1,e2,e3,e4,e5):try:t=eval(expr)except:continueif t==24:res.add(expr)return resdef is_ok_tu(tu):'''性能提高在如果找到第一个解的时候就跳出了,节省计算:param tu: 整数元组:return: 布尔值,能否运算成24点'''situation = it.permutations(tu, 4)for si in situation:a, b, c, d = sifor o1 in "+-*/":for o2 in "+-*/":for o3 in "+-*/":# 那么三个符号根据运算顺序有6种顺序123,132,213,231,321,例如123是先算o1,再o2,再o3,其中312和132重复了e1 = f"(({a}{o1}{b}){o2}{c}){o3}{d}"e2 = f"({a}{o1}{b}){o2}({c}{o3}{d})"e3 = f"({a}{o1}({b}{o2}{c})){o3}{d}"e4 = f"{a}{o1}(({b}{o2}{c}){o3}{d})"e5 = f"{a}{o1}({b}{o2}({c}{o3}{d}))"for expr in (e1, e2, e3, e4, e5):try:t = eval(expr)except:continueif abs(t-24)<0.00000001:#防止恶心的"8/(3-8/3)"之类的发生return Truereturn Falsedef get_defeat_com():all_com=get_all_com()defeat_com = set()  # 失败的组合for tu in all_com:if not is_ok_tu(tu):defeat_com.add(tu)return defeat_comdef get_all_com():#包括重复数字的所有组合#实际上是有1820种组合com = set()  # 所有的组合for a in range(1, 14):for b in range(a, 14):for c in range(b, 14):for d in range(c, 14):# 保证了(a,b,c,d)本身就是非降序的tu = (a, b, c, d)com.add(tu)return comdef get_math_probability(defeat_com):#小数据用数学法,大数据用模蒙特卡洛拟法cnt_defeat=0for a in range(1,14):for b in range(1,14):for c in range(1,14):for d in range(1,14):arr=[a,b,c,d]arr.sort()tu=tuple(arr)if tu in defeat_com:cnt_defeat+=1probability=1-(cnt_defeat/28561)#13*13*13*13=28561return probabilitydef get_sim_probability(defeat_com):times=1000#模拟次数cnt_defeat=0for t in range(times):arr=[random.randint(1,13),random.randint(1,13),random.randint(1,13),random.randint(1,13)]arr.sort()tu=tuple(arr)if tu in defeat_com:cnt_defeat+=1return (times-cnt_defeat)/times# print(len(get_all_com()))#1820
# print(len(get_defeat_com()))#失败组合458,成功组合1362defeat_com=get_defeat_com()#最后大概得到0.80的成功率吧
print(get_math_probability(defeat_com))#0.7918140121144217
print(get_sim_probability(defeat_com))#0.807

24点扑克游戏详细解析附代码相关推荐

  1. php 运营商授权,PHP判断手机号运营商(详细介绍附代码)

    道理很简单,知道手机号规则 进行正则判断就可以 移动:134.135.136.137.138.139.150.151.157(TD).158.159.187.188 联通:130.131.132.15 ...

  2. uniapp获取手机号(详细教程附代码)

    uniapp获取手机号(详细教程附代码) 一.获取code 二.通过code获取获取openId 和 session_key 三.让用户授权(同意后需要对数据解密) 个人小程序不能使用这个功能,必须是 ...

  3. Java对象,Map,List,Set数组等相互转换大全(详细讲解,附代码,讲解案例)

    Java对象,Map,List,Set数组等相互转换大全(详细讲解,附代码,讲解案例) Java对象 转 JSON字符串 JAVA对象转MAP Map转java对象 List转map List和Map ...

  4. HDMI EDID详细解析——C代码实现

    继上一篇<HDMI EDID详细解析> https://blog.csdn.net/cfl927096306/article/details/108017501 现在用C代码来实现解析HD ...

  5. Java【冒泡排序】算法, 大白话式图文解析(附代码)

    文章目录 前言 一.排序相关概念 1, 什么是排序 2, 什么是排序的稳定性 3, 七大排序分类 二.冒泡排序 1, 图文解析 2, 代码实现 3, 冒泡排序的优化 三.性能分析 四.七大排序算法总体 ...

  6. Python关于strftime函数详细解析 附实战代码

    目录 前言 1. strftime函数 2. 实战 前言 项目中的python web中,时间都用到了这个函数 深挖了一下基本的知识点以及实战中的书写 主要参考的知识点有: Python time s ...

  7. 游戏服务端开发-AOI-九宫格法解析(附代码)

    1-啥是AOI AOI全称Area Of Interest,中文就是感兴趣的区域,个人理解就是玩家关注的并且可视的地图区域. 在RPG游戏中,玩家角色移动,攻击,放技能等操作都需要向其他玩家广播,但服 ...

  8. 【智能算法】粒子群算法(Particle Swarm Optimization)超详细解析+入门代码实例讲解...

    喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 01 算法起源 粒子群优化算法(PSO)是一种进化计算技术(evolutionary computation),1995 年由E ...

  9. labview2048小游戏详细解析+改进

    这个账号我的新开的一个CSDN账号,以后就要坚持在这里把自己平时用到的学到的都更新到这里,这次先把我另一个账号中的文章转载过来.反正都是我原创的. _____________ 最近因为实验室需要,需要 ...

  10. python爬虫案例-python爬虫详细解析附案例

    什么是爬虫框架 说这个之前,得先说说什么是框架: 是实现业界标准的组件规范:比如众所周知的MVC开发规范 提供规范所要求之基础功能的软件产品:比如Django框架就是MVC的开发框架,但它还提供了其他 ...

最新文章

  1. php定时执行代码漏洞_【漏洞风险提示】Drupal任意PHP代码执行漏洞通告
  2. node.js安装模式 的区别_如何使用nodejs写一个接口
  3. phoenix 开发API系列 目录
  4. html中调用flex中的函数
  5. ant+jmeter
  6. 【Python】Matplotlib绘制散点图
  7. Unity Occlusion Culling 遮挡剔除研究
  8. testng_TestNG超时示例
  9. [梦]2005.2.10
  10. [转].net中的认证(authentication)与授权(authorization)
  11. flex bison 下载
  12. 用vscode创建一个c项目_vscode怎么创建C语言项目
  13. eclipse汉化.设置为中文 简单好操作 java初学者看过来
  14. excel如何使用函数判断包含某值
  15. Android之按钮点击事件(单击、双击、长按等)
  16. 我崩溃了!Java大厂74道高级面试合集,面试心得体会
  17. TOEFL wordlist 35
  18. 数据中心安全域的设计和划分
  19. 通过nginx实现线上页面访问本地接口
  20. 输入商品显示商品名称和价格

热门文章

  1. 黑莓刷机及情景设置来电和短信等没有声音的解决办法
  2. 刷机必备:BlackBerry ROM,桌面管理器下载
  3. RPG类游戏开发方法
  4. Unix网络编程之epoll函数模拟10万客户端链接服务器
  5. Python实现QQ游戏连连看外挂秒杀
  6. 打开我的收藏夹 -- Python篇
  7. 从零搭建与好友“一起看王心凌《爱你》MV”功能
  8. 视频截取软件哪个好用?免费的视频截取软件分享
  9. 苹果平板计算机音乐,iphone、ipad上传照片、视频、音乐到电脑中 手机电脑互传文件...
  10. HTML+CSS静态页面网页设计作业 仿天猫购物商城(7页) 网页设计作业,网页制作作业, 学生网页作业, 网页作业成品, 网页作业模板