티스토리 뷰

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


이게 무엇일까? 암호문?? 이것은 브레인퍽이라는 프로그래밍 언어의 Hello World 소스이다. 저게 어떻게 Hello World를 출력한다는 건지 궁금해질 것이다. 일단 브레인퍽 인터프리터에 넣어서 진짜로 그렇게 출력하는지 보도록 하자.


브레인퍽 인터프리터 : https://kcal2845.github.io/bf_js/


정말로 Hello World!가 출력되는 것을 볼 수 있다! 그렇다면 어떻게 Hello World!를 출력하는 것일까? 브레인퍽에 대해서 자세히 알아보도록 하자.


브레인퍽(Brain Fuck)은 비속어로 되어있는 이름에서 알 수 있다시피, 프로그램 하나 짜려면 뇌를 쥐어 짜내야 한다. (이런 난해한 프로그래밍 언어를 esolang이라고 한다.) 이름이 비속어이다 보니, 줄임말인 BF라고 많이들 표현한다.


브레인퍽은 간단하게 총 8개의 문자(+ - [ ] < > , . )로 모든 것을 프로그래밍한다. 브레인퍽은 한개의 테이프와 그 테이프를 가리키는 포인터 두개를 메모리로 가지고 있다. 이 테이프와 메모리는 C언어 방식으로 표현하자면, 아래와 같이 선언되어 있다.


unsigned char tape[30000] = {0}

unsigned char * ptr = tape;


테이프는 unsigned char형으로 선언되어있고, 길이는 3만이므로 브레인퍽에서는 총 3만 바이트 용량의 메모리를 사용할 수 있다. 테이프의 각 셀(배열 한자리)에는 0에서 255 사이의 값이 들어갈 수 있다. (테이프와 각 셀의 용량은 인터프리터의 버전마다 다를 수 있다.)


+는 현재 포인터가 가리키고 있는 tape의 셀에 값에 1을 더한다. "++*ptr"와 같은 의미이다.

-는  현재 포인터가 가리키고 있는 tape의 셀에 값에 1을 빼준다. "--*ptr" 와 같은 의미이다.


>는 포인터의 값을 1 증가시킨다. "++ptr"와 같은 의미이다.

<는 포인터의 값을 1 감소시킨다. "--ptr"와 같은 의미이다.


, 는 현재 포인터가 가리키고 있는 셀에 입력한 문자를 저장한다. *ptr = getchar()와 같은 의미이다.

. 는 현재 포인터가 가리키고 있는 값을 출력한다. putchar(*ptr)과 같은 의미이다.


[은 현재 포인터가 가리키고 있는 값이 0이라면 짝이 되는 ]으로 이동한다.

]은 현재 포인터가 가리키고 있는 값이 0이 아니라면, 짝이 되는 [으로 이동한다. 


즉 " [ code ] "을 C언어로 표현하자면 다음과 같다. 

while(*ptr){ 

code

if(*ptr) break;

}


참고로 브레인퍽은 튜링 완전한 언어라고 한다. 쉽게 설명하자면, C언어로 할 수 있는 계산들은 브레인퍽으로도 전부 해낼 수 있다는 뜻이다. 그러고 보니 테이프와 포인터가 있다는 것을 보면 뭔가 튜링 머신과 비슷하다는 느낌이 들지 않는가?

 

그렇다면 이제 위에서 보았던 hello world 소스를 분석해보도록 하겠다. 위 문장을 기능별로 분리해보면 아래와 같다.


1 ++++++++++

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

3 >++.

4 >+.

5 +++++++..

6 +++.>

7 ++.

8 <<+++++++++++++++.

9 >.

10 +++.

11 ------.

12 --------.

13 >+.

14 >.


1. ++++++++++ 

간단하게 0번 셀에 10을 저장한다. 이 0번 셀은 카운터의 역할을 한다고 보면 된다.


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

1번 셀에 7, 2번에 10, 3번에 3, 4번에 1씩 더하고, 0번셀을 1씩 빼준다. 그것을 0번 셀이 0이 될때까지 반복한다는 뜻이다. 반복문이 10번 실행되므로 반복문이 끝다면 1번셀은 70, 2번셀은 100, 3번셀 30, 4번셀 10이 될 것이다.


3. >++. 이제 1번셀로 가서 2를 더하고 출력한다. 그러면 72가 되는데, 72는 ASCII 코드값으로 H가 된다. 

4. >+. 101, 즉 e를 출력한다. 

5. +++++++.. 108, 즉 l을 두번 출력한다.

6~14. 이런 식으로 계속 ASCII 코드를 더하고 빼면서 출력한다. 그러면 Hello World!의 출력이 완료된다.


그렇다면 이번에는 브레인퍽의 간단한 알고리즘을 알아보도록 하겠다. 

먼저 조금이라도 알아보기 쉽게끔 하도록 하겠다. A가 1번 셀에, B가 2번 셀에 저장되어있다고 하자.

A[B+A-] 이 문장은 

>[<+>-] 이 문장과 같은 의미이다.


X = 0 구현

아래같이 하면 된다. 이렇게 하면 X가 0이 될때까지 계속 뺀다. 값을 초기화 하거나 If문에 많이 사용한다.

X[-]

 

X = Y 구현

 

만약 복사 후 Y가 필요하지 않다면 아래와 같은 방법을 사용하면 된다. 

Y[X+ Y-]


그렇지만 X와 Y가 동시의 필요한 경우가 대부분이기 때문에 아래같이 임시 셀과 X 에 동시에 Y값을 복사해 넣은 뒤, 임시 셀에서 다시 Y에 값을 복사하는 방식으로 구현한다.

 

Y[X+ Temp+ Y-] //Y를 X와 Temp에 복사해 넣는다.

Temp[Y+ Temp-] //Temp를 Y에 복사해 넣는다.


IF(X){code1} 구현


if문은 쉽게 구현할 수 있다.

X[ code1  X[-]] 

다만 X가 사라지므로 X가 뒤에도 필요하다면 복사해두는 것이 좋다.


IF(X){code1}else{code2} 구현

T1[-] 

X[code 1 Temp[-]+ X[-]]  //X가 0이 아니라면 code1을 실행한다. 그래고 Temp를 1로 설정한다.

Temp-[code2 Temp[-]]    //만약 code 1이 실행되었다면 Temp가 0이 되므로 실행이 안됨. 아니라면 실행됨.

 

참고로 브레인퍽에서 [과 ]을 쓸 때는 반드시 주의해야 하는 것이 있다. [ 바로 앞의 포인터 상태와 \] 바로 앞에서 포인터 상태가 같아야 한다는 것이다. 예를 들어서, A[코드... A-] 이런 것은 되지만, B[코드... A] 이런 것은 되도록이면 쓰지 말아야 한다는 것이다. []안의 코드가 실행되면 포인터 안에 A의 값이 들어가고, 실행이 안되면 B의 값이 들어가기 때문이다. 이게 왜 문제가 되느냐 하면, 브레인퍽에서는 사용자가 마음대로 포인터를 이동할 수 있는게 아니라 오직 포인터 값을 증가, 감소로 이동하기 때문에 []문 뒤에 실행할 코드가 꼬이게 된다.


그래서 이번엔 간단한 ROT 13 프로그램을 만들어보았다. ROT13은 알파벳을 13글자씩 밀어서 암호화하는 것이다. 즉 A를 입력하면 N, Z를 입력하면 M이 나오는 프로그램이다. C언어로는 한줄로도 만들 수 있는 프로그램을 브레인 퍽에서는 꽤 공들여야 한다. 반복문과 대입문, 조건문을 모두 사용해야 하기 때문에 좋은 예제라고 한다. 아무래도 다른 사람이 짠 프로그램보다는 조금 엉성하긴 하다. 


//ROT13 프로그램 

>>>>, //buf = getchar()

[

<<<<+++++ +++++

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

>+++ >+++++ + // 13/26/90 으로 초기화

<[>>>+<<<-] // buf = buf 더하기 13


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

>>[<<+>>-] //x = buf


<[

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

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

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

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

<<<<->>

-] //if(buf가 90보다 크면){buf = buf 빼기 26}


<. // puchar(buf)


[-]<[-]<[-]<[-]<[-]>>>>,] // 초기화 후 입력받고 다시 반복


한줄 : 

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


실행 결과 :

실행하면 A를 입력하면 N으로, B를 입력하면 O로, Z를 입력하면 M으로 출력되는 것을 볼 수 있다. 


오늘은 이렇게 브레인퍽에 대해서 알아보았다. 프로그램 하나 짜려면 힘들지만, 재미는 있다. 이런 난해한 프로그래밍 언어에는 수십가지가 있고, 개중에는 한글로 된 언어도 있다. 여러 언어를 찾아보면서 자신의 프로그래밍 능력의 한계를 찾아보자. 난해한 프로그래밍 언어에 대한 사이트 : http://esolang.org

'프로그래밍 > 재미난것들' 카테고리의 다른 글

프로그래밍 농담들  (0) 2019.01.11
브레인퍽 C 인터프리터 아두이노 버전  (0) 2019.01.07
그림판으로 코딩하기!  (0) 2018.12.28
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함