10

我正在尝试使用 BrainFuck 编写一个程序,该程序可以读取最多为 9 的两个数字,计算它们的总和,然后将结果打印出来,例如 3 & 5 给出结果 8 。

我只是想理解 BF 语言,但它看起来比我想象的要困难得多。

4

7 回答 7

33

将语言想象成一个巨大的磁带(30K 字节长),您可以在其中读取、写入和向前或向后移动,并一次增加/减少一个单元格(每个单元格为 1 个字节,因此您实际上有 30K 个单元格)。或者,您可以读入和写出字节流包含的内容(以 ASCII 形式)。假设您了解基本运算符,则对两个数字求和的程序应遵循以下几行:

,       ; read character and store it in p1
>       ; move pointer to p2 (second byte)
,       ; read character and store it in p2
[           ; enter loop
    <       ; move to p1
    +       ; increment p1
    >       ; move to p2
    -       ; decrement p2
]           ; we exit the loop when the last cell is empty
<       ; go back to p1
------------------------------------------------ ; subtract 48 (ie ASCII char code of '0')
.       ; print p1
于 2012-05-20T03:24:43.510 回答
14

我在 2-3 天前看到了这篇文章,我已经在研究它,现在我有一个关于多位数加法的解决方案。一开始我觉得这个 PL 的名字有点冒犯,但现在我知道,如果我被授权命名这种编程语言,我会选择相同的。

现在,我将告诉您如何使用我的代码

$ bf sum.bf
199+997=
1196
$

我的代码中只能添加 +ve 数字。并确保在两个输入中使用相同的位数。即,如果您想将 57 与 3 相加,则输入 57+03= 或 03+57= 之类的输入。现在是代码。我已经记录了一个例子。我仍然不喜欢查看我的代码,因为自己设计比在 bf 中学习或排除代码更容易。首先,您需要知道如何比较两个数字。我对这个问题的回答是一种解决方案。在文档中,我使用了 'plus' 而不是 + ,因为 + 是 bf 中的有效操作。

    >> +
    [- >,>+< 
    ----- ----- ----- -----    ; checking with ascii 43 ie plus symbol
    ----- ----- ----- -----
    ---
    [
    +++++ +++++ +++++ +++++
    +++++ +++++ +++++ +++++
    +++
    < ] >>
    ]
    ; first input is over and terminated by a 'plus' symbol
    <->>>>>+
    [- >,>+<
    ----- ----- ----- -----   ; checking with ascii 61 ie = symbol
    ----- ----- ----- -----
    ----- ----- ----- ------
    [
    +++++ +++++ +++++ +++++
    +++++ +++++ +++++ +++++
    +++++ +++++ +++++ ++++++
    < ] >>
    ]
        ; second input is over and terminated by an = symbol
        ; now the array looks like 0 0 0 49 0 50 0 0 0 0 0 0 0 0 49 0 53 0 0 1 0
        ; for an input 12'plus'15=
    <<<<
    [<+<]
                ; filled with 1's in between
    + [<+>-<<[>-]>] ; This is a special loop to traverse LEFT through indefinite no of 0s
                ; Lets call it left traverse
    <<
    [<+<]
    >[>]<
               ; now the array looks like
               ; 0 0 1 49 1 50 0 0 0 0 0 0 0 1 49 1 53 0 0 1 for eg:12plus15
    [
    [->+>   + [>+<->>[<-]<]  ; Right traverse
        >>[>]<+ [<]
        + [<+>-<<[>-]>]  ; Left traverse
        <<-<
    ] 
    + [>+<->>[<-]<] 
    >> [>] <<-<[<]
    + [<+>-<<[>-]>]
    <<-<
    ]
             ; now actual addition took place
             ; ie array is 00000000000000 98 0 103 0 0 1
    + [>+<->>[<-]<]
    >>
    [ 
    ----- ----- ----- -----
    ----- ----- ----- -----
    ----- ---
    >>]
                ; minus 48 to get the addition correct as we add 2 ascii numbers
    >-<         ; well an undesired 1 was there 2 place after 103 right ? just to kill it
            ; now the array is 00000 00000 0000 50 0 55
            ; now comes the biggest task Carry shifting
    <<
    [<<]
    +++++ +++++ +++++ +++++
    +++++ +++++ +++++ +++++
    +++++ +++
    [>>]
        ; we added a 48 before all the digits in case there is an overall carry
        ; to make the size n plus 1
        ; array : 00000 00000 00 48 0 50 0 55
    <<
    <<
    [
    [>>->[>]>+>>>> >>>+<<<< <<<<<[<]><<]
    >+[>]>-
    [-<<[<]>+[>]>]
    >>>>>+>>>
    +++++ +++++ +++++ +++++ +++++
    +++++ +++++ +++++ +++++ +++++
    +++++ +++
    <
                ; comparison loop:  0   1   0   a      b  0
                ;                  (q) (p)    (num)  (58)
    [->-[>]<<]  ; comparison loop to check each digit with 58: greater means 
                ; we need to minus 10 and add 1 to next significant digit
    <[-
            ; n greater than or equal to 58 (at p)
            <<<< <<<
            [<]+
            >
            ----- ----- ; minus 10 to that digit
            <<+         ; plus 1 to next digit
            >
            [>]
            >>>>>>
    ]
    < [-<
            ; n less than 58 (at q)
            <<<<<<
            [<]+
            [>]
            >>>>>
      ]
        ; at (q)
        >>>[-]>[-]
        <<<<< <<<<<
        [<]>
        <<
    ]
        ; Its all over now : something like 0 48 0 52 0 66 ( ie 0 4 18 )
        ; will turn into 0 48 0 53 0 56 (ie 0 5 8)
    >>
    ----- ----- ----- -----
    ----- ----- ----- -----
    ----- ---
            ; here we are just checking first digit is 48 or not
            ; its weird to print 0 ahead but it is defenitely needed
            ; if it is 49 ie 1
    [
    +++++ +++++ +++++ +++++
    +++++ +++++ +++++ +++++
    +++++ +++
    .
    [-]
    ]
    >>
    [.>>]
    +++++ +++++
    .           ; to print nextline : ascii 10

我知道它的代码有点长,可能有更好的解决方案。但仍然值得一试。

于 2013-10-16T20:14:26.020 回答
3

这就是我所知道的

,                           ;read character and store it in p1
------------------------------------------------   ;return ascii to Dec
<                           ;move pointer to p2 (second byte)
,                           ;read character and store it in p2
------------------------------------------------ ;return ascii to Dec
[                           ; enter loop
-                           ; decrement p2
>                           ; move to p1
+                           ; increment p1
<                           ; move to p2
]                           ; we exit the loop when the last cell is empty
>                           ;go back to p1
++++++++++++++++++++++++++++++++++++++++++++++++     ;return Dec to ascii
.                           ;print p1

输入:

12

输出:

3

你应该使用小于 10 的数字,结果小于 10

于 2014-02-10T14:19:19.523 回答
2

我创建了一个解决方案,可以将任意数字与任意数字相加:

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

例如:

input:  13611+85399+35943
output: 134953

确保“内存溢出行为”设置为换行。

于 2019-07-10T10:01:52.933 回答
0

我构建了一个可以处理无限数量的输入数字的代码,但它只能输出 1 或 2 位数字,因此数字总和的范围可以是 0-99

>,                     go to cell #1 and read input
[                      loop while input is not null
  >+++++++[<------->-] subtract 49 from input
  <+                   add 1 to input so we have the value of the input numeral in cell #1
  [-<+>]               add cell #1 to cell #0
  ,                    read next numeral
]                      repeat until no number is being input (the input number can be longer than two digits)
>-                     go to cell #2 and set it to minus 1 so the loop will run (i will explain that at the end of the loop)
[                      loop while number in cell #0 is greater than 9
  +                    set the value of #2 to 0
  <[->+>+<<]           copy the value of #1 to #2 and #3
  >>[-<<+>>]           copy the value of #3 back to #1
  <<<                  go to #0
  [->>>+>+<<<<]        copy it to #3 and #4
  >>>>[-<<<<+>>>>]     restore it in #0
  <                    go to 3
  [-[-[-[-[-[-[-[-[-[  check if number is greater than 9
  <<+<----- ----->>>   if yes increment number in cell #1 and decrease number in cell #0 by 10
  [-]]]]]]]]]]]        set #3 to 0 so we can leave the loop
  <<                   go to #1
                       we need to check if the number in cell #1 was incremented
                       cell #2 will store the most recent value of cell #1
  [->->+<<]            so we subtract the value of cell #2 by the value of cell #1 and 
                       store the value of cell #1 in cell #3
  >>[-<<+>>]           restore the value of #1
  <                    go back to cell #2
]                      if cell #1 was increased then cell #2 will be minus 1 and the loop will restart
<[>+++++++[<+++++++>-] if cell #1 is greater than 0 then add 49 to it
<-.[-]]                subtract 1 so we have the ascii code of the value in #1 then print it and set it to zero
+++++++[<+++++++>-]<-. do the same with the value in cell #0

或简而言之:

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

于 2018-06-19T09:26:02.610 回答
0

许多人已经回答了这个问题,但是由于每个解决方案都有所不同,我也将添加我的。

我的解决方案会进行个位数加法(如果结果大于 9)。因此,例如对于输入“89”,它会返回“17”。我添加了很多评论,所以它应该相对容易理解。

GitHub链接

[
  A brainfuck program for doing a single digit addition.

  Ex. input: '13' -> output: '4'
      input: '99' -> output: '18'

  Author: Florian Baierl
]

initialize #0 with 48 (ASCII char for '0')
>++++ ++++
[
<++++ ++
>-
]

save input to #1 and #2
,>,

substract value from #0 from #1 and #2
<<
[
>-
>-
<<-
]

move to #1
>

substract from #1 and add to #2; now the answer is in #2
[
 ->+<
]

since we need to modify the answer afterwards write it to #3 and #6
as well
>
[>+>>>+<<<<-]


Is the answer bigger than 9?
to continue the memory tape should look like this:
0 1 0 (a) b 0
with the pointer pointing to a

<+
>>>+++++ +++++ b is 10
<              point to a

+>+<           necessary in case a and b are zero

loop to determine whether a or b reach 0 first
[->-[>]<<]

<[-
   a was bigger or equals b
   the answer is still stored in #6

   subtract 10 from #6 (the answer)
   >>>>> ----- -----

   write 48 to #4
   <++++ ++++
   [
   <++++ ++
   >-
   ]
   add 48 to #5 and #6
   <
   [->+>+<<]

   print out the results
   >+.>.

   leave loop (back to #2)
   <<<<
 ]
 <[-
   a was samller so we can simply print the answer out after adding 48 to it
   the answer is still stored in #6

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

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

   print #2
   >>>>.

   we want to leave the loop so go somewhere with the value '0'
   >
]
于 2018-05-06T17:45:40.240 回答
0

我还制作了一个只能处理单个数字条目和答案的程序:

#Make the first cell (Cell 0) hold a value of 48 
>++++ ++++
[
<++++ ++
>-
]

#Get inputs and minus 48 from each to get Decimal 

,>,
<<
[
>-
>-
<<-
]

#Adds the contents of Cells 1 and 2


>
[
>+
<-
]

#Moves answer to Cell 0
>
[
<+
>-
]
<
[
<+
>-
 ]

#Converts answer to ASCII
>++++ ++++
[
<++++ ++
>-
]
<

[
<+
>-
]
<
#Print answer
.
于 2016-11-08T00:25:01.797 回答