1. Dasar-dasar
Untuk memahami Brainfuck, Anda harus membayangkan deretan sel tak terbatas yang diinisialisasi oleh 0
masing-masing sel .
...[0][0][0][0][0]...
Saat program brainfuck dimulai, itu menunjuk ke sel mana saja.
...[0][0][*0*][0][0]...
Jika Anda memindahkan penunjuk ke kanan, >
Anda memindahkan penunjuk dari sel X ke sel X + 1
...[0][0][0][*0*][0]...
Jika Anda meningkatkan nilai sel, +
Anda mendapatkan:
...[0][0][0][*1*][0]...
Jika Anda meningkatkan nilai sel lagi, +
Anda mendapatkan:
...[0][0][0][*2*][0]...
Jika Anda menurunkan nilai sel, -
Anda mendapatkan:
...[0][0][0][*1*][0]...
Jika Anda memindahkan penunjuk ke kiri, <
Anda memindahkan penunjuk dari sel X ke sel X-1
...[0][0][*0*][1][0]...
2. Masukan
Untuk membaca karakter Anda menggunakan koma ,
. Apa yang dilakukannya adalah: Membaca karakter dari input standar dan menulis kode ASCII desimalnya ke sel yang sebenarnya.
Lihat tabel ASCII . Misalnya, kode desimal !
is 33
, while a
is 97
.
Nah, bayangkan memori program BF Anda terlihat seperti:
...[0][0][*0*][0][0]...
Dengan asumsi input standar singkatan a
, jika Anda menggunakan ,
operator koma , yang dilakukan BF adalah membaca a
kode ASCII desimal 97
ke memori:
...[0][0][*97*][0][0]...
Anda biasanya ingin berpikir seperti itu, namun kenyataannya sedikit lebih kompleks. Sebenarnya BF tidak membaca karakter tapi byte (apapun byte itu). Mari saya tunjukkan contoh:
Di linux
$ printf ł
cetakan:
ł
yang merupakan karakter Polandia tertentu. Karakter ini tidak dikodekan oleh pengkodean ASCII. Dalam hal ini adalah pengkodean UTF-8, jadi biasanya memakan waktu lebih dari satu byte dalam memori komputer. Kami dapat membuktikannya dengan membuat dump heksadesimal:
$ printf ł | hd
yang menunjukkan:
00000000 c5 82 |..|
Angka nol diimbangi. 82
adalah yang pertama dan c5
mewakili byte kedua ł
(agar kita akan membacanya). |..|
adalah representasi grafis yang tidak dimungkinkan dalam kasus ini.
Nah, jika Anda mengirimkan ł
sebagai masukan ke program BF Anda yang membaca satu byte, memori program akan terlihat seperti:
...[0][0][*197*][0][0]...
Kenapa 197
? Nah 197
desimal adalah c5
heksadesimal. Tampak akrab? Tentu saja. Ini byte pertama dari ł
!
3. Keluaran
Untuk mencetak karakter Anda menggunakan titik .
Apa yang dilakukannya adalah: Dengan asumsi kita memperlakukan nilai sel aktual seperti kode ASCII desimal, mencetak karakter yang sesuai dengan keluaran standar.
Nah, bayangkan memori program BF Anda terlihat seperti:
...[0][0][*97*][0][0]...
Jika Anda menggunakan operator titik (.) Sekarang, yang dilakukan BF adalah mencetak:
Sebuah
Karena a
kode desimal di ASCII adalah 97
.
Jadi misal program BF seperti ini (97 plus 2 titik):
+++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++++++ ..
Akan meningkatkan nilai sel yang ditunjuknya hingga 97 dan mencetaknya 2 kali.
A A
4. Perulangan
Dalam BF loop terdiri dari loop begin [
dan loop end ]
. Anda bisa menganggapnya seperti saat berada di C / C ++ di mana kondisinya adalah nilai sel sebenarnya.
Lihat program BF di bawah ini:
++[]
++
menambah nilai sel sebenarnya dua kali:
...[0][0][*2*][0][0]...
Dan []
seperti while(2) {}
, jadi ini putaran tak terbatas.
Katakanlah kita tidak ingin putaran ini tidak terbatas. Kita bisa lakukan misalnya:
++[-]
Jadi setiap kali loop loop itu menurunkan nilai sel yang sebenarnya. Setelah nilai sel sebenarnya adalah 0
loop berakhir:
...[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)
Mari kita pertimbangkan contoh lain dari loop terbatas:
++[>]
Contoh ini menunjukkan, kita belum menyelesaikan loop di sel tempat loop dimulai:
...[0][0][*2*][0][0]... loop starts
...[0][0][2][*0*][0]... after first iteration (loop ends)
Bagaimanapun juga merupakan praktik yang baik untuk mengakhiri dari mana kita memulai. Kenapa? Karena jika loop mengakhiri sel lain itu dimulai, kita tidak bisa berasumsi di mana penunjuk sel akan berada. Sejujurnya, praktik ini mengurangi brainfuck.