IT

Brainfuck Hello World는 어떻게 작동 작동합니까?

lottoking 2020. 7. 30. 09:39
반응형

Brainfuck Hello World는 어떻게 작동 작동합니까?


누군가 나에게 보냈고 그것이 Brainfuck의 안녕하세요 세계라고 주장했습니다 (그리고 나는 그렇게 희망합니다 ...)

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

포인터를 움직여 물건을 늘리고 줄임 작동하는 기본 사항을 알고 ...

그래도 여전히 알고 싶습니다. 어떻게 작동 작동합니까? 처음 화면에 어떤 내용을 인쇄합니까? 텍스트를 어떻게 인코딩합니까? 나는 전혀 이해하지 않았다 ...


1. 기본

Brainfuck을 이해 비용 0에 의해 초기화 된 무한한 셀 배열을 상상해야합니다 .

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

brainfuck 프로그램이 시작되면 모든 셀을 가리고 있습니다.

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

포인터를 오른쪽 >으로 이동하면 셀 X에서 셀 X + 1로 포인터가 이동합니다.

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

당신이 셀 값을 늘리면 +당신이 얻을 :

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

셀 값을 다시 늘리면 +다음을 얻습니다.

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

셀 값을 줄이면 -얻을 수 있습니다.

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

포인터를 왼쪽 <으로 이동하면 셀 X에서 셀 X-1로 포인터가 이동합니다.

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

2. 입력

문자를 사용하려면 쉼표를 사용하십시오 ,. 기능 : 표준 입력에서 문자를 읽고 10 진수 ASCII 코드를 실제 셀에 사용합니다.

ASCII 테이블을 대상으로 합니다. 예를 들어, 십진수 코드는 !IS 33이지만, a는 것입니다 97입니다.

BF 프로그램 메모리가 다음과 같다고 상상해.

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

표준 입력이 의미입니다 가정하고 a쉼표 ,연산자 를 사용하면 BF 가하는 일 a십진 ASCII 코드 97를 메모리로 읽는 것 .

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

일반적으로 그렇게 생각하고 싶지만 진실은 좀 더 복잡합니다. 진실은 BF가 문자를 읽지 않고 바이트 (그 바이트가 무엇이든)를 읽습니다. 예를 보여 드리겠습니다.

리눅스에서

$ printf ł

인쇄물 :

ł

특정 특성입니다. 이 문자는 ASCII 인코딩으로 인코딩되지 않습니다. 이 경우 UTF-8 인코딩 컴퓨터 메모리에서 둘 이상의 바이트를 사용했습니다. 16 개의 진수를 만들어서 증명할 수 있습니다.

$ printf ł | hd

그것은 보여줍니다 :

00000000  c5 82                                             |..|

0이 변경됩니다. 82첫 번째이고 c5두 번째 바이트이며 ł(순서대로 읽을 것입니다). |..|이 경우에는 불가능한 그래픽 표현입니다.

ł단일 바이트를 읽는 BF 프로그램에 입력으로 전달하면 프로그램 메모리는 다음과 가변 됩니다.

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

197? 음의 197진수는 c5진수. 익숙한 것 같습니까? 물론이야. 첫 바이트입니다 ł!

3. 출력

도트를 사용하는 문자를 인쇄하여 .다음을 수행하십시오. 실제 셀 값을 10 진수 ASCII 코드처럼 취급 가정하면 해당 문자를 표준 출력으로 인쇄하십시오.

BF 프로그램 메모리가 다음과 같다고 상상해.

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

도트 (.) 연산자를 사용하는 경우 BF의 기능은 다음과 같습니다.

때문에 aASCII의 진수 코드입니다 97.

예를 들어 다음과 같은 BF 프로그램 (97 더하기 2 도트) :

++++++++++++++++++++++++++++++++++++++++++++++++++ ++ +++++++++++++++++++++++++++++++++++++++++++++++. .

셀의 값이 97까지 올라가 2 회 출력됩니다.

aa

4. 루프

BF에서 루프는 루프 시작 [과 루프 끝으로 구성 ]됩니다. 조건이 실제 셀 값인 C / C ++에서와 같다고 생각할 수 있습니다.

아래에서 BF 프로그램을 사용합니다.

++[]

++ 실제 셀 값을 두 번 개선합니다.

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

그리고 []같으 while(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를 덜 현혹하게 만듭니다.


Wikipedia 에는 주석이 달린 달린 코드 버전이 있습니다.

+++++ +++++             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'

질문에 대답하기 위해 ,.문자는 I / O에 사용됩니다. 텍스트는 ASCII입니다.

위키 백과의 문서뿐만 아니라, 좀 더 깊이에 간다.

첫번째 라인의 처음 상태 a[0] = 10단순히 라인 (2)로부터의 루프는 효과적으로 어레이의 초기 값으로 설정 0 후 10 배 증가되어 : a[1] = 70(근접 72를, 문자 'H'을위한 ASCII 코드) a[2] = 100(확대 101 또는 'E' ), a[3] = 30(32에 가까움, 공백 코드) 및 a[4] = 10(줄 바꿈). 루프는 7, 10, 3, 1, 세포에 첨가하여 작동 a[1], a[2], a[3]a[4]10 개를 추가 셀마다 총 (주기 - 루프를 각각마다 a[1]=70등). 루프가 끝나면 a[0]0입니다. >++.그런 다음 포인터를로 이동하여 a[1]70을 유지하고 여기에 2를 더한 다음 (대문자 H의 ASCII 문자 코드 인 72를 생성 함) 출력합니다.

다음 줄은 배열 포인터를 이동 a[2]하고 여기에 하나를 추가하여 101을 생성하고 소문자 'e'를 출력합니다.

'l'은 'e'뒤의 일곱 번째 문자이므로 'll'을 출력하려면 또 다른 7 개를 추가하고 ( +++++++) a[2]결과를 두 번 출력합니다.

'o'는 'l'뒤의 세 번째 문자이므로 a[2]세 번 더 증가하여 결과를 출력합니다.

나머지 프로그램도 같은 방식으로 진행됩니다. 공백과 대문자의 경우 다른 배열 셀이 선택되고 필요에 따라 증가 또는 감소합니다.


인쇄 할 내용을 어떻게 아는지에 대한 질문에 답하기 위해 인쇄가 발생하는 코드 오른쪽에 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)

이름과 같은 Brainfuck . 그것은 단지 8 자 사용 > [ . ] , - +가 만드는 빠른 프로그래밍 언어를 배울 수 있지만, 어려운에 구현하고 이해합니다. …. 그리고 마침내 당신의 두뇌를 망쳐 버리게 만듭니다.

배열에 값을 저장합니다. [72] [101] [108] [111]

let, 처음에는 배열의 셀 1을 가리키는 포인터 :

  1. > 포인터를 오른쪽으로 1만큼 이동

  2. < 포인터를 왼쪽으로 1 이동

  3. + 셀 값을 1 씩 증가

  4. - 요소의 값을 1 씩 증가

  5. . 현재 셀의 값을 인쇄합니다.

  6. , 현재 셀에 입력합니다.

  7. [ ] loop, +++ [-] 카운터 3 카운트 bcz 앞에 3 '+'가 있고-카운트 변수를 1 값만큼 감소시킵니다.

셀에 저장된 값은 ASCII 값입니다.

따라서 위의 배열을 참조하면 : [72] [101] [108] [108] [111] ascii 값과 일치하면 Hello writtern 이라는 것을 알 수 있습니다.

축하합니다! BF의 구문을 배웠습니다.

——- 뭔가 더 ———

첫 번째 프로그램 인 Hello World를 만들고 그 후에이 언어로 이름을 쓸 수 있습니다.

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

조각으로 나누기 :

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

4 개의 셀 (> 개수)의 배열을 만들고 카운터를 10으로 설정합니다. —-psuedo code—-

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

카운터 값은 셀 0에 저장되고> 셀 1로 이동하면 값이 +7만큼 업데이트되고> 셀 2로 이동하면 이전 값으로 10 씩 증가하는 식으로 계속됩니다.

<<< 셀 0으로 돌아가서 값을 1 씩 감소시킵니다.

따라서 루프 완료 후 배열이 있습니다. [70,100,30,10]

>++. 

첫 번째 요소로 이동하여 값을 2 ( '+'두 개) 씩 증가시킨 다음 해당 ASCII 값으로 문자를 인쇄 ( '.')합니다. 예를 들어 파이썬에서 : chr (70 + 2) # 'H'를 출력합니다.

>+.

두 번째 셀 증분 1로 이동하여 값 100 + 1로 인쇄 ( '.') 해당 값 ie chr (101) chr (101) #prints 'e'이제 다음 조각에> 또는 <가 없으므로 현재 값을 사용합니다. 최신 요소 만 증가시키고

+++++ ++..

따라서 latest element = 101, 101 + 7 그리고 두 번 인쇄합니다 (2 '..') chr (108) #prints l 두 번 사용할 수 있습니다.

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

——— 어디에 사용됩니까? ——-

프로그래머에게 도전하기 위해 만들어진 농담 언어 일 뿐이며 거의 모든 곳에서 사용되지 않습니다.


모든 답변은 철저하지만 인쇄라는 작은 세부 사항이 없습니다. brainfuck 번역기를 만들 때 캐릭터도 고려합니다 .. 이것은 실제로 brainfuck에서 인쇄 문이 어떻게 보이는지입니다. 그래서 당신의 brainfuck 번역가는 .문자를 만날 때마다 현재 가리키는 바이트를 인쇄합니다.

예:

-> char *ptr = [0] [0] [0] [97] [0]... 만약 이것이 brainfuck 진술이라면 : >>>.포인터를 오른쪽으로 3 칸 이동해야합니다 : [97], 그래서 이제 *ptr = 97번역자가 a를 만나면 .다음을 호출해야합니다.

write(1, ptr, 1)

또는 현재 가리키는 바이트를 인쇄하는 동등한 인쇄 명령문으로 값이 97 이고 문자 astd_output.


당신이 묻는 것은 Brainfuck이 모든 코드로 무엇을해야하는지 어떻게 아는가하는 것입니다. 점이 무엇을 의미하는지 또는 코드에서 더하기 기호가 의미하는 바를 해석하기 위해 Python과 같은 상위 수준 언어로 작성된 파서가 있습니다.

따라서 파서는 코드를 한 줄씩 읽고 확인> 기호가 있으므로 메모리 위치를 전진해야합니다. 코드는 간단히 다음과 같습니다. if (해당 메모리 위치의 내용) ==>, memlocation = + memlocation 비슷하게 (메모리 위치의 내용) == "."이면 (메모리 위치의 내용)을 인쇄합니다.

이것이 해결되기를 바랍니다. tc

참고 URL : https://stackoverflow.com/questions/16836860/how-does-the-brainfuck-hello-world-actually-work

반응형