Hakkında Künye

Brainfuck

Merhaba e-bergi okurları.

Bergideki ilk yazımda sizlere, bildiklerinizden çok daha farklı bir programlama dili olan “brainfuck”tan (beyindüzen) bahsedeceğim. Sansüre gerek duymadım, çünkü kimsenin alınmasını gerektirecek bir durum olmadığı gibi, bu dil adının hakkını gerçekten veriyor.

Brainfuck, bugüne kadar yazılmış en basit programlama dillerinden biri, hatta belki de en basitidir. Çok fazla kişi tarafından bilinmeyen ve oldukça kısıtlı bir dil olan brainfuck, sadece 8 komut içerir. Class, tür, hatta değişken tanımlamanın bile mümkün olmadığı bu dil, tüm bunlara rağmen Turing-Complete’dir, yani herhangi bir programlama diliyle yapabileceğiniz her şeyi, brainfuck dilinde de yapabilirsiniz. Brainfuck’ın güzelliği, işte bu basitlikte yatar. Dilin yaratıcısı Urban Müller’in amacı, mümkün olan en küçük boyuttaki derleyiciyi yazmaktı. Başardığını rahatlıkla söyleyebiliriz. Öyle ki, bazı brainfuck derleyicileri 200 bayttan bile daha küçüktür.

Şu anda aklınızdan, “Bu dilin hiçbir gerçek kullanım amacı yok.” gibi bir cümle geçiyorsa, sonuna kadar haklısınız. Brainfuck’ın amacı, programcıları eğlendirmek ve zorlamaktır. Peki böyle bir dili neden öğrenesiniz? Birincisi, yeni bir şeyler öğrenmekten asla zarar gelmez. İkincisi, Turing-Complete bir dilin nasıl bu kadar basit olabildiğini görmek sizi gerçekten çok şaşırtacak. Ve son olarak, gerçekten zorlayıcı bir şeyler arıyorsanız, bu dil tam size göre.

Eğer hala benleyseniz, doğru yoldasınız sevgili okurlar. Artık nasıl bir şeymiş bu “brainfuck”, öğrenmeye başlayalım.

Brainfuck dili, pointer mantığına dayanan bir dildir. Bu yüzden başlamadan önce, eğer pointerlara aşina değilseniz, bir göz atmanızda fayda var. Ben yine de elimden geldiğince basitleştirerek ve açıklayarak anlatacağım.

Dilin derleyicisini bu adresten indirdikten sonra, komutların ne işe yaradığını öğrenmekle başlıyoruz.

Daha önce de bahsettiğim gibi, brainfuck programlama dilinde 8 tane komut vardır. Derleyici, bu komutları temsil eden karakterler dışındaki her şeyi görmezden gelir.

 

1-      +        Pointer’ınızın gösterdiği memory cell’in (hafıza kutucuğu gibi düşünebiliriz) değerini bir arttırır.

2-      -         Pointer’ınızın gösterdiği memory cell’in değerini bir azaltır.

3-      >        Pointer’ınızı sonraki memory cell’e kaydırır.

4-      <        Pointer’ınızı önceki memory cell’e kaydırır.

5-      ,         Pointer’ınızın gösterdiği memory cell’e, girilen standart input değerini atar.

6-      .         Pointer’ınızın gösterdiği memory cell’deki değeri output olarak verir.

7-      [         Bulunduğunuz memory cell’deki değer 0 değil ise, bir döngü başlatır.

8-      ]         Döngünün sonunu ifade eder.

 

İlk olarak, bu memory cell'ler arasında gidip gelme, değer artırıp azaltma mantığını oturtmamız gerekiyor. Daha iyi anlaşılabilmesi için, somut bir gösterim üzerinden gideceğim. Her bir parantez bir memory cell’i temsil etsin, “ ^ “ da pointer’ımızı temsil eden imleç olsun.

 

[ 0 ]    [ 0 ]    [ 0 ]
  ^
+++++                                // ilk memory cell’in değerini 5 artır.

[ 5 ]    [ 0 ]    [ 0 ]
  ^
>                                    // sonraki memory cell’e geç

[ 5 ]    [ 0 ]    [ 0 ]
           ^
++++                                 // ikinci memory cell’in değerini 4 artır.

[ 5 ]    [ 4 ]    [ 0 ]
           ^
>                                    // sonraki memory cell’e geç.
+++++++++                            // üçüncü memory cell’in değerini 9 artır. 

[ 5 ]    [ 4 ]    [ 9 ]
                    ^
<                                    // önceki memory cell’e geç
--                                   //  ikinci memory cell’in değerini iki azalt

[ 5 ]    [ 2 ]    [ 9 ]
           ^

 

Her bir memory cell'deki bilgiler maksimum 1 baytlık değer içerebilir. Yani kutulardaki sayılar en fazla 255 olabilir. Eğer kutudaki değer 255 ise ve o değeri bir kez daha artırırsanız, yeni değeriniz 0 olacaktır. Aynı şekilde, 0 olan değeri bir azaltırsanız 255i elde edersiniz.

 

Açıklamalardan kurtulup tekrar yazdığımızda, kodumuz aşağıdaki gibi olacaktır.

 

+++++>++++>+++++++++<--

 

Bu kısmı anladıysak, artık döngülere geçebiliriz. Bildiğiniz üzere döngüler, bir dilin olmazsa olmazıdır ve işimizi gerçekten kolaylaştırırlar.

7 tane memory cell değerimizi sırasıyla 89, 56, 53, 48, 71, 3, 18 yapacak bir kod yazalım. En basit yol olarak, öncelikle memory cell değerlerini 10’un katına tamamlayıp sonra ince ayar kısmını yapabiliriz. Bunun için yazacağımız döngüyü 10 kez kullanmamız gerekiyor. Yani sekizinci bir memory cell’de, 10 değerini tutmalıyız. Hazırsanız başlayalım.

 

+++++ +++++                          // memory cell0 = 10
[                                    // döngüye gir
>                                    // sonraki memory cell  
+++++ ++++                           // memory cell1 += 9
>                                    // sonraki memory cell
+++++ +                              // memory cell2 += 6
>                                    // sonraki memory cell 
+++++                                // memory cell3 += 5
>                                    // sonraki memory cell
+++++                                // memory cell4 += 5
>                                    // sonraki memory cell
+++++ ++                             // memory cell5 += 7
>                                    // sonraki memory cell
>                                    // sonraki memory cell
++                                   // memory cell7 += 2
<<<<<<<                              // memory cell0’a dön
-                                    // memory cell0 --
]                                    // eğer memory cell0’ın değeri 0 ise döngüden çık, değilse başa dön

 

İlk memory cell’in değerini her seferinde 1 azalttık, ve 0 olduğu zaman döngüden çıkmış olduk. Döngüden çıktıktan sonra elimizde olan:

[ 0 ]    [ 90 ]    [ 60 ]    [ 50 ]    [ 50 ]    [ 70 ]    [ 0 ]    [ 20 ]
  ^

 

Memory cell'lerdeki değerler istediklerimize yeterince yakın, devam ediyoruz.

>-
>----
>+++
>--
>+
>+++
>--

 

Ve işte, istediğimiz değerler!

[ 0 ]    [ 89 ]    [ 56 ]    [ 53 ]    [ 48 ]    [ 71 ]    [ 3 ]    [ 18 ]
                                                                       ^

Yeni bir dil öğrenince yapılacak ilk iş, tabii ki “Hello World!” yazmaktır. Malesef diğer dillerdeki kadar kolay olmayacak, ama bir kez alıştıktan sonra size çocuk oyuncağı gibi gelecektir.

Brainfuck dili, outputlarını sayı olarak değil, memory cell'lerdeki değerlerin ASCII tablosundaki karakter karşılığı olarak veren bir dildir. Bu yüzden brainfuck ile kod yazarken, bir sekmenizde ASCII tablosunu açık tutmanızı tavsiye ederim. ASCI tablosuna buradan ulaşabilirsiniz .

Öncelikle kullanacağımız karakterlerin ASCII tablosundaki değerlerine bakalım.

H:  72
e:  101
l:  108
o:  111
boşluk: 32
W:  87
r:  114
d:  100
ünlem işareti: 33

 

108, 111 ve 114 sayıları birbirlerine yeterince yakın, onları bastırmak için tek bir memory cell’i kullanabiliriz. Aynı şey 100 ve 101 için de geçerli. Değerleri atamakla başlayalım. Yine döngümüzü 10 kez çevirmek mantıklı olacak gibi duruyor.

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

İşlem sonunda elimizde

[ 0 ]    [ 70 ]    [ 100 ]    [ 110 ]    [ 30 ]    [ 90 ]
  ^

olacak. Gelelim bastırma aşamasına.

>++ .              // memory cell1 değerini 2 artır. memory cell1 = 72 = “H”, bastır.
>+ .               // memory cell2 değerini 1 artır. memory cell2 = 101 = “e”, bastır.
>-- ..             // memory cell3 değerini 2 azalt. memory cell3 = 108 = “l”, iki kez art arda bastır.
+++.               // Hala memory cell3’teyiz. Değerini 3 artır. memory cell3 = 111 = “o”, bastır.
>++ .              // memory cell4 değerini 2 artır. memory cell4 = 32 = “ “ , bastır.
>--- .             // memory cell5 değerini 3 azalt. memory cell5 = 87 = “W”, bastır.
<< .               // memory cell3’e git. memory cell3’te hala 111 = “o” değeri mevcut. Bastır.
+++ .              // memory cell3 değerini 3 artır. memory cell3 = 114 = “r”, bastır.
------ .           // memory cell3 değerini 6 azalt. memory cell3 = 108 = “l”, bastır.
<- .               // memory cell2 değerini 1 azalt. memory cell2 = 100 = “d”, bastır.
>>+ .              // memory cell4’e git, değerini 1 artır. memory cell4 = 33 = “!”, bastır.

 

Beynimin yandığını hissetmeye başlıyorum. Fakat son derece eğlenceli.

Brainfuck’ın işlevi sadece karakter bastırmakla sınırlı değil. Matematiksel işlemler yapabilir, bir memory cell'deki değeri başka bir memory cell'e kopyalayabilir, hatta if-else koşullarını test edebilirsiniz. Dediğim gibi, brainfuck Turing-Complete bir dildir.

Bu yazımda sizlere Brainfuck programlama dilini tanıtmaya çalıştım. Gerçekten zorlayıcı ve bir o kadar da eğlenceli olan bu dil ile çok daha farklı problemler çözebilirsiniz. Limit, her programlama dilinde olduğu gibi yine sizsiniz. Şahsen bu dilin basitliğinin çok daha farklı çözüm yolları bulunmasına olanak sağlayacağını düşünüyorum. Tabii ki geleceği olan bir dil olduğu söylenemez, fakat boş zamanlarınızda beyninizi “yakmak” isterseniz, ideal ve faydalı bir yol.

 

while(!fucked(brain))
{
	KeepCoding;
}

 

Kaynakça:

Yağız Arkayın
- 5 -