브레인퍽
Brainfuck![]() |
패러다임 | 난해하고, 명령적이고, 구조화된 |
---|---|
설계자 | 어반 뮐러 |
처음 등장했습니다. | 1993년9월 |
타이핑 종목 | 타이프리스 |
파일 이름 확장자 | .b, .bf |
에 의해 영향을 받았습니다. | |
P', FALSE | |
영향받은 | |
말볼지 |
브레인퍽은 어반 뮐러가 1993년에 만든 난해한 프로그래밍 언어입니다.[1] 극도의 미니멀리즘으로 유명한 이 언어는 8개의 간단한 명령어, 데이터 포인터 및 명령어 포인터로 구성되어 있습니다.[2]
브레인퍽은 소위 튜링 타핏(Turing tarpit)의 한 예입니다. 모든 프로그램을 작성하는 데 사용할 수 있지만 브레인퍽은 추상화를 거의 제공하지 않아 프로그램이 매우 길어지거나 복잡해지기 때문에 그렇게 하는 것은 실용적이지 않습니다. 브레인퍽은 튜링이 완전히 완성되었지만 실용적인 용도가 아니라 프로그래머에게 도전하고 즐겁게 해주기 위한 것입니다.[3][4] 브레인퍽은 명령을 미세한 단계로 쪼개는 데 필요합니다.
이 언어의 이름은 비속어 브레인퍽(brainfuck)을 가리키는 말로, 실제 소프트웨어를 설계하기 위해 의도되거나 만들어진 것이 아니라 컴퓨터 프로그래밍의 경계에 도전하기 위해 만들어졌기 때문에 이해의 한계를 초과할 정도로 복잡하거나 특이한 것을 말합니다.
언어의 이름에 비속어가 포함되어 있기 때문에 brainfsck, branflake, brainof, brainfrick, BF와 같은 많은 대체어가 사용됩니다.[5]
역사
뮐러는 FALSE 프로그래밍 언어를 위한 1024바이트 컴파일러에서 영감을 받아 [6]가능한 가장 작은 컴파일러를 구현하는 것을 목표로 브레인퍽을 설계했습니다.[7] 뮐러의 오리지널 컴파일러는 기계어로 구현되어 크기 296바이트의 이진법으로 컴파일되었습니다. 그는 1993년에 최초의 브레인퍽 컴파일러를 아미네에 업로드 했습니다. 프로그램은 언어를 간단히 설명하는 "Readme" 파일과 함께 제공되었으며 독자에게 "누가 유용한 프로그램을 프로그래밍할 수 있습니까? :)"라고 물었습니다. 뮐러는 또한 통역사와 몇 가지 예를 포함했습니다. 두 번째 버전의 컴파일러는 240바이트만 사용했습니다.[8]
P'
Brainfuck은 두 개의 I/O 명령어를 제외하고 1964년 Corrado Böhm이 만든 공식 프로그래밍 언어 P'의 사소한 변형으로, 명시적으로 튜링 기계를 기반으로 합니다. 실제로 Brainfuck 명령어에 해당하는 6개의 기호를 사용합니다. +
, -
, <
, >
, [
, ]
, Böhm은 모든 계산 가능한 함수를 계산하는 역할을 하는 각 기본 함수에 대한 명시적인 프로그램을 제공했습니다. 그래서 최초의 브레인퍽 프로그램은 뵌교의 1964년 논문에 등장하며 튜링의 완전성을 증명하는 데 충분했습니다.
언어디자인
언어는 8개의 명령어로 구성되어 있습니다. 브레인퍽 프로그램(brainfuck program)은 이러한 명령어들의 시퀀스로, 다른 문자들과 함께 흩어져 있을 가능성이 있습니다(이들은 무시됩니다). 명령어들은 순차적으로 실행되며, 일부 예외를 제외하고는 명령어 포인터가 첫 번째 명령어에서 시작되고, 명령어 포인터가 가리키는 각 명령어가 실행되며, 그 후에는 일반적으로 다음 명령어로 넘어갑니다. 명령 포인터가 마지막 명령어를 지나 이동하면 프로그램이 종료됩니다.
브레인퍽 언어는 프로그램과 명령어 포인터로 구성된 간단한 기계 모델과 적어도 30개 이상의 1차원 배열을 사용합니다.0으로 초기화된 000 바이트 셀, 이동 가능한 데이터 포인터(배열의 가장 왼쪽 바이트를 가리키도록 초기화됨), 입력 및 출력을 위한 2개의 바이트 스트림(가장 자주 키보드와 모니터에 각각 연결되고 ASCII 문자 인코딩을 사용함).
8개의 언어 명령어는 각각 하나의 문자로 구성됩니다.
성격 | 의미. |
---|---|
> | 데이터 포인터를 1씩 늘립니다(오른쪽 옆의 셀을 가리킵니다). |
< | 데이터 포인터를 한 개씩 줄입니다(왼쪽에서 다음 셀을 가리킵니다. |
+ | 데이터 포인터의 바이트를 1씩 늘립니다. |
- | 데이터 포인터의 바이트를 1씩 줄입니다. |
. | 데이터 포인터에서 바이트를 출력합니다. |
, | 데이터 포인터의 바이트에 해당 값을 저장하는 입력 1바이트를 수락합니다. |
[ | 데이터 포인터의 바이트가 0이면 명령 포인터를 다음 명령으로 이동하는 대신 일치 후 명령으로 점프합니다. ] 지휘권을 쥐다 |
] | 데이터 포인터의 바이트가 0이 아닌 경우 명령 포인터를 다음 명령으로 이동하는 대신 일치 후 명령으로 다시 점프합니다. [ 지휘권을 [a]쥐다 |
[
그리고. ]
괄호 안은 보통 다음과 같이 일치합니다. [
꼭 일치하는 ]
그리고 그 반대의 경우도 마찬가지입니다. [
가장 먼저 오고, 타의 추종을 불허합니다. [
또는 ]
둘 사이에
이름에서 알 수 있듯이 브레인퍽 프로그램은 이해하기 어려운 경향이 있습니다. 이것은 부분적으로 약간 복잡한 작업은 긴 일련의 명령을 필요로 하기 때문이고, 부분적으로는 프로그램의 텍스트가 프로그램의 상태를 직접적으로 표시하지 않기 때문입니다. 브레인퍽의 비효율성과 제한된 입출력 기능뿐만 아니라 이것들은 심각한 프로그래밍에 사용되지 않는 몇 가지 이유입니다. 그럼에도 불구하고, 다른 튜링 완전 언어와 마찬가지로 브레인퍽은 이론적으로 무한한 양의 메모리에 접근할 수 있다면 어떤 계산 가능한 함수를 계산하거나 다른 계산 모델을 시뮬레이션할 수 있습니다.[9] 다양한 브레인퍽 프로그램이 작성되었습니다.[10] Brainfuck 프로그램, 특히 복잡한 프로그램은 쓰기가 어렵지만 C와 같은 더 전형적인 언어로 Brainfuck의 통역사를 작성하는 것은 간단하기 때문에 상당히 사소합니다. 심지어 브레인퍽 언어 자체로 작성된 브레인퍽 통역사도 존재합니다.[11][12]
예
2개의 값 추가
첫 번째 간단한 예로, 다음 코드 스니펫이 현재 셀의 값을 다음 셀에 추가합니다. 루프가 실행될 때마다 현재 셀이 감소하고 데이터 포인터가 오른쪽으로 이동하며 다음 셀이 증가하고 데이터 포인터가 다시 왼쪽으로 이동합니다. 이 순서는 시작 셀이 0이 될 때까지 반복됩니다.
[->+<]
이는 다음과 같이 간단한 덧셈 프로그램에 통합될 수 있습니다.
++ Cell c0 = 2 > +++++ Cell c1 = 5 [ 루프 카운터에서 셀 포인터로 루프를 시작합니다(c1의 경우). < + Add 1 to c0 > - c1에서 1 빼기 ] 루프 카운터의 셀 포인터로 루프를 종료합니다. 이 시점에서 우리 프로그램은 5 대 2를 추가하여 c0에 7, c1에 0을 남겼습니다. 그러나 ASCII 인코딩이 아니기 때문에 이 값을 터미널에 출력할 수 없습니다. ASCII 문자 "7"을 표시하려면 값 7에 48을 추가해야 합니다. 루프를 사용하여 48 = 6 * 8 을 계산합니다. ++++ ++++ c1 = 8 그리고 이것은 다시 우리의 루프 카운터가 될 것입니다. [ < +++ +++ Add 6 to c0 > - c1에서 1 빼기 ] < . "7"로 번역되는 값 55를 가지는 c0을 출력합니다!
안녕 월드!
다음 프로그램은 "Hello World!"와 화면에 새 줄을 출력합니다.
[ 이 프로그램은 "Hello World!"와 화면에 새 줄을 출력합니다. 길이는 106개의 활성 명령어 문자입니다.. [그것은 가장 짧지 않습니다..] 이 루프는 "초기 코멘트 루프"입니다., 평을 덧붙이는 간단한 방법 명령에 대해 걱정할 필요가 없도록 BF 프로그램에. 성격.. 임의".", ",", "+", "-", "<" 그리고 ">" 캐릭터는 단순합니다. 무시한, 더.[" 그리고 "]" 캐릭터는 균형이 잡혀야 합니다.. 이것. 루프 및 루프에 포함된 명령은 현재 셀 때문에 무시됩니다. 기본값은 0이고, 0 값을 사용하면 이 루프를 건너뛸 수 있습니다.. ] ++++++++ 셀 #0에서 8로 설정 [ >++++ 셀 #1에 4를 추가합니다. 그러면 항상 셀 #1이 4로 설정됩니다. [ 루프에 의해 셀이 제거되기 때문에 >++ 셀 #2에 2 추가 >+++ 셀 #3에 3 추가 >+++ 셀 #4에 3 추가 >+ 5번 셀에 1 추가 <<<<- Cell #1의 루프 카운터 감소 ] 셀 #1이 0이 될 때까지 루프, 반복 횟수는 4번입니다. >+ 셀 #2에 1 추가 >+ 셀 #3에 1 추가 >- 셀 #4에서 1 빼기 >>+ 6번 셀에 1 추가 [<] 처음 발견한 0 셀로 다시 이동합니다. 이렇게 하면 됩니다. 이전 루프에서 제거된 1번 셀입니다. <- 셀 #0에서 루프 카운터 축소 ] 셀 #0이 0이 될 때까지 루프, 반복 횟수는 8입니다. 결과는 다음과 같습니다. 핸드폰 번호 : 0 1 2 3 4 5 6 내용 : 0072 104 88 328 포인터 : ^ >>. 2번 셀의 값은 'H'입니다. >---. 3번 셀에서 3을 빼면 101이 'e'가 나옵니다. +++++++..+++. 마찬가지로 3번 셀의 'lo'도 마찬가지입니다. >>. 5번 셀은 공간에 대해 32입니다. <-. 87번에 해당하는 4번 셀에서 1을 빼면 'W'가 나옵니다. <. 3번 셀은 'Hello' 끝부터 'o'로 설정되었습니다. +++.------.--------. 'rl'과 'd'의 셀 #3 >>+. 5번 셀에 1을 더하면 느낌표가 나옵니다. >++. 그리고 마지막으로 6번 셀의 새로운 라인이 있습니다.
"가독성"을 위해 이 코드는 여러 줄에 걸쳐 퍼졌고 빈칸과 댓글이 추가되었습니다. 브레인퍽은 8개의 명령어를 제외한 모든 문자를 무시합니다. +-<>[],.
따라서 주석에 대한 특별한 구문이 필요하지 않습니다(댓글에 명령어 문자가 포함되어 있지 않은 경우). 코드는 다음과 같이 작성될 수도 있었습니다.
++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
인쇄하는 코드 골프 버전의 또 다른 예 Hello, World!
:[13]
+[-->-[>>+>-----<<]<--<---]>-.>>>+.>>..+++[.>]<<<<.+++.------.<<-.>>>>+.
ROT13
이 프로그램은 입력을 ROT13 암호로 암호화합니다. 이렇게 하려면 문자 A-M(ASCII 65–77)을 N-Z(78-90)에 매핑해야 하며, 그 반대의 경우도 매핑해야 합니다. 또한 a-m(97-109)을 n-z(110-122)로 매핑해야 합니다. 다른 모든 문자를 자신에게 매핑해야 합니다. 문자를 한 번에 하나씩 읽고 프로그램이 종료되는 EOF(여기서는 -1 또는 "변경 없음"으로 표시됨)를 읽을 때까지 암호화된 동등한 문자를 출력합니다.
-,+[ 첫 번째 문자 읽기 및 외부 문자 읽기 루프 시작 -[ 문자가 0이면 앞으로 건너뛰기 >>++++[>++++++++<-] 나눗셈 루프에 대한 나눗셈 설정(32) (MEMORY LOADY : 배당 복사잔액 분배계수 0) <+<-[ 배당(x - 1) 설정 후 분할루프 입력 >+>+>-[>>>] 복사 및 나머지 증가 / 나눗셈 줄이기 / 일반 케이스: 앞으로 건너뛰기 <[[>+<-]>>+>] 특수한 경우: 나머지를 다시 나눗셈으로 이동하고 quotient를 증가시킵니다. <<<<<- 감액배당 ] 종단 분할 루프 ]>>>[-]+ 건너뛰기 루프 종료; 이전의 나눗셈기 0개 및 플래그에 대한 재사용 공간 >--[-[<->+++[-]]]<[ quotient가 2 또는 3이 아니면 해당 플래그 0, quotient 0, check 플래그 ++++++++++++<[ 플래그가 있는 경우 2분할 루프에 대해 디바이저(13)를 설정합니다. (MEMORY LOADY : 0 복사 배당 제수 잔량 0) >-[>+>>] 나눗셈 줄이기; 정상인 경우: 나머지 증가 >[+[<+>-]>+>>] 특수한 경우: 잔량 증가 / 나눗셈으로 다시 이동 / quotient 증가 <<<<<- 배당감소 ] 종단 분할 루프 >>[<+>-] 나머지를 다시 나눗셈에 더하면 유용한 13을 얻을 수 있습니다. >[ 몫이 0인 경우 앞으로 건너뛰기 -[ 감소 몫 및 몫이 1인 경우 앞으로 건너뛰기 -<<[-]>> 몫이 2인 경우 몫과 약수 0 ]<<[<<->>-]>> 몫이 1인 경우 0 나눗셈 및 복사에서 13을 뺀 값 ]<<[<<+>>-] 몫이 0이면 나눗셈을 0으로 하고 13을 더해서 복사합니다. ] 외부 건너뛰기 루프 종료(((문자 - 1)/32가 2 또는 3이 아닌 경우 여기로 점프) <[-] 두 번째 분할을 건너뛸 경우 첫 번째 분할에서 나머지 삭제 <.[-] 복사 후 지우기에서 ROT13ed 문자 출력 <-,+ 다음 문자 읽기 ] 끝 문자 읽기 루프
참고 항목
메모들
- ^ 그 대신에.
]
명령어는 대신 해당 명령어로 무조건 점프하는 것으로 번역될 수 있습니다.[
명령어 또는 그 반대입니다. 프로그램은 동일하게 동작하지만 불필요한 이중 검색으로 인해 더 느리게 실행됩니다.
참고문헌
- ^ Easter, Brandee (2020-04-02). "Fully Human, Fully Machine: Rhetorics of Digital Disembodiment in Programming". Rhetoric Review. 39 (2): 202–215. doi:10.1080/07350198.2020.1727096. ISSN 0735-0198. S2CID 219665562.
- ^ Temkin, Daniel (2017-09-01). "Language without code: intentionally unusable, uncomputable, or conceptual programming languages". Journal of Science and Technology of the Arts. 9 (3): 83–91. doi:10.7559/citarj.v9i3.432. ISSN 2183-0088.
- ^ 헉, 마이클. "콜라에서 브레인퍽 구현 중"
- ^ 콕스, 제프, 알렉스 맥린. "재미만을 위한 것이 아닙니다." 블룸스버리 아카데미, 2014. 157-173.
- ^ "brainfuck - Esolang". esolangs.org. Retrieved 2024-02-07.
- ^ "The Brainfuck Programming Language". Muppetlabs.com. Retrieved 2023-04-30.
- ^ "The FALSE Programming Language — Wouter van Oortmerssen". Strlen.com. 2013-08-03. Retrieved 2023-04-30.
- ^ "Aminet - dev/lang/brainfuck-2.lha". Aminet. Retrieved 2023-04-30.
- ^ "BF is Turing-complete". Iwriteiam.nl. Retrieved 2023-04-30.
- ^ "Index of /esoteric/brainfuck/bf-source/prog". sange.fi. 2002-01-22. Retrieved 2023-04-30.
- ^ "BF interpreter written in BF". Iwriteiam.nl. Retrieved 2023-04-30.
- ^ "brainfuck interpreter". Daniel B. Cristofani.
- ^ "code golf - "Hello, World!" - Code Golf Stack Exchange". Retrieved 2023-04-29.