Advent of Code 2025 day8
嗯,用户让我总结一下这篇文章的内容,控制在一百个字以内。首先,我需要仔细阅读文章,理解它的主要部分。 文章分为两部分,Part1和Part2。Part1讲的是在三维空间中连接接线盒的问题。每个接线盒对应一个坐标点,精灵们用灯串连接它们,优先连接距离最近的点对。通过多次连接,点会被分组,形成不同的组。任务是在N次连接后找到前三个最大的组,并计算它们的乘积。 Part2则是在所有点都连接成一个大组后,找到最后一根连线的两个点的X坐标乘积。 用户的需求是用中文总结内容,不需要特定的开头,直接描述即可。所以我要抓住关键点:三维空间、最短距离、分组、乘积计算。 现在我要把这些信息浓缩到一百字以内。确保涵盖Part1和Part2的主要任务和目标。 </think> 文章描述了在三维空间中通过最短距离连接接线盒的问题。首先计算所有点之间的距离并排序,按规则进行N次连接分组,找到前三个最大的组并计算它们的乘积(Part1)。接着继续连线直到所有点连成一个组,找到最后一根连线并计算两个点X坐标的乘积(Part2)。 2025-12-8 07:43:0 Author: taxodium.ink(查看原文) 阅读量:0 收藏

day8 的输入是:

162,817,812
57,618,57
906,360,560
592,479,940
352,342,300
466,668,158
542,29,236
431,825,988
739,650,466
52,470,668
216,146,977
819,987,18
117,168,530
805,96,715
346,949,466
970,615,88
941,993,340
862,61,35
984,92,344
425,690,689

每一行对应一个三维空间的坐标点,例如 162,817,812 表示的是 X=162,Y=817,Z=812 的一个点。

在谜题里,每个点对应的是一个 接线盒,精灵们会用灯串连接接线盒,当两个接线盒通过一串灯连接时,电流可以在这两个接线盒之间通过。但是精灵们的灯串不够多,所以他们希望专注于连接那些 直线距离 尽可能靠近的接线盒对。

换句话说,在空间里有很多个点,需要计算每个点之间的距离,优先连接距离短的两个点。按照这样的规则,连接几次后,可能某几个点会连成一组,另外几个点也会连成一组。

例如在上面的例子里:

  • 162,817,812 和 425,690,689 距离最短,它们连接在一起。形成了一个组 [162,817,812, 425,690,689]
  • 接下来,距离最短的是 162,817,812 和 431,825,988,把它们连在一起。又发现 162,817,812 已经和另一个点连接了,所以这三个点都连在了一起,形成了 [162,817,812, 425,690,689, 431,825,988]
  • 接下来距离最短的是 906,360,560 和 805,96,715。形成了 [906,360,560, 805,96,715]
  • 接下来距离最短的是 431,825,988 和 425,690,689。它们已经连在一起了,在 [162,817,812, 425,690,689, 431,825,988] 之中。
  • 依次类推
  • 在这个例子中,做 10 次连接之后,会得到:
    • 一个包含 5 个点的组、一个包含 4 个点的组、两个包含 2 个点的组,以及七个包含 1 个点的组

part1 的问题是,按照最短距离连线 N 次后,找到前三个点的数量最多的组,获取这三个组中点的数量,计算它们的乘积。

在上面的例子中,分别是 5、4、2,乘积是 40。


part1 的思路是:

  1. 首先计算所有点之间的距离,存储在一个数组中,数组的每一个元素记录一对点的坐标、两点之间的距离
  2. 数组按照两点距离升序排序,截取前 N 个数据
  3. 遍历这 N 个数据,获取每一对点的坐标,对它们进行连接分组:
    • 如果两个点不在任何分组中,则把它们归类到一个新的分组
    • 如果两个点都在已有的分组中,且是同一个分组,什么都不用做
    • 如果两个点都在已有的分组中,但所在的分组不一样,合并这两个分组
    • 如果只有一个点在已有的分组中,则把另一个点加入到这个分组中
  4. 按照分组中的点的数量降序排序,获取点的数量最多的前 3 个分组,获取分组中点的数量,计算乘积

由于示例中没有给出最终分组的情况,我无法验证我连接分组做的对不对。所以我先计算了所有点的距离并排序,例如这是我处理得到的数据:

{
('162,817,812', '425,690,689'): 316.90219311326956,
('162,817,812', '431,825,988'): 321.560258738545,
('906,360,560', '805,96,715'): 322.36935338211043,
('431,825,988', '425,690,689'): 328.11888089532425,
('862,61,35', '984,92,344'): 333.6555109690233,
('52,470,668', '117,168,530'): 338.33858780813046,
('819,987,18', '941,993,340'): 344.3893145845266,
('906,360,560', '739,650,466'): 347.59890678769403,
('346,949,466', '425,690,689'): 350.786259708102,
('906,360,560', '984,92,344'): 352.936254867646,
('592,479,940', '425,690,689'): 367.9823365326113,
('352,342,300', '542,29,236'): 371.70552861102294,
('352,342,300', '117,168,530'): 372.02284876066415,
('352,342,300', '466,668,158'): 373.41130138226936,
...
}

('162,817,812', '425,690,689'): 316.90219311326956 的意思是 162,817,812 和 425,690,689 的直线距离是 316.90219311326956。

然后按照规则,对点进行分组:

格式说明

第 N 次连线:当前连线的点 (备注)
分组1
分组2
分组3

例如:

3: '906,360,560', '805,96,715'
'162,817,812', '425,690,689', '431,825,988'
'906,360,560', '805,96,715'

表示第 3 次连线,当前连线的两个点是 '906,360,560', '805,96,715'。

连线后,形成了 2 个分组:

  • 分组 1: '162,817,812', '425,690,689', '431,825,988'
  • 分组 2: '906,360,560', '805,96,715'
1: '162,817,812', '425,690,689'
'162,817,812', '425,690,689'

2: '162,817,812', '431,825,988'
'162,817,812', '425,690,689', '431,825,988'

3: '906,360,560', '805,96,715'
'162,817,812', '425,690,689', '431,825,988'
'906,360,560', '805,96,715'

4: '431,825,988', '425,690,689' (没有变化)
'162,817,812', '425,690,689', '431,825,988'
'906,360,560', '805,96,715'

5: '862,61,35', '984,92,344'
'162,817,812', '425,690,689', '431,825,988'
'906,360,560', '805,96,715'
'862,61,35', '984,92,344'

6: '52,470,668', '117,168,530'
'162,817,812', '425,690,689', '431,825,988'
'906,360,560', '805,96,715'
'862,61,35', '984,92,344'
'52,470,668', '117,168,530'

7: '819,987,18', '941,993,340'
'162,817,812', '425,690,689', '431,825,988'
'906,360,560', '805,96,715'
'862,61,35', '984,92,344'
'52,470,668', '117,168,530'
'819,987,18', '941,993,340'

8: '906,360,560', '739,650,466'
'162,817,812', '425,690,689', '431,825,988'
'906,360,560', '805,96,715','739,650,466'
'862,61,35', '984,92,344'
'52,470,668', '117,168,530'
'819,987,18', '941,993,340'

9: '346,949,466', '425,690,689'
'162,817,812', '425,690,689', '431,825,988','346,949,466'
'906,360,560', '805,96,715','739,650,466'
'862,61,35', '984,92,344'
'52,470,668', '117,168,530'
'819,987,18', '941,993,340'

10: '906,360,560', '984,92,344' (合并了两个分组)
'162,817,812', '425,690,689', '431,825,988','346,949,466'
'906,360,560', '805,96,715','739,650,466', '862,61,35', '984,92,344'
'52,470,668', '117,168,530'
'819,987,18', '941,993,340'

通过这样的过程,我验证了整个分组过程,也是在这个过程中发现了我忽略的一个细节,即分组之间可能会合并。

具体的代码见:day8/solution.py

用少量的数据,验证逻辑,观察规律,有助于找到思路。

分组的代码我折腾了很久才写出来,因为我在遍历的过程中修改了被遍历的数组,产生了很多混乱,后来把查找和修改两个动作分开,逻辑才清晰了。


part2 的问题是,一直连线,最后所有的点都会连接在一起,找到最后的那根连线,获取连线上两个点的 X 坐标,计算两个 X 坐标的乘积。

所有点都连接在一起,意味着最终只会有一个分组,且分组中包含所有的点。

完成 part1 后,part2 就很简单了,只需要在每次连线之后,判断当前是否只有一个分组,且分组中点的数量等于所有点的数量。当找到这样的连线,就返回对应的两个点,获取点的 X 坐标,计算乘积即可。

具体的代码见:day8/solution.py


文章来源: https://taxodium.ink/aoc-2025-day-8.html
如有侵权请联系:admin#unsafe.sh