Zig ile Düşük Seviyeli Kontrol: Bellek, Hatalar ve Derleme Zamanı

zig-ile-dusuk-22

C, onlarca yıldır işletim sistemlerinden gömülü cihazlara kadar düşük seviyeli yazılımın ortak diliydi. Zig ise C’nin performans ve donanıma yakınlık avantajlarını korurken, bellek yönetimini daha görünür, hata takibini daha disiplinli ve derleme zamanını daha üretken hâle getirmeyi amaçlar. Çöp toplayıcıya ihtiyaç duymadan güvenli alışkanlıklar kazandırması, onu özellikle sistem programlama meraklıları için ilginç bir seçenek yapar.

Devamı...

Union-Find ile Bağlantılı Bileşenleri Hızla Takip Etmek

Bir sosyal ağdaki arkadaş gruplarını, şehirler arasındaki yol ağını veya bir labirentin hangi odalarının birbirine bağlı olduğunu düşünün. Her sorguda grafiği baştan sona gezmek mümkündür; fakat milyonlarca düğüm ve kenar varken bu yaklaşım pahalılaşır. Union-Find ya da diğer adıyla Disjoint Set Union (DSU), birbirinden ayrık kümeleri temsil eder, iki kümeyi birleştirir ve iki elemanın aynı kümede olup olmadığını son derece hızlı biçimde söyler. Kruskal minimum yayılım ağacı algoritmasının motoru da tam olarak budur.

Devamı...

Trie (Önek Ağacı) ile Hızlı Kelime Tamamlama ve Sözlük Arama

Arama kutusuna birkaç harf yazdığınızda önerilerin anında belirmesi sihir değil; çoğu zaman arka planda çalışan akıllı bir veri yapısıdır: Trie. “Prefix Tree” yani önek ağacı olarak da bilinen Trie, kelimeleri karakter karakter dallandırarak saklar. Bu yaklaşım, özellikle sözlük araması, yazım denetimi, URL yönlendirme ve otomatik tamamlama gibi senaryolarda klasik liste taramasından çok daha verimli olabilir.

trie-onek-agaci-15

Devamı...

Topolojik Sıralama ile Bağımlılık Çözümü ve Görev Zamanlama

Bir yazılım projesinde testleri çalıştırmadan önce kodu derlemek, derlemeden önce bağımlılıkları indirmek gerekir. Aynı mantık; ders ön koşullarında, üretim hattında, CI/CD süreçlerinde ve paket yöneticilerinde de karşımıza çıkar. İşte topolojik sıralama, “A tamamlanmadan B başlayamaz” türündeki kısıtları geçerli bir işlem dizisine dönüştüren graf algoritmasıdır.

Devamı...

Segment Ağaçları: Aralık Sorgularını Logaritmik Zamanda Yönetmek

Bir dizide belirli bir aralığın toplamını, minimumunu ya da maksimumunu sıkça hesaplamanız gerekiyorsa, düz bir yaklaşım hızla pahalılaşır. Örneğin her sorguda elemanları tek tek gezmek $O(n)$ sürer; dizi de güncelleniyorsa önceden hesaplanmış önek toplamları bile yetersiz kalır. Segment ağacı (segment tree), bu iki ihtiyacı dengeler: Hem aralık sorgularını hem de noktasal güncellemeleri $O(\log n)$ zamanda gerçekleştirir.

Devamı...

R ile İstatistiksel Modelleme: Regresyon ve Hipotez Testlerini Uygulamalı Öğrenin

R dili, istatistiksel modelleme dünyasında hem akademisyenlerin hem de veri analistlerinin vazgeçilmez araçlarından biridir. Bunun sebebi yalnızca zengin paket ekosistemi değildir: R, veri temizlemeden görselleştirmeye, regresyondan hipotez testlerine kadar analiz sürecini okunabilir kodlarla kurmayı sağlar. Bu yazıda yerleşik mtcars veri setini kullanarak doğrusal regresyon kuracak, model sonuçlarını yorumlayacak ve iki grubun ortalamasını t testiyle karşılaştıracağız.

r-ile-istatistiksel-79

Devamı...

Konveks Zarf Algoritması: Nokta Bulutunun Lastik Bandı

Bir harita üzerindeki sensörleri, bir oyundaki çarpışma sınırlarını veya bir görseldeki nesnenin dış konturunu düşünün. Konveks zarf (convex hull), verilen nokta kümesini içine alan en küçük dışbükey çokgendir. Sezgisel olarak noktaların etrafına lastik bir bant geçirirsek, bant gevşediğinde oluşan şekil konveks zarftır. İçeride kalan noktalar bantla temas etmez; yalnızca sınırdaki kritik noktalar sonuçta yer alır.

Devamı...

Kombinatorik Olimpiyat Sorularında Modüler Aritmetik Rehberi

Kombinatorik olimpiyat sorularında ilk bakışta masum görünen $n!$, $\binom{n}{k}$ ve permütasyon ifadeleri, $n$ büyüdükçe devasa sayılara dönüşür. Neyse ki çoğu sorunun gerçekten istediği şey sayının tamamı değil, belirli bir sayıya bölümünden kalanıdır. İşte modüler aritmetik burada sahneye çıkar: Büyük sayıları yazmak yerine kalıntıları yönetir, akıllı sadeleştirmelerle imkânsız görünen hesapları birkaç satıra indirir.

Devamı...

Kayan Pencere Algoritması: Alt Dizilerde Maksimum ve Minimumu Hızlandırma

Bir dizide ardışık $k$ elemanlık her grubun maksimumunu veya minimumunu bulmak, ilk bakışta basit görünür: Her konumda pencereyi tara, sonucu yaz. Ancak veri büyüdüğünde bu yaklaşım bir performans tuzağına dönüşür. Kayan Pencere (Sliding Window), pencerenin her adımda yalnızca bir eleman kaybettiği ve bir eleman kazandığı fikrinden yararlanarak tekrar eden işi ortadan kaldırır. Özellikle zaman serileri, sensör verileri, borsa grafikleri ve log analizi gibi alanlarda oldukça kullanışlıdır.

Devamı...

İkili Arama Varyasyonları: Diziden Cevap Uzayına Akıllı Arama

ikili-arama-varyasyonlari-80

İkili arama denince çoğu kişinin aklına sıralı bir dizide hedef sayıyı bulmak gelir. Oysa bu algoritmanın asıl süper gücü, yalnızca elemanları değil, monotonik kararları aramasıdır. Bir problemde “Bu cevap mümkün mü?” sorusuna verilen yanıt, belirli bir eşikten sonra sürekli evet ya da sürekli hayır oluyorsa, cevap uzayında ikili arama yapabiliriz. Böylece devasa olasılıkları logaritmik sayıda denemeyle küçültürüz.

Devamı...

İki İşaretçi Tekniği: Sıralı Dizilerde Toplam Hedefini Avlamak

İki İşaretçi (Two Pointers), özellikle sıralı dizilerde “hangi iki elemanın toplamı hedefe eşit?” sorusunu doğrusal zamanda çözmeye yarayan klasik bir olimpiyat programlama tekniğidir. İlk bakışta tüm ikilileri denemek doğal görünür; ancak bu yaklaşım dizinin büyüklüğü arttıkça pahalılaşır. İki uçtan yürüyen işaretçiler, sıralama bilgisini bir pusula gibi kullanır: toplam küçükse büyütmek, büyükse küçültmek için hangi yönde ilerleyeceğini bilir.

iki-isaretci-teknigi-58

Devamı...

Greedy Sırt Çantası: Yerel En İyi Seçim Ne Zaman Gerçekten Kazandırır?

greedy-sirt-cantasi-88

Açgözlü algoritmalar, her adımda o an için en avantajlı görünen seçimi yapar ve geriye dönüp kararlarını değiştirmez. Bu yaklaşım kulağa biraz aceleci gelse de doğru problemde inanılmaz hızlı ve zariftir. Sırt çantası problemi ise bu stratejinin sınırlarını görmek için mükemmel bir laboratuvardır: Aynı fikir, kesirli eşyalar için optimum sonucu verirken 0/1 sürümünde bizi tuzağa düşürebilir.

Devamı...

Geriye İzleme ile N Vezir Problemi: Vezirleri Çarpıştırmadan Yerleştirmek

N Vezir Problemi, $N \times N$ boyutundaki bir satranç tahtasına $N$ adet veziri, hiçbir vezir diğerini tehdit etmeyecek biçimde yerleştirmeyi ister. Vezir yatay, dikey ve çapraz hareket edebildiği için mesele yalnızca boş bir kare bulmak değildir: Her yeni yerleşim, önceki tüm kararlarla uyumlu olmalıdır. Bu yüzden problem, kombinasyonel patlamayı yönetmeyi öğreten klasik bir geriye izleme laboratuvarıdır.

Devamı...

Floyd-Warshall ile Tüm Çiftler En Kısa Yol: Dinamik Programlamanın Gücü

Bir şehir haritasında her kavşaktan diğer tüm kavşaklara en kısa yolu aynı anda bulmak istediğinizi düşünün. Floyd-Warshall algoritması tam olarak bu işi yapar: ağırlıklı bir graftaki tüm düğüm çiftleri arasındaki en kısa mesafeleri hesaplar. Tek kaynaklı Dijkstra’nın aksine, başlangıç düğümünü tekrar tekrar değiştirmek zorunda kalmazsınız. Negatif ağırlıklı kenarları da desteklemesi, onu özellikle maliyet farkları, kur dönüşümleri ve bağımlılık analizleri gibi senaryolarda değerli kılar.

Devamı...

EBOB ve Öklid Algoritması: Özyinelemenin Sayılarla Dansı

İki sayının ortak bölenlerini tek tek aramak, küçük sayılarda masum görünen ama sayılar büyüdükçe sabrımızı sınayan bir iştir. En Büyük Ortak Bölen (EBOB), iki ya da daha fazla tam sayıyı kalansız bölen en büyük pozitif sayıdır. Öklid algoritması ise bu değeri bulmak için binlerce yıldır kullanılan, şaşırtıcı derecede zarif ve verimli bir yöntemdir. Dahası, algoritmanın mantığı özyinelemeli fonksiyonlar için mükemmel bir uygulama alanı sunar.

Devamı...

Dinamik Programlama ile En Uzun Ortak Alt Dizi (LCS): Metin Benzerliğini Adım Adım Bulmak

İki metnin ne kadar benzediğini yalnızca ortak kelimeleri sayarak ölçmek yanıltıcı olabilir. Çünkü sıralama da anlam taşır: "programlama harikadır" ile "harikadır programlama" aynı kelimeleri içerse de dizilişleri farklıdır. En Uzun Ortak Alt Dizi (Longest Common Subsequence, LCS), iki dizideki elemanların sırasını koruyarak bulunabilen en uzun ortak yapıyı hesaplar. Metin karşılaştırma, DNA analizi, sürüm kontrol sistemleri ve dosya farkı araçlarının temelinde bu fikir bulunur.

dinamik-programlama-ile-45

Devamı...

Dijkstra Algoritması ile En Kısa Yol: Öncelik Kuyruğunun Gücü

Bir harita uygulamasının sizi en kısa rotadan götürmesi, ağ paketlerinin hızlı yolu seçmesi veya bir oyundaki karakterin hedefe ulaşması çoğu zaman aynı soruya dayanır: Ağırlıklı bir graf üzerinde iki nokta arasındaki en düşük maliyetli yol nedir? Dijkstra algoritması, kenar ağırlıkları negatif olmadığı sürece bu soruyu sistematik ve oldukça verimli biçimde çözer.

dijkstra-algoritmasi-ile-15

Devamı...

Bitmask Dinamik Programlama: Küçük Kümelerde Büyük Kombinasyonları Yönetmek

bitmask-dinamik-programlama-72

Bazı problemler vardır ki eleman sayısı küçük görünür, fakat olası seçimlerin sayısı astronomiktir. Örneğin 20 şehir arasındaki tüm ziyaret sıralamalarını denemek yaklaşık $20!$ olasılık demektir; bu, kahveniz soğumadan bitecek bir hesap değildir. Bitmask Dinamik Programlama (DP), küçük kümelerdeki alt kümeleri bitlerle temsil ederek tekrar eden hesapları saklar ve bu tür kombinasyon patlamalarını yönetilebilir hâle getirir.

Devamı...

Bellman-Ford Algoritması: Negatif Ağırlıklar ve Döngü Avcılığı

En kısa yol problemleri, haritalardaki rota bulmadan ağ paketlerinin yönlendirilmesine kadar pek çok sistemin kalbinde yer alır. Ancak her yolun maliyeti pozitif olmak zorunda değildir: indirimler, kazançlar veya enerji geri kazanımı gibi senaryolar negatif ağırlıklı kenarlar üretir. Dijkstra bu durumda güvenilirliğini kaybederken Bellman-Ford algoritması sahneye çıkar. Üstelik yalnızca en kısa mesafeleri bulmaz; maliyetin sonsuza kadar azaltılabildiği negatif döngüleri de yakalar.

bellman-ford-algoritmasi-70

Devamı...

Ağ Akışı Problemleri: Ford-Fulkerson ile Maksimum Kapasiteyi Bulmak

ag-akisi-problemleri-82

Bir lojistik ağında kamyonların, internet omurgasında paketlerin veya bir üretim hattında ham maddelerin taşındığını düşünün. Her bağlantının bir kapasitesi vardır ve amaç, başlangıç noktasından hedefe toplamda ne kadar malzeme gönderebileceğimizi bulmaktır. İşte maksimum akış (max flow) problemi tam olarak bu soruyu matematiksel bir modele dönüştürür. Ford-Fulkerson yöntemi ise kapasite sınırlarına çarpmadan akışı adım adım büyüten klasik ve öğretici bir yaklaşımdır.

Devamı...