用SQL求解advent of code 2024年23题

原题地址 https://adventofcode.com/2024/day/23

第 23 天:局域网派对

当历史学家们在复活节兔子总部的安全区域闲逛时,你发现了今天计划举行的局域网派对的宣传海报!或许你能找到它;你连接到一个附近的数据链路端口,并下载了本地网络的地图(你的谜题输入)。

网络地图提供了每两台计算机之间的连接列表。例如:

复制代码
kh-tc
qp-kh
de-cg
ka-co
yn-aq
qp-ub
cg-tb
vc-aq
tb-ka
wh-tc
yn-cg
kh-ub
ta-co
de-co
tc-td
tb-wq
wh-td
ta-ka
td-qp
aq-cg
wq-ub
ub-vc
de-ta
wq-aq
wq-vc
wh-yn
ka-de
kh-ta
co-tc
wh-qp
tb-vc
td-yn

网络地图中的每一行文本代表一个连接;例如,行 kh-tc 表示名为 kh 的计算机和名为 tc 的计算机之间的连接。连接是无方向的;tc-kh 表示的意思完全相同。

局域网派对通常涉及多人游戏,所以也许你可以通过查找连接的计算机群来定位它。首先查找由三台计算机组成的集合,其中集合中的每台计算机都与其他两台计算机相连。

在这个例子中,有 12 个这样的三台互连计算机的集合:

复制代码
aq,cg,yn
aq,vc,wq
co,de,ka
co,de,ta
co,ka,ta
de,ka,ta
kh,qp,ub
qp,td,wh
tb,vc,wq
tc,td,wh
td,wh,yn
ub,vc,wq

如果首席历史学家在这里,并且他在局域网派对上,最好能马上知道。你相当确定他的计算机名称以 t 开头,因此只考虑那些至少有一台计算机名称以 t 开头的三台计算机集合。这将列表缩小到 7 个三台互连计算机的集合:

复制代码
co,de,ta
co,ka,ta
de,ka,ta
qp,td,wh
tb,vc,wq
tc,td,wh
td,wh,yn

找出所有三台互连计算机的集合。其中有多少个集合包含至少一台名称以 t 开头的计算机?

要开始,请获取你的谜题输入。


第二部分

结果还是太多,无法逐一查看。你必须用另一种方法找到局域网派对并亲自前往。

既然看起来没有任何员工在附近,你推测他们一定都在局域网派对上。如果真是这样,那么局域网派对将是所有计算机都相互连接的最大计算机集合。也就是说,对于局域网派对上的每台计算机,该计算机都与派对上的其他每台计算机有连接。

在上面的例子中,所有计算机都相互连接的最大集合由 co, de, kata 组成。该集合中的每台计算机都与集合中的其他每台计算机有连接:

复制代码
ka-co
ta-co
de-co
ta-ka
de-ta
ka-de

局域网派对的宣传海报上说,进入局域网派对的密码是派对上每台计算机的名称,按字母顺序排序,然后用逗号连接起来。(显然,运营局域网派对的是一群书呆子。)在这个例子中,密码将是 co,de,ka,ta

进入局域网派对的密码是什么?

我的解答如下

sql 复制代码
--第一部分

with tt as (from read_csv('2423-input.txt',header=0, delim='-')t(a, b) )
, tl as (from(select a, b from tt union all select b, a from tt) where a<b)
select distinct  t.a,t1.a,t1.b from tl t,tl t1 
where t.b=t1.a and
( t.a like 't%' or t1.a like 't%' or t1.b like 't%' )
and (t.a,t1.b) in (from  tl)
;
--第二部分

with recursive tt as (from read_csv('2423-input.txt',header=0, delim='-')t(a, b) )
, tl as (from(select a, b from tt union all select b, a from tt) where a<b)
,t as(select 1 lv,b, [a, b]g from tl
union all 
select distinct lv+1, tl.b, g||[tl.b]from t, tl where t.b=tl.a and len(g)= (select count(*) from unnest(g)g(b) where(g.b , tl.b)in(from  tl))
)
select listagg(g)from(select unnest(g)g from t where lv =(select max(lv) from t));

思路是从网络地图中提取出按机器名大小排列的连接列表,从此列表按照新增首部等于已有尾部多次递归连接,并检查新加入的机器满足和已有网络中每台机器都连接。

将检查条件len(g)= (select count(*) from unnest(g)g(b) where(g.b , tl.b)in(from tl))改为 not exists(select 1 from unnest(g)g(b) where(g.b , tl.b) not in(from tl))也可得到结果,效率都不太高。

相关推荐
We་ct2 小时前
LeetCode 5. 最长回文子串:DP + 中心扩展
前端·javascript·算法·leetcode·typescript
王老师青少年编程6 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【哈夫曼贪心】:合并果子
c++·算法·贪心·csp·信奥赛·哈夫曼贪心·合并果子
Flying pigs~~6 小时前
RAG智慧问答项目
数据库·人工智能·缓存·微调·知识库·rag
叼烟扛炮6 小时前
C++第二讲:类和对象(上)
数据结构·c++·算法·类和对象·struct·实例化
天疆说6 小时前
【哈密顿力学】深入解读航天器交会最优控制中的Hamilton函数
人工智能·算法·机器学习
misL NITL7 小时前
mysql之如何获知版本
数据库·mysql
许彰午7 小时前
CacheSQL(二):主从复制——OpLog 环形缓冲区与故障自动恢复
java·数据库·缓存
wuweijianlove7 小时前
关于算法设计中的代价函数优化与约束求解的技术7
算法
leoufung8 小时前
LeetCode 149: Max Points on a Line - 解题思路详解
算法·leetcode·职场和发展
样例过了就是过了8 小时前
LeetCode热题100 最长公共子序列
c++·算法·leetcode·动态规划