Q-journal 100 种语言 :第 10 集:Befunge

Q神日志 2023-06-14 21:24:55

深奥的编程语言的目标是挑战常见的假设,源代码是一个扁平的逐行文本文件是其中最基本的。

Befunge 源代码是一个二维字符数组。让我们看看它长什么样!

有趣的是,与我们在上一集中尝试过的 Ada 不同,Befunge 在 OSX 上完全受支持,您只需要安装brew install befunge93它的bef解释器即可。

无限循环

这是 Befunge 中的无限循环:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>>v
^<
</code></span></span>

 

这里发生了什么?

  • 我们从左上角开始,面向右
  • 我们继续朝我们一直走的方向前进,直到箭头(ASCII ><v^- 它早于 Unicode)告诉它改变方向

令人惊讶的是,Befunge 带有一个内置的可视化调试器。如果您运行此代码,bef -d loop.befunge您可以在屏幕上看到网格,突出显示在循环中四处移动。

数学

Befunge 没有字符串,只有整数。我们将进入 Hello, World!,但最好先从一些数学开始。

这是一个打印的程序12

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>48+.@
</code></span></span>

 

这里发生了什么:

  • 4像或 之类的单个数字8是将数字压入堆栈的指令 - 可以直接获取 0 到 9 范围之外的数字
  • +将顶部的两个数字添加到堆栈并将结果压入那里 - 您可能会猜到什么*/-, 和%做什么
  • .将堆栈顶部打印为数字
  • @退出程序 - 如果它没有命中@,程序将绕过屏幕并且永不停止(它不会转到下一行,它会再次转到同一行的开头)

掷骰子 1 到 6

让我们实际进行一些二维编程。这是一个掷 6 面骰子的程序:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>>    v
 v <   > v
   3   6
 v2?<?>?5v
   1   4
 > >   > >.@
</code></span></span>

 

  • 程序从左上角开始,然后向下进入两半之间的洞
  • 中央?以随机方向发送程序-它可以向左走1-3,向右走4-6,顶部或底部-顶部显然会被击中v并反弹回来,但是底部方向呢?事实证明,它会一直继续下去,直到到达程序的末尾,然后环绕,从同一列的屏幕顶部继续。顶部或底部将最终重新滚动?

如果它向左走,它将朝随机方向走:

  • top push 3,然后绕到底线
  • 左推 2,然后下到底线
  • bottom 压1,然后下到底线
  • 右踩<并弹回?

4-6 的右格是完全对称的。

一旦它到达底行,程序打印数字并.退出@

顺便说一句,来自自制软件的 Befunge 解释器使用当前时间作为随机种子,所以如果你在同一整秒内多次运行它,你会得到相同的结果。

这个程序显然可以在很多方面进行“优化”。

你好世界!

打印 Hello, World! 有很多有趣的方法!

Befunge,命令将栈顶数字作为 ASCII 值打印出来。我们不能直接在源码里放101for ,只是等等。e1019*9 + 9*2 + 2

因此,让我们做一些非常简单的事情——每一行将计算“Hello, World!\n”的一个字符的 ASCII 值,然后下一行将返回到开头。几乎错过了 2D 编程的全部要点,但我们需要从某个地方开始:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>98*     ,v
v        <
>92+9*2+,v
v        <
>93+9*  ,v
v        <
>93+9*  ,v
v        <
>93+9*3+,v
v        <
>94*8+  ,v
v        <
>93*5+  ,v
v        <
>99*6+  ,v
v        <
>93+9*3+,v
v        <
>93+9*6+,v
v        <
>93+9*  ,v
v        <
>92+9*1+,v
v        <
>93*6+  ,v
v        <
>91+    ,@
</code></span></span>

 

而且它不起作用!原来我们使用的原始 Befunge-93 将程序大小限制为 80x25。这是后来在 Befunge-98 中删除的限制。

好吧,让我们加倍空间。

让我们每行放两个:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>98*     , 92+9*2+,v
v                 <
>93+9*  , 93+9*  ,v
v                 <
>93+9*3+, 94*8+  ,v
v                 <
>93*5+  , 99*6+  ,v
v                 <
>93+9*3+, 93+9*6+,v
v                 <
>93+9*  , 92+9*1+,v
v                 <
>93*6+  , 91+    ,@
</code></span></span>

 

它有效!

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>$ bef hello.befunge
Befunge-93 Interpreter/Debugger v2.25
Hello, World!
</code></span></span>

 

更好你好,世界!

让我们做一个更好的。首先,大多数 ASCII 码之间的距离很近,所以我们不需要从 0 一路计算。

最有用的命令是:复制堆栈顶部的任何内容,这样我们就可以做到。

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>98*     :, 93*+2+ :,v
v                   <
>7+     :,        :,v
v                   <
>3+     :, 97*-4- :,v
v                   <
>9-3-   :, 96*+1+ :,v
v                   <
>83*+   :, 3+     :,v
v                   <
>6-     :, 8-     :,v
v                   <
>93*6+  ,  91+     ,@
</code></span></span>

 

除了最后两个字符 ( !\n) 之外,我用先前数字的重复和差异替换了每个计算。对于小写字符,这是相当不错的。当我们从小写字母改为标点符号或大写字母时,我们实际上并没有节省太多。

好吧,让我们停止退货,好好利用每一行。奇数行将从左到右,偶数行将从右到左。削减的线数是一半。它还破坏了我们迄今为止的任何可读性,但对于 Befunge 这实际上是一件好事。

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>98*     :, 93*+2+ :,v
v,:        ,:     +7<
>3+     :, 97*-4- :,v
v,: +1+*69 ,:   -3-9<
>83*+   :, 3+     :,v
v,:     -8 ,:     -6<
>93*6+  ,  91+     ,@
</code></span></span>

 

当然,您可以将说明排列成螺旋形、之字形、某些徽标或任何您想要的形式。箭头使它非常灵活。

还有一种“无聊”的方式来做“Hello, World!”。作为对所有可能的字符串需求的让步,Befunge 具有 ASCII 模式。"命令进入 ASCII 模式,对于它遇到的每个字符,它只是将其值压入堆栈,直到遇到下一个"。我们需要做的唯一两件特别的事情是计算新行的 10,并将所有内容倒过来。

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>55+"!dlroW ,olleH",,,,,,,,,,,,,,@
</code></span></span>

 

斐波那契数列

我将跳过斐波那契数列。Befunge-93 有一些严重的限制——它可以在堆栈上保存 32 位整数,但它只能对堆栈的顶部两个元素进行操作,可选择使用命令将顶部与第二个顶部交换\

它具有某种“内存”,p可以g放入和获取程序的任何单元格,但它只存储 ASCII 值 -128 到 +127。

我们需要 3 个变量以正常方式进行斐波那契计算。如果我们可以在内存中存储常规大小的整数,或者访问更深一点的堆栈,这些都可以用于合理的斐波那契程序。

我什至在网上查过 Befunge 中的一些 Fibonacci 程序,我能找到的最好的程序是将我们需要跟踪的两个数字都编码为512*a+b,然后从本质上提取一个或另一个num%512num/512。显然,它必须在数字达到 512 之前停止。

为了清楚起见,这里对其进行了一些编辑:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>1.01>:888***++\1+:67+`#@_\:888**%\888**/\:.v
    ^                                      <
</code></span></span>

 

它使用的额外命令是 greater-than `、 skip next instruction#和 "horizo​​ntal if" ,一旦达到限制,_它将向左转并命中跳过的指令。@

打印数字 1 到 100

在开始 FizzBu​​zz 之前,让我们做一些更简单的事情,打印 1 到 100 的所有数字。

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>0v
v<         <
          @
>1+:554**`|
v         <
>:.55+,    ^
</code></span></span>

 

第一行只是压入 0 并进入循环。程序的其余部分是逆时针的文字循环。在循环中,我们用 增加数字1+,用 来检查它是否已经大于 100 :554**\`,然后用 vertical 如果|我们将程序向上发送到它的出口@,或者向下发送以继续循环。

循环的底行用 打印数字:.,然后用 打印换行符55+,

我想这都应该是可以理解的。

嘶嘶声

现在我们知道如何循环,如何打印数字和字符串,并且我们知道这%是模运算,我们可以轻松地执行 FizzBu​​zz。

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>0v
v<                                <
          @
>1+:554**`|
v         <
       >"zzuBzziF",,,,,,,,v
>:53*%!|
v      <
     >"zzuB",,,,v
>:5%!|
v    <
     >"zziF",,,,v
>:3%!|
v    <
:
.
>               >         >   55+,^
</code></span></span>

 

它可能看起来很复杂,但它有一些我们已经知道的不同部分。

该程序有一个大循环。在循环期间,会发生以下事情:

  • 数字递增1+
  • 检查数字是否大于 100 :554**`|,将其发送到退出@
  • 检查数字是否为零模 15 :53*%!|,如果是,则打印 FizzBu​​zz 并转到底线,跳过其余的迭代
  • 检查 number 是否为零模 5 :5%!|,如果是,则打印 Buzz 并转到底线,跳过其余的迭代
  • 检查数字是否为零模 3 :3%!|,如果是,则打印 Fizz 并转到底线,跳过其余的迭代
  • 如果这些都没有发生,则打印数字:.
  • 底线打印换行符55+,

你应该试试 Befunge 吗?

Befunge 是一种极具影响力的深奥编程语言,它催生了一个全新的二维编程语言家族。

大多数使用灵活的程序大小而不是固定的 80x25。正如我已经提到的,一些额外的指令允许在单元格中存储任意数字,或者访问堆栈而不是前两项,将大大改善可以表达的内容。

我绝对推荐你试一试。


关注我的博客,您将在其中获得提示、技巧和挑战,以保持您的技能敏锐。记得关注我哦!

 

...全文
441 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

6

社区成员

发帖
与我相关
我的任务
社区描述
分享
java-rocketmqpygame前端 个人社区 广东省·广州市
社区管理员
  • Q shen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧