How to calculate the sum of 2 numbers with BrainFu

2019-01-17 18:17发布

问题:

I'm trying to write a program with BrainFuck that can read two numbers up to 9, calculate the sum of them and then print the result out, e.g. 3 & 5 give the result 8 .

I'm just trying to understand the BF language but it looks much harder than I thought it would be.

回答1:

Think of the language as a huge tape (30K bytes long) where you can read, write and move forward or backward and increment/decrement one cell at a time (each cell being 1 byte, so you effectively have 30K cells). Optionally, you can read in and write out stuff that the byte stream holds(in ASCII form). Assuming that you know the basic operators, a program to sum two numbers should go along the following lines:

,       ; 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


回答2:

I saw this post 2-3 days ago and I've worked on it and now I have a solution on multi-digit addition. First I thought the name of this PL is a bit offensive but now I know, if I was authorized to name this programming language, I'd choose the same.

Now, I'll tell you how to use my code.

$ bf sum.bf
199+997=
1196
$

Only +ve numbers can be added in my code. And make sure you use the same number of digits in both inputs. i.e. if you want to add 57 with 3, then give input like 57+03= or 03+57= . Now the code. I've documented with an example. Still I prefer NOT to look into my code, as designing by yourself is easier than studying or troubleshooting a code in bf. First you need to know how to compare two numbers. My answer in this question is one solution. In documentation, I used 'plus' instead of + ,as + is a valid operation in 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

I know its a bit lengthy code, may be there are better solutions possible. But still it worth a shot.



回答3:

That is what I know

,                           ;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

input:

12

output:

3

You should use numbers under 10 and that result under 10



回答4:

I also made a program that can only handle single digit entries and answers:

#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
.


回答5:

If you want to get results with more than one digit, you have to use a decimal-converter in your brainfuck-code. The rest is the normal calculation:

    ,                           writing input char in cell(0)
    >,                          writing input char in cell(1)
    >>++++++++[<++++++>-]       writing 48 / 0x30 / ASCII('0') in cell(2)
    <                           go to cell(2)
    [-<-<->>]                   subtract cell(2) from cell(1) and cell(2)
    <                           go to cell(1)
    [<+>-]                      calculating the sum
                                cell(0) = cell(0) plus cell(1); cell(1) = 0
    <                           go to cell(0)


    >[-]++++++++[>[-]<[->+<]>-]<<<<<<<<<    here begins the converter code
    this first line sets all cells between cell(1) and cell(9) to 0 (including!)

    [->+<]>                 moving cell(0) to cell(1)
    [>+<-<+>]>              moving cell(1) to cell(0) and cell(2)
                            this ends up in copying cell(0) to cell(2)
    [                       here begins a complex loop
                            it doesn't end at the same cell as it starts
        >>>>>
        [->+<]
        >
        +
        <<<<<
        ++++++++++
        <
        [
            -
            >>
            +
            <
            -
            [>>>]
            >
            [
                [<+>-]
                >
                +
                >>
            ]
            <<<<<
        ]
        >
        [-]
        >
        [-<<+>>]
        >
        [-<<+>>]
        <<
    ]
    >>>>>
    [                       this is the output loop
                            it also doesn't end at the same cell as it starts
        <<<<
        +++++++
        [-<+++++++>]
        <
        -
        [<+>-]
        <
        .
        [-]
        >>>>>>
        [-<+>]
        <
        -
    ]
    <<<<<<<                 this probably sets the pointer to 0
                            but I don't know if there are still values in some cells

sadly I have to say, that I don't understand the whole converter code, though I really tried. I just copied it from the german wikipedia site. Maybe someone could explain it? :)



回答6:

Numerous people have answered the question already, but since every solution differs a bit, I'll just add mine as well.

My solution does single digit additions (also if the result is >9). So e.g. for the input "89" it retuns "17". I added quite a lot of comments so it should be relatively easy to understand.

GitHub link

[
  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'
   >
]


回答7:

I built a code that will work with an infinite amount of input numbers but it can only output 1 or 2 digits so the range of the sum of digits can be 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

or in short:

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



标签: brainfuck