Merhaba,
Bu bayram verimli geçti ama bir noktada takıldım! Türkiye içinde gezerken, bilişim açısından programlamanın tarihinde de bir yolculuk yaptım...
Çoğunluk bilir, el-Hârizmî ne kadar önemliyse Alan Turing'de öyledir. Beraberinde Turing Machine ve Urban Müller'in uyguladığı Brainfuck Interpreter basittir. Bunlar ezoterik diller arasında yer alıyor ve konumuz olan kod hakkında şurada çok bilgi mevcut:
https://esolangs.org/wiki/Brainfuck_algorithms
Hoş, Thue gibi daha güzel diller ve kendinizin yapıp geliştirebileceği çok basit yorumlayıcılar mutlaka mevcuttur. Ancak ismiyle de aykırı olan (ben Beyin Farkı diyorum) BF, pekala 10 dakikada her dilde oturup yazılabilir. Hiç D dilinde yapıldı mı bilmiyorum, benim eksik çalışan (sadece ilk 4 sayının karesini doğru hesaplıyor!) ve orijinal sürüme bir komut (:) ekleyerek yaptığım şöyle:
(aslında 100 satır bile değil!)
void main()
{
size_t ptr, i, n; // n = gereksiz döngü sayacı
ushort[25] mem; // 25 eleman 100'üm karesine yeter
auto s = CODE.dup;
while(i < s.length)
{
size_t b = 1;
switch(s[i])
{
case '+' : ++mem[ptr]; break;
case '-' : --mem[ptr]; break;
case '>' : ++ptr; break;
case '<' : --ptr; break;
case '[' :// <-YILDIZ EKLE VE GEÇİŞ YAP
++n;
stack.push = i;/*/
if(!mem[ptr])
{
while(b)
{
switch(s[++i])
{
case ']': --b; break;
case '[': ++b; break;
default : ++n; break;
}
}
}//*/
break;
case ']' :// <-YILDIZ EKLE VE GEÇİŞ YAP
if(mem[ptr]) i = stack.front;
else stack.popFront;/*/
if(mem[ptr])
{
while(b)
{
switch(s[--i])
{
case ']': ++b; break;
case '[': --b; break;
default : ++n; break;
}
}
}//*/
break;
case ':' : writefln("->%s: %s", mem[ptr], mem); break;
case '.' :
const chr = cast(char) mem[ptr];
chr.writef!"%s"; /*
if(chr > ' ') {
chr.write;
mem.writefln!":->%s";
}//*/
break;
case ',' :
auto chr = cast(ubyte) stdin.readln[0];
mem[ptr] = chr;
break;
default:
}
++i;
}
n.writefln!"n = %s"; // gereksiz döngüler
mem[$-5..$].writeln; // belleğin son 5 hücresi
}
import std.stdio;
StackLIFO!size_t stack;
struct StackLIFO(T)
{
T[] data;
bool empty() {
return data.length == 0;
}
T back() {
return data.length ? data[0] : T.init;
}
void push(T data) {
this.data ~= data;
}
T front() {
return data[$ - 1];
}
void popFront() {
data.length--;
}
}
// kodun ilk satırının sonuna (...+<+) artı işareti yerine
// eğer virgül koyarsanız ASCII değerine kadar hesaplatılabilir,
// misal ünlem(!) işareti 33'dür, en son 1024'ü hesaplar...
enum CODE = ` 30'a kadar karelerini yazar
++[>+++<-]>[<+++++>-]+<+: ; burada 31 var
[>
[>+>+<<-]++>>
[<<+>>-]>>>
[-]++>
[-]+>>>+
[
[-]++++++>>>
]<<<
[
[<++++++++<++>>-]+<.< ; ekrana yaz
[>----<-]< ; enter \n
]<<
[>>>>>
[>>>
[-]+++++++++<
[>-<-]+++++++++>
[-
[<->-]+
[<<<]
]<
[>+<-]>
]<<-
]<<-
]`;
Lütfen değerlendirme yapmadan önce şu açıklamamı okuyun:
Kodun orijinalinden çok uzaklaşmadım. Çünkü kodda olması gerektiği gibi b değişkeni ile bracket (köşeli parantezleri) sayıyoruz. Tamam, ama bunu yapabilmek için ']' karakterinden geriye doğru gereksiz döngü ve koşullar işletiliyor. Bunu kanıtlamak için n değişkenini kullandım ve 1050'nin karesi için 208 milyon gereksiz döngü sayabildim:
>1102500, n = 207162628
Çözüm olarak basit bir LIFO Stack
oluşturdum ve döngü başladığı noktayı i değişkeni ile öğrendim. Sonuçta atlama yapılması gerekiyorsa geri yükledim (if(mem[ptr]) i = stack.front;
) gerekmiyorsa bunu yığından çıkardım (else stack.popFront) yani her şey mantığa uygun ama şu sonuç elde ediliyor:
[0, 1, 4, 9, @, I, T, a, p ...]
Anlaşılacağı üzere iç içe döngülerde bir şey yolunca gitmiyor. Bazı BF programları çalışıyor ama böyle özel programda patlıyorum. Eğer kod içindeki <-YILDIZ EKLE VE GEÇİŞ YAP
satırlarına /*/ olacak şekilde yıldız eklerseniz orijinal sürüme geri dönebilirsiniz. O zaman her şey gerektiği gibi çalışmakta. Belleğin anlık görüntüsü için ':' karakterini kodun (enum CODE) herhangi bir bir yerine koyabilirsiniz.
Özetle Beyin Farkı Yorumlayıcısı'nı, stack ile niye çalışmaz? Soruna neden olan fark ne :)
Dip Not: Orijinal interpreter'den uzaklaştığım bir diğer nokta 8 bitlik char yerine ushort kullanarak hesaplama derinliğini arttırmak oldu.
Sevgiler...