使用DuckDB SQL求解Advent of Code 2024第17题

题目原始地址 https://adventofcode.com/2024/day/17

第 17 天:时空计算机

历史学家们按下了他们那个奇怪设备上的按钮,但这一次,你们都只觉得像是在下坠。

"情况危急,"设备用一个熟悉的声音宣布。“引导过程失败。正在初始化调试器……”

那个小型手持设备突然展开,变成了一整台计算机!历史学家们紧张地环顾四周,然后其中一人把它扔给了你。

这似乎是一台 3 位计算机:它的程序是一个 3 位数字(0 到 7)的列表,例如 0,1,2,3。计算机还有三个名为 A、B 和 C 的寄存器,但这些寄存器不受 3 位限制,可以存储任何整数。

计算机知道八条指令,每条指令由一个 3 位数字(称为指令的操作码)标识。每条指令还读取其后的一个 3 位数字作为输入;这被称为它的操作数。

一个称为指令指针的数字标识了程序中下一个操作码将被读取的位置;它从 0 开始,指向程序中的第一个 3 位数字。除了跳转指令外,每条指令处理完毕后,指令指针增加 2(以越过指令的操作码及其操作数)。如果计算机试图读取程序结束之后的操作码,则改为停止运行。

因此,程序 0,1,2,3 将运行操作码为 0 的指令并传递操作数 1,然后运行操作码为 2 的指令并传递操作数 3,然后停止。

操作数有两种类型;每条指令规定其操作数的类型。字面操作数的值就是操作数本身。例如,字面操作数 7 的值就是数字 7。组合操作数的值可以按如下方式找到:

  • 组合操作数 0 到 3 代表字面值 0 到 3。
  • 组合操作数 4 代表寄存器 A 的值。
  • 组合操作数 5 代表寄存器 B 的值。
  • 组合操作数 6 代表寄存器 C 的值。
  • 组合操作数 7 被保留,不会出现在有效程序中。

八条指令如下:

  • adv 指令(操作码 0) 执行除法。分子是寄存器 A 中的值。分母是通过将 2 提升到指令的组合操作数的幂来找到的。(因此,操作数为 2 会将 A 除以 4 (2^2);操作数为 5 会将 A 除以 2^B。)除法运算的结果被截断为整数,然后写入寄存器 A。

  • bxl 指令(操作码 1) 计算寄存器 B 与指令的字面操作数的按位异或,然后将结果存储在寄存器 B 中。

  • bst 指令(操作码 2) 计算其组合操作数对 8 取模的值(从而仅保留其** 3 位),然后将该值写入寄存器 B。

  • jnz 指令(操作码 3) 如果寄存器 A 为 0,则不执行任何操作。但是,如果寄存器 A 不为零,则通过将指令指针设置为其字面操作数的值来进行跳转;如果此指令跳转,则指令指针在此指令执行后不增加 2。

  • bxc 指令(操作码 4) 计算寄存器 B 和寄存器 C 的按位异或,然后将结果存储在寄存器 B 中。(由于历史原因,此指令读取操作数但忽略它。)

  • out 指令(操作码 5) 计算其组合操作数对 8 取模的值,然后输出该值。(如果程序输出多个值,它们用逗号分隔。)

  • bdv 指令(操作码 6) 工作方式与 adv 指令完全相同,只是结果存储在寄存器 B 中。(分子仍然从寄存器 A 读取。)

  • cdv 指令(操作码 7) 工作方式与 adv 指令完全相同,只是结果存储在寄存器 C 中。(分子仍然从寄存器 A 读取。)

以下是一些指令操作的示例:

  • 如果寄存器 C 包含 9,程序 2,6 会将寄存器 B 设置为 1。
  • 如果寄存器 A 包含 10,程序 5,0,5,1,5,4 会输出 0,1,2
  • 如果寄存器 A 包含 2024,程序 0,1,5,4,3,0 会输出 4,2,5,6,7,7,7,7,3,1,0 并在寄存器 A 中留下 0。
  • 如果寄存器 B 包含 29,程序 1,7 会将寄存器 B 设置为 26。
  • 如果寄存器 B 包含 2024 且寄存器 C 包含 43690,程序 4,0 会将寄存器 B 设置为 44354。

历史学家的奇怪设备已经完成了其调试器的初始化,并正在显示有关它试图运行的程序的一些信息(你的谜题输入)。例如:

Register A: 729
Register B: 0
Register C: 0

Program: 0,1,5,4,3,0

你的首要任务是确定程序试图输出什么。为此,将寄存器初始化为给定值,然后运行给定程序,收集由 out 指令产生的任何输出。(始终用逗号连接 out 指令产生的值。)在上述程序停止后,其最终输出将是 4,6,3,5,6,3,5,2,1,0

使用调试器提供的信息,将寄存器初始化为给定值,然后运行程序。一旦它停止运行,如果你用它输出的值并用逗号连接成一个字符串,你会得到什么?

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值