这出奇的棘手,而且我不认为这是最佳的...
<.@!$?
填充并展开代码后,这表示以下十六进制网格:
这使用了类似的控制流程,例如我最近使用的无错误cat程序,它沿着反对角线移动。为此,我们首先将指令指针(IP)偏向左侧,紫色的路径环绕到左下角。
?
读取输入为整数。!
打印回来。.
只是一个禁忌。现在,网格的角充当分支:
如果输入的是0
IP,则IP将沿红色路径继续,该路径仅以终止程序@
。
如果输入为1
,则IP将在绿色路径上继续。同样,.
这只是一个$
禁忌操作,但等同于Befunge的蹦床:它将跳过下一条指令。换行后,下一条指令将为?
,但由于$
执行实际上在蓝色路径上继续,因此从!
打印的另一副本开始1
。!..$
现在仅无限重复此仅包含的循环。
六角形控制流的研究...
我相信上述解决方案是最佳的。我写了一个野蛮的冲头,检查所有6个字节Hexagony方案,其中包含每一个的至少一个?!@
(这是必要的;我还检查:
和%
到位的@
一个师零错误终止,但那也没有帮助)。支票打印所有程序,其中a)产生0
on输入0
并终止,b)产生至少1
2s(无其他值),并且不终止于程序的前60个滴答声(5字节解决方案为200个滴答声) 。我怀疑任何有效的解决方案都需要200多个滴答声才能在如此小的网格上正确打印第一个0
或第二个1
,所以我认为我没有错过任何潜在的解决方案。
搜索没有得到5个字节的任何结果,但是得到了6个字节的57个结果(使用@
;如果我们可以在相同数量的字节中干净地解决这个问题,则无需以错误结尾)。在这57个中,只有6个为假阳性,实际上只打印了2 1
s,然后进入了无限循环而不再打印。一种解决方案被列出两次,因为它包含两个!
命令。剩下的就是50个有效的解决方案。
解决方案之间存在一定程度的简并性,其中一个或两个字符并不重要,例如,因为它们实际上实际上是无操作的。解决方案可以分为23套真正不同的程序(在某些情况下,两组之间只有一个字符差异,但是它会大大改变控制流程,因此我将它们分开计算)。其中两个组甚至以非常意外的方式使用多个指令指针。由于我永远不会想出使用支路和镜面的大多数方法,因此它们对Hexagony中可能存在的控制流类型进行了非常有趣的研究,并且我无疑为以后的高尔夫学习了一些新技巧。
在整体控制流程几乎都是一样的:看一个数字,打印。如果0
找到通向的方法@
,则在保持!
边值的同时继续循环浏览1
。有四个值得注意的例外:
- 一种解决方案(具有两个解决方案
!
)1
每次通过网格打印两次,因此打印速度约为大多数程序的两倍。我已经在x2
下面标记了这个。
- 一些解决方案(那些包含
o
)替换1
用111
(字符代码o
),所以它们打印3个 1
每人S迭代,使他们以最快的速度打印约三倍,因为大多数的节目。我在x3
下面用这些标记。
- 在每次迭代中,有两个解决方案将 a 附加
1
到边缘值上(因此1
-> 11
-> 111
-> ...)。这些打印速度非常快,但最终它们将耗尽内存。我在OoM
下面用这些标记。
- 两种解决方案进入一个非常紧密的循环,该循环仅
!
在上来回跳动,每隔一个刻度(而不是每5个左右)打印一次,这使它们略快(更整洁)。我在><
下面用这些标记。
所以这是整个动物园:
#1 #5 #12 #19
?!/$.@ ?$!>$@ .?!/$@ |!|?$@ # ><
?!/$1@ # OoM ?$!|$@ =?!/$@
?!/$=@ #20
?!/$\@ #6 #13 $@.?<!
?!/$o@ # x3 ?/!<|@ .?/!$@ $@1?<! # OoM
?!/$!@ # x2 =?/!$@ $@=?<!
#7 $@o?<! # x3
#2 ?\!<|@ #14
?!>$)@ \!?__@ #21
?!>$1@ #8 _>_!?@
?!>$o@ # x3 ?<!>$@ # >< #15
?!|$)@ \_?!$@ #22
?!|$1@ #9 <!@.$?
?!|$o@ # x3 ?\$!@$ #16 <!@/$?
\_?!_@ <!@=$?
#3 #10 <$@!$?
?!|)$@ ?~#!@) #17 <.@!$?
?!|1$@ ?~#!@1 $$?\@! </@!$?
?!|o$@ # x3 <=@!$?
#11 #18
#4 ?$)\@! \$?\@! #23
?_!<@> ?$1\@! <<@]!?
?$o\@! # x3
以下是少数几个具有代表性的小组的简短演练。特别是第10组和第23组值得一试。在其他小组中,还有许多其他有趣且有时令人费解的路径,但是到此为止,我想我已经很无聊了。对于真正想学习六角形的人来说,这些绝对值得研究,因为它们展示了更多可能的镜子和用途$
。
第一组
这个解决方案比我最初的解决方案要复杂得多,但是路径却朝着不同的方向发展。它还可以在单个单元格中实现最大数量的变体,因为最右边的无操作可以用5个不同的命令代替,这些命令在不更改结构的情况下仍然有效:
2组
这个很有趣,因为它只能水平移动。包装到后>
,IP立即反转,将分支移到角落。显然,这并不是完全没有图表,但是在1
我们再次遍历第一行的情况下,但是这次是向后的。这也意味着我们?
再次遇到,现在返回0
(EOF)。这是固定的)
(递增)以保持打印1
。这也有5个变体,)
也可以是1
或o
,>
也可以是|
:
第三组
这个看起来和上一个几乎一样,但是很混乱。直到击中|
然后遍历底行或顶行都是一样的。但是,在一个循环的情况下,$
现在将跳过的)
上反射镜。所以我们按照绿松石路径正确,打到现在的增量,跳过@
之前,我们绕到|
再次和再回到绿色通道顶部。
4组
我认为这个特别好看:
_
右上角的镜子最初是禁止操作的,因此我们使用打印!
并点击<
。0
现在,路径撞击水平镜并终止。不过,该1
路径采用了一个非常有趣的轨迹:它向下偏转,环绕到!
,重新定向到水平,然后!
再次环绕到。然后,它继续以菱形形状移动,每次迭代打印两次(每三个刻度)。
8组
这是两个打印循环非常紧密的解决方案之一:
将<
充当分支。包装两次后,0
命中@
。1
另一方面,首先跳过?
,然后再次>
将其发送到$
,因此跳过@
。然后,IP 绕入青绿色的路径,在该路径之间,它在>
和之间来回反弹<
(环绕在它们之间的边缘处)。
第10组
使用其他指令指针的两组之一,它绝对漂亮。六角形有6个-每个都从顺时针边缘的不同角开始,但是一次只有一个处于活动状态。
像往常一样,我们用阅读?
。现在~
是一元的否定:它把1
成-1
。接下来,我们点击#
。这是在IP之间进行切换的一种方法:它将当前边沿值取模6,然后切换到相应的IP(IP 0
沿顺时针方向编号)。因此,如果输入的是0
IP,则IP仍然保持不变,并且无聊地直接进入!@
。但是,如果输入的是1
,那么当前值是-1
是5 (mod 6)
。因此,我们切换到在同一单元(绿色路径)上开始的IP。现在#
是无操作,?
并将内存边缘设置为0
。)
递增,因此!
输出1
。现在我们~
再次点击以确保#
仍然是空操作(与将我们切换到IP 1会终止程序相反)。令人难以置信的是,在这个小程序中,各方面的融合程度如何。
22组
请注意,这是我最初的解决方案所在的组。它也恰好是最大的组,因为无操作可能位于两个不同的位置,并且实际(有效的无操作)命令有多种选择。
23组
这是另一个使用多个IP的组。实际上,这个使用3个不同的IP。右上角有些混乱,但我将尝试向您介绍:
因此,您之前看到的开始:<
偏向东北,?
读取输入。现在]
是在IP之间进行切换的另一种方法:它将控制权按顺时针顺序移交给下一个IP。因此,我们将控制切换到绿松石路径,该路径(从我知道很难看到)始于东北角,朝东南方向延伸。它立即被反射,<
从而环绕到东南角,向西北延伸。它也命中了,]
所以我们切换到下一个 IP。这是一条从东角开始向西南行驶的灰色小路。它打印输入,然后包装到东北角。<
将路径偏转到水平方向,并在另一 方向反射<
。现在是右手<
充当分支:如果输入为0
,则IP向东北移动,并包装到@
。如果输入为1
,则IP移至!
,然后缠绕到<
左上角,然后反射到该处...现在在角落,它绕回到上!
,向右偏斜<
,由左侧反射,<
路径开始过度...
一团糟,但一团糟。:)
由Timwi的惊人HexagonyColorer生成的图。