February 17, 2012

Sanırım ne kadar teşekkür etsem azdır...:)

Henüz biz doğmadan, 1955 yılında keşfedilmiş olan bağlı liste (linked list) hakkında bugüne kadar (yıl 2012!) hiç bir şey duymamışım. Aslında elektronikteki yığın belleğe (stack register) benziyor ama temel bir öğe olan bu olaya o kadar yabancıyım ki ne var ne yok araştırmaya başladım. Hatta bir sitedeki (-bknz. Bubble sort [linked list] (http://www.c.happycodings.com/Sorting_Searching/code5.html)) sıralama algoritmasını şu an inceliyorum bile...

Alıntı (Wikipedia Maddesi):

>

Bir bağlantılı listenin n. elemanına erişmek için n tane işlem yapmak yani kendinden önceki (n-1) eleman üzerinden geçmek gerekmektedir. Elemanların bellekteki yerleri dizilerdeki gibi sıralı olmadığından elemanlar ve sıraları ile yerleştikleri bellek bölgeleri arasında bir ilişki yoktur[2].
Bu durumda, basit mantıkla yapmış olduğumuz diziye Ekleme/Çıkarma algoritması bundan daha iyi netice verebilir; hatta daha da iyilenebilir! Ancak bunu denememiz gerekir ve ben ne D'de, ne de başka bir dilde bu olayın nasıl yapılacağını henüz bilmiyorum...:(

Sanırım 24 saat gibi bir sürede bu başlığı olgunlaştırıp bir netice elde etmeye başladık. Her halde önümüzdeki 24 saat içinde kesin bir sonuç alacağız, ne dersiniz? Acaba Stroustrup, sunumu üzerine yaptıklarımızı görse gözleri yaşarır mıydı! Nereden nereye, adamın başında saç kalmamış ben hala emeklemeye çalışıyorum. Stroustrup, sanırım aslen Alman çünkü aksanlı konuşuyor; yanılıyor muyum?

Başarılar...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 17, 2012

Alıntı (Salih Dinçer):

>

Ancak birbirimizin yazdığı kodları genelde ne olursa olsun ilk anda anlamakta hep zorlanırız. Hani derler ya; birinin yazdığı kodu çözmektense yeniden yazsan daha kısa süre alacaktır. Haksız mıyım?

Belki yıllar yıllar önce kodların bir ya da bir kaç programcı tarafından yazılabildiği günler için geçerli olabilir. Ama günümüzde yazılım geliştirme bir ekip işi. Hatta günümüzde 'github' kullanmayı bilmeyen programcıya kız vermeyenler çıkarsa şaşmamak lazım :-)

O yüzden kodun okunabilirliği önemli..

Alıntı:

>

Ona dikkat ederken zamanından önce uygulanan eniyileştirme hatasına düşmemek de çok önemli. ("Premature optimization is the root of all evil.")

Sonra hatırladığım kadarıyla 'programınızda sihirli sabitler kullanmaktan kaçının' gibi yararlı öğütler de vardı.

Alıntı (Salih Dinçer):

>

Haklısınız, aslında bir elektronikçi olarak George Boole'u çok severim ve tabi Boolean Aritmatiği'ni de. O yüzden bu true/false deyimlerini elimden geldiğince her yerde kullanmayı seviyorum. Çünkü çok pratik ve anlamlılar.

Bu kadar tesadüf olur! :-p

Ben de tam Çizgi TAGEM araştırma geliştirme ekibinin hazırlamış olduğu sayısal devreler (http://www.cizgi-tagem.org/e-kampus/education.aspx?key=digital2010) konulu dersleri okuyordum. Boole Aritmetiği gerçekten çok zevkli ve ilginç bir konu.

C++ için bu veri yapılarının karşılıkları 'std::vecto'r ve 'std::list''dir.

Vektör tek uçlu bir dinamik dizi gerçeklemesidir. Vektör rastgele erişime izin verir. Yani operator [] işlecini kullanarak belirli bir sıradaki elemana erişebilirsiniz. Vektörün en sonuna eleman eklemek ve çıkarmak çok hızlıdır. Ancak vektörün --başına ya da ortasına-- eleman eklemek yavaştır çünkü tüm elemanların sırayı bozmadan kaydırılmaları gerekir.
'
vektör
---------------------------------
| | | | | | | | | | | -->
---------------------------------
'

Liste ise bir çift bağlı liste gerçeklemesidir.Bu demektir ki her eleman kendine ait bir bellek alanı işgal eder. Listeler rastgele erişime izin vermezler. Örneğin 10. elemana erişmek için ilk 9 eleman arasından zinciri takip ederek yol almalısınız. Listenin avantajı --herhangi bir konuma eleman eklenmesi veya çıkarılması çok hızlıdır-- Sadece bağların değiştirilmesi yeterlidir.Bu da bir listenin ortasına bir eleman eklemenin bir vektör ya da listeye kıyasla çok hızlı olduğu anlamına geliyor.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 17, 2012

Alıntı (zafer):

>

Ali en sonda yapılacak açıklamayı en başta yapmışsın :)

Bir şey farketmez. :) Dizi tarafını hallettik. Şimdi aynı işi bağlı liste ile yapmaya geçebiliriz. Tabii 100 adet eleman aslında çok az 100_000 gibi daha gerçekçi sayılara bakmak gerek. Bol veri işleyen bir program olduğunu düşünebiliriz.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 17, 2012

Alıntı (Salih Dinçer):

>

dilim kullanılarak yapılan yöntem 3 kat daha hızlıymış. Belki gösterge (pointer) kullanılsa daha da hızlı olur bilemiyorum.

Eğer diziyi kendimiz gerçekleştirmekten bahsediyorsan o da olur ama eleman araya gireceği için dizinin sonrasındaki elemanları bir konum sağa kaydırmak gerekecek, vs. O işleri dizileri kullanırken D çalışma ortamı (D runtime) bizim için yapıyor.

Alıntı:

>

Bu şekilde return ile dizi döndürmelere pek alışık değilim ama gayet iyi çalışıyorlar...:)

Altını çizmek için: Onun nedeni, dilimler referans türleri olduklarından diziden döndürülen şey, elemanlarla birlikte bütün dizi değil, yalnızca var olan elemanlara erişim sağlayan bir dilimdir. O dilim toplam iki bilgiden oluşuyor: dilimin ilk elemanını gösteren gösterge ve dilimin uzunluğu.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 17, 2012

Affınıza sığınarak diziyeEkleÇıkart()'ı eleştireceğim: :blush:

false/true gibi parametrelerden kaçınmak gerekir çünkü işlevin çağrıldığı noktadaki 'true' gibi değerin ne anlama geldiği bilinemez. Onun yerine şöyle enum'lar kullanmak çok daha yararlıdır:

   enum Eylem { çıkart, ekle };

Ama ona da gerek yok, çünkü eylemi işlevin ismine gömebiliriz ve böylece kod çok daha temiz hale gelir. Yoksa if(ekleyim_mi) gibi denetimler işlevin içerisine birden fazla işlem akışı sokmuş olurlar. Bunlar hep kaçınmak istediğimiz karmaşıklıklardır.

Dahası, işlevi ikiye ayırınca e parametresi üzerindeki tehlike de ortadan kalkar: Eklerken eleman değeri, çıkartırken ise konum. Büyük karışıklık!

Bu bir şey daha farkettiriyor. e ve k gibi isimler yerine değişkenin tam olarak ne anlama geldiğini yazmış olsak burada bir tehlike olduğu farkedilirdi. ;) e yerine elemanVeyaKonum? :)

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 17, 2012

Alıntı (Salih Dinçer):

>

Bağlı Liste olaylarını hiç kullanmadım. Acaba "Associative Arrays" mi demek istiyoruz?

Bağlı liste linked list anlamında. Associative array'e eşleme tablosu dedik.

Alıntı:

>

Sonrasındaki çizelge yoktu ve sanal olarak varmış gibi davrandık..:)

Evet, sunum sırasında bir hata oluyor. :) Oradaki 'slides' diyen bağlantıya tıklarsanın bütün yansıları indirebilirsiniz. Çizelge orada 45 numaralı yansı olarak var:

http://channel9.msdn.com/Events/GoingNative/GoingNative-2012/Keynote-Bjarne-Stroustrup-Cpp11-Style

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 17, 2012

Alıntı:

>

elimden geldiğince anlaşılır ama kaynakları iyi kullanan kodlar yazmaya gayret ediyorum

Ona dikkat ederken zamanından önce uygulanan eniyileştirme hatasına düşmemek de çok önemli. ("Premature optimization is the root of all evil.") Bu konu da çok geniş ama kodu istersek bin kat hızlandıralım, eğer o kod programa milisaniye katkıda bulunuyorsa o eniyileştirme yalnızca kodun anlaşılırlığını bozar.

Öncelikle şu ilkeler önemli:

  • Anlaşılır, temiz, bakımı kolay kod

  • Algoritma karmaşıklıklarına dikkat. Bunu bu konuda gördük: zaten sıralanmış bir dizide ararken gereksizce sırayla aramaya gerek yok; ikili arama da kullanılabilir. (Ama bu konuyu bulandırmak istemiyorum; sonunda bağlı liste ile karşılaştırırken dizimizde yine de sırayla arayabilirsiniz. Stroustrup farketmediğini söylüyor. İnanırım. :))

Alıntı:

>

Örneğin basit şeyler için işlev yazıp return ile döndürmemeyi tercih ediyorum

Kodun anlaşılırlığı ve bakımı açısından işlevler ne kadar küçükseler ve ne kadar küçük kavramları temsil ediyorlarsa o kadar önemlidir.

Alıntı:

>

Çünkü bunları bir döngü içinde çağırdığınızda ve döngüde binlerce kez tekrar ettiğinde yüksek hızlı bir işlemcide bile saniyeler ile ifade edilebilecek farklar oluşuyor.

Olabilir veya olmayabilir. Ölçmeden bilinemiyor. Derleyiciler bir çok eniyileştirme uygularlar. dmd henüz gcc kadar iyi değil ama bu bizim kodlama gücümüzü etkilememeli. dmd nasıl olsa gelişecek. :)

Kaldı ki, saniyeler, yanlış algoritma seçiminin yanında farkedilmeyecek kadar düşük hızlardır. Yanlış bir algoritma belirli N değerleri için göz açıp kapayana kadar kısa sürer ama N büyüdüğünde yüz yıllar kadar sürebilir. (Abartmıyorum.)

Örneğin elemanları sırayla gezmemizin gerektiğini varsayalım. Çalışanları baştan sona ilerleyerek maaşlarına %90 zam yapacağız... (İyiymiş! :-p) Bu işlem O(N)'dir. Yani N çalışan için N işlem.

Ek olarak, çalışanlara bir de ikramiye vereceğiz diyelim. (O daha da iyi: %200! :-p) O da O(N).

Burada tek foreach döngüsü kurup içinde hem zam yapılabilir hem de ikramiye verilebilir. İşlevin ismi ne olabilir? zamVeİkramiye()? Öyle bir şey...

Öte yandan iki farklı işlev yazabiliriz: zamYap() ve ikramiyeVer(). İki işlev durumunda iki döngü gerekir. Yani başından sonuna iki kere gitmek gerek. Karmaşıklığı nedir? Yine O(N). Bilgisayar bilimine göre hiçbir şey farketmez.

Evet, döngünün ilerletilmesi sırasında biraz zaman kaybı olur ama o nanosaniyelik bir işlemdir. Her çalışanın işlemi zaten mikrosaniye sürüyorsa, tek çalışanın işi bile bütün döngünün bin katı zaman almaktadır. Tek işlev kullanmak ne kadar anlamsız bir kazanç, değil mi?

Alıntı:

>

Bunu 'insertInPlace()''da görüyoruz, meğer aynı şeyi yapıyormuşuz...:)

Standart kütüphaneler affedilebilir çünkü bin bir çeşit programa hizmet ediyorlar. Kodun okunaklılığından ödün verebilirler.

Alıntı:

>

true/false deyimlerini elimden geldiğince her yerde kullanmayı seviyorum. Çünkü çok pratik ve anlamlılar. Üstelik bu işleve çok güzel oturdular.

Kabul ama oturmadıkları çok işlev de oluyor.

Alıntı:

>

Türkçe'ye uygun doğru/yanlış ve evet/hayır gibi şeyler kullanabilseydik ne iyi olurdu.

Ancak yine değerleri 'evet' ve 'hayır' olan enum'larla olurdu.

Alıntı:

>

Sanırım D'de makro (#define) olayı da yok, olur mu bilmem?

Yok.

Alıntı:

>

Alıntı (Ali Çehreli):

>

Bağlı liste linked list anlamında. Associative array'e eşleme tablosu dedik.
Hmm, sanırım bugüne kadar hiç bir dilde kullanmadığım için çok yabancıyım.

Ne iyi ki C++ ve D gibi üst düzey olanakları olan dillerde elle bağlı liste yazmak zorunda kalmıyoruz. Ama her programcının en az bir kere bağlı liste yazmış olması gerekir. ;) En temel veri yapılarındandır (topluluk).

http://en.wikipedia.org/wiki/Linked_list

Türkçesi de var:

http://tr.wikipedia.org/wiki/Ba%C4%9Fl%C4%B1_liste

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 17, 2012

Alıntı (Salih Dinçer):

>

Bu durumda, basit mantıkla yapmış olduğumuz diziye Ekleme/Çıkarma algoritması bundan daha iyi netice verebilir;

Bağlı listenin de yararları var: eleman eklemek ve çıkartmak, topluluktaki başka elemanları göstermekte olan referansları bozmaz. Dizide öyle değildir: tek eleman eklemek ya sonrakileri bir adım kaydırır; ya da bütün diziyi olduğu gibi başka yere taşır. Eleman çıkartmak da öyle: çıkartılan elemandan sonrakiler bir hane sola kayarlar. Bağlı listede öyle bir sorun yok.

Ama elimizdeki bu örnekte dizi bağlı listeyi kat kat geçiyor.

Alıntı:

>

hatta daha da iyilenebilir! Ancak bunu denememiz gerekir ve ben ne D'de, ne de başka bir dilde bu olayın nasıl yapılacağını henüz bilmiyorum...:(

Göstergelere çok bağlı bir kavramdır. Onun için şu bölümde "Basit bir bağlı liste" başlığı ile geçmiş:

http://ddili.org/ders/d/gostergeler.html

O bölümün üçüncü problemini de sana bırakıyorum! ;)

Alıntı:

>

Stroustrup, sanırım aslen Alman

Danimarkalı. Sizin televizyon Wikipedia'yı çekmiyor mu? ;)

http://en.wikipedia.org/wiki/Bjarne_Stroustrup

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 18, 2012

Salih'in geliştirdiği metotla ilgili çok güzel paylaşımlar zaten önceki mesajlarda yapılmış. Neticede amacımız birbirimizn kodlarını inceleyip daha iyiyi yapmak adına kendimizi geliştirmek, bu açıdan Salih'in geliştirdiği metotdan bende güzel şeyler öğrendim.

Alıntı (Salih Dinçer):

>

void diziyeEkleÇıkart (ref int[] d, int e, bool ekleyim_mi)

Salih'in yazdığı kodu görünce bende bilgilerimi tazalemek adına küçük bir çalışma yaptım. Buradaki dikkat edilmesi gereken yer dizinin 'ref' anahtar kelimesi ile işaretlenmiş olması, bildiğimiz gibi diziler metotlara zaten referans olarak aktarılırlar yani ekstradan bizim bunu referans olarak işaretlememiz gerekmez.

Alıntı (acehreli):

>

Altını çizmek için: Onun nedeni, dilimler referans türleri olduklarından diziden döndürülen şey, elemanlarla birlikte bütün dizi değil, yalnızca var olan elemanlara erişim sağlayan bir dilimdir. O dilim toplam iki bilgiden oluşuyor: dilimin ilk elemanını gösteren gösterge ve dilimin uzunluğu.

Ali'nin burdaki notuda zaten olayı güzel bir şekilde açıklıyor. Ancak aynı hataya bende sık sık düştüğüm için bu aktarımı biraz daha göz önüne çıkaran küçük bir çalışma yaptım, incelemek isteyenler için kodlar aşağıda

import std.stdio;

void main()
{
   int[] dizi = [1, 2, 3, 4, 5];

   writefln("Main içindeki dizinin oturduğu koltuk: %s", dizi.ptr);

   int[] d1 = BirinciMetot(dizi);

   writefln("Birinci mettotdan dönüp buraya "
            "gelen dizinin oturduğu koltuk: %s", d1.ptr);

   /* Burada tanımladığım dizi ile metotdan dönen dizinin aynı
      koltukta oturduğunu düşünüyorum, yani Ali ve Zafer diye bildiğimiz
      kişi aynı kişi :), bakalım haklımıyım.*/
   assert(dizi.ptr == d1.ptr, "Hatalıysam bildirin :)");

   IkinciMetot(d1);
}

int[] BirinciMetot(int[] d1)
{
   writefln("Birinci metoda gönderilen dizinin oturduğu koltuk: %s", d1.ptr);

   d1 = d1[0 .. 2];

   return d1;
}

void IkinciMetot(int[] d2)
{
   writefln("ikinci metoda gönderilen dizinin oturduğu koltuk: %s", d2.ptr);
   UcuncuMetot(d2);
}

void UcuncuMetot(int[] d3)
{
   writefln("Ücüncü metoda gönderilen dizinin oturduğu koltuk: %s", d3.ptr);
}

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 18, 2012

Evet, dilimlerin farklı dünyasında hala anlamam gereken çok şey var :)

Sanırım bu belirsiz durumlar için yan etki üreten değilde değer döndüren metotlarla çalışmak daha doğru bir seçim gibi görünüyor.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]