我今天做了我的第一个Brainfuck程序,打印数字0-255和相应的字符。
我想知道是否可以改进我的程序,因为我重复了很多次(例如3x复制和粘贴“比较器”功能):
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
[
> +
< -
]
+
>
[
< -
> -
]
<
]
发布于 2014-01-14 23:34:27
祝贺你。按照brainfuck的标准,这是相当可读的代码。我能追踪到它。
通过将max
单元格初始化为256个,您的代码也可以移植到无包装的brainfuck解释器上。如果您只想让它工作在包装brainfuck解释器(即,一个工作模块256),您可以将单元格设置为0。我考虑将程序更改为只循环256次,而不是将字符与最大值进行比较,但结果表明,当机器运行模块256时,255次要比循环256次简单得多。您已经有了比较例程,所以很容易再次使用它。(不过最好不要复制和粘贴代码--下面将有更多信息。)
虽然可能有更简单的方法将数字打印为十进制字符串,但是您要求优化可读性,所以我选择了接近您最初的策略。
我认为,可读性的关键是增加战略评论。在brainfuck中,除八个命令(><+-.,[]
)以外的任何字符都会被忽略。您还可以添加表单[-][Any comment text goes here]
的注释,但有两个注意事项:
你的评论的主要目的应该是澄清:
对于在代码中重复三次比较例程,您会引起合理的关注。在brainfuck中处理这一问题的方法是让常规沿着细胞一帧一帧地爬行,就像建筑工人在一段高速公路上工作一样。只要把适当的路标,让它知道在哪里停止爬行。
[-][
# 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_done
和all_done
重用相同的单元,这会损害可读性。
发布于 2014-01-14 23:33:04
我认为这将是一种更有效的方法(至少对于可打印的ASCII字符):
++++[->++++++++<] 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)。
下面是一些与问题中的代码具有相同原始格式的不同代码:
++++++++[>+++++++>++++>+>++++[>++++++++<-]>>>>>++++++>+++++++>>>>++++++>+++++++>>>>++++++>+++++++<<<<<<<<<<<<<<<<<<<<-]>++>>++>>>>>>>++>>>>>++>>>>>++<<<<<<<<<<<<<<<<<<<<>>>>>>+[->>>.>>>>>.>>>>>.<<<<<<<<<<<<<<<<<<.>.>>.<.>>>>>>>>>>>>>>>>+[->->>>+<<<<]>>+<[>-]>[>]>[<<<+<+>>>>-]<<<<>>[<<----------<<<<<+>>>>>>>-]<<<<<<<[->->>>+<<<<]>>+<[>-]>[>]>[<<<+<+>>>>-]<<<<>>[<<----------<<<<<+>>>>>>>-]<<<<<<<<<<<<+[->->>>+<<<<]>>+<[>-]>[>]>[<<<+<+>>>>-]<<<<>>[>+<-]+>[<->-]<]
https://codereview.stackexchange.com/questions/26648
复制相似问题