Reflection: Çalışan Bir Program Aynaya Baktığında Ne Görür?

Bir programın çalışırken kendi sınıflarını, metotlarını ve alanlarını inceleyebilmesi kulağa bilim kurgu gibi gelebilir. Oysa reflection, modern programlama dillerinde test araçlarından web çatılarının otomatik yapılandırmasına kadar pek çok sistemin görünmez kahramanıdır. Program aynaya bakıp “Ben hangi türüm, hangi yeteneklere sahibim?” diye sorar; reflection API’si de ona cevap verir.

Devamı...

Probabilistic DP: Olasılıklı Olimpiyat Problemlerini Durumlara Ayırma Sanatı

probabilistic-dp-olasilikli-29

Bir zar atılıyor, yazı gelirse ilerliyor, tura gelirse başa dönüyorsun… İlk bakışta şans oyunu gibi görünen bu problemler, doğru durumlar tanımlandığında gayet düzenli birer dinamik programlama sorusuna dönüşür. Probabilistic DP, rastgele olayların sonuçlarını tek tek simüle etmek yerine her durumdan ulaşılabilecek sonuçların olasılıklarını matematiksel olarak birleştirir.

Devamı...

Pattern Matching’in Evrimi: switch İfadelerinden Yapısal Eşleşmeye

Programlamada karar vermek uzun süre “Bu değer kaç?” sorusuna cevap aramak demekti. Ancak modern uygulamalarda değerler; listelerden, nesnelerden, ağaçlardan ve iç içe geçmiş veri yapılarından oluşuyor. Bu nedenle diller de basit switch ifadelerinden, verinin hem biçimini hem içeriğini inceleyebilen pattern matching yaklaşımına evrildi. Başka bir deyişle artık yalnızca kutunun etiketine değil, kutunun içine ve düzenine de bakıyoruz.

pattern-matchingin-evrimi-94

Devamı...

Palindromic Tree: Bütün Palindromları Tek Yapıda Toplamak

palindromic-tree-butun-36

Bir metindeki bütün palindromları bulmak ilk bakışta kolay görünür: Her merkezi seç, iki yana doğru genişle ve eşleşmeler bitene kadar devam et. Fakat metin uzadığında ve aynı palindromlar tekrar tekrar karşımıza çıktığında işler karışır. Palindromic Tree, diğer adıyla Eertree, farklı palindromları tek bir yapıda saklayarak bu karmaşayı oldukça zarif biçimde çözer.

Devamı...

Monotonic Stack: Dizideki Görünmeyen İlişkileri Tek Geçişte Yakalamak

Bir dizide her elemanın sağındaki ilk büyük değeri bulmanız istendiğinde, akla hemen iç içe döngüler gelebilir. Ancak bu yaklaşım büyüyen girdilerde bilgisayarınızı küçük bir jet motoruna dönüştürür. Monotonic Stack, henüz cevabı bulunmamış elemanları düzenli biçimde saklayarak görünmeyen komşuluk ilişkilerini tek geçişte ortaya çıkarır.

monotonic-stack-dizideki-81

Devamı...

Monotonic Queue: Kayan Pencerelerde Maksimum ve Minimum Avı

Bir dizide belirli genişlikteki pencereyi soldan sağa kaydırıp her konumdaki maksimum veya minimum değeri bulmak, ilk bakışta zararsız görünen bir problemdir. Fakat pencere büyüdükçe her adımda tüm elemanları yeniden taramak, işlemciyi küçük bir maratona çıkarır. Monotonic Queue, yalnızca işe yarayabilecek adayları saklayarak bu avı doğrusal zamanda tamamlar.

Devamı...

Kodun Aynaya Bakışı: Macros ve Metaprogramming

kodun-aynaya-bakisi-12

Bir programın başka bir program üretmesi ilk bakışta bilim kurgu gibi gelebilir. Oysa derleyicilerden web çatılarındaki otomatik yönlendirmelere kadar pek çok araç bu fikri kullanır. Metaprogramming, kodu veri gibi okuyup değiştirme veya yeni kod üretme tekniğidir; macro ise bu geniş ailenin en tanınmış üyelerinden biridir.

Devamı...

Inclusion-Exclusion Principle: Üst Üste Binen Kümeleri Doğru Saymak

Bir etkinliğe katılanların 30’u Python, 25’i JavaScript biliyorsa toplam 55 yazılımcımız olduğunu düşünebiliriz. Fakat iki dili de bilenler varsa aynı kişileri iki kez saymış oluruz. Inclusion-Exclusion Principle, Türkçesiyle Dahil Etme–Hariç Tutma İlkesi, tam olarak bu tür üst üste binmeleri düzeltmek için kullanılan zarif bir sayma yöntemidir.

Devamı...

Gradual Typing: Statik ve Dinamik Tiplerin Aynı Dilde Dansı

Bir programlama dili hem özgür ruhlu hem de disiplinli olabilir mi? Gradual Typing, yani kademeli tipleme, bu soruya güçlü bir “evet” yanıtı verir. Geliştiriciye dinamik tiplerin esnekliğini sunarken ihtiyaç duyulan bölgelerde statik tip denetimini devreye sokar. Böylece mevcut bir projeyi baştan yazmadan, tip güvenliğini adım adım artırmak mümkün olur.

Devamı...

Foreign Function Interface: Programlama Dilleri Arasında Köprü Kurmak

foreign-function-interface-85

Bir Python uygulamasının C ile yazılmış ışık hızındaki bir kütüphaneyi çağırması veya Rust kodunun işletim sistemine ait işlevleri kullanması sihir değildir. Bu iletişimi sağlayan mekanizma Foreign Function Interface, kısaca FFI olarak adlandırılır. FFI, farklı kurallara ve çalışma zamanlarına sahip programlama dillerinin aynı masaya oturup anlaşmasını sağlayan teknik bir tercümandır.

Devamı...

Deque Optimizasyonu: Dinamik Programlamayı Kuyrukla Hızlandırmak

Dinamik programlama bazen doğru bağıntıyı bulduğumuz anda bitmiş gibi görünür. Sonra zaman karmaşıklığını hesaplarız ve karşımıza tatsız bir $O(nk)$ çıkar! Neyse ki geçişler belirli bir pencere içindeki minimum veya maksimum değere dayanıyorsa, çift uçlu kuyruk yani deque yardımımıza yetişebilir.

Devamı...

Dependent Types: Tipler Matematiksel Önermeye Dönüşünce

Bir fonksiyonun yalnızca Int döndürdüğünü değil, pozitif bir Int, tam olarak üç elemanlı bir liste veya belirli bir denklemi sağlayan sonuç döndürdüğünü tip seviyesinde ifade edebilseydik ne olurdu? Dependent Types, yani bağımlı tipler, tiplerin değerlere bağlı olmasına izin vererek bu fikri gerçeğe dönüştürür. Böylece tip denetleyici, kodun kapısında bekleyen bir güvenlik görevlisinden matematik ödevimizi kontrol eden son derece titiz bir asistana dönüşür.

Devamı...

Cartesian Tree: Dizi ile Ağacın Garip Ama Güçlü Birleşimi

cartesian-tree-dizi-13

Bir dizi düşünün: elemanların hem soldan sağa sırasını korumak hem de onları önceliklerine göre bir ağaca yerleştirmek istiyoruz. İlk bakışta “Ağaç mı yapıyoruz, diziyi mi saklıyoruz?” diye sorabilirsiniz. Cartesian Tree tam olarak bu iki dünyayı birleştirir: dizinin sırasını bozmadan heap özelliği taşıyan bir ikili ağaç üretir. Üstelik bunu doğrusal zamanda yapmak mümkündür.

Devamı...

B-Ağaçlarının Perde Arkası: Dosya Sistemleri Neden İkili Ağaç Kullanmaz?

Bir dosyayı açtığınızda işletim sistemi milyonlarca kayıt arasından doğru disk bloğunu şaşırtıcı bir hızla bulur. Bu numaranın arkasında çoğu zaman ikili arama ağacı değil, tek düğümüne adeta küçük bir mahalle sığdırabilen B-ağacı veya onun akrabaları vardır. Çünkü disk dünyasında pahalı olan karşılaştırma yapmak değil, verinin bulunduğu bloğa fiziksel ya da mantıksal olarak ulaşmaktır.

b-agaclarinin-perde-81

Devamı...

Aho-Corasick: Binlerce Kelimeyi Tek Geçişte Aramak

Bir metinde tek kelime aramak kolaydır; fakat yasaklı sözcükler, virüs imzaları veya anahtar kelimelerden oluşan dev bir listeyi aramak istediğimizde işler değişir. Her kelime için metni baştan sona taramak, aynı yolu binlerce kez yürümeye benzer. Aho-Corasick algoritması ise kelimeleri ortak bir veri yapısında birleştirerek metni yalnızca bir kez tarar.

Devamı...

Ternary Search: Tek Tepeli Fonksiyonlarda Optimumu Hızla Bulmak

Bir dağın zirvesini bulmak istediğinizi düşünün; ancak sis yüzünden yalnızca bulunduğunuz noktaların yüksekliğini ölçebiliyorsunuz. Her yeri adım adım dolaşmak yerine dağı düzenli biçimde daraltabilirsiniz. Ternary Search, yani üçlü arama, tam olarak bu fikri kullanarak tek tepeli fonksiyonların minimum veya maksimum noktasını bulur.

Devamı...

Tarjan Algoritması: Güçlü Bağlı Bileşenleri Tek DFS ile Yakalamak

tarjan-algoritmasi-guclu-35

Yönlü bir grafın içinde birbirine karşılıklı olarak ulaşabilen düğüm gruplarını bulmak, bağımlılık analizinden sosyal ağlara kadar pek çok alanda karşımıza çıkar. Tarjan algoritması, bu grupları yani güçlü bağlı bileşenleri yalnızca tek bir derinlik öncelikli arama sürecinde keşfeder. Üstelik bunu yaparken yanında yalnızca bir yığın, birkaç dizi ve etkileyici derecede zarif bir fikir taşır.

Devamı...

Sweep Line Algoritması: Düzlemdeki Olayları Tek Boyuta İndirerek Çözmek

Bilgisayarsal geometri problemleri ilk bakışta ürkütücüdür: Doğrular kesişir, dikdörtgenler üst üste biner ve noktalar düzleme dağılır. Sweep Line, yani tarama doğrusu algoritması, bu iki boyutlu karmaşayı hareket eden hayali bir doğru ve sıralanmış olaylar yardımıyla yönetilebilir hâle getirir. Kısacası bütün düzleme aynı anda bakmak yerine, önemli değişiklikleri sırayla işleriz.

Devamı...

Simplex Algoritması: Kötü Teoriye Rağmen Şaşırtıcı Derecede İyi Çalışan Yöntem

Simplex algoritması, doğrusal optimizasyon problemlerini çözmek için 1947 yılında George Dantzig tarafından geliştirildi. İlginç olan şu: Algoritmanın en kötü durumdaki çalışma süresi üstel olabilir, fakat gerçek hayattaki problemlerde çoğunlukla son derece hızlıdır. Kısacası Simplex, teorik karnesi biraz problemli olsa da iş hayatında sürekli terfi alan o gizemli çalışan gibidir.

Devamı...

Rekabetçi Programlama: Zihinsel Spor mu, Hız Tuzağı mı?

Rekabetçi programlama; belirli süre ve bellek sınırları altında algoritmik problemler çözme pratiğidir. Bir bakıma satranç, matematik olimpiyatı ve klavye yarışının aynı masaya oturmuş hâlidir. Doğru uygulandığında düşünme becerisini keskinleştirir; yanlış hedeflerle yapıldığında ise yazılım geliştirmenin yalnızca hızlı kod yazmaktan ibaret olduğu yanılgısını doğurabilir.

Devamı...