
已解决问题的优化技巧 基础知识 “Golfing”是编程爱好者社区的术语。“代码高尔夫”是一种游戏,参与者尝试用尽可能少的字符在特定编程语言中解决问题。还有其他类型的高尔夫,比如针对速度、复杂度或美观度优化程序。 在《Opus Magnum》中,“Golfing”指的是最小化解决方案的周期数、占地面积或成本。通常无法同时优化这三个方面,不过占地面积和成本往往是相关的。 大多数情况下,可以通过使用单臂并配合一系列冗长复杂的指令来最小化占地面积和成本。而针对周期数的优化则复杂得多。因此,本指南的其余部分将专门聚焦于周期数优化。时间线的工作原理 时间线是屏幕底部的一组格子。它控制事件发生的顺序,同时也决定组件何时处于等待状态而非执行有效操作。这些规则起初可能有些难以理解,因为它们旨在为任何设计实现“正确的功能”。 每个组件都有一系列指令。如果在两条指令之间留有空白(但不是在时间线的起始处),游戏会自动填充空白指令。空白指令始终算作“实际”指令,每条指令执行都需要恰好一个周期。时间线起始处的空白不计算在内,因为游戏仅在首次运行时执行该延迟。 整个机器有一个周期。机器的周期就是整个机器完成一次循环所需的周期数。拥有最多指令的组件将决定周期长短。 游戏不允许某个组件与机器其他部分不同步。因此,如果某个组件的指令未达到完整周期的数量,游戏会自动用空白指令填充。这些填充的空白指令会显示在你放置的指令末尾,呈现为浅色背景。 举个例子,假设有这样一台简单的机器: 机械臂1有两条指令,开头没有空白。 机械臂2有三条指令,开头额外有一个空白。 机械臂3有五条指令,中间包含一个间隔。 机械臂4有六条指令。 在编辑器中,它看起来是这样的:

当你点击【步骤】按钮时,它会变成这样:

这台机器的周期为6,因为4号机械臂拥有最多的指令。具体如下: 1号机械臂需要填充4个空指令,计算方式为6减2等于4。 2号机械臂需要填充3个空指令,计算方式为6减3等于3。这些空白部分没有影响。 3号机械臂需要填充1个空指令,同时空隙也会转变为1个空指令,总共达到6个指令。 4号机械臂无需填充,因为6减6等于0。同样,开头的所有空白部分都会被忽略。 理解时间线的工作原理对于正确优化你的解决方案至关重要。通常来说: 每个机械臂在机器重复运行前只会执行一次其指令。如果你需要某个机械臂在整个机器周期内多次执行相同操作,请使用重复指令。你可以使用时钟指令来延长机器的周期。这会影响整个谜题,因此你只需要一个时钟。大多数时候,你根本不需要时钟。 时间线开头的空白部分通常无关紧要。时间线中间的空白部分会被计算在内,末尾的空白部分也是如此。 会被计算的空白时间通常是由于等待另一个组件造成的。如果你能让该组件运行得更快,就能减少时间线上的空白时间。 识别瓶颈 正如我们之前所讨论的,时间线中间或末尾的间隔会拖慢机器速度,因为组件之间必须相互等待。当你看到大量间隔时,就应该寻找【瓶颈】。这是机器中拖慢其他部分运行速度最严重的部件。以下是一个简单的例子:

显然,这并非最佳设计。那么具体问题出在哪里呢? 问题在于右侧的机械臂。它承担了太多任务。你可以看出来,它一直在不停地移动,而左侧的机械臂则不然。机械臂持续移动意味着游戏没有在时间轴上添加任何缓冲,因此它肯定拥有最多的指令。拥有最多指令的组件始终决定着整个机器的周期,所以右侧机械臂拖慢了整个机器的速度。 因此,如果我们能让右侧机械臂工作得更快,就能加快整个机器的速度。另一方面,加快左侧机械臂的速度暂时没有帮助,因为它最终只会等待更长时间。在这种情况下,解决方案很简单:增加第三个机械臂,它可以分担当前由右臂完成的部分工作。这样操作后,我们就能得到类似这样的设计:

这样稍微好一些,节省了几个周期,但真正的改进还需要更多机械臂。目前,两个固定长度的机械臂都要负责两个原子,不过如果每个机械臂只需连接一个原子,效率会更高。你可以清楚地看到,每个固定机械臂都花了大量时间在移动,等待的时间却不多。 在最终版本中,我们还移动了钙化符文,这样火原子和水原子在键合后会进行钙化。其实我们并非必须这样做;我们完全可以在新的活塞臂移动原子时对它们进行钙化。但通常先键合再钙化会更简单,因为这样可以将整个分子作为一个整体在符文上方移动。

当然,还可以进一步改进,但目前这样或许已经足够好了。多臂

最简单的优化方法之一是使用带有多个抓取器的机械臂。多抓取器机械臂比单抓取器机械臂的重置速度更快。例如,本指南的封面图(见右侧)展示了一个三爪机械臂,它在旋转后无需重置。根据经验法则: 旋转三次后需要重置的机械臂,应更换为双爪机械臂。 旋转两次后需要重置的机械臂,应更换为三爪机械臂。 旋转一次后需要重置的机械臂,应更换为六爪机械臂。 完成这些替换后,你可以将任何重置指令替换为单个释放指令,这能节省大量时间。 进行此优化时,请在继续操作前仔细测试你的更改。在这个例子中,它之所以能运行,是因为分子一被放到产物槽上就会消失。但如果你希望分子能停留一段时间,除非用另一个机械臂将其移开,否则你的机械臂会立即把它重新捡起来。 你也能注意到,我们没有费心将两个单机械臂优化成六向机械臂。这是因为在这个方案中,三爪机械臂一直在持续运作,它是整个流程的瓶颈。除非让三爪机械臂提速,否则无法让机器运行得更快。而且,六向机械臂需要相互等待以避免同时抓取同一个原子,所以单机械臂的方案其实已经是最优的了。 平移与旋转 “平移”指的是通过活塞或轨道让分子沿直线移动。“旋转”指的是用机械臂旋转分子。这两种运动方式存在重要区别。 平移每移动一个六边形格子需要消耗一个周期。它会保持分子的朝向,特别适合制造长链聚合物或无限产物。在分子移动过程中也很容易对其进行修改,例如进行键合或钙化处理。 旋转每旋转六十度消耗一个周期。距离无关紧要,长机械臂和短机械臂的旋转速度相同。因此,旋转适合较大的非聚合物分子,以及需要快速移动多个六边形格子的情况。当然,缺点是分子在到达目的地的过程中会经过更多的六边形格子,你需要确保这些格子没有障碍物。 说到轨道,我们应该指出几个实用特性。你可以将轨道布置成闭合回路,这样机械臂就能通过绕圈回到起始位置。你也可以在同一条轨道上放置多个机械臂,但它们不能发生碰撞。结合这些技巧,你可以让一个机械臂进行移动操作,同时另一个机械臂进行复位,这能显著提高聚合物分子的处理效率。 输入与当你试图判断一台大型复杂机器是否达到最优状态时,从输入(反应物)和输出(产物)的角度来思考会很有帮助。 通常情况下,大多数机器不会大量储存原子。每一个被消耗的输入原子或分子最终都会被加工成输出产物(在后续关卡中,也可能会被直接销毁)。任何机器都占据有限的空间,最终会耗尽空间。因此,一旦你的机器进入稳定运行状态,其输出产物的生成速率(以每个原子所需的周期数计算)必须等于输入反应物的消耗速率(需考虑不同类型的原子,例如一个锡原子等于一个铅原子加一个水银原子,或者两个铅原子)。归根结底:在稳定状态下,如果你以最快速度消耗输入材料,那么你也在以最快速度生产输出产物。判断你的方案速度的一个好方法是观察输入情况。如果你的机器持续不断地从试剂槽中提取原子和分子,那么它很可能已接近最优状态,不过你或许还能改善其启动时间。如果试剂槽经常处于闲置状态,你的机器很可能还有很大的提速空间。 结论 有许多不同的方法可以改进你的方案。要时刻留意从常见操作中挤出额外周期的机会。大多数相互作用(如键合、钙化等)一个周期内可以完成多个操作,但移动一个原子可能需要三步甚至更多步骤(抓取、旋转、释放),因此几乎总有优化的空间。 但请记住:无法正常运行的设计是无法精简的。如果你因为找不到合理的方法而感到沮丧,只需先构建一个较慢的版本,然后逐步迭代改进。最终你会得到更好的设计。
2026-03-18 01:00:20 发布在
Opus Magnum
说点好听的...
收藏
0
0
