Якім чынам Brainfuck Hello World сапраўды працуе?

Хтосьці прыслаў мне гэта і сцвярджаў, што гэта прывітанне свет у Brainfuck (і я спадзяюся, што так ...)

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

Я ведаю асновы, што гэта працуе, перамяшчаючы паказальнік і прырашчэнне і декремент рэчы ...

Тым не менш, я ўсё яшчэ хачу ведаць, як гэта на самай справе працуе? Як раздрукаваць што-небудзь на экране ў першую чаргу? Як гэта закадаваць тэкст? Я не разумею наогул ...

94
@ Ring0: Нах, гэта толькі для запісу мовы.
дададзена аўтар LetMeSOThat4U, крыніца
Павінна быць даволі цяжка падтрымліваць прыкладання, напісаныя на гэтай мове ..
дададзена аўтар Ring Ø, крыніца
@YashVerma Гэта выразна паказана ў назве мовы.
дададзена аўтар Mateen Ulhaq, крыніца
@YashVerma не патрэбны ..
дададзена аўтар Insane, крыніца
што гэта практычнае прымяненне?
дададзена аўтар Yash Kumar Verma, крыніца

6 адказы

1. Асновы

Каб зразумець Brainfuck вы павінны ўявіць сабе бясконцае мноства вочак, ініцыялізаваць 0 кожны.

...[0][0][0][0][0]...

Пры запуску праграмы Brainfuck, ён ўказвае на любую клетку.

...[0][0][*0*][0][0]...

If you move pointer right > you are moving pointer from cell X to cell X+1

...[0][0][0][*0*][0]...

Калі павялічыць значэнне ячэйкі + вы атрымаеце:

...[0][0][0][*1*][0]...

Калі павялічыць значэнне ячэйкі зноў + вы атрымаеце:

...[0][0][0][*2*][0]...

Калі паменшыць значэнне ячэйкі - вы атрымаеце:

...[0][0][0][*1*][0]...

If you move pointer left < you are moving pointer from cell X to cell X-1

...[0][0][*0*][1][0]...

2. Увод

To read character you use comma ,. What it does is: Read character from standard input and write its decimal ASCII code to the actual cell.

Паглядзіце на ASCII табліцы . Напрыклад, дзесятковы код ! гэта 33 , а а гэта 97 .

Ну, давайце прадставім вашу BF праграму памяці выглядае наступным чынам:

...[0][0][*0*][0][0]...

Мяркуючы, што стандартны ўвод азначае а , калі вы карыстаецеся коску , аператар, тое, што BF Ці чытаецца а дзесятковы код ASCII 97 у памяць:

...[0][0][*97*][0][0]...

Як правіла, вы хочаце, каб думаць, што шлях, аднак праўда крыху больш складана. Ісціна заключаецца ў тым BF не чытае сімвал, але байты (незалежна гэты байт). Дазвольце мне паказаць вам прыклад:

У Linux

$ printf ł

друкуе:

ł

які спецыфічны польскі характар. Гэты знак не кадуюцца кадоўкай ASCII. У гэтым выпадку гэта UTF-8 кадаванне, таму ён выкарыстоўваецца, каб прыняць больш аднаго байта ў памяці кампутара. Мы можам даказаць гэта, зрабіўшы шаснаццатковы дамп:

$ printf ł | hd

які паказвае:

00000000  c5 82                                             |..|

Нулі накіраваны. <�Код> 82 з'яўляецца першым і С5 з'яўляецца другой байт, які прадстаўляе L (для таго, мы будзем чытаць іх). <�Код> | .. | гэта графічнае прадстаўленне, якое не магчыма ў гэтым выпадку.

Ну, калі вы перададзіце L у якасці ўваходных дадзеных для вашай BF праграмы, якая счытвае адзін байт, памяць праграмы будзе выглядаць наступным чынам:

...[0][0][*197*][0][0]...

Чаму 197 ? Ну 197 дзесятковая С5 шаснаццатковае. Здаецца знаёмым? Канешне. Гэта першы байт L !

3. Выхад

To print character you use dot . What it does is: Assuming we treat actual cell value like decimal ASCII code, print corresponding character to standard output.

Ну, давайце прадставім вашу BF праграму памяці выглядае наступным чынам:

...[0][0][*97*][0][0]...

(.) Калі вы выкарыстоўваеце кропкавы аператар цяпер, што BF робіць друк:

<�Р> а </р>

Паколькі а дзесятковы код у ASCII з'яўляецца 97 .

Так, напрыклад, BF праграмы, як гэта (97 плюсы 2 кропак):

<�Р> +++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++ ..

Падвысіцца значэнне вочка ён паказвае да 97 і раздрукаваць яго ў 2 разы.

<�Р> аа </р>

4. Loops

У даменнай печы цыкл складаецца з пачатку цыкла [ і канец цыклу ] . Вы можаце думаць, што гэта, як у той час як у C/C ++, дзе ўмова з'яўляецца фактычным значэннем вочка.

Вазьміце праграму выгляд BF ніжэй:

++[]

++ increments actual cell value twice:

...[0][0][*2*][0][0]...

І [] падобны , а (2) {} , так што гэта бясконцы цыкл.

Скажам, мы не хочам, каб гэты цыкл будзе бясконцым. Мы можам зрабіць, напрыклад:

++[-]

Такім чынам, кожны раз, калі пятля пятля гэта памяншае фактычнае значэнне вочка. Пасля таго, як фактычнае значэнне ячэйкі 0 цыкл завяршаецца:

...[0][0][*2*][0][0]...        loop starts
...[0][0][*1*][0][0]...        after first iteration
...[0][0][*0*][0][0]...        after second iteration (loop ends)

Давайце разгледзім яшчэ адзін прыклад канчатковага цыкла:

++[>]

Гэты прыклад паказвае, мы не да канца цыклу ў вочку, цыкл пачаўся:

...[0][0][*2*][0][0]...        loop starts
...[0][0][2][*0*][0]...        after first iteration (loop ends)

Аднак гэта добрая практыка, каб пакласці канец, дзе мы пачалі. Чаму? Таму што, калі цыкл сканчаецца на іншую вочка запушчанай, мы не можам выказаць здагадку, дзе паказальнік ячэйкі будзе. Шчыра кажучы, гэтая практыка робіць Brainfuck менш Brainfuck.

187
дададзена
Крута, цяпер я зразумеў :)
дададзена аўтар speeder, крыніца
Гэта ідэальнае рашэнне для пачаткоўца, які спрабуе зразумець гэтую моўную ідэалогію. Congrats і вялікі пост.
дададзена аўтар Casey, крыніца
Я думаю, што калі вам патрэбен праект для вашага вольнага часу, вы заўсёды можаце дадаць падтрымку Unicode у Brainfuck.
дададзена аўтар Álvaro González, крыніца
Што наконт , [ і ] ? :(
дададзена аўтар Josh M, крыніца
Наогул мая мэта была проста растлумачыць БФ ідэалогію, але вы маеце рацыю. Я буду павялічыць свой адказ у бліжэйшы час.
дададзена аўтар Scony, крыніца
@Scony рэальнага (мозгу) F * ckers не клапоцяцца пра Da Rulez: $ рэха «++++++++ [> ++++ [> ++> +++> +++ > + <<<< -]> + >> + >> + [<] <-] >> >> --- + & ZWNJ ;. ++++++ .. +++> ... .. << -> & ZWNJ; +++ ------ .-------- & ZWNJ;> +> ++ «.... | БФ Прывітанне свет!
дададзена аўтар YoYoYonnY, крыніца
Лепшае ўвядзенне Brainfuck я бачыў. Шчыра кажучы, вы адмяніце BF трохі па вашых пастоў
дададзена аўтар Boyang, крыніца
Пасля вашага паста, BF ёсць! BF больш!
дададзена аўтар thanos.a, крыніца
Гэта самы лепшы спосаб, якім я магу зразумець BrainF *** мову! Цяпер я ведаю, як мой заказ Brainf *** перакладчык пераўтворыць код у радок!
дададзена аўтар Obinna Nwakwue, крыніца

Wikipedia has a commented version of the code.

+++++ +++++             initialize counter (cell #0) to 10
[                       use loop to set the next four cells to 70/100/30/10
    > +++++ ++              add  7 to cell #1
    > +++++ +++++           add 10 to cell #2 
    > +++                   add  3 to cell #3
    > +                     add  1 to cell #4
    <<<< -                  decrement counter (cell #0)
]                   
> ++ .                  print 'H'
> + .                   print 'e'
+++++ ++ .              print 'l'
.                       print 'l'
+++ .                   print 'o'
> ++ .                  print ' '
<< +++++ +++++ +++++ .  print 'W'
> .                     print 'o'
+++ .                   print 'r'
----- - .               print 'l'
----- --- .             print 'd'
> + .                   print '!'
> .                     print '\n'

Для таго, каб адказаць на вашыя пытанні, тым , і . сімвалы выкарыстоўваюцца для ўводу/высновы. Тэкст ASCII.

артыкулы Вікіпедыі ідзе на больш некаторай глыбіні, а таксама.

The first line initialises a[0] = 10 by simply incrementing ten times from 0. The loop from line 2 effectively sets the initial values for the array: a[1] = 70 (close to 72, the ASCII code for the character 'H'), a[2] = 100 (close to 101 or 'e'), a[3] = 30 (close to 32, the code for space) and a[4] = 10 (newline). The loop works by adding 7, 10, 3, and 1, to cells a[1], a[2], a[3] and a[4] respectively each time through the loop - 10 additions for each cell in total (giving a[1]=70 etc.). After the loop is finished, a[0] is zero. >++. then moves the pointer to a[1], which holds 70, adds two to it (producing 72, which is the ASCII character code of a capital H), and outputs it.

The next line moves the array pointer to a[2] and adds one to it, producing 101, a lower-case 'e', which is then output.

As 'l' happens to be the seventh letter after 'e', to output 'll' another seven are added (+++++++) to a[2] and the result is output twice.

'o' is the third letter after 'l', so a[2] is incremented three more times and output the result.

The rest of the program goes on in the same way. For the space and capital letters, different array cells are selected and incremented or decremented as needed.

45
дададзена
Але чаму ён друкуе? ці як? Каментары тлумачаць мне намер лініі, што зараз гэта зрабіць.
дададзена аўтар speeder, крыніца
Я чакаў больш падрабязных тлумачэнняў ... але: /
дададзена аўтар speeder, крыніца
А таксама таму, што гэта ўстаноўка неабходных вочак для цэлалікавых значэнняў для сімвалаў ASCII ў «Hello World»
дададзена аўтар slugonamission, крыніца
@speeder - я дадаў тлумачэнне паглыбленую кода з Вікіпедыі да адказу. Вы можаце ўбачыць звязаную артыкул для атрымання дадатковай інфармацыі.
дададзена аўтар ken, крыніца
Ён друкуе, таму што кампілятар ведае, што , і . выкарыстоўваюцца для ўводу/высновы, гэтак жа, як C адбіткаў з дапамогай putchar . Гэта дэталь рэалізацыі апрацоўваецца кампілятарам.
дададзена аўтар ken, крыніца

Для таго, каб адказаць на пытанне аб тым, як ён ведае, што друкаваць, я дадаў вылічэнне значэнняў ASCII справа ад кода, дзе адбываецца друк:

> just means move to the next cell
< just means move to the previous cell
+ and - are used for increment and decrement respectively. The value of the cell is updated when the increment/decrement happens

+++++ +++++             initialize counter (cell #0) to 10

[                       use loop to set the next four cells to 70/100/30/10

> +++++ ++              add  7 to cell #1

> +++++ +++++           add 10 to cell #2 

> +++                   add  3 to cell #3

> +                     add  1 to cell #4

<<<< -                  decrement counter (cell #0)

]            

> ++ .                  print 'H' (ascii: 70+2 = 72) //70 is value in current cell. The two +s increment the value of the current cell by 2

> + .                   print 'e' (ascii: 100+1 = 101)

+++++ ++ .              print 'l' (ascii: 101+7 = 108)

.                       print 'l' dot prints same thing again

+++ .                   print 'o' (ascii: 108+3 = 111)

> ++ .                  print ' ' (ascii: 30+2 = 32)

<< +++++ +++++ +++++ .  print 'W' (ascii: 72+15 = 87)

> .                     print 'o' (ascii: 111)

+++ .                   print 'r' (ascii: 111+3 = 114)

----- - .               print 'l' (ascii: 114-6 = 108)

----- --- .             print 'd' (ascii: 108-8 = 100)

> + .                   print '!' (ascii: 32+1 = 33)

> .                     print '\n'(ascii: 10)
8
дададзена

Brainfuck same as its name. It uses only 8 characters > [ . ] , - + which makes it the quickest programming language to learn but hardest to implement and understand. ….and makes you finally end up with f*cking your brain.

Ён захоўвае значэння ў масіве: [72] [101] [108] [111]

хай, першапачаткова паказальнік паказвае на вочка 1 масіва:

  1. > move pointer to right by 1

  2. < move pointer to left by 1

  3. + increment the value of cell by 1

  4. - increment the value of element by 1

  5. . print value of current cell.

  6. , take input to current cell.

  7. [ ] loop, +++[ -] counter of 3 counts bcz it have 3 ′+’ before it, and - decrements count variable by 1 value.

значэння, якія захоўваюцца ў вочках з'яўляюцца значэннем ASCII:

так са спасылкай на масіў вышэй: [72] [101] [108] [108] [111] калі вы падыходзіце значэння ASCii вы выявіце, што гэта <�моцны> Hello writtern

Congrats! you have learned the syntax of BF

--- <�моцны> Нешта больш ---

давайце зробім нашу першую праграму г.зн. <�моцны> Hello World , пасля чаго вы зможаце напісаць сваё імя на гэтай мове.

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

разломлівання:

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

Makes an array of 4 cells(number of >) and sets a counter of 10 something like : —-psuedo code—-

array =[7,10,3,1]
i=10
while i>0:
 element +=element
 i-=1

because counter value is stored in cell 0 and > moves to cell 1 updates its value by+7 > moves to cell 2 increments 10 to its previous value and so on….

<<< return to cell 0 and decrements its value by 1

такім чынам, пасля завяршэння завесы мы маем масіў: [70,100,30,10]

>++. 

пераходзіць да элемента 1, і прырашчэнне яго значэння на 2 (два «+») і затым друкуе ( «») сімвала з гэтым значэннем ASCII. гэта значыць, напрыклад, у Python: CHR (70 + 2) # друкуе 'Н'

>+.

moves to 2nd cell increment 1 to its value 100+1 and prints(‘.’) its value i.e chr(101) chr(101) #prints ‘e’ now there is no > or < in next piece so it takes present value of latest element and increment to it only

+++++ ++..

апошняе элемент = 101, такім чынам, 101 + 7 і друкуе яго ў два разы (так як ёсць два «..») Chr (108) #prints л двойчы можа быць выкарыстаны ў якасці

for i in array:
    for j in range(i.count(‘.’)):
           print_value

--- <�моцны> Дзе яна выкарыстоўваецца? ---

Гэта проста мова жарты зрабілі выклік праграмістаў і не выкарыстоўваецца практычна ў любым месцы.

5
дададзена

Усе адказы старанна, але ім не хапае аднаго драбнюткай дэталі: друк. Пры стварэнні вашага Brainfuck перакладчык, вы таксама разгледзець сімвал . , гэта на самай справе тое, што друкаванае заяву выглядае ў Brainfuck. Так што ваш Brainfuck перакладчык павінен рабіць гэта кожны раз, калі ён сустракае . сімвал друкуецца ў дадзены момант ўказаў байт.

<�Моцны> Прыклад: </моцны>

suppose you have --> char *ptr = [0] [0] [0] [97] [0]... if this is a brainfuck statement: >>>. your pointer should be moved 3 spaces to right landing at: [97], so now *ptr = 97, after doing that your translator encounters a ., it should then call

write(1, ptr, 1)

або любой эквівалентны аператар друку для друку ў цяперашні час указаў байт, які мае значэнне 97 і ліст а затым будзе надрукаваны на std_output .

3
дададзена

Я думаю, што вы пытаецеся, як гэта Brainfuck ведае, што рабіць з усім кодам. Існуе парсер напісаны на мове больш высокага ўзроўню, такіх як Python інтэрпрэтаваць тое, што азначае, што кропка, або тое, што даданне знака азначае, што ў кодзе.

So the parser will read your code line by line, and say ok there is a > symbol so i have to advance memory location, the code is simply, if (contents in that memory location) == >, memlocation =+ memlocation which is written in a higher level language, similarly if (content in memory location) == ".", then print (contents of memory location).

Спадзяюся, што гэта ачышчае яго. ДЦ

1
дададзена