压缩Befunge程序


17

Befunge是一种二维深奥的编程语言。基本思想是将(一个字符)命令放置在二维网格上。控制流遍历网格,执行传递过来的命令,并在命中箭头(>^<v)时更改方向。命令是基于堆栈的;看到这个清单。另请参见http://esolangs.org/wiki/Befunge

提供Befunge-98的规格

问题

编写一个程序,将Befunge程序转换为更紧凑的表示形式。例如,以下程序打印0

>   0   v

>   @   .

^       <

在这种情况下,可以通过删除空格行来压缩它而无需更改程序的行为,从而得到

>0v
>@.
^ <

更复杂的转换可以旋转或镜像命令序列,并消除不必要的控制流命令以压缩程序。例如,使用此程序:

>12345v
      6
v....7<
.
.
.
@

您可能会将程序的结尾塞进洞里:

>12345v
>...@ 6
^....7<

对于第一个示例,最紧凑的程序是

>0.@

您可以使用任何转换,只要输出程序给出的结果相同即可。

输入程序

输入程序是有效的Befunge-98程序。

您可以假设输入程序是确定性的。也就是说,它不使用读取外部状态的命令:用户输入命令&~,随机化器?以及自修改代码命令pg

您可以假设输入程序终止。

计分

这不是代码高尔夫,而是编写执行代码高尔夫的程序的问题。

输入是一组测试用例(满足上述输入限制的Befunge程序)。总分是测试案例的总分。

每个测试用例的得分

分数是输出程序中非空单元格的凸包的面积,其中每个单元格都视为一个正方形,其四个角为笛卡尔平面中的晶格点。例如,

>   v
 @  <

获得9.5分。

如果您的程序在特定输入上没有在合理的时间和内存中终止,则得分为输入程序的得分。(这是因为您可以简单地添加一个限时包装程序,如果您的程序没有及时终止,则该包装程序将不变地输出输入程序。)

如果用您的程序处理后,测试用例程序具有不同的结果(或无法终止),则分数为输入程序的分数加100分的罚款。


8
是什么防止运行程序完成并编写打印相同输出的Befunge程序?
基思·兰德尔

5
是否允许“获取”和“放置”?如果允许“放置”(自修改代码),那么将很难做任何事情。
基思·兰德尔

2
执行从哪里开始?左上角?如果是这样,您能否解释第二个示例的输出?.表示输出整数,但是如果从左上角开始,则堆栈中没有要输出的整数。
elssar 2013年

1
@elssar是,.输出一个整数。而且,当堆栈上没有足够的参数时,碰巧会假装那里有足够数量的零。因此,第二个示例将输出000
daniero

@KeithRandall:编写具有相同输出的新程序仅适用于输出较短的程序。g并且p不允许(抱歉,忘记了这些内容;已编辑)。
机械蜗牛

Answers:


12

我花了很长时间乘飞机编码了这个。我编写了一个伪befunge编译器,该编译器运行befunge程序,提取基本块,并以紧凑的表示形式进行布局。

链接到程序

在此99瓶程序上运行时:

92+9*                           :. v  <
>v"bottles of beer on the wall"+910<
,:
^_ $                             :.v
            >v"bottles of beer"+910<
            ,:
            ^_ $                     v
>v"Take one down, pass it around"+910<
,:
^_ $                           1-v
                                 :
        >v"bottles of beer"+910.:_          v
        ,:
        ^_ $                          ^
                    >v" no more beer..."+910<
                    ,:
                    ^_ $$ @

它生成以下输出:

92+9*:.019+"llaw eht no "v
v  _v# :"bottles of beer"<
>    ,:    v
^  _v#     <
    >$:.019+"reeb f"v
 v _  v#:"bottles o"<
 >     ,:  v
 ^ _  v#   <
      >$019+"dnuo"v
     v"pass it ar"<
     >" ,nwod eno"v
 v _    v#:"Take "<
 >       ,:v
 ^ _    v# <
        >$1-:v
 v _      v# <
 >         :.019+"reeb "v
  v_  v#   :"bottles of"<
  >        ,v
  ^_  v#   :<
      >    $019+"llaw"v
           v" on the "<
           >"reeb fo "v
^  _^#      :"bottles"<
          >019+"...r"v
v  _v#:" no more bee"<
>    ,:    v
^  _v#     <
    >$$@    

实际上,它并没有比源代码紧凑得多,但是在大型/稀疏程序上可能会做得更好。

该程序的布局左侧为路由区,右侧为基本块内容。通常将一个基本块布置成偶数行,以便入口和出口邻接路由区域。在每个基本块的末尾,#^_v从右到左排列的小工具和变体执行条件分支并将路由流分成几列。在每个基本块的开头,这些列都被路由到目标基本块的行中。

另外,如果输出很短,它将仅显式生成输出,如下所示:

"output">:#,_@

我没有做任何事情来优化基本块本身,只是布局。去做。

那么测试在哪里?


1
源代码链接现在似乎是500。服务器配置错误?
John Dvorak

1
@JanDvorak:的确如此。固定。
基思·兰德尔

1

Sed,5个字符

因此,即使这不是codegolf,这也是一种解决方案,它将具有相当好的代码长度与得分比率,但不一定是好的得分。

/^$/d

它只是删除空白行。


10
您的代码不正确!您不能简单地删除空白行。我无法在评论中编写2D代码。但是请考虑方向朝下,并且常量字符串开始(")的情况。方式中的每个空白行都应视为空格字符。如果我们打印出该字符串,则您生成的代码在输出中将没有空格!
saeedn

3
查看ideone.com/BdcRcf中的代码,它应该打印出来b a。但缩短后,它将打印出来ba
2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.