谜题提示/技巧与解法(无剧透)

0 点赞
Silicon Zeroes
转载

帮助你独立解决(大部分)谜题的小贴士,不含剧透。网上很容易找到直接告诉你答案的攻略,但那样就没意思了。 无剧透引言 本指南面向那些不想直接被告知答案,而希望自己解开谜题的玩家。也许你只是卡关了,需要一点小小的提示! 通用提示:你应该仔细阅读谜题描述。每段描述都经过精心编写,提供了解决方案的线索以及从何处开始研究或操作。接下来,查看可用的模块(因为它们通常会根据谜题而变化),然后检查【内存】选项卡(如果有的话),了解其初始值和预期值,以及示例测试(如果有的话)。以下每个部分都由若干提示组成,每个提示单独分隔。查看第一行/第一个提示时,只会显示第一个,而非整个区块。这些提示一开始会比较模糊,之后会逐渐增加细节,这样你可以一次获得一点帮助,并有望自己发现其余内容。 下方的顺序大致对应一条良好的“基于先前解决方案进行构建”的路线。随着游戏深入,通常会出现分支和并行路径,然后是多个电路板。这让你可以跳着尝试不同的谜题,但后期的谜题往往建立在早期学到的简单知识基础上,所以尽量不要跳过太多内容。你可以立刻尝试构建完整的CPU,但如果先理解了加法器、寄存器、内存等知识会更好。首先,这可能会简单得多。 我不一定在寻找最优解(低于目标模块数量),只是那些人们容易理解的方案。其他人和攻略已经涵盖了“最佳”角度。 如果你最终查看所提供的解决方案(没关系!),我已尽量将线路布置得清晰易懂以便复制,而不是尽可能密集。为此,有时(但不总是)我会对直接相连的输入/输出进行颜色编码,以便一眼就能看明白。 【电路板1:开端】 前提条件:无!这是游戏中的第一个电路板。

【连线★】 前置条件:无!这是游戏中的第一个谜题。 目标:2个模块 连接那些麻烦的线路! 你无需添加任何模块即可获得完美解决方案,只需连接线路。 解决方案:

多线连接 ★ 前置要求:完成“线路连接”关卡。 目标:2个模块 连接那些麻烦的线路! 你无需添加任何模块即可获得完美解决方案,只需连接线路。 解决方案:

放置★ 前置条件:完成“多重布线”。 目标:3个模块 看看你可以使用哪些模块。限制能激发创造力! 你不能添加任何数字模块,只能使用加法器模块。 你也不能修改数字模块,所以它始终锁定为1。 一个加法器模块,其两个输入都连接到数字模块,就能得到2。已经完成一半了…… 如果你再这样做一次,最终会得到两个都输出2的加法器。再添加一个加法器,你应该就能解决问题了。 你能减少一个加法器来获得完美解决方案吗?你将数字模块的输出连接到了一个加法器的两个输入…… 用一个加法器输出2,然后将该输出使用两次…… 解法:

配置★ 前置条件:完成“放置”关卡。 目标:2个模块 按照指示操作! 连接那些麻烦的线路! 将数字配置为有用的数值。 解决方案:

模块 ★ 前置条件:完成“配置”关卡。 目标:3个模块 你可以使用数字模块和加法器模块。 需要加法器输出5。 所以选择任意相加等于5的输入…… 由于5是奇数,你不能使用之前将一个数字连接到加法器两个输入的解决方案…… 解决方法:

记忆★ 前置条件:完成“模块”关卡。 目标:2个模块 你拥有一个读取器模块,需要让它输出6。 查看右侧的【内存】标签页,看看能否找到有用的值。 在那里找到6了吗?现在要把它取出来…… 6在哪个地址? 将该地址加载到读取器模块中…… 解法:

Memsum ★★ 前置条件:完成“Memory”关卡。 目标:使用6个模块 我们无法添加或编辑任何数字,因此只能使用3作为唯一常量。 我们需要一个加法器输出7。不能直接使用3,那么从哪里能得到7呢? 你能否通过查看内存标签找到得到7的方法? 内存中有一些数值相加可以得到7,但如何读取它们呢? 我们需要从内存中读取两个数值,所以需要两个读取器模块。 如何将内存地址输入读取器模块以使其输出正确数值? 首先读取内存中的5——它位于哪个地址?如何使用我们的数字模块得到6? 现在读取内存中的2——它位于哪个地址?如何使用我们已提取的数值得到8?记住,输出通常可以连接到多个输入……现在我们有3、6、5、8和2这几个输出。该把它们相加得到7了!解决方法:

【时间】★ 前置条件:完成【记忆总和】。 目标:4个模块 你无法编辑面板,因此点击底部的测试按钮,让解决方案运行。 【锁存器】★ 前置条件:完成【时间】。 目标:2个模块 你只有两个模块可进行实验:数字和锁存器。 你需要锁存器输出15,因此将其连接到输入... 解决方案:

撰写者★ 前置条件:完成“Latch”关卡。 目标:3个模块 你只有两个模块可以使用:数字模块和撰写者模块。 写入地址和写入值均为常量。 因此,将一些常量连接到撰写者模块…… 解法:

停滞 ★★ 前置条件:完成“写入器”关卡。 目标:使用3个模块 你只能在面板上添加两种模块:数字模块和锁存器模块。 查看“良好记忆”标签页可了解预期输出:地址0和地址1均需设为1。 你只有一个写入器模块,因此不能仅使用数字常量。 写入的值始终为常量。 但地址会从0变为1。 锁存器模块初始状态始终为0…… 解决方案:

重写 ★★ 前提条件:完成“Writer”关卡。 目标:使用4个模块 面板上已有一个加法器模块,且无法再添加更多加法器。 我们只能添加数字、读取器和写入器模块。 但数字模块的数值固定为1…… 我们需要向内存槽1写入数字8。 当前该内存槽的数值似乎为0。 只要最终数值为8,我们可以对内存槽进行任意次数的读写操作。 那么,如果只有固定为1的数字模块,以及初始值为0且可读写的内存槽,如何得到8呢? 描述文本中提供了累加至目标值的提示。 这似乎需要某种反馈循环。 在面板上放置一个读取器和一个写入器。 读取器和写入器模块只会访问地址1,因此配置这些输入应该很简单。现在我们该如何连接读取器输出、加法器和写入器输出呢? 我们需要加法器依次输出1、2、3、4、5…… 这些输出应该写入到哪里呢? 解决方案:

计数器 ★★ 前置条件:完成“写入器”谜题。 目标:使用4个模块 注意:先解决“延迟”和“重写”谜题会有所帮助,因为你会更熟悉所使用的模块。 注意:记住这个解决方案,因为你在未来的谜题中会经常用到它的变体。你也可以在谜题之间复制粘贴! 面板上只有一个写入器模块,且我们无法添加更多。 我们只能添加数字、加法器和锁存器模块。 我们需要向地址0输出0,向地址1输出1,向地址2输出2,以此类推…… 所以我们只需要生成一个数字流。 这应该能让写入器模块的配置更简单。 但我们如何输出这个数字流呢? 我们需要一个反馈循环,但不能使用内存(没有读取器模块可用)。锁存器模块初始值为0,并会将前一个数值记忆一个周期…… 那么我们能否使用这三个模块创建一个反馈回路呢? 我们需要一个加法器…… 我们需要为加法器提供一个常量输入。解决方案需要用到1、2、3、4……这样数字值就很容易猜到了。 我们该如何将剩余部分连接到锁存器模块呢? 记住,锁存器的输出可以连接到多个模块。 解决方案:

验证★ 前置条件:完成“计数器”关卡。 目标:4个模块 注意:此处的用户界面可能有点令人困惑。当你点击“测试”标签时,它会显示“验证中...”,然后停在失败的测试上(带有闪烁的红色文本)。你需要忽略这个,点击底部的“开始”按钮来让它实际运行。一旦完成,你将获得解开谜题的奖励。 阅读描述后,查看右侧“内存”标签中的可用测试。总共有3个测试,每个测试都有不同的初始内存值和最终预期/正确值。 你能发现初始内存值和正确内存值之间可能存在的关系吗? 想出一个对前两个测试有效的简单代数方程,但对第三个测试无效。这个等式会非常简单 :) 你已经有两个操作数了,所以只需弄清楚运算方式,以及还能加入什么。 你可以使用数字模块、加法器模块、读取器模块和写入器模块。 你有没有发现一个可能有2个输入、1个输出并执行某种数学运算的模块? 你应该已经得出等式:【内存 #0】= 2 *【内存 #0】。 你想要乘以2,但你只有一个加法器…… 一旦你有了加法器,就需要读取和写入内存。但地址是什么呢? 将读取器连接到加法器作为输入…… 将加法器连接到写入器作为输入…… 解决方案:

Increment ★★ 前置要求:完成“Counter”。 目标:6个模块 任务分解:你需要完成哪些不同的操作? 你需要从内存槽#0开始处理内存。听起来像是之前的一个谜题…… 先从“Counter”的解决方案入手。 现在你可以访问从#0开始及以上的内存槽,但你要用它们做什么呢? 你需要将每个槽的值设置为其原始值加一,那么该如何分解这个任务呢? 首先,你需要一个读取器来获取原始值…… 然后,你需要一个加法器来给原始值加一…… 然后,你需要一个写入器来保存结果。 将它们连接起来,你应该就能完成了。 解决方案:

备用方案 ★★ 前置要求:完成“写入器”关卡。 目标:使用5个模块 看看你可以使用哪些模块。限制往往能激发创造力! 正如描述中所说,你无法使用任何数字模块或地址模块。情况开始变得棘手了。 根据描述,你在这里需要做什么? 你需要将内存槽#0中的数值翻倍,那么需要哪些模块呢? 通常我们需要一个读取器、一个加法器和一个写入器。 先专注于第一部分:如何读取槽#0? 读取器模块需要一个输入:内存地址。我们想要读取地址#0,但没有数字模块。 仔细查看模块,看看是否有其他方法可以获得#0输入。试着将模块放置在面板上仔细检查。 锁存器模块有一个恒定的0输出!那么将一个锁存器模块连接到读取器模块,现在我们就能读取到43了。但如何在没有加法器模块的情况下将43翻倍得到86呢?回想一下基本的加减法规则。你现在有哪些常量作为输入?你有0(来自锁存器)和43(读取器的输出)。如果将它们相减,能得到什么?列出不同的组合及其结果。只会有4种可能的算式哦。43减0等于43,但我们已经有43了,所以这似乎没什么用。0减0等于0,43减43也等于0,可我们已经有0了,这同样没什么用。那就只剩下0减43等于-43了。现在你有三个常量可以作为另一个减法模块的输入。用这些常量又能得到什么呢?再次列出所有的组合及其结果吧。现在只有9种可能的方程(其中4种你之前已经得到了)。 忽略那些能得出你已有的三个常数的方程。这样应该能筛选出两种可能的方程…… -43减43等于-86,这和你想要的结果很接近。还记得负数的减法规则吗? 43减负43等于86!现在把这些连接起来并写出结果。 答案:

奶牛 ★★★ 前置要求:无!此谜题在第一个面板上即可立即使用。 目标:10个模块 注意:如果你一开始想跳过这个,在完成第二个面板后再回来做,也是可以的!到那时,你会更熟悉各种模块以及使用它们的技巧。这个谜题不需要按照特定顺序与其他谜题完成。 仔细阅读描述一到两遍,理解你需要做什么。 这就像中学时的数学题,对吧?提炼出重要信息,忽略所有无关细节。 你可以尝试计算每年的预期奶牛数量,甚至编写程序来计算(给技术宅加分),或者你可以直接查看【良好记忆】视图来获取该列表。如果盯着数字看无法启发你想到算法,那就再看看描述。页面上有没有你第一次没注意到的文字? 找找像你在板子上看到的那种铅笔写的文字。 你应该已经找到了这个等式:f(x) = f(x-1) + f(x-3)。这可以计算出每年的奶牛数量(其中x是当前年份)。你可以在良好记忆视图中试一下,让自己确信这一点。 尝试用你可用的模块自己实现这个算法。现在先采用直接明了的解决方案。 你需要从内存槽0开始处理内存。如果你通过了第一个板子,这应该听起来很熟悉。 从“计数器”获取你的解决方案开始。 是不是在尝试读取未初始化或无效的内存(比如-1或-3)并将它们相加时遇到了困难?如果你通过了第二关,先尝试解决【Nil】谜题。 能否用等于模块以有趣的方式检测这种情况? 等于模块可以让你检测空值,但不容易将它们相加…… 是否有其他模块可以处理无效/有效状态之间的转换? 锁存器模块看起来很有趣…… 如果你已经进展到更远的地方,可能仍然会遇到读取器模块在使用锁存器模块时过早或过晚访问值的问题。无论你在其中放置多少个,似乎仍然会不同步。也许这需要一种完全不同的方法? 考虑一下:是否有可以用作存储单元的模块? 仔细查看你可用的模块。哪个模块可以将上一个周期的值保存到下一个周期? 锁存器模块看起来很有意思…… 那么看看之前的公式,你需要自行处理多少个存储单元? 你能将它们设置为自动级联吗? 现在你能在将值反馈回去之前,在正确的时机取出该值吗? 或许可以专注于公式的前半部分:f(x) = f(x-1)。你能让这部分在最初的3年正常工作吗? 你应该已经将【计数器】连接到写入器模块的地址。此时可以暂时忽略这些模块,因为解决这个谜题不需要用到它们。 你应该用一个锁存器连接到加法器模块,形成反馈回路,并连接到写入器模块的值输入。还在琢磨初始年份锁存器输出为0的问题吗?再试试等于模块…… 你可以将锁存器的输出与0进行比较,这样等于模块就会仅输出一次1。 现在,你应该已将锁存器和等于模块连接到反馈回路中的加法器模块。这应该足以连接到写入器模块,以处理前三年的数据。 那么,如何扩展它来处理方程后半部分的f(x-3)呢? 如果你现在的锁存器代表当前的单个存储单元,如何扩展它以增加两个存储单元呢? 将三个锁存器模块串联起来。这样应该能让最近的3个值依次传递。 如何将f(x-3)连接到写入内存前的现有输出呢?如何将完整计算结果连接回反馈循环? 希望你放置了另一个加法器模块,将现有的加法器输出与f(x-3)锁存器输出组合起来。这样应该足以得到一个可行的解决方案。 嗯,但你的模块数量超过目标要求了?就多了一个模块! 似乎几乎每个模块都是必需的,无法删减。不过再看看等于模块。 它现在是如何测试以确定初始状态的?它是否在比较0和锁存器模块的初始输出?你能否用其他方式测试初始状态? 到目前为止,你忽略了组成“计数器”的模块…… 这些模块中是否有一些输入/输出,你可以测试并且只在初始年份传递信号? 解决方案:

【第二关:中央处理器】 前置条件:完成第一关(“递增”)

【调色板 ★★】 前置要求:完成第一关(“递增”)。 目标:4个模块 注意:记住这个解决方案,因为你在未来的谜题中会经常用到它的变体!在未来的谜题中使用它不会被视为剧透,所以一定要记住并识别这个简单的模式。 注意:(解决此谜题后。)如果你不喜欢你创建的条目,可以将其从调色板中移除。右上角的红点就是用来删除的。 注意:(解决此谜题后。)你可以为每个调色板条目添加描述,方便自己使用。点击每个条目下方的“组 #”文本即可编辑。 阅读说明,它会准确解释你需要做什么。 看看底部的工具栏,有没有什么新东西?希望你注意到那个闪烁的按钮了。那是【调色板】功能! 将鼠标悬停在按钮和子菜单上,可以查看更多关于其工作方式的说明。 现在尝试使用它似乎无法正常工作。 再仔细看看说明,了解可以在哪里使用它…… 回到第一块板子上的“计数器”谜题。 你需要在那里使用【调色板】功能来复制可见的模块。 首先要选择所有模块,然后使用【调色板】功能在菜单中创建一个新条目。 回到“调色板”谜题,粘贴刚才复制的那组模块。 连接所有线路,使解决方案看起来与“计数器”中的一致。 解决方案:

【Deref ★★】 前置条件:完成【Palette】关卡。 目标:使用6个模块。 仔细阅读描述,理解任务要求。 如果你熟悉C/C++语言,这相当于实现一个指针功能! 首先,你需要一个能从地址0开始更新内存中每个地址的模块。 利用调色板功能,从你在【Counter】关卡的解决方案开始。 你需要读取当前地址的值…… 然后用该值读取另一个地址以获取目标值…… 接着将这个目标值写回原始地址。 你需要将两次读取和一次写入模块连接起来…… 将这三个模块放置到面板上并进行连线! 解决方案:

【零值】★★ 前置条件:完成【解引用】。 目标:7个模块 首先,你需要能从地址0开始更新内存中的每个地址。 使用调色板功能,从你解决【计数器】时的方案开始。 尝试构建一个基本能实现描述中功能的方案:读取内存中的每个值并写入内存中的每个值。此时不必担心其他方面是否正确。 现在你已经将【计数器】链接到读取器模块,读取器模块链接到写入器模块,还剩下什么呢? 重新查看描述后,看看你可以使用哪些模块。 那个新的输入选择器控制模块是什么?它是如何工作的?可以稍微试用一下。注意,输入选择器用于确定多个输入中的哪一个连接到输出线路。 当输入选择器的值不是0或1时会发生什么?输出线路会显示什么? 如果你尝试将那个【无】写入内存,会发生什么? 现在尝试使用输入选择器修改从内存读取的值,然后再将其写回。 任务要求你在写回前只更改一个值…… 如果你只连接输入#1(不连接输入#0),但输入选择线路被设置为1以外的值(例如0、2、3、7等),输出线路会被设为【-】(也就是【无】)。 当地址输入有效但值输入(【待写入】)为【无】时,写入器模块会做什么? 写入器模块会什么都不做!写入该内存地址的操作会被跳过!现在将所有部分整合起来……解决方案:

【多路复用器 ★★】 前置条件:完成“从零开始”关卡。 目标:7个模块 首先,你需要能从内存地址0开始更新每个地址的组件。 使用调色板功能,从你“计数器”关卡的解决方案开始。 现在再读一遍描述。本谜题的重点是教你输入选择器的使用,所以没有什么技巧。直接按要求实现即可。 谜题开始时你有哪些输入可用?随着模块执行,又会有哪些输入可用? “计数器”会依次输出0、1、2…… 将其与输入选择器配合使用。 右键点击输入选择器模块,确保至少有4条输入线路。 按照描述将输入选择器的输入线路与对应数值连接。使用数字模块生成所需的固定数值。不要自作聪明! 解决方法:

【任务:Ones ★★】 前置条件:完成“多路复用器”任务。 目标:使用6个模块 首先,你需要能从地址0开始更新内存中的每个地址。 使用调色板功能,以你“计数器”任务的解决方案作为基础。 尝试构建一个基本能实现描述功能的解决方案:读取内存中的每个值并写入内存中的每个值。此时不必担心其他方面是否正确。 既然你已经将“计数器”连接到读取器模块,读取器模块又连接到写入器模块,那么还缺少什么呢? 再次查看任务描述后,看看你可以使用哪些模块。 那个新的输出选择器控制模块是什么?它是如何工作的?可以先试用一下。希望你已经弄明白,它就像你在【Zeroes】谜题中摆弄过的输入选择器控制模块一样。 你能把从【Zeroes】中学到的知识用在这里吗? 你只需要把0的值改成1…… 还记得未连接的输入线路会发生什么吗?未连接的输出线路也会发生同样的情况…… 所以如果输出选择器没有向写入器模块输出任何内容…… 现在把它们整合起来吧…… 答案:

Fastcount ★ 前置条件:完成“Ones”。 目标:6个模块 阅读描述。这里没有技巧。 这个谜题的重点是教你速度和模块数量之间的权衡。 有时模块越少,最终的解决方案速度越慢…… 使用的模块越多,你可以更快地实现功能…… 所以只需按照描述的要求,使用你唯一可用的模块(数字模块和写入模块)来完成即可。 解法:

前置条件:完成【调色板】关卡。 目标:7个模块 首先,你需要能从内存地址0开始更新每个地址的东西。 使用调色板功能,以你在【计数器】关卡的解决方案为基础开始。 重新阅读描述后,查看你可以使用的模块。 那个新的指令解码器控制模块是什么?它是如何工作的?可以稍微试用一下,它看起来有点复杂。 查看内存中的数值,获取关于你应该做什么以及如何做的提示。 你已经将【计数器】、读取器模块和指令解码器模块连接起来了。现在只需实现【0MEM】指令! 将写入器模块连接到正确的端口,应该就能完成了。 解决方案:

设置内存 ★ 前置条件:完成“指令”关卡。 目标:6个模块 这听起来和最近的一个谜题非常相似…… 也许就是你刚刚完成的那个? 将你在“指令”关卡中的可行解决方案复制到这里,然后根据描述进行调整。 你只需调整指令解码器模块的输出以及它们与写入器模块的连接方式。 解决方案:

翻转 ★★★ 前置要求:完成“ Ones ”。 目标:8个模块 首先,你需要能从地址0开始更新内存中的每个地址。 使用调色板功能,以你解决“计数器”时的方案作为起点。 尝试构建一个基本能实现描述功能的方案:读取内存中的每个值并将每个值写回内存。此时不必担心方案是否完全正确。 现在使用输出选择器模块,在将读取的值写回之前对其进行更改。记得之前谜题中的“无操作”技巧。暂时不用担心方案是否达到目标模块数量限制。 如果你使用数字模块生成0和1这两个常量…… 并将它们连接到两个不同的输出选择器……一个选择器将0转换为1,另一个将1转换为0…… 不能将两条输入线连接到单个写入器模块,因此此时你需要使用两个写入器模块。 希望此时你已有一个可行的解决方案,即使它超过了目标数量。 读取器模块连接到两个输出选择器,每个输出选择器又连接到一个独立的写入器模块。 解决方案:

我们有一个可行的解决方案,但超出目标值1。我们需要彻底改变思路!如果我们使用输出选择器来控制写入器模块的地址,而不是将其设为固定值(一直不变)会怎样?这样一来,我们从内存中读取的值现在将用于选择输出线路……写入器模块要写入的值将是固定的……解决方案:

【拖拽】★ 前置要求:完成【翻转】和【设置内存】。 目标:2个模块 只需按照指示操作! 【寄存器文件】★★ 前置要求:完成【拖拽】。 目标:7个模块 这听起来和同一块电路板上的早期谜题非常相似…… 或许是那个同样需要读取内存并解码指令的? 将你在【指令】中的可行解决方案复制到这里,然后根据描述进行调整。 再次查看描述后,看看你可以使用哪些模块。 那个新的寄存器状态模块是什么?它是如何工作的?稍微试用一下。它看起来有点复杂。 描述中说要存储8个值,但寄存器状态模块最初只有2个。还记得如何调整模块吗?你只需要调整指令解码器模块的输出以及它们更新寄存器模块的方式。 你不能直接写入寄存器模块,但也许可以通过多路复用的方式来实现…… 查看输出选择器模块。你能将它们链接起来吗? 记得也要通过右键点击来调整输出选择器模块的输出。 希望“拖拽”谜题现在也更有头绪了。 解决方法:

基础中央处理器 ★★★ 前置要求:完成“寄存器堆”关卡。 目标:10个模块 这听起来和最近的一个谜题非常像…… 也许就是你刚刚完成的那个? 将你在“寄存器堆”关卡中的可行解决方案复制到这里,然后根据描述进行调整。 查看内存以了解需要处理哪些不同的指令。 你已经能处理SETR指令了,所以只剩下SAVE指令需要处理。 SAVE指令仅从寄存器读取数据,而非内存或指令本身。 因此,我们需要根据指令参数选择特定的寄存器,然后将结果写入内存。 如果我们连接一些输入选择器模块,或许能帮助我们实现所需功能。 输入选择器模块的输入应该很明显——我们需要将8个输入多路复用到1个输出,这些输入是什么呢? 哪些指令字段与SAVE指令相关?解决方案:输入选择器线路有些混乱。两个模块的输入#0-#7均连接到对应的寄存器0-7。

【操作选择器 ★★】 前置条件:完成“基础CPU”关卡。 目标:使用13个模块。 这听起来和同一块面板上之前的某个谜题非常像…… 不是最近的那些…… 也许是那个同样需要读取内存并解码指令的? 将你在“指令”关卡中的可行解决方案复制到这里,然后根据描述进行调整。 再次查看描述后,看看你可以使用哪些模块。 那个新的操作选择器控制模块是什么?它是如何工作的?试着操作一下。它看起来有点复杂。 现在你已经将操作选择器连接到现有的“指令”解决方案上了,是时候完成这个谜题了! 查看内存中的指令,了解它们的工作方式以及预期功能。目前没有什么技巧:只需使用你拥有的模块来实现两条新指令【MSET】和【ADDM】。 先尝试实现【MSET】,暂时不用管【ADDM】。这应该相对简单,你可以通过查看内存输出来确保至少【MSET】已被正确处理。 现在并行实现【ADDM】! 指令解码器模块可以将其输出同时连接到多个输入,这或许会有所帮助。 解决方案:

【算术CPU】★★★ 前置要求:完成“操作码选择”关卡。 目标:使用13个模块 请查看内存中需要支持的所有指令。 希望你能认出其中许多指令都是你已经实现过的! 因此,将之前谜题的解决方案组合到这里,形成一个完整的工作方案。 你需要从“基础CPU”开始…… 然后将其与“操作码选择”中的内容结合…… 接着实现新的ADDR指令。 不要局限于使用一个操作码选择器模块,你需要两个! 解决方案:

交流发电机 ★★★ 前置条件:完成“调色板”关卡。 目标:使用6个模块 首先,你需要能从内存地址0开始更新每个地址的模块。 使用调色板功能,以你“计数器”关卡的解决方案为基础开始。 现在你“只需要”弄清楚如何输出0和1的值:) 看看你可以使用哪些模块。限制往往能激发创造力! 很容易想到直接使用能检测“计数器”输出数字流的模块(比如除以2、取模2等)来决定输出0还是1。但你并没有这类模块…… 相反,思考如何生成一个0和1交替的数字流。 想想“计数器”的工作原理:它生成从0开始递增的数字流。添加模块以生成第二个类似【计数器】的数字流。但略有不同……或许可以在反馈循环中不一直加1,而是使用其他运算?如果使用【减法】模块会怎样?不行,生成一串负数(0、-1、-2、-3等)没什么用。通过这个反馈循环还能生成什么?操作数的顺序重要吗?解决方法:

【三三】★★★ 前置条件:完成【交替器】。 目标:8个模块 这听起来和最近的一个谜题非常像…… 也许就是你刚刚完成的那个? 将你在【交替器】中的可行解决方案复制到这里,然后根据描述进行调整。 不用担心你现有的【计数器】模块——它们会保持原样。 你“只”需要在生成0和1流的反馈回路中添加模块,使其生成新的1、0、0重复流。 首先专注于想出一个可行的解决方案,即使它超过了目标模块数量。你之前使用的反馈回路用了一个【锁存器】来保存一个值,那么如果添加两个【锁存器】模块并在它们之间进行运算以帮助切换状态呢?一旦完成这一步,你就需要创造性地将反馈回路中的锁存器模块精简到两个(当然不包括“计数器”回路)。解决方法:

【成就:Multiply ★★★★】 前置条件:完成“Multiplex”。 目标:18个模块 在直接往面板上放置模块之前,最好先尝试将问题分解。 回顾描述和内存,理解起来相当简单。 查看可用模块会发现一些问题:有加法器模块,但没有减法器模块,也没有乘法器模块。 因此,你必须使用加法器模块自行实现乘法运算。 内存中有两个数字,但第三个位置需要存放的乘积结果并不在其中。 首先要弄清楚这个基本算法,因为这是你必须实现的内容。试着大声念出等式7×2=14。 希望你能明白“七乘二”的意思是“把二加七次”(或者“把七加两次”)。那么在第一次计算中,你需要计算2+2+2+2+2+2+2并写出结果(14)。 不断将问题分解成可以独立测试的部分,避免混淆。 你需要读取第一个内存槽(7),然后读取第二个内存槽(2),接着进行加法运算,再将结果保存回内存。 专注于第一部分:遍历内存并读出数值。 如果你回到【计数器】,你会有一个按1地址遍历内存的电路,但这次你需要步长为3。 但你不希望在每个时钟周期都向前步进3……你需要阻止它递增,直到其他事情发生…… 你能完成谜题的第一部分吗?读取第一个槽(7),然后从0数到该数值。这需要几个模块。一旦那部分能正常工作,你能利用它来控制内存地址何时递增吗? 如果你在这些部分遇到困难,再仔细看看你的组件。输入选择器模块有帮助吗? 你有没有尝试将它与等于模块结合使用?你在选择哪些输入之间进行切换? 如果你还没尝试过【Nil】谜题,去试试看。 你需要尝试输出“空值”并将其连接到锁存器模块。这样应该足以让内存地址仅在你计数到乘法中的第一个数字(7)后才递增3。 现在来看下一部分:如何实际进行累加? 你需要读取第二个内存槽(2),然后用它来持续累加……其他某个数值。 你要把这个“其他数值”存放在哪里呢?你有这么多内存可用……再仔细阅读描述。要求是什么?你可以使用部分内存来保存中间状态吗? 第三个插槽最终需要保存相乘后的值,但在此之前它可以保存中间值…… 听起来这是个记录你所计数数值的好地方。 但那个内存地址初始状态是“无”而不是0!?还记得该如何处理这种情况吗? 再回顾一下你之前用过的锁存器模块和输入选择器来帮助设置。 希望你已经能够通过每次增加2的方式,将第三个内存插槽的数值计数到14。之后它会自动移至下一组内存地址。 但你的锁存器模块一直记住太多内容而没有重置为零?你得解决这个问题!不像“计数器”中那样使用加法器与锁存器模块直接形成反馈循环,你能否在两者之间加入另一个模块来帮助控制锁存器的输入?或许可以试试输入选择器模块? 如果将这些模块组合起来,你应该能得到一个可行的解决方案,但可能会比目标尺寸更大。继续关注那些可能冗余的部分,或者寻找基于谜题中其他情况来检测状态转换的方法。测试选项卡以及在时间刻度上前后逐步调试非常有帮助! 或许有个提示:与其给内存地址遍历器恒定加3,不如看看是否在其他地方已经计算出了下一个所需的值…… 解决方案:

【第三关:高速运转】 前置条件:完成第二关(“算术CPU”)

哦不 ★★ 前置条件:完成第二关(“算术CPU”)。 目标:2个模块 查看你可以使用的模块。限制能激发创造力! 仔细阅读描述并按提示进行探索。 这里你只有两个模块,试着把它们放到面板上并连接起来。 尝试连接输入,直到输入/输出显示除“无”之外的内容。 运行测试看看会发生什么! 解法:

延迟★ 前置条件:完成“Oh No”。 目标:3个模块 这里没有什么技巧:按描述操作即可。 你可以尝试并观察mTick的运行方式,但解决方案仍然很直接。 如果你有1个,通常如何加到3个呢? 解决方法:

时钟★ 前置条件:完成“延迟”关卡。 目标:3个模块,18微刻 描述看起来相当简单:你需要一个锁存器模块来存储3…… 但你无法配置任何模块!所以数字模块始终固定为1。 用1能做什么呢? 内存地址#1处有一个值3。这会有用吗? 将数字模块连接到读取器模块,再连接到锁存器模块,看看会发生什么! 哎呀,失败了。你在锁存器中存储了一个“?”,描述中说不能这样做。 为什么会失败?你能通过某种方式解决吗?锁存器模块每6微刻更新一次,而读取器模块需要12微刻才能稳定,所以这似乎是不可能的。 还有哪里可以得到3?你有一个1,或许可以把它加起来?将1+1连接到一个加法器模块,然后将该输出用于计算1+2。这样可行吗? 哎呀,这也失败了,但就差一点点!加法器模块稳定的时间晚了1微滴答。看来这又是一堂关于时序工作原理的课(两个加法器模块需要6微滴答,但锁存器是在6微滴答开始时提交,而不是结束时)。 重新开始思考。还有什么方法可以在锁存器模块中存储3呢? 描述中说只能在锁存器中存储3吗?似乎只说了不要存储“?”…… 运行测试时,显示的微滴答限制是多少? 24微滴答的时间限制看起来相当宽松,因为锁存器模块更新只需6微滴答。也许你需要使用一些速度稍慢但不违反描述中要求的方法……24个微刻度意味着锁存器模块可以循环4次(24÷6=4)。所以在时间耗尽前你可以进行3次操作…… 这个3听起来很熟悉。就像你必须向锁存器模块输出一个3。那么什么情况需要3次操作呢…… 你还在哪些地方同时使用过加法器模块和锁存器模块?也许这能帮到你…… 回想一下你所有同时使用这三个模块的情况…… 【计数器】谜题有帮助吗? 解法:

延迟锁存器 ★ 前置条件:完成“时钟”关卡。 目标:使用2个模块,耗时3微刻 希望这关对你来说很简单:先阅读描述,然后看看你能使用哪些模块。 可用的模块是不是很少?把你拥有的模块放到面板上并连接起来。 这道谜题的关键似乎是尝试不同的时钟周期,所以试试看吧。 默认的1微刻时钟周期会导致锁存器模块的输出存储为“?”,所以试试其他数值。 不断尝试,直到达到目标限制。 解决方案:将时钟周期设置为3。

四星任务 前置条件:完成“延迟”任务。 目标:使用4个模块。 任务描述相当简单:从内存中读取一个数值并将其乘以4。 这里甚至有一个新的乘法器模块! 把它们组合起来看看是否能行。 哦,时间不够了是吧?看看时间限制,再看看一开始需要哪些模块。 所以你需要一个数字模块来读取0号插槽。这很简单。 你不能直接硬编码内存中的当前值(46),因为有许多不同的测试,起始值也不同。 所以你肯定需要用读取器模块来读取0号插槽。 这样我们就用了12毫秒,而时间限制是18毫秒。乘法器模块需要8毫秒,12加8大于18,所以不行。 还有什么能在剩下的6毫秒内使用呢?查看可用的模块,看看哪些适用。 希望你已经找到了这里唯一可用的另一个模块:加法器模块。 它需要3毫刻度。这肯定比6毫刻度少。 你能想办法用加法代替乘法来输出一个是初始值四倍的结果吗? 希望你记得4x就是1+1+1+1,而这些看起来就像加法器模块。 你是不是想出了一个可行的解决方案,但使用了太多模块?听起来你用了两个加法器模块输入到第三个加法器来输出最终答案。 这实现了(1+1)+(1+1)。但再看看加法的方式。你能用更少的操作数做到吗? 也许其中一个加法器是多余的…… 解决方案:

迷宫 ★★ 前置要求:完成“四元组”。 目标:7个模块 阅读完描述后,四处看看哪里能得到4。 查看内存以及其中可用的值。 你可能不会直接看到4,但能看到相加等于4的数字吗? 看看你可以使用哪些模块。限制能激发创造力! 你应该会发现只能使用加法器和读取器模块,甚至没有数字模块! 你应该会看到面板上已经有一个数字模块。你能使用它吗? 回想一下之前的谜题及其解法。 还记得“解引用”吗?它是怎么运作的? 如果将其发挥到极致会怎样? 尝试将数字模块(5)连接到读取器模块。你会得到什么输出? 如果将那个读取器连接到另一个读取器呢? 继续尝试!希望你已经有了可以尝试运行的解决方案。结果如何呢? 你是不是用了一个数字模块连接到一系列读取器模块,并且用一个加法器模块将3和1相加? 这个方案成功了吗? 是不是时间不够了?但其实已经非常接近了,对吧?只需要再多几个时钟周期就能成功? 仔细观察各个模块达到稳定状态所需的不同时间。它们的稳定时间都一样吗? 数字模块是即时的(0毫秒周期),但读取器模块比加法器模块慢得多(12毫秒周期对比3毫秒周期)。如果一系列读取器模块无法正常工作(因为按顺序处理速度太慢),或许你可以用更快的方式获取所需的数字? 查看内存中的数值及其地址,以及你可以立即访问的数字。内存中的地址为3、5、10、11。内存中的值为11、10、3、1。你可以立即访问到5。 你用读取器模块将哪些数字串联起来了?有没有更快的方式获取地址? 你用了一个5数字和读取器得到了10。能更快得到它吗? 用加法器替换读取器,这样5+5=10。 尝试再次运行它作为可能的解决方案。这种方法够快了吗? 不行,虽然更接近了,但还是有点慢。显然你需要替换另一个读取器模块。 看看你拥有的数字和需要的数字。还有其他地方可以使用加法器模块吗? 试着倒着思考。得到4的唯一方法是用3和1相加,所以你肯定需要读取器模块来访问这些值。你能用加法器模块替换其他读取器模块吗?专注于那些数字,看看如何将它们相加得到目标值。你有一个5、一个来自加法器的10,以及第一个读取器(输入地址为10)得到的3。你需要从内存中读取地址11来获取最后那个麻烦的1,然后将它们相加得到4。那么,如何用你现在拥有的5、10、3得到11呢?答案:

返回: 前置条件:完成【延迟锁存器】和【四元组】关卡。 目标:使用5个模块,耗时105微滴答。 首先,你需要一个能从地址0开始更新内存中每个地址的装置。 使用调色板功能,以你在【计数器】关卡的解决方案为基础开始搭建。 接下来,只需在正确的位置进行内存的读写操作…… 然后调整时钟限制,直到方案能够正常运行。 你可以通过累加已连接模块的耗时来快速找到最慢路径。例如,一个加法器(3微滴答)+ 读取器(12微滴答)+ 写入器(12微滴答)+ 1微滴答 = 单个周期28微滴答。 到这里,仅使用这些模块,你应该能很快想出一个可行的解决方案。我找不到能同时满足两个目标的解决方案,所以如果你达成了模块数量目标,但还想达成微节拍目标,不必担心模块数量过多。我必须使用大量的锁存器模块,才能将慢速路径压缩到最短。解决方案:

延迟归零 ★★ 前置条件:完成“回溯”关卡。 目标:7个模块,174毫秒周期 首先,你需要能从地址0开始更新内存中的每个地址。 使用调色板功能,以你“计数器”关卡的解决方案为基础开始。 希望在完成第二关后,组装这个应该会相当容易。 现在不用在意毫秒周期,先专注于让它能正常运行。 如果这看起来很熟悉,那是因为确实如此……你在第二关已经做过非常类似的事情了…… 如果仍然卡住,可以回顾你“指令”关卡的解决方案。 解法:

Slowstall ★★ 前置要求:完成“零延迟”。 目标:3个模块 26微刻 查看你可用的模块并尝试组合使用。 你需要向地址#0写入0,所以这应该不会太难,对吧? 将模块直接连接到写入器模块在测试时似乎会停滞?那是因为你写入0的速度太快了!再仔细看看描述,明确你需要做什么。 将所有模块放到面板上,观察它们处理输入和输出分别需要多少微刻。 你能找到那些处理时间比写入器模块的一个周期长,但又不到两个周期的模块吗? 描述中说你需要写入0,所以从一个能输出0的模块开始…… 描述中还提到你需要进行写入操作,所以添加一个写入器模块……现在在中间放置一些能读取和写入数值的东西,这样就能刚好把所有速度都放慢…… 解决方法:

【分裂计数】★★★ 前置条件:完成【Slowstall】。 目标:7个模块 首先,你需要能从内存地址0开始更新每个地址的东西。 使用调色板功能,以你解决【计数器】时的方案为基础开始。 现在你应该按照描述来实现:这相当简单直接。 如果你尝试使用多个读取器模块并遇到时序问题,试着减少到一个读取器,并使用其他模块在中间保存数值。 解法:

快速二星★★★ 前置条件:完成“拆分计数”。 目标:11个模块,261毫秒。 你已经在之前的谜题中实现了本谜题的各个子部分。回想一下之前的谜题,看看哪些可以应用到这里。 其中一个子部分会在第二块电路板上,另一个则在这块电路板上(最近完成的)。 回顾“操作选择”和“拆分计数”。你应该能将它们组合起来找到解决方案。 如果遇到速度过慢的问题,可以查看底部的时钟周期,找到最慢的路径并专注于优化该部分。 解决方案:

延迟中央处理器 ★★★ 前置要求:完成“快速双运算”。 目标:14个模块 184毫滴答 你已经在之前的谜题中实现了本谜题的子部分。回想一下之前的谜题以及哪些部分适用于这里。 其中一个部分会在第二个面板上,另一个部分会在当前面板上(最近的那个)。 回顾“算术中央处理器”“拆分计数”和“快速双运算”。你应该能够将它们组合起来解决本谜题。 如果遇到速度过慢的问题,请查看底部的时钟周期,找出最慢的路径以及需要优化的重点。 解法:

组合器 ★★★ 前置条件:完成“慢速延迟”。 目标:7个模块,48毫秒周期 如果你仔细阅读描述,会发现一个有趣的技巧:你只需要写入一个数值一次。这意味着你只需要一个写入器模块 :) 还记得写入器模块何时会写入内存、何时不会吗? 写入器模块的两个输入都必须有效且不为“空”。如果其中任何一个为“空”,它也不会执行任何操作。这个特性是解决本谜题的关键。 让我们先回顾一下你在此处可使用的模块。注意到面板上已放置的模块以及你的选择中明显缺少的模块了吗? 没错,你只有一个读取器模块。但你需要读取不止一个数值……从你之前的【计数器】解决方案入手,以此遍历内存并为读取器模块生成内存地址。 现在重点是从内存中取出两个数值,将它们相加后再输出。 由于每个周期只能读取一个数值,你需要能够跨多个周期保留一个数值…… 你拥有哪些可以跨周期保留数值的模块? 锁存器和寄存器模块看起来很有用…… 你是否已正确连接各个模块,以便读取两个数值并将它们相加得到正确结果? 如果你已经做到这一步,但仍然过早写入数据或写入了错误的地址,现在请专注于这部分。 写入器模块只需其中一个输入为“无”,就会被跳过……只要写入器地址仍为【无】,你就可以让加法器模块继续输出数值(即使这些数值目前不正确)。 你是否发现有一个模块默认输出【无】但可以被更改? 寄存器模块看起来很有意思…… 所以,使用寄存器插槽逐步构建最终的内存地址2,并在准备就绪后再发送它。 如果你现在已有可行的解决方案,但超过了毫 tick 目标,请查看底部栏中的时钟周期。它会显示最慢的路径,以及你需要优化哪些部分才能达成目标。 查看总体毫 tick 目标48。你需要从内存中读取两个值,而你只有一个读取器模块,因此绝不可能在一个周期内完成谜题。这意味着至少需要两个周期,并且现在你对时钟周期的每周期节拍数有了上限…… 如果你将读取器模块直接连接到写入器模块,那会大大拖慢速度。所以一定要用速度快得多的模块来缓冲读取器模块的输出…… 如果你的模块数量超过目标,可能是因为锁存器模块太多了。或许你可以在电路板上使用其他能容纳更多插槽但不影响模块数量的模块…… 如果模块数量仍然超标,仔细检查一下你从“计数器”借鉴的内存地址生成器。考虑到你只需要读取两个内存地址并写入一个,或许可以对其进行简化……如果你仍然超过模块目标,你知道寄存器模块可以将输出反馈到自身的输入吗? 解决方法:

交换 ★★★ 前置条件:完成“组合器”关卡。 目标:使用7个模块,耗时45毫秒周期 将你从之前“组合器”谜题中学到的所有经验应用到这里。 你仍然只有一个读取器模块,所以需要读取两个数值并将它们保存在自己的模块中。 不过你可以根据需要使用多个写入器模块…… 还记得在“组合器”中如何对从内存读取的值进行排队和延迟吗?使用同样的策略。 如果你有一个可行的解决方案但模块数量过多,记得在“组合器”中如何利用寄存器模块…… 还要记住,寄存器模块的输出可以作为输入来创建一个链…… 解决方案:

复制器 ★★★ 前置条件:完成“组合器”关卡。 目标:6个模块,75毫秒周期。 一旦你完成了“交换器”关卡,这关应该会很轻松。 将从“计数器”“交换器”和“组合器”中学到的知识应用到这里。 用你的“计数器”解决方案生成地址…… 然后延迟读取器模块的输出…… 接着将内存中的下一个地址连接到你之前保存的值…… 解决方案:

【产品】★★★ 前置要求:完成【拆分计数】。 目标:9个模块,150毫秒周期。 如果先完成【合并器】、【交换器】、【复制器】和【空值】,会让你更容易上手。将从那里学到的经验应用到这里。 先专注于构思一个可行的方案,而不是追求最小模块数。完成后再优化部分细节会更简单。 查看可用模块,你可以添加任意数量的读取器和写入器模块,并且有一个乘法器模块,所以不需要像在【乘法】关卡中那样复杂操作。 你应该从【计数器】关卡的解决方案开始,用于遍历内存地址。 然后使用一些读取器模块提取正确的值。 接着将它们通过乘法器和写入器模块处理。这样基本就完成了!你可能会注意到,初始产品在进入反馈循环前需要额外处理。解决“Nil”后,你就会知道该如何操作。 如果时间不够用,记得查看底部的时钟周期,找到速度最慢的路径。然后回想一下你是如何解决“组合器”及类似关卡来加快速度的。 一旦部署了一些锁存器/寄存器模块来加快队列时间(并修复了它们引入的轻微偏差),还剩下什么呢?:) 看看“组合器”和“交换器”中是如何使用寄存器模块来同时减少模块数量和毫 tick 数的。 如果你想进一步减少模块数量,可以尝试像“组合器”关卡那样,限制自己只使用一个读取器模块。 你可以将模块数量控制在目标值以下,但毫 tick 数可能会增加。每个目标都能获得独立的学分。解决方法:

【板块⭐:其他内容】 前置条件:完成第二板块(“算术CPU”)

【Nil】 前置条件:完成第二关(“算术CPU”)。 目标:2个模块 这个谜题旨在鼓励尝试。阅读说明并动手操作吧。 谜题中只有2种不同的模块,试着将它们连接起来…… 解法:

【Deref-R】 前置条件:完成“Nil”。 目标:6个模块。 这听起来和你做过的另一个谜题很像…… 也许是在第二块电路板上…… 看看“Deref”谜题。从你对该谜题的解决方案开始。 如果你比较这两个谜题,“Deref”会更新从0开始的每个地址。而“Deref-R”不会这样做。 所以只需从地址0开始,然后从那里跟随指针即可。 解法:

【否定】★★ 前置要求:完成第二关(“算术CPU”)。 目标:使用8个模块 首先,你需要能从地址0开始更新内存中的每个地址。 使用调色板功能,以你在“计数器”关卡中的解决方案为基础开始。 现在你需要读取数值…… 对其进行处理(查看描述)…… 然后将其写回…… 因此,在将数据发送到写入器模块之前,先将读取器模块连接到某个模块。 尝试使用可用的模块。等于模块看起来有用吗?你能以有趣的方式使用它吗? 仔细阅读描述,它会给出简化逻辑的提示。 如果初始值为0/1/2/3,它们应该变成什么? 结果应该是0/1/1/1。你是否注意到已经是0和1的值不会改变?描述中并没有说不能读取0/1并将其写回……解决方法:

【微型中央处理器】★★ 前置条件:完成第二个关卡(“算术中央处理器”)。 目标:10个模块 这与你之前做过的一个谜题非常相似…… 或许可以在第二个关卡中找找看…… 从你在“操作选择器”中的解决方案开始。 然后通过使用寄存器模块来调整流水线。 解决方案:

【加载CPU】★★ 前置条件:完成第二关(“算术CPU”)。 目标:14个模块 如果你已经完成了“跳转”关卡,可以运用在那里学到的知识。如果还没完成也没关系,这里是更好的起点哦。 这个谜题听起来和你之前做过的另一个CPU关卡很像…… 将你在“算术CPU”中的可行解决方案复制到这里,然后根据描述进行调整。 如果你在“算术CPU”中获得了完美解决方案,那么只需稍作调整,就能轻松在这里也获得完美解决方案…… 解法:

【跳跃】★★ 前置条件:完成第二关(“算术CPU”)。 目标:14个模块 如果你还没完成“加载CPU”关卡,建议先去完成它。那里学到的知识对你很有帮助。 将你在“加载CPU”关卡中的可行方案复制到这里,然后根据本关描述进行调整。 如果你在“加载CPU”中获得了完美解决方案,那么只需稍作修改,就能轻松在此关也获得完美解决方案…… 重点在于实现新的跳转指令。你会在哪里插入该逻辑呢? 如果你将初始的“计数器”模块视为程序计数器(PC),这会有帮助吗? 解决方案:

【分支】★★ 前置条件:完成【跳跃】关卡。 目标:16个模块 这听起来和最近的一个谜题非常像…… 也许就是你刚刚完成的那个? 将你在【跳跃】关卡中的可行解决方案复制到这里,然后根据描述进行调整。 如果你在【跳跃】关卡中获得了完美解决方案,那么只需稍作调整,就能轻松在此处获得完美解决方案…… 解决方案:

【满负载CPU】★★ 前置要求:完成【加载CPU】和【分支】关卡。 目标:17个模块 这听起来和最近的谜题非常相似…… 也许就是你刚刚完成的那些? 将你在【加载CPU】和【分支】关卡中的可行解决方案复制到这里,然后根据描述进行组合。 如果你在【加载CPU】和【分支】关卡中获得了完美解决方案,那么只需稍作调整,就能轻松在此处获得完美解决方案…… 解法:

【难度】★★★ 前置条件:完成第二关(算术CPU) 目标:16个模块 看完描述后,这似乎不是什么难题? 接下来查看内存,了解需要处理的可能输入。 嗯,你需要处理所有正负数范围,所以不能只假设是正值。 看看可用的模块:你有加法器、减法器和等于模块,所以在模块方面没有限制。 想想要如何解决这个问题。希望现在你能轻松地以可控方式浏览内存(只需复制你在其他谜题中做过的部分即可)。所以重点放在实际比较上。 由于需要处理正负数,你需要几组并行的模块。或许你可以构建另一个值来进行比较,而不是直接修改内存中的数值…… 如果你有一个能生成所有正偶数的计数器,然后使用不同的运算将其与输入值进行比较,应该就能检查结果了吧? 另外,记得灵活运用输入选择器模块哦。 达到目标模块数量应该不难:看看哪些并行的模块组可以合并。 要低于目标模块数量则稍微棘手一些:仔细检查测试输入,如果你需要的数值在特定时间能由其他模块输出(而不是一直生成那个常数),那就尝试用这些模块来替代数字模块。再结合输入选择器,你就能发挥出不少创意了。 解决方法:

【Faux-Reg】★★★ 前置条件:完成第二关(“算术CPU”)。 目标:6个模块 描述看起来很简单,所以肯定有陷阱哦:) 看看可用的模块,你的面板上只有一个读取器模块,这会限制你的操作。 怎样才能在需要写入数值之前记住它们呢? 哪些模块允许跨多个周期保存输入? 你已经准备好一个寄存器模块了,但如何将输入路由到正确的位置呢?有什么有用的模块吗? 你已经将输入选择器模块连接到寄存器模块了。还剩下什么呢!? 你有无限的写入器模块可用,所以放置它们吧! 变体1:

嗯,既然你已经通关了,再看看描述吧。事情开始变得有趣了,对吧? 希望你的第一个解决方案满足了第一个变体的约束条件。如果没有,再仔细看看上面的部分。 从你对变体1的解决方案开始。要满足变体3,你需要移除什么呢? 你不能将寄存器模块连接到选择器模块(无论是输入还是输出!)。不过,你仍然需要寄存器模块来同时保存所有的值…… 看看内存中的布局方式,以及地址和数值的间隔。 你能想出如何级联这些值,然后在恰当的时机挑选出这些数值对吗? 你知道可以将寄存器模块的输出连接到它自己的输入吗? 变体2:

从变体1的解决方案开始。要满足变体3,你需要移除什么? 你必须去掉寄存器模块。那么,你可以用什么来替代它以记住数值呢? 记住,对于写入器模块来说,内存地址和输入值都必须有效(不能是“无”)才能进行写入。你能在这里利用这个特性吗? 变体3:

【成就:Divide】 前置条件:完成第二块电路板(“算术CPU”)。 目标:使用22个模块。 乍一看,这似乎比实际难度更高:实现一个能处理任意被除数和除数组合的除法功能。 描述中明确说明可以假设输入在特定范围内:没有负数,且除数永远不为零。这极大地简化了问题。 查看可用模块,有加法器和减法器模块,这应该能提示你该如何实现除法。 接下来你可能会担心如何检测何时停止对当前输入集的迭代。观察剩余值何时变为0或负值有点困难。但也许这里可以做另一个假设……浏览内存中的测试用例,看看你能否发现需要处理的数值范围有什么规律。除数是否总是在某个特定范围内?这个范围有用吗?或许和某些选择器模块的范围相似?最后要注意,题目描述只要求最终的内存值正确。所以你可以把这些内存槽用作临时的中间存储空间,不必在其他模块中一直保留数值,然后只进行一次写入(当然,这取决于你的选择!)。有了这些思路,就可以将问题分解了。首先是常规的内存遍历和解码指令,到目前为止你应该已经完成过很多类似的谜题了。接下来添加计算并输出商的部分。应该是一个简单的计数器(并处理初始值)。 现在添加计算并输出余数的部分。这部分应该与商的计算类似,但需要多做一些工作。 现在你的解决方案可能会出现计数过头的问题。是时候使用选择器模块添加检查功能,并以此来决定何时执行下一条指令了。 解决方案:

【更高级】★★★★ 前置条件:完成第二关(“算术CPU”)。 目标:17个模块 看完描述,似乎是个挺简单的问题? 但看看你能用的模块……数量并不多。 你有加法器和等于模块可用,但没有减法模块,所以得想点办法。 仔细看看内存测试,了解需要处理哪些可能的输入。 输入包含各种符号组合:正数+正数、正数+负数、负数+正数、负数+负数。直接比较两者的简单方法行不通:(。 如果不能直接把数字加起来,也许有别的办法? 要是记住初始值,然后在不同位置修改它们呢?这样你就能将修改后的值与初始值进行比较…… 但该如何修改它们呢? 要是你在循环中对数字执行常量运算,同时将它们与原始值进行比较会怎样? 你有一个加法器模块,所以这会是一个加法运算…… 如果你持续给两个值各加1,并将它们与原始值进行比较,这看起来有用吗? 现在只需想办法在完成循环之前不推进内存。 然后想办法在循环开始时的初始值和你持续加1的值之间进行切换。 如果你想减少模块数量,请记住,锁存器模块一次只能保存一个值,而寄存器模块可以保存多个值。如果你仍然使用了过多模块,可以尝试减少数字模块的使用数量。你能否通过其他模块的输出来获取相同的数值(至少在某些情况下)? 解决方法:

【数字键盘】★★★★ 前置要求:完成第二关(“算术CPU”)。 目标:16个模块 乍一看,这关似乎有点烦人。但只要你稍微专注一下,就会发现其实没那么难! 首先使用“计数器”来遍历内存。 想办法将前三个数值保存到内存中。在单次测试中,这些数值永远不会改变。 然后想办法通过一个级联数值的滑动窗口来跟踪当前的三个数值。 一旦你把这些部分搞定,剩下的就很简单了:这里没有什么 trick。 使用等于模块来实现检查功能。只有当当前三个数值都匹配时,代码才算匹配…… 如果你现在有三个等于模块(每个数字对应一个),要如何将它们组合起来得到一个结果呢? 或许可以直接将它们合并?或许可以把它们加起来? 但是要如何使用可能值(0/1/2/3)的结果呢? 也许有办法可以选择一个有效的值并忽略其余的…… 如果此时你的数值略高于目标数量,可以看看比较模块,以及是否有可以走的捷径…… 解决方法:注意:此解决方法仅针对目标数量。不过,如果你记得其他谜题(比如第三关的那些)中使用的技巧,可以从其中减少2个模块。

【第四关:山姆】 前提条件:完成第三关(“延迟中央处理器”)

【并行处理】★★★ 前置条件:完成第三关(“延迟CPU”)。 目标:11个模块,96毫滴答 到目前为止,想出一个可行的解决方案应该相当容易。 回顾像“操作选择”这样的谜题,在这里也照做。 然后复制它,以便并行运行。 调整“计数器”以生成两组要操作的地址应该足够简单。 此时,只要稍加努力,你甚至应该能够达到毫滴答目标。 棘手的部分是精简模块以达到模块目标。 在指令解码器模块之后应该有一个简单的小型精简。 但你仍然需要两个写入器模块。 专注于地址生成,看看是否可以将其优化得既小巧又足够快。 解决方案:

【碰撞】★★★ 前置条件:完成“平行世界”。 目标:12个模块,102毫刻度。 正如描述所示,从你上一个谜题“平行世界”的解决方案开始。 它几乎能正常工作,但随后会损坏内存…… 注意到问题所在了吗?是哪两条并行执行的指令导致了问题? 两个写入器模块在同一周期写入同一地址时,发生冲突就会损坏目标!所以不能这样做哦。:) 添加一些逻辑来检测是否即将写入同一地址,然后跳过其中一个以避免冲突。 希望到这里你已经有了一个达到模块数量目标的解决方案。 如果你的毫刻度目标数略高,仔细看看你为这个谜题添加的新模块。你能调整其中一个使其速度稍微快一点吗?或许可以尝试以有效的方式更改它们的参数?右键点击输入选择器模块……解决方法:

【Parallac ★★★★】 前置条件:完成“Collisions”关卡。 目标:16个模块,172毫秒周期。 你已经在之前的谜题中实现了本谜题的子部分。回想一下之前的关卡,哪些内容适用于这里。 其中一个子部分在【⭐】面板上,另一个则在本面板上(最近出现的)。 如果你从“微处理器”开始,虽然能运行,但速度会太慢…… 你需要将“微处理器”和“Collisions”结合起来。 先实现功能,不要一开始就想着减少模块数量。 一旦基础功能正常运行,你可能很快会遇到两个操作之间的冲突。因此,你需要添加逻辑来处理这些特殊情况。 不用尝试合并两个写入器模块——你始终需要它们来并行处理两个SVAC。别费心尝试合并地址生成和指令解码部分——这两部分始终需要并行运行。 想想看,如果先执行LDAC再执行SVAC会发生什么。你能找到捷径吗? 如果你的解决方案能正常工作但模块数量过多,可以看看是否能合并一些逻辑测试。 仔细观察LDAC和SVAC的参数。注意它们在指令解码模块中使用不同的输出,以及在未使用时如何被设置为“无”。你能利用这一点吗? 看看操作选择器模块。由于你只需要处理LDAC和SVAC这两种操作码,或许可以把它当作输入选择器模块来(滥用)使用……输入不一定非要来自同一个解码流水线……这里还有一个优化方法,你可以通过对指令流及其顺序做出假设来实现。这感觉有点像作弊,但却是达成模块数量目标的方法。 如果你看到一个SVAC和LDAC指令对,可以假设它们访问的是相同的地址,并相应地简化逻辑。不过有点可惜,因为在我看来,通用解决方案(需要额外增加一个模块)其实相当巧妙。 解决方法:

【备份】★★★★ 前置条件:完成【并行计算】关卡。 目标:23个模块,168毫秒周期。 从你刚刚完成的【并行计算】关卡设计开始,添加对新指令的支持。 在开始此关卡前,你应该尝试获得【并行计算】的完美解决方案。如果那已经不够快,那么为此谜题扩展它将会更加困难。 你主要需要在【并行计算】的解决方案基础上添加模块,而不是重新布线(操作选择器模块的线路除外)。 起初,使用备份寄存器处理额外指令可能看起来有些棘手,但只需系统地处理即可。 你必须像在【并行计算】中那样使用双阶段流水线才能及时解决此问题。单级互锁流水线永远不够快,所以不要尝试。如果你仍然感到无从下手,可以尝试列出你需要处理的5条指令。然后逐步尝试各种排列组合——数量其实并不多! 如果你顺利通关了“Parallac”关卡,那么你应该知道需要处理LDAC/SVAC指令对的冲突,但对于LDAC/LDAC指令对,可以忽略第一个LDAC。并且你已经根据这些原则将第一阶段的输出结构化为第二阶段的输入。现在,对更多的指令对执行同样的操作吧! 先处理ADAC指令,暂时忽略BAKP/RSTR指令可能会有所帮助。你可以逐步进行一些测试(并忽略这些指令产生的错误结果),确保ADAC指令能够正常工作。希望这能为你提供一个扩展处理备份寄存器的模式。就像你有一个累加器锁存器模块,其两侧各有一个运算选择器模块一样,你需要为备份寄存器采用相同的设置。然后只需弄清楚两条流水线之间的依赖关系以及如何将它们连接起来! 有些特定组合永远不会出现,所以如果没有必要,就不必费心支持它们。值得注意的是,绝不会出现两个SVAC指令对同一内存地址进行写入的情况。 解决方法:

快速 2-2 ★★★★ 前置条件:完成【碰撞检测】关卡。 目标:24个模块,153毫秒周期 你已经在之前的关卡中实现了本谜题的各个子部分。回想一下之前的关卡,看看哪些内容适用于这里。 其中一个子部分会在第二个面板上,另一个则在当前面板上(最近的那个)。 如果你从【操作选择器】开始,虽然能运行,但速度会太慢…… 你需要将【操作选择器】和【碰撞检测】结合起来。 要达成这两个目标,不需要什么巧妙的技巧。只需满足要求即可。 先实现第一条流水线,无需考虑碰撞问题。 然后将其复制为第二条流水线。接着进行测试,并通过地址检测和必要的结果短路处理来解决明显的碰撞问题。接下来你可能会遇到最后一个测试失败,但现在用另一个碰撞检测来修复它应该很简单。解决方法:

【Shift One ★★★】 前置条件:完成“快速 2-2”。 目标:10 个模块,135 毫刻钟。 如果你直接实现流水线,它能运行,但速度会太慢。无论如何先尝试一下,以了解流水线的重要阶段。 运用从“组合器”和“交换器”中学到的知识来加快速度。如果你还没完成这两个关卡,现在就去完成吧。 采用与那些谜题类似的方法,应该能让模块数量达到或低于目标。 如果你的模块数量超过目标,并且使用了锁存器模块,你知道寄存器模块可以将输出连接到自身输入吗? 如果你的毫刻钟数超过目标,思考一下你插入存储缓冲区的位置。是太早了?还是太晚了?查看每个阶段花费的时间,找到平衡点! 读取阶段应该是你最慢的阶段…… 解法:

更多关卡 ★★★★ 前置条件:完成【Shift One】。 目标:16个模块,190毫秒周期 注意:如果你不熟悉CPU指令流水线,建议先了解相关知识,这对你很有帮助。 你已经在之前的谜题中实现了本谜题的各个子部分。回想一下之前的谜题,看看哪些内容适用于这里。 其中一个子部分会在第二个面板上,另一个则在当前面板(最近的那个)。 如果你从【OP选择】开始,虽然能运行,但速度会太慢…… 你需要结合【OP选择】和【Shift One】的思路。不过,这里不适合用【快速2-2】。 希望你已经将流水线分为两个明显的阶段(解码和执行),这样就能更接近可行的解决方案,但速度仍然会稍慢一些……查看底部的时钟周期后,你会发现执行阶段因写入操作而速度过慢,此时需要再次拆分…… 但现在你在执行过程中发现了一些错误。回想一下“冲突”…… 你应该能在模块数量目标(或低于目标)的情况下得到一个可行的解决方案。 如果仍未达到mTicks目标的速度要求,是否将第二次拆分放在了正确的位置? 你应该设置为解码+读取+(执行+写入)阶段,而不是解码+(读取+执行)+写入阶段。 解决方案:

延迟跳转 ★★ 前置条件:完成“更多关卡”。 目标:17个模块 180毫刻 如你所知,这款游戏的核心在于基于之前的谜题和所学知识进行拓展。 因此,将你“更多关卡”的解决方案与“跳转”相结合,应该就能顺利完成。 如果你已经有“更多关卡”的完美解决方案,那么轻松就能得到本关的完美解。如果还没有,就继续攻克“更多关卡”,完成后再回到这里。 解法:

【延迟分支】★★★★ 前置要求:完成“延迟跳转”。 目标:22个模块,242毫滴答 正如你现在所了解的,这款游戏的核心就是基于之前的谜题和知识进行拓展。 所以,将你在“更多阶段”中的解决方案与“分支”相结合,应该就能顺利完成。 如果你已经有了“更多阶段”的完美解决方案,那么要得到这个谜题的完美解应该会相当容易。如果还没有,那就继续攻克“更多阶段”,完成后再回到这里。 这个谜题唯一的难点在于检查流水线中是否有对内存地址的待处理写入操作。 你可以通过对执行的测试做出假设来加快并精简你的解决方案。例如,如果你完全不比较地址,而只比较它们的值,会怎么样呢?如果测试从未设置内存中不同地址包含相同值的情况,那么这应该不成问题…… 解决方案:注意:此解决方案不具有通用性,在执行分支时会表现出延迟槽行为。但它通过了所有测试并达成了目标,所以应该没问题!? :)

【Reg Hazard】★★★★ 前置条件:完成“更多阶段”。 目标:23个模块,456毫滴答。 如你所知,这款游戏的核心在于基于之前的谜题和知识进行构建。 因此,将你在“更多阶段”中的解决方案与“算术CPU”相结合,就能取得很大进展。 完成所有所需指令的实现。一旦能正常运行,你就会遇到时间限制。 希望从“更多阶段”中能明显看出拆分流水线的第一个位置。 当然是紧跟指令解码器之后…… 选择下一个拆分流水线的位置可能会比较困难。利用时钟周期来找出最慢的路径以及下一个阶段的放置位置。这个谜题名为【寄存器冲突】,所以你可能需要关注向寄存器写入数据时会触发冲突(也称为“碰撞”)的情况。 可以将寄存器文件视为两个独立的阶段:读取阶段和写入阶段。 尽管输出选择器模块位于寄存器模块的左侧,而输入选择器位于右侧,但流水线阶段可能会颠倒这种关系? 如果你在时间限制内但遇到了一些错误,请注意指令的所有字段。SAVE指令与其他所有指令之间有什么重要区别? 记住,如果寄存器模块的输入为“无”,它将不会更新其输出,可能会保留陈旧的值…… 解决方案:

【终局】★★★★ 前置条件:完成【延迟分支】和【寄存器冒险】。 目标:30个模块,408毫滴答。 到目前为止,你应该已经了解到,这款游戏的核心就是基于之前的谜题和所学知识进行构建。 所以,拿出你解决【寄存器冒险】的方案,再将【延迟分支】的内容整合进去,这样你就已经有了不错的基础。 可以利用描述作为线索来了解如何实现。BEQ、JUMP以及其他所有指令之间存在不同时序预算是有原因的。 你不需要调整【寄存器冒险】的解决方案,只需在指令解码器模块附近插入与代码流程相关的更改,所以专注于该区域,忽略其他部分。 从JUMP指令开始着手,因为它应该是最简单的。如果描述中提到你只能为此获得一个额外周期,那么你应该在代码流程的哪个位置处理这个变更? 在指令解码器模块之后、寄存器模块缓冲区之前放置一个操作选择器模块。在此处处理JUMP指令。 BEQ处理应该放在哪里?放在指令解码器模块之后似乎太早了,因为它需要来自内存的值…… 在连接到指令解码器模块的寄存器模块缓冲区之后放置一个操作选择器模块。在此处处理BEQ指令。 如果你的“延迟分支”解决方案在执行分支时表现出延迟槽行为,那么现在你需要正确处理这一点。 如果你在JUMP/BEQ路径上增加额外的模块,应该能够轻松达到mTicks目标。如果你想到的解决方案模块数量低于目标值但速度太慢,而你只是想要那个成就,这可能会有所帮助。 解决方法:此解决方案的关键在于处理BEQ(连接到操作码字段的那个特殊的等于模块)时,在流水线中插入一个气泡。JUMP处理很简单(只需第一个操作选择器模块),但BEQ需要一些额外的逻辑来检查插入的气泡。如果有测试用例中存在一个BEQ指向另一个BEQ,这种方法就不起作用,但这种情况似乎不会出现。

【成就:秘密】 前置条件:完成“制作人员名单”

成就:隐藏成就#1 前置条件:通关第二关(“算术CPU”)。 获取“隐藏成就#1”! 关卡:反向(难度:★★) 前置条件:通关“成就”关卡。 目标:14个模块 这个谜题其实没有什么特别的技巧。仔细阅读描述然后尝试解决即可。 唯一的小技巧是弄清楚“终点”在哪里。第一个测试的内存中只有14个值,但并非所有测试都有这么多,所以不能硬编码最后一个地址…… 所以直接暴力破解吧!从地址0开始扫描内存,直到找到第一个指向“空”的地址。 希望此时想出解决方案不会太困难:你已经知道了第一个和最后一个内存地址,只需交换它们即可。只需添加逻辑,确保在内存扫描完成前不会开始交换。使用选择器模块应该能轻松实现这一点…… 记住,当“无”通过模块(如加法器和写入器模块)传播时,会使它们不执行任何操作,因此它们会保持“暂停”状态。 解决方法:

【硅基零号】 前置条件:完成“Credits”成就。 目标:15个模块 字母与数字的转换会让这关有点棘手。可以使用内存视图查看每个字母对应的数值,说不定会有帮助。 比如要把“A”(对应数值1)变成“B”(对应数值2),只需给它加1就行。 那空格(对应数值0)该怎么处理呢?看来你得加个判断了…… 你希望“Z”能变成“A”,但给“Z”加1并不能得到“A”。看来你也得为这种情况加个判断…… 到这里,只要稍微尝试一下,想出解决方案应该不难。 难的是如何把这些特殊情况组合起来,以达到模块数量的目标。 数字模块的数值不能超过16,所以要判断数值是否超过这个范围会有点麻烦……或许在测试有效性时使用减法会有所帮助…… 解决方法:

【密码】★★★★ 前置要求:完成【反转】和【硅基归零】。 目标:25个模块 希望现在你已经知道,应该用刚刚解决的前两个谜题来解决这个。 所以将【硅基归零】和【反转】复制到面板上。 仔细检查描述后,你会发现可以借鉴【反转】中的一些思路,但必须对算法进行调整,并且要运行多次。 如果你尝试先扫描所有内容,然后再回溯,速度会太慢。 注意,你不需要交换每个单词的首尾字母,只需将它们向前滚动。这意味着你完全不需要向前扫描。 实际上,在使用【硅基归零】算法更新字母时,你只需要记住一个字母……听起来有点像锁存器模块,对吧?解决方法: