机器由节点组成。每个节点都有可读写的管道(上左下右)。读取管道后,管道中的值就会消失。它还具有两个寄存器
ACC
和BAK
。只能使用BAK
和SAV
操作码访问SWP
。每个节点都有自己执行的代码。此代码限制为每节点15行,每行18个字符。我已经解决了这一级别。我们的目标是计算序列:
- SEQUENCE COUNTER -
> SEQUENCES ARE ZERO-TERMINATED
> READ A SEQUENCE FROM IN
> WRITE THE SUM TO OUT.S
> WRITE THE LENGTH TO OUT.L
语法语法变短(基于我使用的命令):
MOV <src> <dest> //moves from source to destination. Blocks if source is a pipe and doesn't have a value available. Blocks if dest is a pipe and already has a value.
ADD value //adds to ACC
<label>: //defines a label (for jumps)
JMP <label> //jumps execution to label
JEZ <label> //jumps to label if ACC = 0. JumpifEqualsZero
//there's also JumpifNotZero (JNZ), JumpifGreaterZero (JGZ), JumpifLesserZero (JLZ).
SAV //MOV ACC BAK
SWP //switches values of ACC and BAK
游戏是这样描述的:
我的程序有点难以完整发布,因此将其限制在三个主要节点。 br />
这是负责计算序列长度的节点:
S: MOV LEFT ACC
JEZ E
SWP
ADD 1
SAV
JMP S
E: SWP
MOV ACC DOWN
MOV 0 ACC
SAV
这是负责对序列求和的节点:
S: MOV UP ACC
JEZ E
MOV ACC LEFT
SWP
ADD LEFT
SAV
JMP S
E: SWP
MOV ACC DOWN
MOV 0 ACC
这是我滥用作为临时存储的节点:
MOV RIGHT ACC
MOV ACC RIGHT
我不喜欢我的代码是
序列计数器如下所示:
START
read value to ACC
if ACC is 0, then GOTO END
swap ACC and BAK
add 1 to ACC
write ACC to BAK
GOTO START
END
swap ACC and BAK
write ACC as output
set ACC to 0
write ACC to BAK
这里有重复项,无论您在哪里在
then
或else
的(隐式)JEZ
情况下,首先交换ACC
和BAK
。另外,我正在滥用“交换集写入”来更改BAK
,但这也许是最短的方法。仅用于临时存储。它可以正常工作。
作为参考,以下是直方图,显示了各个级别的人员得分,并通过箭头突出显示了我的得分:
#1 楼
不幸的是,包含我的保存游戏的硬盘驱动器昨天崩溃了,因此我无法查找解决方案,但是我可以说您认为这很丑陋是由于旧计算机系统的局限性。我一直都在滥用节点作为临时存储,而我的解决方案看上去几乎一样(如果我没记错的话)。如直方图所示,您还不错(尤其是在周期上)。我们可以根据指令数和周期来优化您的解决方案。我专注于优化现有算法,而不是创建新程序。我无法测试优化的解决方案,因为我没有在此包装盒上安装Steam,但是它们仍然可以正常工作:
您的临时存储节点可以简化为:
MOV RIGHT RIGHT
这是一条有效的指令,可为您节省一条指令。
我只保存我的
ACC
在它被覆盖之前。这将删除一些重复的代码(即计数器中至少有一个SAV
)并简化了控制流程。我重写的算法比您少了一条指令:L:
SAV # Save counter
MOV LEFT ACC # Next item
JEZ EZ # End of sequence
SWP # Restore counter
ADD 1 # Increment
JMP L # Loop
EZ: # End of sequence
SWP # Restore counter
MOV ACC DOWN # Output
SUB ACC # Clear ACC
您的求和节点中不需要BAK
。您只需要临时存储节点中的值和新值。指令的某些重新排序使您可以直接将保存的总和添加到新值。我在最后一刻再次保存了ACC
:L:
MOV ACC LEFT # Save sum
MOV UP ACC # Next item
JEZ EZ # End of sequence
ADD LEFT # Add sum
JMP L # Loop
EZ: # End of sequence
MOV LEFT DOWN # Output sum
SUB ACC # Clear ACC
摆脱BAK,为我们节省了3条说明!
结论:绝对滥用指令集(例如,我的第一个要点)和游戏的可能性(在管道中存储值),以在不同指标上取得良好的成绩。不要尝试对所有内容进行优化,每个级别可以节省3次!
评论
\ $ \ begingroup \ $
不知道MOV RIGHT RIGHT是有效的,我认为这将写入仍然包含传入值的管道。几分钟后,我自己发现了#2(我说了几句话,但更像是15)……至于#3,那是非常好的发现。新的解决方案在253/6/22中运行,我可能也可以通过夏季MOV ACC RIGHT来减少节点。
\ $ \ endgroup \ $
– Pimgd
2015年6月7日在18:38
\ $ \ begingroup \ $
空白行是否免费(如L:\ nMOV ...)?
\ $ \ endgroup \ $
– Pimgd
2015年6月7日在18:46
\ $ \ begingroup \ $
@Pimgd我很确定它们是,但是可以随意将标签后的行移动到带有标签的行中。
\ $ \ endgroup \ $
– TimWolla
2015年6月7日18:47
\ $ \ begingroup \ $
也可以将解决方案减少到仅4个节点(我的第一个解决方案),但这并不是最快的。我以某种方式倾向于使用尽可能少的节点,在SpaceChem中也是如此
\ $ \ endgroup \ $
– max-m
15年6月7日在19:07
\ $ \ begingroup \ $
@Pimgd空行和标签不会增加您的指令数量,但会占用宝贵的空间(即每个节点可以有15行文本)
\ $ \ endgroup \ $
–格兰特·彼得斯
15年7月3日在4:36