从围棋收官到秦楚大战的数据库SQL实现(下)
| 收官术语 | 名词解释 |
|---|---|
| 单先 | 己方的关键点,占据后对方必须立即应对,否则将遭受损失。 |
| 双先 | 双方都认为紧急且必须立即应对的点,无论谁下都会迫使对方回应。 |
| 后手 | 对方可以不立即应对的着手。 |
| 逆收 | 抢占对方的单先点,阻止对方获得先手权。 |
注:本文代码可左右滑动观看
1
双先量化,得失权衡
秦孝公:甚善!恩公驾临,令寡人喜出望外。适逢吾等论八城之争最优解,梁先生快快助孤。
梁敬彬:大王,吾以为策无定法,唯有相对优劣。胡先生以为然否?
胡傲华:然也。人难尽知收官奥妙,能大致不差已属难得。先前所言双先是否可置之不理,实需精算双方得失。今不妨试将此得失量化,以求相对最优。
商鞅:如何量化?
胡傲华:譬如弈棋,黑落一子,白若不应,则白之损失几何?或言之,黑因对方不理而得利几何?此即量化之所在。
商鞅:此值未必甚大,须因盘面而定,不可一概而论吧?
胡傲华:商君所言甚是。然大致量化,或可助吾等深究收官之道。姑且假设此利至少逾当前先手价值两倍。
秦孝公:何以倍之?
胡傲华:此乃假设,亦有其理。盖因盘上大抵难寻两倍之利,能令对手心生恐惧而应之。
商鞅:实则或远超两倍。
胡傲华:然也。
嬴驷:胡先生,那单先可有不应之理乎?
胡傲华:理论上可也。然单先与双先迥异,双先若被占,几乎必遭损失。单先虽被抢,然先手仍在己方。为避繁琐,暂且只论双先之争。
嬴驷:明矣。
2
各守城池,妥协攻守
胡傲华:吾等所言双先、单先、逆收、后手之序,乃常理也。然后手逆收其序易变,双先亦然。试设想秦楚互不相让,秦取平原1,楚随即取平原2,而后双方皆不欲生事,各自回防。此为第三次改良攻城之策,诸君思之,此策若用,结果几何?
嬴华:容吾思之。嗯...若秦楚面对对方双先城之攻,皆选收兵。其结果如下表。
哇,胡先生,此策较前,楚竟多得平原2一城!
胡傲华:华公子,楚得平原2,实从秦手中夺之,此消彼长,可知其意?
嬴华:胡先生,秦楚之势消长,面积相去已达75*2=150之多!
胡傲华:诸君至此可明白了?围棋双先之妙,非同小可。
众人皆点头称是。
3
SQL演算,三策评详
秦孝公:今日恩公在此,寡人以SQL神功再验之。然建表和插数如旧,如下。
-- 创建城池表
CREATE TABLE cities (
id NUMBER(5) PRIMARY KEY,
name VARCHAR2(50),
types VARCHAR2(10),
sizes NUMBER(5)
);-- 插入城池数据,包括大小
INSERT INTO cities (id, name, types, sizes) VALUES (1, '平原1', '双先', 80);
INSERT INTO cities (id, name, types, sizes) VALUES (2, '平原2', '双先', 75);
INSERT INTO cities (id, name, types, sizes) VALUES (3, '草原1', '秦先手', 70);
INSERT INTO cities (id, name, types, sizes) VALUES (4, '草原2', '秦先手', 65);
INSERT INTO cities (id, name, types, sizes) VALUES (5, '山水1', '楚先手', 60);
INSERT INTO cities (id, name, types, sizes) VALUES (6, '山水2', '楚先手', 85);
INSERT INTO cities (id, name, types, sizes) VALUES (7, '高原1', '后手', 55);
INSERT INTO cities (id, name, types, sizes) VALUES (8, '高原2', '后手', 180);
此次改良,乃在前策基础上更进一步。秦楚双方,皆从最大者始,依次争夺双先之城,SQL之策如下。
-- 初始化城池数据,为每个城池分配类型顺序和大小排名
WITH city_data AS (
SELECT
id, name, types, sizes,
CASE
WHEN types = '双先' THEN 1
WHEN types = '秦先手' THEN 2
WHEN types = '楚先手' THEN 3
WHEN types = '后手' THEN 4
END AS type_order,
ROW_NUMBER() OVER (PARTITION BY types ORDER BY sizes DESC) AS size_rank
FROM cities
),
-- 计算战略选择所需的最大后手和楚先手城池大小
strategic_choice AS (
SELECT
id, name, types, sizes, type_order, size_rank,
MAX(CASE WHEN types = '后手' THEN sizes ELSE 0 END) OVER () AS max_后手_size,
MAX(CASE WHEN types = '楚先手' THEN sizes ELSE 0 END) OVER () AS max_楚先手_size
FROM city_data
),
-- 根据战略规则决定每个城池的归属
capture_process AS (
SELECT
id, name, types, sizes, type_order, size_rank,
CASE
-- 双先城池按大小轮流分配给秦楚
WHEN types = '双先' THEN
CASE
WHEN MOD(size_rank, 2) = 1 THEN '秦'
ELSE '楚'
END
-- 秦先手城池归秦
WHEN types IN ('秦先手') THEN '秦'
-- 最大后手城池如果大于楚先手两倍,归秦
WHEN types = '后手' AND sizes = max_后手_size
AND sizes > 2* max_楚先手_size THEN '秦'
-- 如果没有满足上述条件的后手城池,楚先手归秦
WHEN types = '楚先手' AND
NOT EXISTS (SELECT 1 FROM strategic_choice
WHERE types = '后手' AND sizes > 2* max_楚先手_size) THEN '秦'
-- 其他情况归楚
ELSE '楚'
END AS captured_by
FROM strategic_choice
)
-- 汇总结果,按秦楚分类显示占领的城池数量、总大小和详细列表
SELECT
captured_by AS category,
COUNT(*) AS count,
SUM(sizes) AS total_size,
LISTAGG(name || ' ('|| types || ', 大小: '|| TO_CHAR(sizes) || ')', ', ')
WITHIN GROUP (ORDER BY type_order, sizes DESC) AS cities
FROM capture_process
GROUP BY captured_by
ORDER BY
CASE WHEN captured_by = '秦' THEN 1 ELSE 2 END;
此SQL查询模拟了秦楚争城之过程,关键步骤如下:
双先城池按大小轮流分配予秦楚,秦先取之。 秦先手城池直接归秦。 若最大后手城池大小逾最大楚先手城池两倍,则秦选该后手城池。 若无前述条件之后手城池,秦选楚先手城池。 其余城池归楚。
输出结果:
秦楚各占4城,其中秦域395,楚域275。如诸君所料。
category | count | total_size | cities
---------|-------|------------|-------------------------------------------------------
秦 | 4 | 395 | 平原1 (双先, 大小: 80), 草原1 (秦先手, 大小: 70), 草原2 (秦先手, 大小: 65), 高原2 (后手, 大小: 180)
楚 | 4 | 275 | 平原2 (双先, 大小: 75), 山水2 (楚先手, 大小: 85), 山水1 (楚先手, 大小: 60), 高原1 (后手, 大小: 55)梁敬彬:大王SQL之术,已臻炉火纯青之境。
4
寸土必争,利益倍增
嬴驷:胡先生,若双方心有不甘,不肯各自收兵,当如何处之?
胡傲华:驷公子不妨一试。
嬴驷:嗯...楚若不应秦之进攻,则遭双倍平原1之损,秦可增加=160地(80*2)。同理,秦若不应楚之进攻,则遭双倍平原2之损,楚可增加75*2=150之地(75*2),结果如下表。
如此一来,秦必较楚多占130而非120之地。看来双先相争不相让,反使秦之收益增加。秦可选择,楚则无选择之余地。似乎此第四次改良攻城之策方为最优。余悟矣,围棋收官遇双先,当思针锋相对之策。
胡傲华:驷公子聪慧过人,他日必成大器。
5
SQL再演,策略精进
-- 创建城池表(增加sb字段)
CREATE TABLE cities (
id NUMBER(5) PRIMARY KEY,
name VARCHAR2(50),
types VARCHAR2(10),
sizes NUMBER(5),
sb NUMBER(5)
);-- 插入城池数据,包括大小和二次利益
INSERT INTO cities (id, name, types, sizes, sb) VALUES (1, '平原1', '双先', 80, 160);
INSERT INTO cities (id, name, types, sizes, sb) VALUES (2, '平原2', '双先', 75, 150);
INSERT INTO cities (id, name, types, sizes, sb) VALUES (3, '草原1', '秦先手', 70, 0);
INSERT INTO cities (id, name, types, sizes, sb) VALUES (4, '草原2', '秦先手', 65, 0);
INSERT INTO cities (id, name, types, sizes, sb) VALUES (5, '山水1', '楚先手', 60, 0);
INSERT INTO cities (id, name, types, sizes, sb) VALUES (6, '山水2', '楚先手', 85, 0);
INSERT INTO cities (id, name, types, sizes, sb) VALUES (7, '高原1', '后手', 55, 0);
INSERT INTO cities (id, name, types, sizes, sb) VALUES (8, '高原2', '后手', 180, 0);
-- 初始化城池数据,为每个城池分配类型顺序和大小排名
WITH city_data AS (
SELECT
id, name, types, sizes, sb,
CASE
WHEN types = '双先' THEN 1
WHEN types = '秦先手' THEN 2
WHEN types = '楚先手' THEN 3
WHEN types = '后手' THEN 4
END AS type_order,
ROW_NUMBER() OVER (PARTITION BY types ORDER BY sizes DESC) AS size_rank
FROM cities
),
-- 计算战略选择所需的最大后手和楚先手城池大小
strategic_choice AS (
SELECT
id, name, types, sizes, sb, type_order,size_rank,
MAX(CASE WHEN types = '后手' THEN sizes ELSE 0 END) OVER () AS max_后手_size,
MAX(CASE WHEN types = '楚先手' THEN sizes ELSE 0 END) OVER () AS max_楚先手_size
FROM city_data
),
-- 确定每个城池的占领方和有效大小
capture_process AS (
SELECT
id, name, types, sizes, sb, type_order, size_rank,
CASE
-- 双先城池:秦占领第一个,楚占领第二个,之后交替分配
WHEN types = '双先' THEN
CASE
WHEN size_rank = 1 THEN'秦'
WHEN size_rank = 2 THEN'楚'
ELSE CASE WHEN MOD(size_rank, 2) = 1 THEN '秦' ELSE '楚' END
END
-- 秦先手城池:全部归秦
WHEN types = '秦先手' THEN '秦'
-- 后手城池:如果最大后手大于最大楚先手两倍,归秦
WHEN types = '后手' AND sizes = max_后手_size
AND max_后手_size > 2 * max_楚先手_size THEN '秦'
-- 楚先手城池:如果没有符合条件的后手城池,最大楚先手归秦
WHEN types = '楚先手' AND size_rank = 1 AND
max_后手_size <= 2 * max_楚先手_size THEN '秦'
-- 其余城池归楚
ELSE '楚'
END AS captured_by,
CASE
WHEN types = '双先' THEN sizes + sb -- 双先城池的有效大小为初始大小加双倍利益
ELSE sizes
END AS effective_size
FROM strategic_choice
)
-- 最终结果汇总
SELECT
captured_by AS category,
COUNT(*) AS count,
SUM(effective_size) AS total_size,
LISTAGG(name || ' ('|| types || ', 初始利益: '|| TO_CHAR(sizes) ||
CASE WHEN types = '双先' THEN ', 总利益: '|| TO_CHAR(sizes + sb) ELSE''END|| ')', ', ')
WITHIN GROUP (ORDER BY type_order, sizes DESC) AS cities
FROM capture_process
GROUP BY captured_by
ORDER BY
CASE WHEN captured_by = '秦' THEN 1 ELSE 2 END;
CASE
WHEN types = '双先' THEN sizes + sb -- 双先城池的有效大小为初始大小加双倍利益
ELSE sizes
END AS effective_size
此逻辑虑及双先城池额外之价值,取初始大小与二次利益相加为有效大小。双先城池之分配逻辑调整如下:
WHEN types = '双先' THEN
CASE
WHEN size_rank = 1 THEN '秦'
WHEN size_rank = 2 THEN '楚'
ELSE CASE WHEN MOD(size_rank, 2) = 1 THEN '秦' ELSE '楚' END
END
结果展示中包含总利益。于最终结果之 LISTAGG 函数中,对于双先城池,并示初始利益和总利益(包括二次利益):
CASE WHEN types = '双先' THEN ', 总利益: '|| TO_CHAR(sizes + sb) ELSE''END
CATEGORY COUNT TOTAL_SIZE CITIES
秦 4 555 平原1 (双先, 初始利益: 80, 总利益: 240), 草原1 (秦先手, 初始利益: 70), 草原2 (秦先手, 初始利益: 65), 高原2 (后手, 初始利益: 180)
楚 4 425 平原2 (双先, 初始利益: 75, 总利益: 225), 山水2 (楚先手, 初始利益: 85), 山水1 (楚先手, 初始利益: 60), 高原1 (后手, 初始利益: 55)6
棋道相通,治国有术
秦孝公:收获甚丰,胡先生可否绘制新之收官流程图,以助吾等深入领悟?
胡傲华:大王,围棋之道,玄妙无穷,远不止于此,逾4段之境,再难以流程图述之。棋道如人生,规则难穷尽,唯有勤加实践,方为正道。
秦孝公:棋之奥秘,果真非吾等所能尽探啊。
梁敬彬:大王。有一技,名曰人工智能(AI),必令大王大开眼界。
秦孝公:AI者,比SQL更为神妙乎?
梁敬彬:AI之核心在于深度神经网络,模仿人脑之结构,然规模更大、速度更快。应用于围棋时,AI以数百万次自我对弈为训,每局皆可调整其亿万参数,逐步优化决策能力。此法使AI从零开始自我学习,却能发现人类所未及之全新策略。经此锤炼,无人类可与之匹敌矣。
秦孝公:连胡先生亦无法胜之乎?
胡傲华:AI之棋技远胜于吾。
秦孝公:叹为观止,闻所未闻!
梁敬彬:AI不拘泥于固定规则,通过海量实践自行总结最优策略。此理念不仅用于棋艺,亦可应用于治国安邦。这恰如大王治国,应因时制宜,灵活应对。
秦孝公:妙哉!此理贯通棋道与治国之术,当真乃智慧至高境界。
梁敬彬:大王若有兴趣深究,可观此链接——小朋友都能懂的人工智能系列。
随即,胡傲华与梁敬彬起身告辞。秦孝公依依不舍,目送二人离去。
全剧终
小朋友都能懂的人工智能⓷ -惊世骇俗的狗故事 小朋友都能懂的人工智能⓸ -狗大师的修仙之路
小朋友都能懂的人工智能⓺ -注意,句中高能!
小朋友都能懂的人工智能⑪一滴墨汁成就一代画师
小朋友都能懂的人工智能⑫从画师到视频大师
小朋友都能懂的人工智能⑬AI时代,未来就业走势
数据库二十年目睹之怪现状⓵ 太!多!了!
数据库二十年目睹之怪现状⓶ 测评现形记
数据库二十年目睹之怪现状⓷ 隐蔽的套壳
数据库二十年目睹之怪现状⓸ 小黑入狱记
从12306改签困惑到数据库设计——高铁随记
从DTCC专场变换窥探数据库风云
从围棋收官到秦楚大战的数据库SQL实现(上)
从围棋收官到秦楚大战的数据库SQL实现(中)
12306业务系统升级也能被普通人推动?
为了和大家一起探索AI相关技术在大数据、数据资产管理、数据库、运维等领域的最佳落地方式,挖掘由此激发的软件发展和技术进步,第九届DAMS中国数据智能管理峰会将于2024年11月29日在上海举办,携手一众产学研界技术领跑单位,带来新思路、重实践、可落地的全日干货盛宴。
梁敬彬的议题为《数智化时代打造超融合数据库》
议题要点及收获:
超融合数据库的技术原理和实际应用
超融合数据库如何成为现代数据处理不可或缺的解决方案
超融合数据库的强大潜力和关键作用
欢迎报名,扫码或长按图中二维码,领取优惠。
预告:《超融合数据库》即将出版。