现在,不久前,我在聊天中说:


我已经完成了BF编程。


除了我猜我在撒谎。这是我写的Brainfuck程序,它打印出最多12个乘法表。它的作用是:


循环到1-12;假设我们当前的值是x


循环12次,每次加x,并打印结果
重置数字



代码:

Cell 0 is space
Cell 1 is newline
Cell 2 is outer counter
Cell 3 is outer number
Cell 4 is inner counter
Cell 5 is inner number
Cell 6 is copy workspace

>++++[<+++++ +++>-]                                 set cell 0 to space
+++++ +++++                                         set cell 1 to new line

>+++++ +++++ ++                                     set counter to 12
[                                                   while counter is not 0
    >+                                              increment number
    >+++++ +++++ ++                                 set inner counter to 12
    [                                               while inner counter is not 0
        <[>>+>+<<<-]>>>[<<<+>>>-]                   increment inner number

        >++++++++++<<[->+>-[>+>>]>[+[-<+>]>+>>]
        <<<<<<]>>[-]>>>++++++++++<[->-[>+>>]>
        [+[-<+>]>+>>]<<<<<]>[-]>>[>++++++
        [-<++++++++>]<.<<+>+>[-]]<[<[->-<]++++++
        [->++++++++<]>.[-]]<<++++++[-<++++++++>]
        <.[-]<<[-<+>]                               print number gotten off SO

        <<<<<<.                                     print space
        >>>>-                                       go to inner counter
    ]                                               end inner loop
    >[-]<                                           reset number
    <<<.                                            print new line
    >-                                              go to counter
]                                                   end outer loop



>++++[<++++++++>-]++++++++++>++++++++++++[>+>++++++++++++[<[>>+>+<<<-]>>>[<<<+>>>-]>+++++++
+++<<[->+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]>>[-]>>>++++++++++<[->-[>+>>]>[+[-<+>]>+>>]<<<<<]>[-]
>>[>++++++[-<++++++++>]<.<<+>+>[-]]<[<[->-<]++++++[->++++++++<]>.[-]]<<++++++[-<++++++++>]<
.[-]<<[-<+>]<<<<<<.>>>>-]>[-]<<<<.>-]


输出:

1 2 3 4 5 6 7 8 9 10 11 12 
2 4 6 8 10 12 14 16 18 20 22 24 
3 6 9 12 15 18 21 24 27 30 33 36 
4 8 12 16 20 24 28 32 36 40 44 48 
5 10 15 20 25 30 35 40 45 50 55 60 
6 12 18 24 30 36 42 48 54 60 66 72 
7 14 21 28 35 42 49 56 63 70 77 84 
8 16 24 32 40 48 56 64 72 80 88 96 
9 18 27 36 45 54 63 72 81 90 99 108 
10 20 30 40 50 60 70 80 90 100 110 120 
11 22 33 44 55 66 77 88 99 110 121 132 
12 24 36 48 60 72 84 96 108 120 132 144 


一些注意事项:


乘法表缺少格式。我意识到这一点,并将在以后的一段时间中添加它(如果我能弄清楚如何比较两个值)。
我意识到,由于BF单元大小仅为8,因此不适用于16或更高的乘法表位或最多255。值16 * 16将产生256,将单元格的值设置为0。这是不可避免的吗?还是有窍门?

关注点:


这有意义吗? (考虑到Brainfuck,这应该没有道理...)
我的“注释”有意义吗?
是否存在我可以删除/减少的多余命令?


评论

“是否有意义?” “ Brainfuck”选一个

外部思维训练可能没有任何意义。稍微弯曲一下通常会很有用,因为它可以将您带到您不习惯的地方。

受到鼓吹是因为面对BF成瘾,您的意志力破裂的想法使我感到高兴。 <3

#1 楼


乘法表缺少格式。我意识到这一点,如果我能弄清楚如何比较两个值,将在以后添加它。


比较两个值并不那么复杂,只要您知道该怎么做它。但是,如果一遍又一遍地进行,则效率极低。最好的选择是如果没有数百或数十个字,则要打印数字和打印空间。

我设法对此做了一些概念验证。可以进一步优化。想法如下:


在打印100的循环之前,在另一个单元格上设置一个临时标志
如果进入循环,请在以下位置重置临时标志结束
在循环外,转到临时标志,如果已设置,则打印一个空格。清除标志并返回到单元格。

此增强的“打印数字”代码的未格式化且未优化的版本如下:

        >++++++++++<<[->+>-[>+>>]>[+[-<+>]>+>>]
        <<<<<<]>>[-]>>>++++++++++<[->-[>+>>]>
        [+[-<+>]>+>>]<<<<<]>[-]>>

>>>+<<<[

    [x>++++++[-<++++++++>]<.<<+>+>[-]]

>>>-<<<]>>>[++++++++++ ++++++++++ ++++++++++ + . [-]]<<<

<

>>>+<<<[
    [y<[->-<]++++++[->++++++++<]>.[-]]
>>>-<<<]>>>[++++++++++ ++++++++++ ++++++++++ + . [-]]<<<


<<++++++[-<++++++++>]
        <.[-]<<[-<+>]                               print number gotten off SO


我用x标记了打印100的循环,而用y标记了10的循环,以使您更容易看到我所做的更改。


我请注意,由于BF单元大小只有8位或最多255,因此不适用于16或更高的乘法表。值16 * 16将导致256,将单元的值设置为0。这不可避免吗?还是有技巧?


对此有一些可能的解决方案:


使用支持更高值的Brainfuck解释器(免责声明:那是我的项目)

将单元格的值打印为任何大小的单元格的数字
使用位宽转换
以不同的方式执行乘法。这将涉及一种完全不同的方法,即通过将数字循环并相乘,将每个数字存储在自己的单元格中,并在更详细的级别上进行乘法。我将不做更多详细介绍,因为这将需要大量工作。

我很遗憾,只有使用支持更高值的Brainfuck解释器时,我才有经验。我完全不知道位宽转换是如何工作的,或者然后您将如何打印数字。


这有意义吗? (考虑到Brainfuck,这应该没有道理...)

我的“评论”有意义吗?


出乎意料的是,是的。对于Brainfuck开发人员而言,您的代码非常容易遵循,并且您的注释也很有帮助。


是否有多余的命令可以删除/减少?


在代码中有两个地方,无需进行过多分析,就可以找到优化的可能性:如何构造内存以及如何打印数字。

构造内存时,请考虑您需要去的地方以及去的顺序。当前,您已将空间(值32)定位在磁带上的索引0处,但它是访问次数最多的值之一。将其定位在更接近“内部数字”的位置,将使您更轻松地使用它。

数字的打印是Stack Overflow上的常见算法,很好。但是我已经意识到,打印多个数字有点低效,因为它会多次从值0变为值48(ASCII值表示“ 0”),并且每次都重置为0。最好将一个“ 0”初始化为一个单元格,然后多次重用该单元格,而无需对其进行重置。

#2 楼

1)有道理。您使自己成为一个挑战并已掌握它。

2)评论也很有意义。它们是为您量身定做的,但我也很容易理解它们。

3)您可以优化一些内容。初始化磁带时,可以一次乘以多个值,因此,您可以执行以下操作:

>++++[<+++++ +++>-] set cell 0 to space
+++++ +++++         set cell 1 to new line
>+++++ +++++ ++     set counter to 12


您可以这样做: br />
磁带上的前导0没问题。
然后您可以重新排列变量以使复制指令和跳转到空格字符的时间更短。

您可以使用esolangs.org上可用的短号打印功能。

这就是我编写的代码。变化不大,但是从310字节减少到233个字节。

+++++ +++++[->+++>+>+<<<][set values to 0, 30, 10, 10]
>++>>++                   set values to 0 32 10 12


评论


\ $ \ begingroup \ $
我做了一些小的更改,以便表将以前导“ 0”格式化。
\ $ \ endgroup \ $
–多里安(Dorian)
18年7月4日在9:03

\ $ \ begingroup \ $
我做了一些小的更改,以便表将以前导“ 0”格式化。数字打印例程为每个数字使用三个单元格。它将数字除以十,将剩余的一个单元格留在右边,将除以3的结果留在当前单元格的右边,然后将48加到余数,因此它是可打印的,然后对结果进行相同的处理直到结果为0为止。
\ $ \ endgroup \ $
–多里安(Dorian)
18年7月4日在9:10

\ $ \ begingroup \ $
我对其进行了更改,使其一直持续到结果为-1。这永远不会发生,因此我用-1标记了第三个数字,并且打印例程将打印带有前导零的三位数。 `>> >>> >>> >>>-设置中止数字打印的标志<<< <<< <<<返回数字打印例程的开始+ [[-] <[-> + <[-> + <[-> + <[-> + <[-> + <[-> + <[-> + <[-> + <[-> + <[-> [-] >> +> + <<< ]]]]]]]]]]]]>]>]> +] <<< [。[-] <<<< ]使用esolangs [。] org中的数字打印例程
\ $ \ endgroup \ $
–多里安(Dorian)
18年7月4日在9:11



#3 楼

我想我想出了一种解决方案,可以打印大于16 * 16的值。是否可以打印值之间没有空格?如果是这样,我敢肯定有一种方法可以使16 * 16变成25,然后在5(或2然后是56)之间没有空格,并使用所有大于255的值来做到这一点。

关于您的担忧:
1)它可以正常工作,因此必须有意义
2)您的评论我认为没有任何问题
3)我没有看到效率低下的任何问题。这不是语言的重点吗?真正做到极简和高效。

评论


\ $ \ begingroup \ $
我不太了解您打算如何计划打印大于或等于256的值...我什至不确定您是否确切了解问题所在。
\ $ \ endgroup \ $
–西蒙·福斯伯格
2015年12月13日在9:41

\ $ \ begingroup \ $
问题是每个单元格最多只能增加255个。因此,要打印更大数量的唯一方法是在打印时将两个单元格合并。
\ $ \ endgroup \ $
–Ulthran
15年12月13日在16:48

\ $ \ begingroup \ $
不仅在打印时,而且在计算时,因为当前值存储在单个单元格中。因此,即使您可以打印出高于255的值(当前代码在技术上可以达到该值,它最多可以支持999),您将如何精确地计算和存储该值呢?与打印值之间没有空格的问题相比,这是一个更大的问题。
\ $ \ endgroup \ $
–西蒙·福斯伯格
15年12月13日在16:57

\ $ \ begingroup \ $
我并不是说我知道如何做到这一点。我只是建议没有空间将是一个开始。
\ $ \ endgroup \ $
–Ulthran
15年12月13日在20:10