首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >ASCII表( Brainfuck )

ASCII表( Brainfuck )
EN

Code Review用户
提问于 2013-05-26 23:27:25
回答 2查看 6.3K关注 0票数 50

我今天做了我的第一个Brainfuck程序,打印数字0-255和相应的字符。

我想知道是否可以改进我的程序,因为我重复了很多次(例如3x复制和粘贴“比较器”功能):

代码语言:javascript
运行
复制
max   == 255
LF    == 10
space == 32
'0'   == 48
'9'   == 57
':'   == 58
Memory: counter
        ':' space LF
        char max&1 cmp1 0 0
        num1 '9'&1 cmp2 0 0
        num2 '9'&1 cmp3 0 0
        num3 '9'&1 cmp4 0 0

+++++ +++
[
    > +++++ ++
    > ++++
    > +

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

    >>>>
    > +++++ +
    > +++++ ++
    >>>
    > +++++ +
    > +++++ ++
    >>>
    > +++++ +
    > +++++ ++

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

<<<<< <<<<< <<<<< <<<<<

Memory: 0
        58 32  10
        0  256 0 0 0
        48 57  0 0 0
        48 57  0 0 0
        48 57  0 0 0

>>>>> >
+
[
    -

    >>> .
    >>>>> .
    >>>>> .
    <<<<< <<<<< <<<<< <<<
    .
    > .
    >> .
    < .

    Number increasing logic
        >>>>> >>>>> >>>>> >
        +
            Comparer: num1 num2 out 0 0
            [
                -
                >-
                >>>+
                <<<<
            ]
            >>+ set equal flag
            <   if num1 != num2
            [
                >-  clear equal flag
            ]
            >  if num1 == num2
            [
                >
            ]
            >  go to last and put numbers back
            [
                <<<+
                <+
                >>>>-
            ]
            <<<<   reset pointer
        >>
        [
            << ----- -----
            <<<<< +
            >>>>> >> -
        ]
        <<

        <<<<<
            Comparer: num1 num2 out 0 0
            [
                -
                >-
                >>>+
                <<<<
            ]
            >>+ set equal flag
            <   if num1 != num2
            [
                >-  clear equal flag
            ]
            >  if num1 == num2
            [
                >
            ]
            >  go to last and put numbers back
            [
                <<<+
                <+
                >>>>-
            ]
            <<<<   reset pointer
        >>
        [
            << ----- -----
            <<<<< +
            >>>>> >> -
        ]
        <<

    <<<<< <<<<<
    +

        Comparer: num1 num2 out 0 0
        [
            -
            >-
            >>>+
            <<<<
        ]
        >>+ set equal flag
        <   if num1 != num2
        [
            >-  clear equal flag
        ]
        >  if num1 == num2
        [
            >
        ]
        >  go to last and put numbers back
        [
            <<<+
            <+
            >>>>-
        ]
        <<<<   reset pointer

    >>

        Inverter: in/out 0 0
        [
            > +
            < -
        ]
        +
        >
        [
            < -
            > -
        ]
        <
]
EN

回答 2

Code Review用户

回答已采纳

发布于 2014-01-14 23:34:27

祝贺你。按照brainfuck的标准,这是相当可读的代码。我能追踪到它。

通过将max单元格初始化为256个,您的代码也可以移植到无包装的brainfuck解释器上。如果您只想让它工作在包装brainfuck解释器(即,一个工作模块256),您可以将单元格设置为0。我考虑将程序更改为只循环256次,而不是将字符与最大值进行比较,但结果表明,当机器运行模块256时,255次要比循环256次简单得多。您已经有了比较例程,所以很容易再次使用它。(不过最好不要复制和粘贴代码--下面将有更多信息。)

虽然可能有更简单的方法将数字打印为十进制字符串,但是您要求优化可读性,所以我选择了接近您最初的策略。

我认为,可读性的关键是增加战略评论。在brainfuck中,除八个命令(><+-.,[])以外的任何字符都会被忽略。您还可以添加表单[-][Any comment text goes here]的注释,但有两个注意事项:

  1. 指针必须指向包含0的单元格或要被归零的单元格。
  2. 只要方括号成对出现,任何字符都可以出现在里面。

你的评论的主要目的应该是澄清:

  1. 每个代码块的意图是什么。在我看来,只要你能理解全局,就能跟踪每一次微观操作,这并不重要。
  2. 内存布局是什么,以及为什么是这样布局的。我给所有重要的细胞都取了“可变名称”。下面的代码中也有一个关于我所称的“框架”(即连续单元格组)的很长的解释性注释。
  3. 哪个单元格是程序中任意一点上的当前单元格。如果单元格包含错误的值,这是一个相对较小的错误。然而,如果指针不是它应该在的地方,程序就会以一种壮观的方式爆炸。因此,我已经开发了标记当前指针位置的表示法,在整个代码的策略点处的圆括号中。

对于在代码中重复三次比较例程,您会引起合理的关注。在brainfuck中处理这一问题的方法是让常规沿着细胞一帧一帧地爬行,就像建筑工人在一段高速公路上工作一样。只要把适当的路标,让它知道在哪里停止爬行。

代码语言:javascript
运行
复制
[-][
    # See MEMORY_LAYOUT below for explanation of SETUP.
]
SETUP
    +++++ +++ [ -
        > +++++ ++      (Colon)
        > ++++          (Space)
        > +             (Newline)

        >>>>>>
        ++++ [ -
            > +++++ +++ (Loop_limit)
            <
        ]

        >>>>> >
        > +++++ ++      (C_limit)
        > +++++ +       (c_ascii)
        >>>>
        > +++++ ++      (X_limit)
        > +++++ +       (x_ascii)
        >>>>
        > +++++ ++      (I_limit)
        > +++++ +       (i_ascii)

        <<<<< <<<<< <<<<< <<<<< <<<<< <<<<
    ]
    > ++                (Colon)
    >> ++ >             (all_done)
    >> + >>>>           (Loop_limit)
    >> + >>>> ++        (C_limit)
    >> + >>>> ++        (X_limit)
    >> + >>>> ++        (I_limit)

    <<<<< <<<<< <<<<< <<<<< <<<<< <<<
END_SETUP

MEMORY_LAYOUT
[-][
    # Using Roman abbreviations i, x, and c for units, tens, and hundreds,
    # respectively.  Braces { } indicate a frame: a repeated consecutive group
    # of cells.  Cells named with Uppercase are constants.  At all times,
    # parentheses indicate the current cell; neighboring cells may be noted
    # as well in the code.

    # The main loop starts working from the last frame.  It compares the last
    # two cells in the frame, and performs a carry if applicable.  It then
    # proceeds to the preceding frame and repeats.  The first "frame" is
    # special, as noted by the first cell being 0.  The comparison routine
    # will not be performed on it.  However, when ascii reaches Loop_limit,
    # all_done will be incremented to 1, since it is located at the offset
    # within the frame where carrying would increment a value.

  { (0)  Colon=":"=58  Space=" "=32  Newline="\n"=10  not_all_done=0 all_done=0 }
  { Compare_frame_0=1  0 0 0  Loop_limit=256       ascii="\0"=0   }
  { Compare_frame_1=1  0 0 0  C_limit=":"=58       c_ascii="0"=48 }
  { Compare_frame_2=1  0 0 0  X_limit=":"          x_ascii="0"    }
  { Compare_frame_3=1  0 0 0  I_limit=":"          i_ascii="0"    }
]
END_MEMORY_LAYOUT

>>>>
+
WHILE (not_all_done) [ -
    # Print one line of output
    >>>>> >>>>> >>> .                   (c_ascii)
    >>>>> > .                           (x_ascii)
    >>>>> > .                           (i_ascii)
    <<<<< <<<<< <<<<< <<<<< <<<<< <<< . (Colon)
    > .                                 (Space)
    >>>>> >>>> .                        (ascii)
    INCR (ascii)
    +
    <<<<< <<< .                         (Newline)

    >>>>> >>>>> >>>>> >>>>> >>>>> >
    INCR (i_ascii)
    +

    <<<<<
    REPEAT (Compare_frame_?) [
        >>>>>
        IFEQ eq_flag=0 ascii_save=0 ?_limit (?_ascii)
            [ -
                < - < + >>
            ] ascii_save=ascii; diff=limit=limit MINUS ascii; ascii=0

            <<< + (eq_flag=1)
            >> [
                << - >> [ - > + < ]
            ]    ifneq { eq_flag=0 ; ascii=diff }; (diff=0)
            # Restore diff
            > [ - < + > ]
            # Restore limit and ascii
            << (ascii_save) [ - > + > + << ]
            < (eq_flag) [
            THEN
                [-][
                    # Perform carrying.  If ascii == Loop_limit, then
                    # "carrying" will set the all_done flag.
                ]
                <<< +
                >>>>> > ----- -----
                <<<
            ]
        END_IFEQ (eq_flag=0) ascii_save=0 ?_limit ?_ascii

        <<<<< <<<
        (Compare_frame_next)
    ]

    >>>>>
    BOOL_NEGATE_AND_CLEAR not_all_done=0 (all_done)
        < +
        > [ - < - > ]
        < (not_all_done)
    END_BOOL_NEGATE_AND_CLEAR
]

这是有可能减少一个帧大小。但是,您可能不得不为not_all_doneall_done重用相同的单元,这会损害可读性。

票数 41
EN

Code Review用户

发布于 2014-01-14 23:33:04

我认为这将是一种更有效的方法(至少对于可打印的ASCII字符):

代码语言:javascript
运行
复制
++++[->++++++++<]                        Use cell 0 for loop and cell 1 for ASCII codes
++++[->>++++++++<<]>>>                   Use cell 2 for the space
+++>++>                                  Use cells 3 and 4 for the number equivalent
++++++++<<<<<                            Use cell 5 for incrementing the number equivalent
++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++ Get 95 for the loop
+++++++++++++++
[>.+>.>.>.+>-[----------<<->>>]<++++++++++<<+ Output ASCII & space & equivalent ASCII code
<<<]                                      Go back to cell 0

告诉我这对你是怎么回事。我不太明白你为什么需要那个比较函数。另外,请注意,我确实使用单元格6,但只使用转义循环(因为它的值为0)。

固定代码

下面是一些与问题中的代码具有相同原始格式的不同代码:

代码语言:javascript
运行
复制
++++++++[>+++++++>++++>+>++++[>++++++++<-]>>>>>++++++>+++++++>>>>++++++>+++++++>>>>++++++>+++++++<<<<<<<<<<<<<<<<<<<<-]>++>>++>>>>>>>++>>>>>++>>>>>++<<<<<<<<<<<<<<<<<<<<>>>>>>+[->>>.>>>>>.>>>>>.<<<<<<<<<<<<<<<<<<.>.>>.<.>>>>>>>>>>>>>>>>+[->->>>+<<<<]>>+<[>-]>[>]>[<<<+<+>>>>-]<<<<>>[<<----------<<<<<+>>>>>>>-]<<<<<<<[->->>>+<<<<]>>+<[>-]>[>]>[<<<+<+>>>>-]<<<<>>[<<----------<<<<<+>>>>>>>-]<<<<<<<<<<<<+[->->>>+<<<<]>>+<[>-]>[>]>[<<<+<+>>>>-]<<<<>>[>+<-]+>[<->-]<]
票数 11
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/26648

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档