Advent Of Code 2022 第十三天 - 求救信号
本文是关于 Advent Of Code 2022 的。
编程圣诞日历,圣诞节前每天一个编程问题。
有兴趣的朋友可以在官网答题,用自己喜欢的编程方式去收集星星⭐️。在官网答题需要登陆并下载为你单独生成的谜题输入,每个人的都不一样。
问题
对动态类型列表进行解析和处理。
第一部分
你爬上山头,再次尝试与精灵们联系。然而,你却收到了一个你意想不到的信号:一个 求救信号 。
你的手持设备肯定还是工作不正常;求救信号的数据包被乱序解码了。你需要对收到的数据包列表(你的谜题输入)重新排序,以解码该信息。
你的列表由成对的数据包组成;成对的数据包之间有一个空行。你需要确定 有多少对数据包的顺序是正确的。
1 | [1,1,3,1,1] |
包数据由列表和整数组成。每个列表以[
开头,以]
结尾,并包含零个或多个逗号分隔的值(整数或其他列表)。每个数据包总是一个列表,并出现在自己的行中。
当比较两个值时:
- 如果 两个值都是整数 ,那么 低的整数 应该排在前面。如果左边的整数比右边的整数低,则输入的顺序是正确的。如果左边的整数比右边的整数高,输入的顺序就不对了。否则,输入是同一个整数;继续检查输入的下一个部分。
- 如果 两个值都是列表 ,比较每个列表的第一个值,然后是第二个值,依次类推。如果左边的列表先用完了项目,那么输入的顺序是正确的。如果右边的列表中的项目先用完,则输入的顺序不对。如果列表的长度相同,并且没有比较来决定顺序,继续检查输入的下一部分。
- 如果 正好有一个值是整数 ,就把这个整数转换成一个列表,其中包含这个整数作为它的唯一值,然后重试比较。例如,如果比较
[0,0,0]
和2
,将右边的值转换为[2]
(一个包含2
的列表);然后改用比较[0,0,0]
和[2]
的方法找到结果。
使用这些规则,你可以确定例子中的哪些对的顺序是正确的。
1 | == Pair 1 == |
已经 在正确顺序中 的一对的索引是多少?(第一对的索引是1,第二对的索引是2,以此类推。)在上面的例子中,正确顺序的一对是1,2,4和6;这些索引的总和是 13
。
确定哪些数据包对已经处于正确的顺序。 这些数据对的索引之和是多少?
第二部分
现在,你只需要把 所有 的数据包按正确的顺序排列。不考虑你的接收数据包列表中的空白行。
遇险信号协议还要求你包括两个额外的 分割器 数据包。
1 | [[2]] |
使用与之前相同的规则,将所有数据包(在你的接收数据包列表中的数据包以及两个分隔数据包),整理成正确的顺序。
在上面的例子中,将数据包按正确顺序排列的结果是。
1 | [] |
之后,找到分割器数据包。为了找到这个求救信号的 解码器密钥 ,你需要确定两个分割器数据包的索引,然后将它们相乘。(第一个数据包的索引是1,第二个数据包的索引是2,以此类推。)在这个例子中,分割器数据包是第 10 个和第 14 个,因此解码器密钥是 140
。
将所有的数据包整理成正确的顺序。 求救信号的解码器密钥是什么?
代码
完整的代码可以在 这里 找到。
1 | use std::cmp::Ordering; |
解析器
这里用了rust的 enum
来表达可以是列表也可以是数字。这里的处理方法就是在解析一个 json
的列表,递归对于每一层进行处理:
- 数字找到结尾之后放到
enum
中 - 列表当深度归零时代表找到了对应的开括号和关括号,将其递归处理。
第一部分
按照题目指示对 Packet
进行处理,并且在遇到列表时递归处理。
Option<bool>
所表达的意思是:
None
: 代表需要继续查询Some(true)
: 代表方向正确Some(true)
: 代表方向错误
第二部分
搞一个 Ord
的判断大小的 Trait
然后直接 sort
排序就好了。
运行时间
1 | Day 13 |