미래 지향적인 웹 앱 구축: The Codest의 전문가 팀이 제공하는 인사이트
The Codest가 최첨단 기술로 확장 가능한 대화형 웹 애플리케이션을 제작하고 모든 플랫폼에서 원활한 사용자 경험을 제공하는 데 탁월한 성능을 발휘하는 방법을 알아보세요. Adobe의 전문성이 어떻게 디지털 혁신과 비즈니스를 촉진하는지 알아보세요...
"실용적인 프로그래머"라는 책(아직 읽지 않았다면 이 글을 읽지 말고 지금 당장 읽으세요!)에 따르면 매년 새로운 프로그래밍 언어를 하나씩 배워야 한다고 합니다.
너무 많은 노력이 필요하다고 주장하는 사람들도 있지만, 좋은 생각이라는 데는 모두 동의할 수 있습니다. 새로운 언어를 배우는 것은 그리 쉬운 일이 아닙니다. 실제로는 전혀 사용하지 않을지도 모르는 언어에 시간을 투자하고 싶지는 않잖아요, 그렇죠? 하지만 가끔은 예외를 인정하고 재미를 위해 무언가를 배워야 하지 않을까요? 저는 여러분께 브레인퍽 언어를 소개해드리고자 합니다. 몇 분이면 배울 수 있는 언어이기 때문에 시간을 헛되이 투자할 염려가 없습니다. 또한 Brainfuck으로 문제를 해결하면 두뇌를 자극 할 것이라고 약속 할 수 있습니다 (모든 씨발은 보너스 일뿐입니다 ;)). 시작합시다!위키피디아에 따르면:
Brainfuck 는 난해한 프로그래밍 언어 1993년 어반 뮐러가 만들었습니다. 이 언어는 8개의 간단한 명령어와 명령 포인터로만 구성되어 있습니다. 튜링을 완벽하게 지원하지만 실용적인 용도가 아니라 프로그래머에게 도전과 재미를 주기 위한 것입니다.
셀로 구성된 무한히 긴 리본(또는 테이프)이 있고 각 셀은 0으로 초기화되어 있다고 상상해 보세요. 또한 처음에 첫 번째 셀을 가리키는 이동식 데이터 포인터가 있습니다. 입력과 출력을 위한 두 개의 바이트 스트림도 있습니다. 명령어는 하나씩 순차적으로 실행됩니다. 마지막 명령어를 실행한 후 기계는 멈춥니다.
명령
어떤 기능을 하나요?
>
데이터 포인터를 오른쪽의 다음 셀로 이동합니다.
<
데이터 포인터를 왼쪽의 다음 셀로 이동합니다.
+
현재 셀의 증분 값
–
현재 셀의 감소 값
.
현재 가리키는 셀의 바이트를 ASCII로 출력합니다. 코드
,
STDIN에서 1바이트를 읽고 현재 셀에 해당 값을 저장합니다.
[
현재 셀이 0이면 일치하는 ]로 이동합니다.
]
일치하는 [
다음을 제외한 모든 문자 ><+-.,[]
는 무시됩니다.
간단한 예를 살펴보겠습니다:
,+.
다음과 같이 해석됩니다:
결과적으로 입력에서 한 문자가 읽혀지고 ASCII 테이블에서 다음 문자가 인쇄됩니다.
브레인퍽에서 유용한(?) 프로그램을 작성하기 위해서는 인터프리터나 컴파일러가 필요합니다. 아쉽게도 공식적인 것은 없지만 문제될 것은 없습니다. 인터넷에는 비공식적으로 수십 개가 있습니다. 이 두 가지를 추천해드릴 수 있습니다:
"Hello World!"는 우리가 새로운 언어를 배우면서 가장 먼저 작성하는 프로그램이어야 합니다. 하지만 브레인퍽으로 작성하는 것은 다른 언어보다 조금 더 어렵습니다. 좀 더 쉬운 것부터 시작해야 하는데요... 화면에 "H" 한 글자를 출력하는 프로그램을 작성해 봅시다(너무 신나네요 :D):
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.
어떻게 작동하나요? 현재 셀의 값을 72로 설정하고(72 단위로 증가) "."를 사용하여 화면에 인쇄합니다(H는 ASCII에서 코드 72를 가짐). 이제 화면에 "Hello World!"를 출력하기 위해 무엇을 해야 하는지 알겠지만, 그 전에 작은 리팩터링을 해보겠습니다. 이 모든 '+'를 작성하려면 너무 많은 타이핑과 계산이 필요합니다. 다음을 사용하여 더 짧게 만들 수 있습니다. [
그리고 ]
를 사용합니다. 예를 들어 값을 72로 설정하려면 값을 10씩 7번 증가시키는 루프를 만들 수 있습니다. 이렇게 하면 70이 됩니다. 2를 더하면 72가 됩니다. 이렇게 됩니다:
++++++++++ # 셀0을 10으로 설정
[ 셀0이 0이 될 때까지 # 반복
- # 셀0 감소
> # 데이터 포인터를 오른쪽으로 이동(셀1)
+++++++ # 셀1 7 증가
# 데이터 포인터를 오른쪽으로 이동(셀1)
++ # 2 증가
. # 결과를 인쇄합니다.
모든 것이 어떻게 작동하는지 명확하게 설명하기 위해 주석을 달았습니다. 댓글이 없는 동일한 프로그램:
++++++++++[->+++++++++.
예쁘지 않나요? 🙂
"Hello World!" 프로그램으로 돌아가 보겠습니다. 첫 번째 셀의 값을 72(H)로 설정하여 인쇄하고, 두 번째 셀의 값을 101(e)로 설정하여 인쇄하고, 세 번째 셀의 값을 108로 설정하여 인쇄하는 등의 작업을 수행할 수 있습니다. 이 알고리즘의 구현은 다음과 같습니다:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
++++++++++++++++++++++++++++++++.>
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
+++++++++++++++++++++++++++++++++.>
저는 한 글자 한 글자 쓸 만큼 미치지 못하기 때문에 약간 속임수를 써서 루비로 이 프로그램을 생성했습니다:
puts "Hello World!".chars.map { |c| c.ord.times.map { "+" }.join + ".>" }.join("n")`
네, "Hello World!"를 인쇄하는 데 1120바이트밖에 안 됩니다... 하지만 더 잘할 수 있습니다! 각 문자에 대해 새 셀을 사용하는 대신 하나만 사용하겠습니다. 문자 "e"(101)를 인쇄하려면 셀0(72)의 값을 재사용할 수 있습니다. 29배(101 - 72)로 1씩 증가시킬 수 있습니다. 결과는 다음과 같습니다:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.
+++++++++++++++++++++++++++++.
+++++++.
.
+++.
-------------------------------------------------------------------------------.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++.
++++++++++++++++++++++++.
+++.
------.
--------.
-------------------------------------------------------------------.
또 속임수를 썼어요!
puts "Hello World!".chars.inject(["", 0]) { |(code, prev), char| [code + "++-"[char.ord - prev 0] * (char.ord - prev).abs + ".n", char.ord] }[0]) }[0]`)
큰 진전을 이루었습니다. 1120바이트에서 377바이트로 줄었습니다. 하지만 여전히 개선의 여지가 있습니다. 몇 가지 아이디어를 알려드리겠습니다:
+
그리고 -
다음은 이러한 아이디어를 사용한 Wikipedia의 버전입니다:
++++++++[>++++[>++>+++>+++>+<<<+>+>->>+[<]>.>---.+++++++..+++.>>.<-.>+.>++.
106바이트에 불과하고 마지막에 새 줄을 인쇄합니다! 놀랍습니다.
이제 좀 더 어려운 것을 작성할 준비가 되었습니다. 입력에서 한 줄을 읽고 역순으로 인쇄하는 프로그램을 작성해 보겠습니다. 첫 번째 문제는 문자를 읽고 새 줄 문자에서 멈추는 것입니다. 기억하세요. break
, 만약
또는 기타 유사한 문장을 사용해야 합니다. 다음을 사용해야 합니다. [
그리고 ]
. 입력된 모든 문자를 읽고 연속된 셀에 넣는 프로그램부터 시작해 보겠습니다:
,[>,]
첫 번째 문자 읽기부터 시작하여 마지막 문자까지 계속됩니다. ,
연산 반환 0
. 그러나 구현에서 영원히 반복되어 다음과 같은 다른 것을 반환합니다. O
에 대한 EOF
(언어에서 이 동작을 지정하지 않음). 그렇다면 새 줄 문자에서 어떻게 멈출 수 있을까요? 여기에 트릭이 있습니다:
+[++++++++++>,----------]
셀0을 1로 설정하여 루프가 한 번 이상 실행되도록 합니다. 루프에서는 현재 셀의 값을 10씩 증가시키고, 데이터 포인터를 다음 셀로 이동하고, 한 문자를 읽고 그 값을 10씩 감소시킵니다. 이렇게 하면 새 줄 문자(ASCII로 10)를 읽으면 다음 반복에서 프로그램이 중지되고, 그렇지 않으면 10을 더하여 값이 복원됩니다.
이 단계가 끝나면 세포는 다음과 같은 모양이 됩니다:
11 C1 C2 C3 0* 0 0
Cn
는 입력에서 n번째 문자이고 *
는 현재 데이터 포인터 위치입니다. 이제 데이터 포인터를 왼쪽으로 이동하기 시작하고 값 11에 도달할 때까지 모든 셀을 인쇄해야 합니다. 이 작업에 대한 제 생각은 다음과 같습니다:
+[++++++++++>,----------]<-----------[+++++++++++.<-----------]
직접 분석해 보시기 바랍니다 :-).
난해한 프로그래밍 언어인 브레인퍽을 처음 접했을 때, 처음에는 그저 기믹이나 농담에 불과한 것으로 치부했습니다. 이 독특하고 많은 사람들이 주장하는 것처럼 놀라울 정도로 어려운 언어는 저에게 단지 재미를 위한 것으로만 보였습니다. 하지만 시간이 지나면서 브레인퍽에 대한 제 인식은 크게 바뀌었습니다.
브레인퍽의 수수께끼 같은 특성은 여러분에게 도전을 주며, 다음 사항에 대한 관점을 넓히도록 유도합니다. 프로그래밍 언어. 이 난해한 언어를 통해 우리에게 익숙한 고급 언어의 아름다움과 필요성을 이해할 수 있습니다. 프로그래밍 언어의 영역에서 추상화, 적절한 명명 규칙, 체계적인 메모리 레이아웃의 중요성에 초점을 맞출 수 있습니다. 이는 단 8개의 간단한 명령어로 구성된 미니멀한 디자인의 Brainfuck이 제공하지 못하는 부분입니다.
브레인퍽은 명확하고 일관된 소스 코드의 중요성을 더욱 강조하는 튜링 완전 언어입니다. 프로그램을 작성하기 가장 어려운 난해한 언어 중 하나로 알려져 있지만, 아이러니하게도 브레인퍽 컴파일러나 브레인퍽 인터프리터를 직접 만들고자 하는 초보자들이 가장 선호하는 언어이기도 합니다. 그 이유는 명령 집합이 단순하고 복잡한 구문 분석이 필요하지 않기 때문입니다.
브레인퍽 프로그램을 만드는 것은 두 가지 면에서 독특합니다. 첫째, 단일 메모리 포인터 사용에 적응해야 하므로 소스 코드를 다르게 생각해야 합니다. 둘째, 메모리 셀을 0으로 초기화하는 기능인 '제로 옵션'이 있는데, 이는 다른 공식 프로그래밍 언어에서는 흔히 볼 수 없는 기능입니다.
학습 측면에서 보면 Brainfuck에는 눈에 보이는 것 이상의 것이 있습니다. 충분한 시간과 올바른 마음가짐만 있다면 다양한 브레인퍽 코드를 사용해 같은 프로그램을 여러 가지 방법으로 작성할 수 있습니다. 이 여정의 마지막 절반은 창의력을 발휘하여 여섯 가지 기호를 활용하는 새롭고 창의적인 방법을 찾는 것입니다.
브레인퍽 인터프리터는 최소한의 기능이지만 코드 실행 방식, 프로그램이 출력하는 내용, 튜링 완전 언어의 기본 메커니즘을 깊이 있게 이해할 수 있게 해줍니다. 결국 브레인퍽은 단순한 난해한 프로그래밍 언어가 아닙니다. 완전히 새로운 차원으로, 우리가 프로그램을 보고 이해하고 작성하는 방식에 대한 완전히 다른 관점입니다.