123
返回列表 发新帖
楼主: 〇〇

[转载] sql算24点大赛

[复制链接]
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
21#
 楼主| 发表于 2024-1-13 14:40 来自手机 | 只看该作者
19楼的解析,比直接查表还是**
我是分析几种计算形态获取的,ABC_D形态,D是整数,ABC计算,AB结果是小数,但是C必然是整数。
AB_CD形态,AB和CD可能同时是小数,但是只有一种可能性,就中间计算符是加减,两边是除,但这总形态最大计算值是4.5+4.5=9。
所以最终归纳出这个结论。
通过这个结论,进一步去想计算24点需要哪些组合(第一个参数表TMP_CALC),比如72-48是一个算24点的公式,那72和48是怎么产生的呢?8*9和6*8,把8*9和6*8等运算放在一个参数表(TMP_AB),这个参数表记录了所有100之内的整数计算关系。
TMP_CALC和TMP_AB通过字段关联,能得到大部分的公式。
第二种是需要反除的,比如5*4.8=24,我们需要推导4.8是怎么来的,比如6*8/10,5-1/5=4.8,前者在AB表,后者不在AB表,所以前者是可以直接通过第一种方式实现,而后者因为1/5不是整数,不在AB表里面,所以需要额外一个参数表补充,这个参数表其实是可以分两步,第一步保存除的关系,第二步再考虑这个小数和1-10范围內整数加减关系(如果是乘除的话,又转化成第二个参数表了),我最终简化成一个参数表。
又因为,数据库默认的小数长度是固定的,这些参数是中间值,没有经过二次运算,所以可以直接用=关联,避免了需要估算计算精度的问题。
然后,这个算法是一个4个数运算的通用模型,所以扩展结果24到其它数也没问题(<9不知道是否有问题,没思考验证),计算13张牌也没问题。

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
22#
发表于 2024-1-14 04:08 | 只看该作者
他这个代码针对1-10,四个数的特定情形做了简化,如果取值范围扩大,四个数变五个数,代码就很难改。

这个判断是否为整数的写法非常奇怪:where a.n/b.n REGEXP '^[0-9]*\.[0-9]*$' = 1
要是我会写:where mod(a.n/b.n,1)<>0

tmp_ab里面的tmp_100完全可以换成tmp_num,中间数据会少很多。

这个也很可疑:
"又因为,数据库默认的小数长度是固定的,这些参数是中间值,没有经过二次运算,所以可以直接用=关联,避免了需要估算计算精度的问题。"

他说的是tmp_fr1里面的where  a.r=b.n。但是这等式两边还是保存着除不尽的结果,理论上还是有可能不匹配。

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
23#
 楼主| 发表于 2024-1-14 18:34 来自手机 | 只看该作者
tmp_ab用少于100的数列关联是不行的,我加了个where a. n>=b. n 结果都漏了一些解

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
24#
 楼主| 发表于 2024-1-14 18:43 来自手机 | 只看该作者
用mod也有漏的
MariaDB [test]> \. 247.sql
+---------------+
| count(result) |
+---------------+
|        843800 |
+---------------+
1 row in set (0.784 sec)

MariaDB [test]> \. 246.sql
+---------------+
| count(result) |
+---------------+
|        855800 |
+---------------+
1 row in set (0.792 sec)

MariaDB [test]> system sh
$ diff 246.sql 247.sql
41c41
<     where a.n/b.n REGEXP '^[0-9]*\.[0-9]*$' = 1
---
>     where mod(a.n/b.n,1)<>0/* REGEXP '^[0-9]*\.[0-9]*$' = 1*/
46c46
<     where a.n/b.n REGEXP '^[0-9]*\.[0-9]*$' = 1),
---
>     where mod(a.n/b.n,1)<>0 /* REGEXP '^[0-9]*\.[0-9]*$' = 1*/),

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
25#
 楼主| 发表于 2024-1-14 21:32 来自手机 | 只看该作者
和程序作者说了,他也说这个regexp条件没什么用

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
26#
发表于 2024-1-14 23:49 | 只看该作者
我看错他的代码了,tmp_ab并不是只存放两个操作数的结果,而是包含了三个操作数的结果。
那个mod判断整数应该是数据库的问题,Oracle是可以这么用的,如果你有环境对比两种数据库的结果就可以知道到底哪个判断出了问题。判断整数也可以用TRUNC(N)=N这种写法。

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
27#
 楼主| 发表于 2024-1-15 05:57 来自手机 | 只看该作者
本帖最后由 〇〇 于 2024-1-15 07:44 编辑

他说用两个tmp_100关联多了,只要用两个46关联就够,46是两个1-10的数四则运算得到的不同数值个数
不过影响几乎没有

/*tmp_100 (n) as (
  SELECT 1
  UNION ALL
  SELECT n +1
  FROM tmp_100
  WHERE n < 100),*/
tmp_100 (n) as(
select a.n+b.n from tmp_num a,tmp_num b
union
select a.n-b.n from tmp_num a,tmp_num b where a.n>b.n
union
select a.n*b.n from tmp_num a,tmp_num b
),

改之前
mysql> \. d:/cn5.sql
+----------+----------+--------------------+
| count(s) | count(1) | count(distinct id) |
+----------+----------+--------------------+
|     8556 |     8556 |                566 |
+----------+----------+--------------------+
1 row in set (0.18 sec)
改之后
mysql> \. d:/cn6.sql
+----------+----------+--------------------+
| count(s) | count(1) | count(distinct id) |
+----------+----------+--------------------+
|     8556 |     8556 |                566 |
+----------+----------+--------------------+
1 row in set (0.18 sec)

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
28#
发表于 2024-1-15 22:58 | 只看该作者
本帖最后由 newkid 于 2024-1-16 08:15 编辑

贴主的努力还是在取值范围1-10做文章,试图人工预先消除一些不可能出现的答案,但是这种做法很有局限性,首先是不通用,而且到一定程度就无法提高。

这个24点题目太老已经没有新鲜感了,我们每周一题的网站https://devgym.oracle.com 每周都有一道逻辑题,已经出了很多年了,这个很适合做编程练习。例子:

每题固定给出两个线索:

12,24,7,21 => 153
3,9,5,25 => 88

求解:
14,28,9,18 =>?

根据线索推出公式,这个公式必须同时满足两个线索。四个数的位置是相对应的, 编号A,B,C,D,不是随便摆放的。

这个例子的公式是 (D - A) * (B - C) :

(21 - 12) * (24 - 7) = 153

(25 - 3) * (9 - 5) = 88

所以答案是:
(18 - 14) * (28 - 9) = 76

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表