<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://sonsuzus.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://sonsuzus.github.io/" rel="alternate" type="text/html" /><updated>2026-06-04T13:05:57+00:00</updated><id>https://sonsuzus.github.io/feed.xml</id><title type="html">SonsuzUs</title><subtitle>Programlama ve Yazılım</subtitle><author><name>Sonsuz Us</name></author><entry><title type="html">SQL Detaylı Çalışma Notları</title><link href="https://sonsuzus.github.io/posts/sql-detayli-calisma-notlari/" rel="alternate" type="text/html" title="SQL Detaylı Çalışma Notları" /><published>2026-06-04T00:00:00+00:00</published><updated>2026-06-04T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/sql-detayli-calisma-notlari</id><content type="html" xml:base="https://sonsuzus.github.io/posts/sql-detayli-calisma-notlari/"><![CDATA[<p>SQL temellerini bilen ama sorguları daha bilinçli yazmak isteyenler için 70 konu, açıklama, örnek ve pratik notlarla hazırlanmış kapsamlı bir çalışma rehberi.</p>

<!--more-->

<p><strong>Pratik sıralama:</strong> <code class="language-plaintext highlighter-rouge">SELECT</code> → <code class="language-plaintext highlighter-rouge">FROM</code> → <code class="language-plaintext highlighter-rouge">JOIN</code> → <code class="language-plaintext highlighter-rouge">WHERE</code> → <code class="language-plaintext highlighter-rouge">GROUP BY</code> → <code class="language-plaintext highlighter-rouge">HAVING</code> → <code class="language-plaintext highlighter-rouge">SELECT</code> hesapları → <code class="language-plaintext highlighter-rouge">ORDER BY</code> → <code class="language-plaintext highlighter-rouge">LIMIT</code>. SQL yazarken bu mantıksal akışı akılda tutmak hata sayısını ciddi azaltır.</p>

<table>
  <thead>
    <tr>
      <th>Konu aralığı</th>
      <th>Odak</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1–20</td>
      <td>Temel sorgulama, veri ekleme/güncelleme/silme, anahtarlar ve transaction</td>
    </tr>
    <tr>
      <td>21–40</td>
      <td>JOIN türleri, aggregate fonksiyonlar, filtreler, tablo yapısı ve constraint konuları</td>
    </tr>
    <tr>
      <td>41–70</td>
      <td>CTE, window functions, performans, transaction izolasyonu, JSON, full text search ve ileri konular</td>
    </tr>
  </tbody>
</table>

<hr />

<h2 id="bölüm-1--temel-ve-orta-seviye-konular">Bölüm 1 — Temel ve Orta Seviye Konular</h2>

<h3 id="1-select">1. SELECT</h3>

<p><strong>Ne işe yarar?</strong> Tablodan hangi kolonları okuyacağını seçersin.</p>

<p><strong>Ne zaman kullanılır?</strong> Raporlama, kontrol ve analiz sorgularının başlangıcıdır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">ad</span><span class="p">,</span> <span class="n">soyad</span><span class="p">,</span> <span class="n">sehir</span>
<span class="k">FROM</span> <span class="n">musteriler</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">SELECT *</code> hızlı deneme için iyidir; kalıcı sorgularda ihtiyacın olan kolonları yazmak daha temizdir.</p>
</blockquote>

<hr />

<h3 id="2-where">2. WHERE</h3>

<p><strong>Ne işe yarar?</strong> Satırları koşula göre filtreler.</p>

<p><strong>Ne zaman kullanılır?</strong> Büyük tabloda doğru satırlara odaklanmanı sağlar.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">*</span>
<span class="k">FROM</span> <span class="n">siparisler</span>
<span class="k">WHERE</span> <span class="n">toplam_tutar</span> <span class="o">&gt;</span> <span class="mi">1000</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">WHERE</code> satır seviyesinde çalışır; <code class="language-plaintext highlighter-rouge">GROUP BY</code> sonrası filtreleme için <code class="language-plaintext highlighter-rouge">HAVING</code> kullanılır.</p>
</blockquote>

<hr />

<h3 id="3-join">3. JOIN</h3>

<p><strong>Ne işe yarar?</strong> İlişkili tabloları ortak alan üzerinden birleştirir.</p>

<p><strong>Ne zaman kullanılır?</strong> Müşteri-sipariş, ürün-kategori gibi parçalanmış veriyi anlamlı hale getirir.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">m</span><span class="p">.</span><span class="n">ad</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">toplam_tutar</span>
<span class="k">FROM</span> <span class="n">musteriler</span> <span class="n">m</span>
<span class="k">JOIN</span> <span class="n">siparisler</span> <span class="n">s</span> <span class="k">ON</span> <span class="n">s</span><span class="p">.</span><span class="n">musteri_id</span> <span class="o">=</span> <span class="n">m</span><span class="p">.</span><span class="n">id</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">JOIN</code> koşulunu yazmayı unutmak çarpım etkisi oluşturabilir ve satır sayısını patlatır.</p>
</blockquote>

<hr />

<h3 id="4-group-by">4. GROUP BY</h3>

<p><strong>Ne işe yarar?</strong> Satırları gruplar ve grup bazlı özet üretir.</p>

<p><strong>Ne zaman kullanılır?</strong> Şehir bazlı müşteri sayısı, ürün bazlı satış gibi özetlerde kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">sehir</span><span class="p">,</span> <span class="k">COUNT</span><span class="p">(</span><span class="o">*</span><span class="p">)</span> <span class="k">AS</span> <span class="n">musteri_sayisi</span>
<span class="k">FROM</span> <span class="n">musteriler</span>
<span class="k">GROUP</span> <span class="k">BY</span> <span class="n">sehir</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">SELECT</code> içinde aggregate olmayan her kolon genelde <code class="language-plaintext highlighter-rouge">GROUP BY</code> içinde de yer almalıdır.</p>
</blockquote>

<hr />

<h3 id="5-order-by">5. ORDER BY</h3>

<p><strong>Ne işe yarar?</strong> Sonuçları artan veya azalan sıralar.</p>

<p><strong>Ne zaman kullanılır?</strong> En pahalı ürünler, en yeni siparişler, en çok satanlar gibi listelerde kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">ad</span><span class="p">,</span> <span class="n">fiyat</span>
<span class="k">FROM</span> <span class="n">urunler</span>
<span class="k">ORDER</span> <span class="k">BY</span> <span class="n">fiyat</span> <span class="k">DESC</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">DESC</code> azalan, <code class="language-plaintext highlighter-rouge">ASC</code> artan sıralama yapar. <code class="language-plaintext highlighter-rouge">ASC</code> varsayılandır.</p>
</blockquote>

<hr />

<h3 id="6-index">6. INDEX</h3>

<p><strong>Ne işe yarar?</strong> Arama ve <code class="language-plaintext highlighter-rouge">JOIN</code> performansını artıran veri yapısıdır.</p>

<p><strong>Ne zaman kullanılır?</strong> <code class="language-plaintext highlighter-rouge">WHERE</code>, <code class="language-plaintext highlighter-rouge">JOIN</code>, <code class="language-plaintext highlighter-rouge">ORDER BY</code> alanlarında sık kullanılan kolonlarda faydalıdır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">CREATE</span> <span class="k">INDEX</span> <span class="n">idx_siparis_musteri</span>
<span class="k">ON</span> <span class="n">siparisler</span><span class="p">(</span><span class="n">musteri_id</span><span class="p">);</span>
</code></pre></div></div>

<blockquote>
  <p>Index okumayı hızlandırır ama <code class="language-plaintext highlighter-rouge">INSERT</code>/<code class="language-plaintext highlighter-rouge">UPDATE</code>/<code class="language-plaintext highlighter-rouge">DELETE</code> işlemlerini biraz yavaşlatabilir.</p>
</blockquote>

<hr />

<h3 id="7-primary-key">7. PRIMARY KEY</h3>

<p><strong>Ne işe yarar?</strong> Tablodaki her satırı benzersiz tanımlar.</p>

<p><strong>Ne zaman kullanılır?</strong> <code class="language-plaintext highlighter-rouge">id</code> gibi tekrar etmeyen ana kimlik alanıdır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">CREATE</span> <span class="k">TABLE</span> <span class="n">musteriler</span> <span class="p">(</span>
  <span class="n">id</span> <span class="nb">SERIAL</span> <span class="k">PRIMARY</span> <span class="k">KEY</span><span class="p">,</span>
  <span class="n">ad</span> <span class="nb">TEXT</span> <span class="k">NOT</span> <span class="k">NULL</span>
<span class="p">);</span>
</code></pre></div></div>

<blockquote>
  <p>Primary key hem benzersizlik sağlar hem de <code class="language-plaintext highlighter-rouge">NULL</code> olamaz.</p>
</blockquote>

<hr />

<h3 id="8-foreign-key">8. FOREIGN KEY</h3>

<p><strong>Ne işe yarar?</strong> Bir tablodaki alanın başka tablodaki anahtara bağlı olmasını sağlar.</p>

<p><strong>Ne zaman kullanılır?</strong> Veri tutarlılığı için kullanılır; olmayan müşterinin siparişi girilemez.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">CREATE</span> <span class="k">TABLE</span> <span class="n">siparisler</span> <span class="p">(</span>
  <span class="n">id</span> <span class="nb">SERIAL</span> <span class="k">PRIMARY</span> <span class="k">KEY</span><span class="p">,</span>
  <span class="n">musteri_id</span> <span class="nb">INT</span> <span class="k">REFERENCES</span> <span class="n">musteriler</span><span class="p">(</span><span class="n">id</span><span class="p">)</span>
<span class="p">);</span>
</code></pre></div></div>

<blockquote>
  <p>Foreign key veri kalitesini korur; silme/güncelleme davranışları için <code class="language-plaintext highlighter-rouge">ON DELETE</code> / <code class="language-plaintext highlighter-rouge">ON UPDATE</code> düşünülür.</p>
</blockquote>

<hr />

<h3 id="9-insert">9. INSERT</h3>

<p><strong>Ne işe yarar?</strong> Tabloya yeni satır ekler.</p>

<p><strong>Ne zaman kullanılır?</strong> Yeni müşteri, yeni sipariş, yeni log kaydı oluştururken kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">INSERT</span> <span class="k">INTO</span> <span class="n">musteriler</span><span class="p">(</span><span class="n">ad</span><span class="p">,</span> <span class="n">sehir</span><span class="p">)</span>
<span class="k">VALUES</span> <span class="p">(</span><span class="s1">'Ali'</span><span class="p">,</span> <span class="s1">'Ankara'</span><span class="p">);</span>
</code></pre></div></div>

<blockquote>
  <p>Kolon listesini yazmak güvenlidir; tablo yapısı değişse de sorgu daha okunur kalır.</p>
</blockquote>

<hr />

<h3 id="10-update">10. UPDATE</h3>

<p><strong>Ne işe yarar?</strong> Var olan satırları günceller.</p>

<p><strong>Ne zaman kullanılır?</strong> Adres, fiyat, durum, stok gibi değerleri değiştirmek için kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">UPDATE</span> <span class="n">urunler</span>
<span class="k">SET</span> <span class="n">fiyat</span> <span class="o">=</span> <span class="n">fiyat</span> <span class="o">*</span> <span class="mi">1</span><span class="p">.</span><span class="mi">10</span>
<span class="k">WHERE</span> <span class="n">kategori</span> <span class="o">=</span> <span class="s1">'Elektronik'</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">WHERE</code> unutulursa tablodaki tüm satırlar güncellenir. Önce <code class="language-plaintext highlighter-rouge">SELECT</code> ile kontrol etmek iyi alışkanlıktır.</p>
</blockquote>

<hr />

<h3 id="11-delete">11. DELETE</h3>

<p><strong>Ne işe yarar?</strong> Satır siler.</p>

<p><strong>Ne zaman kullanılır?</strong> Yanlış, geçersiz veya artık gerekli olmayan kayıtları kaldırır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">DELETE</span> <span class="k">FROM</span> <span class="n">sepet</span>
<span class="k">WHERE</span> <span class="n">kullanici_id</span> <span class="o">=</span> <span class="mi">10</span> <span class="k">AND</span> <span class="n">urun_id</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">DELETE</code> de <code class="language-plaintext highlighter-rouge">WHERE</code> ister. Kalıcı silme yerine bazı sistemlerde soft delete kullanılır.</p>
</blockquote>

<hr />

<h3 id="12-having">12. HAVING</h3>

<p><strong>Ne işe yarar?</strong> Gruplandırılmış sonuçları filtreler.</p>

<p><strong>Ne zaman kullanılır?</strong> <code class="language-plaintext highlighter-rouge">COUNT</code>, <code class="language-plaintext highlighter-rouge">SUM</code>, <code class="language-plaintext highlighter-rouge">AVG</code> gibi özet sonuçlar üzerinden koşul kurarsın.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">musteri_id</span><span class="p">,</span> <span class="k">SUM</span><span class="p">(</span><span class="n">toplam_tutar</span><span class="p">)</span> <span class="k">AS</span> <span class="n">toplam</span>
<span class="k">FROM</span> <span class="n">siparisler</span>
<span class="k">GROUP</span> <span class="k">BY</span> <span class="n">musteri_id</span>
<span class="k">HAVING</span> <span class="k">SUM</span><span class="p">(</span><span class="n">toplam_tutar</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">5000</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">WHERE</code> gruplamadan önce, <code class="language-plaintext highlighter-rouge">HAVING</code> gruplamadan sonra çalışır.</p>
</blockquote>

<hr />

<h3 id="13-subquery">13. SUBQUERY</h3>

<p><strong>Ne işe yarar?</strong> Bir sorgunun içinde başka sorgu kullanmaktır.</p>

<p><strong>Ne zaman kullanılır?</strong> Önce bir liste/sonuç bulup dış sorguda kullanmak için kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">ad</span>
<span class="k">FROM</span> <span class="n">musteriler</span>
<span class="k">WHERE</span> <span class="n">id</span> <span class="k">IN</span> <span class="p">(</span>
  <span class="k">SELECT</span> <span class="n">musteri_id</span> <span class="k">FROM</span> <span class="n">siparisler</span>
<span class="p">);</span>
</code></pre></div></div>

<blockquote>
  <p>Subquery okunabilir olabilir; performans için bazen <code class="language-plaintext highlighter-rouge">JOIN</code> veya <code class="language-plaintext highlighter-rouge">EXISTS</code> daha iyi olur.</p>
</blockquote>

<hr />

<h3 id="14-distinct">14. DISTINCT</h3>

<p><strong>Ne işe yarar?</strong> Tekrar eden değerleri teke indirir.</p>

<p><strong>Ne zaman kullanılır?</strong> Tekil şehirler, tekil kategoriler, tekrar etmeyen kullanıcı listeleri için kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="k">DISTINCT</span> <span class="n">sehir</span>
<span class="k">FROM</span> <span class="n">musteriler</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">DISTINCT</code> tüm seçilen kolon kombinasyonuna bakar; sadece tek kolona değil.</p>
</blockquote>

<hr />

<h3 id="15-limit">15. LIMIT</h3>

<p><strong>Ne işe yarar?</strong> Döndürülecek satır sayısını sınırlar.</p>

<p><strong>Ne zaman kullanılır?</strong> Deneme, sayfalama ve ilk N sonucu görmek için kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">*</span>
<span class="k">FROM</span> <span class="n">siparisler</span>
<span class="k">ORDER</span> <span class="k">BY</span> <span class="n">created_at</span> <span class="k">DESC</span>
<span class="k">LIMIT</span> <span class="mi">10</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">LIMIT</code> genelde <code class="language-plaintext highlighter-rouge">ORDER BY</code> ile birlikte anlamlıdır; aksi halde hangi 10 satırın geleceği belirsiz olabilir.</p>
</blockquote>

<hr />

<h3 id="16-union">16. UNION</h3>

<p><strong>Ne işe yarar?</strong> İki sorgu sonucunu alt alta birleştirir.</p>

<p><strong>Ne zaman kullanılır?</strong> Benzer kolon yapısına sahip listeleri tek sonuç setinde toplar.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">email</span> <span class="k">FROM</span> <span class="n">musteriler</span>
<span class="k">UNION</span>
<span class="k">SELECT</span> <span class="n">email</span> <span class="k">FROM</span> <span class="n">tedarikciler</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">UNION</code> tekrarlı satırları kaldırır. Hepsini korumak için <code class="language-plaintext highlighter-rouge">UNION ALL</code> kullanılır.</p>
</blockquote>

<hr />

<h3 id="17-case">17. CASE</h3>

<p><strong>Ne işe yarar?</strong> SQL içinde if-else benzeri koşullu ifade yazar.</p>

<p><strong>Ne zaman kullanılır?</strong> Raporlarda sınıflandırma ve etiketleme için çok kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">ad</span><span class="p">,</span>
  <span class="k">CASE</span>
    <span class="k">WHEN</span> <span class="n">toplam_harcama</span> <span class="o">&gt;=</span> <span class="mi">10000</span> <span class="k">THEN</span> <span class="s1">'VIP'</span>
    <span class="k">ELSE</span> <span class="s1">'Standart'</span>
  <span class="k">END</span> <span class="k">AS</span> <span class="n">musteri_tipi</span>
<span class="k">FROM</span> <span class="n">musteriler</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">CASE</code> kolon üretir; <code class="language-plaintext highlighter-rouge">WHERE</code>, <code class="language-plaintext highlighter-rouge">SELECT</code>, <code class="language-plaintext highlighter-rouge">ORDER BY</code> içinde kullanılabilir.</p>
</blockquote>

<hr />

<h3 id="18-view">18. VIEW</h3>

<p><strong>Ne işe yarar?</strong> Kaydedilmiş sorgu gibi davranan sanal tablodur.</p>

<p><strong>Ne zaman kullanılır?</strong> Karmaşık sorguları basitleştirmek ve raporları standartlaştırmak için kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">CREATE</span> <span class="k">VIEW</span> <span class="n">aktif_musteriler</span> <span class="k">AS</span>
<span class="k">SELECT</span> <span class="o">*</span> <span class="k">FROM</span> <span class="n">musteriler</span>
<span class="k">WHERE</span> <span class="n">aktif</span> <span class="o">=</span> <span class="k">TRUE</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p>View veri kopyalamaz; sorgulandığında alttaki tablolardan okur.</p>
</blockquote>

<hr />

<h3 id="19-trigger">19. TRIGGER</h3>

<p><strong>Ne işe yarar?</strong> Tabloda olay olunca otomatik çalışan mekanizmadır.</p>

<p><strong>Ne zaman kullanılır?</strong> Log tutma, denetim, otomatik alan güncelleme gibi işlerde kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">-- PostgreSQL'de önce function, sonra trigger yazılır</span>
<span class="k">CREATE</span> <span class="k">TRIGGER</span> <span class="n">trg_log</span>
<span class="k">AFTER</span> <span class="k">INSERT</span> <span class="k">ON</span> <span class="n">siparisler</span>
<span class="k">FOR</span> <span class="k">EACH</span> <span class="k">ROW</span> <span class="k">EXECUTE</span> <span class="k">FUNCTION</span> <span class="n">log_siparis</span><span class="p">();</span>
</code></pre></div></div>

<blockquote>
  <p>Trigger güçlüdür ama gizli iş mantığı yaratabilir; dikkatli ve dökümante kullanılmalıdır.</p>
</blockquote>

<hr />

<h3 id="20-transaction">20. TRANSACTION</h3>

<p><strong>Ne işe yarar?</strong> Birden fazla işlemi tek bir bütün olarak çalıştırır.</p>

<p><strong>Ne zaman kullanılır?</strong> Para transferi gibi yarım kalmaması gereken işlemlerde kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">BEGIN</span><span class="p">;</span>
<span class="k">UPDATE</span> <span class="n">hesaplar</span> <span class="k">SET</span> <span class="n">bakiye</span> <span class="o">=</span> <span class="n">bakiye</span> <span class="o">-</span> <span class="mi">100</span> <span class="k">WHERE</span> <span class="n">id</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">UPDATE</span> <span class="n">hesaplar</span> <span class="k">SET</span> <span class="n">bakiye</span> <span class="o">=</span> <span class="n">bakiye</span> <span class="o">+</span> <span class="mi">100</span> <span class="k">WHERE</span> <span class="n">id</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="k">COMMIT</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p>Hata olursa <code class="language-plaintext highlighter-rouge">ROLLBACK</code> ile tüm işlemleri geri alırsın.</p>
</blockquote>

<hr />

<h3 id="21-inner-join">21. INNER JOIN</h3>

<p><strong>Ne işe yarar?</strong> Sadece iki tabloda da eşleşen satırları getirir.</p>

<p><strong>Ne zaman kullanılır?</strong> Siparişi olan müşterileri görmek gibi eşleşme şart olan raporlarda kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">m</span><span class="p">.</span><span class="n">ad</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">id</span>
<span class="k">FROM</span> <span class="n">musteriler</span> <span class="n">m</span>
<span class="k">INNER</span> <span class="k">JOIN</span> <span class="n">siparisler</span> <span class="n">s</span> <span class="k">ON</span> <span class="n">s</span><span class="p">.</span><span class="n">musteri_id</span> <span class="o">=</span> <span class="n">m</span><span class="p">.</span><span class="n">id</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">JOIN</code> yazdığında çoğu veritabanında varsayılan <code class="language-plaintext highlighter-rouge">INNER JOIN</code>‘dir.</p>
</blockquote>

<hr />

<h3 id="22-left-join">22. LEFT JOIN</h3>

<p><strong>Ne işe yarar?</strong> Sol tablodaki tüm satırları, sağdan eşleşenleri getirir.</p>

<p><strong>Ne zaman kullanılır?</strong> Siparişi olmayan müşterileri de görmek istediğinde kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">m</span><span class="p">.</span><span class="n">ad</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">id</span> <span class="k">AS</span> <span class="n">siparis_id</span>
<span class="k">FROM</span> <span class="n">musteriler</span> <span class="n">m</span>
<span class="k">LEFT</span> <span class="k">JOIN</span> <span class="n">siparisler</span> <span class="n">s</span> <span class="k">ON</span> <span class="n">s</span><span class="p">.</span><span class="n">musteri_id</span> <span class="o">=</span> <span class="n">m</span><span class="p">.</span><span class="n">id</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p>Sağ tarafta eşleşme yoksa kolonlar <code class="language-plaintext highlighter-rouge">NULL</code> gelir.</p>
</blockquote>

<hr />

<h3 id="23-right-join">23. RIGHT JOIN</h3>

<p><strong>Ne işe yarar?</strong> Sağ tablodaki tüm satırları, soldan eşleşenleri getirir.</p>

<p><strong>Ne zaman kullanılır?</strong> <code class="language-plaintext highlighter-rouge">LEFT JOIN</code>‘in ters yönlüsüdür.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">m</span><span class="p">.</span><span class="n">ad</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">id</span>
<span class="k">FROM</span> <span class="n">musteriler</span> <span class="n">m</span>
<span class="k">RIGHT</span> <span class="k">JOIN</span> <span class="n">siparisler</span> <span class="n">s</span> <span class="k">ON</span> <span class="n">s</span><span class="p">.</span><span class="n">musteri_id</span> <span class="o">=</span> <span class="n">m</span><span class="p">.</span><span class="n">id</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p>Okunabilirlik için çoğu ekip <code class="language-plaintext highlighter-rouge">RIGHT JOIN</code> yerine tablo sıralamasını değiştirip <code class="language-plaintext highlighter-rouge">LEFT JOIN</code> kullanır.</p>
</blockquote>

<hr />

<h3 id="24-full-outer-join">24. FULL OUTER JOIN</h3>

<p><strong>Ne işe yarar?</strong> İki tablodaki tüm satırları getirir; eşleşenleri yan yana koyar.</p>

<p><strong>Ne zaman kullanılır?</strong> İki kaynağı karşılaştırma ve eksik eşleşmeleri bulma işlerinde kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">a</span><span class="p">.</span><span class="n">id</span><span class="p">,</span> <span class="n">b</span><span class="p">.</span><span class="n">id</span>
<span class="k">FROM</span> <span class="n">kaynak_a</span> <span class="n">a</span>
<span class="k">FULL</span> <span class="k">OUTER</span> <span class="k">JOIN</span> <span class="n">kaynak_b</span> <span class="n">b</span> <span class="k">ON</span> <span class="n">b</span><span class="p">.</span><span class="n">id</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">id</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p>Her veritabanında desteklenmeyebilir; MySQL’de alternatif çözüm gerekir.</p>
</blockquote>

<hr />

<h3 id="25-count">25. COUNT</h3>

<p><strong>Ne işe yarar?</strong> Satır veya değer sayar.</p>

<p><strong>Ne zaman kullanılır?</strong> Raporların en temel aggregate fonksiyonudur.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="k">COUNT</span><span class="p">(</span><span class="o">*</span><span class="p">)</span> <span class="k">AS</span> <span class="n">toplam_siparis</span>
<span class="k">FROM</span> <span class="n">siparisler</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">COUNT(*)</code> satır sayar; <code class="language-plaintext highlighter-rouge">COUNT(kolon)</code> <code class="language-plaintext highlighter-rouge">NULL</code> olmayan değerleri sayar.</p>
</blockquote>

<hr />

<h3 id="26-sum">26. SUM</h3>

<p><strong>Ne işe yarar?</strong> Sayısal değerleri toplar.</p>

<p><strong>Ne zaman kullanılır?</strong> Ciro, toplam stok, toplam ödeme gibi hesaplarda kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="k">SUM</span><span class="p">(</span><span class="n">toplam_tutar</span><span class="p">)</span> <span class="k">AS</span> <span class="n">ciro</span>
<span class="k">FROM</span> <span class="n">siparisler</span>
<span class="k">WHERE</span> <span class="n">durum</span> <span class="o">=</span> <span class="s1">'tamamlandi'</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">NULL</code> değerler toplama dahil edilmez; gerekirse <code class="language-plaintext highlighter-rouge">COALESCE</code> kullanılır.</p>
</blockquote>

<hr />

<h3 id="27-avg">27. AVG</h3>

<p><strong>Ne işe yarar?</strong> Ortalama hesaplar.</p>

<p><strong>Ne zaman kullanılır?</strong> Ortalama sepet tutarı, ortalama yaş, ortalama puan gibi raporlarda kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="k">AVG</span><span class="p">(</span><span class="n">toplam_tutar</span><span class="p">)</span> <span class="k">AS</span> <span class="n">ortalama_sepet</span>
<span class="k">FROM</span> <span class="n">siparisler</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">AVG</code> <code class="language-plaintext highlighter-rouge">NULL</code> değerleri yok sayar.</p>
</blockquote>

<hr />

<h3 id="28-min--max">28. MIN / MAX</h3>

<p><strong>Ne işe yarar?</strong> En küçük ve en büyük değeri bulur.</p>

<p><strong>Ne zaman kullanılır?</strong> En erken tarih, en son sipariş, en ucuz ürün gibi sorgularda kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="k">MIN</span><span class="p">(</span><span class="n">fiyat</span><span class="p">)</span> <span class="k">AS</span> <span class="n">en_ucuz</span><span class="p">,</span> <span class="k">MAX</span><span class="p">(</span><span class="n">fiyat</span><span class="p">)</span> <span class="k">AS</span> <span class="n">en_pahali</span>
<span class="k">FROM</span> <span class="n">urunler</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p>Tarihlerde <code class="language-plaintext highlighter-rouge">MIN</code> en eskiyi, <code class="language-plaintext highlighter-rouge">MAX</code> en yeni tarihi verir.</p>
</blockquote>

<hr />

<h3 id="29-between">29. BETWEEN</h3>

<p><strong>Ne işe yarar?</strong> İki sınır arasını filtreler.</p>

<p><strong>Ne zaman kullanılır?</strong> Tarih, fiyat, yaş aralıklarında pratik kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">*</span>
<span class="k">FROM</span> <span class="n">siparisler</span>
<span class="k">WHERE</span> <span class="n">toplam_tutar</span> <span class="k">BETWEEN</span> <span class="mi">100</span> <span class="k">AND</span> <span class="mi">500</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">BETWEEN</code> iki sınırı da dahil eder.</p>
</blockquote>

<hr />

<h3 id="30-in">30. IN</h3>

<p><strong>Ne işe yarar?</strong> Bir kolonun verilen listede olup olmadığını kontrol eder.</p>

<p><strong>Ne zaman kullanılır?</strong> Birden fazla eşitlik koşulunu temiz yazmak için kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">*</span>
<span class="k">FROM</span> <span class="n">musteriler</span>
<span class="k">WHERE</span> <span class="n">sehir</span> <span class="k">IN</span> <span class="p">(</span><span class="s1">'Ankara'</span><span class="p">,</span> <span class="s1">'Istanbul'</span><span class="p">,</span> <span class="s1">'Izmir'</span><span class="p">);</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">IN</code> listesi subquery ile de doldurulabilir.</p>
</blockquote>

<hr />

<h3 id="31-like">31. LIKE</h3>

<p><strong>Ne işe yarar?</strong> Metin desenine göre arama yapar.</p>

<p><strong>Ne zaman kullanılır?</strong> İsim, email, açıklama gibi alanlarda basit arama yapar.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">*</span>
<span class="k">FROM</span> <span class="n">musteriler</span>
<span class="k">WHERE</span> <span class="n">ad</span> <span class="k">LIKE</span> <span class="s1">'A%'</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">%</code> herhangi uzunlukta karakter, <code class="language-plaintext highlighter-rouge">_</code> tek karakter anlamına gelir.</p>
</blockquote>

<hr />

<h3 id="32-is-null">32. IS NULL</h3>

<p><strong>Ne işe yarar?</strong> <code class="language-plaintext highlighter-rouge">NULL</code> değeri kontrol eder.</p>

<p><strong>Ne zaman kullanılır?</strong> Eksik telefon, atanmış olmayan teslimat tarihi gibi kayıtları bulur.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">*</span>
<span class="k">FROM</span> <span class="n">musteriler</span>
<span class="k">WHERE</span> <span class="n">telefon</span> <span class="k">IS</span> <span class="k">NULL</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">NULL = NULL</code> yazılmaz; <code class="language-plaintext highlighter-rouge">IS NULL</code> veya <code class="language-plaintext highlighter-rouge">IS NOT NULL</code> kullanılır.</p>
</blockquote>

<hr />

<h3 id="33-exists">33. EXISTS</h3>

<p><strong>Ne işe yarar?</strong> Alt sorguda en az bir satır var mı diye bakar.</p>

<p><strong>Ne zaman kullanılır?</strong> İlişkili kaydın varlığını kontrol etmek için güçlüdür.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">m</span><span class="p">.</span><span class="n">ad</span>
<span class="k">FROM</span> <span class="n">musteriler</span> <span class="n">m</span>
<span class="k">WHERE</span> <span class="k">EXISTS</span> <span class="p">(</span>
  <span class="k">SELECT</span> <span class="mi">1</span> <span class="k">FROM</span> <span class="n">siparisler</span> <span class="n">s</span> <span class="k">WHERE</span> <span class="n">s</span><span class="p">.</span><span class="n">musteri_id</span> <span class="o">=</span> <span class="n">m</span><span class="p">.</span><span class="n">id</span>
<span class="p">);</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">EXISTS</code> genelde varlık kontrolünde <code class="language-plaintext highlighter-rouge">IN</code>‘e göre daha niyet belirgin ve performanslı olabilir.</p>
</blockquote>

<hr />

<h3 id="34-alter-table">34. ALTER TABLE</h3>

<p><strong>Ne işe yarar?</strong> Tablo yapısını değiştirir.</p>

<p><strong>Ne zaman kullanılır?</strong> Kolon ekleme, kolon tipi değiştirme, constraint ekleme gibi işlerde kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">ALTER</span> <span class="k">TABLE</span> <span class="n">musteriler</span>
<span class="k">ADD</span> <span class="k">COLUMN</span> <span class="n">dogum_tarihi</span> <span class="nb">DATE</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p>Canlı sistemde <code class="language-plaintext highlighter-rouge">ALTER TABLE</code> dikkat ister; büyük tabloda kilit ve süre sorunu yaratabilir.</p>
</blockquote>

<hr />

<h3 id="35-drop-table">35. DROP TABLE</h3>

<p><strong>Ne işe yarar?</strong> Tabloyu tamamen siler.</p>

<p><strong>Ne zaman kullanılır?</strong> Test tablosunu kaldırmak veya eski yapıları temizlemek için kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">DROP</span> <span class="k">TABLE</span> <span class="n">eski_raporlar</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">DROP</code> geri dönüşü zor bir işlemdir. Üretimde mutlaka yedek ve yetki kontrolü gerekir.</p>
</blockquote>

<hr />

<h3 id="36-create-table">36. CREATE TABLE</h3>

<p><strong>Ne işe yarar?</strong> Yeni tablo oluşturur.</p>

<p><strong>Ne zaman kullanılır?</strong> Veriyi düzenli saklamak için kolonlar ve veri tipleri belirlenir.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">CREATE</span> <span class="k">TABLE</span> <span class="n">urunler</span> <span class="p">(</span>
  <span class="n">id</span> <span class="nb">SERIAL</span> <span class="k">PRIMARY</span> <span class="k">KEY</span><span class="p">,</span>
  <span class="n">ad</span> <span class="nb">TEXT</span> <span class="k">NOT</span> <span class="k">NULL</span><span class="p">,</span>
  <span class="n">fiyat</span> <span class="nb">NUMERIC</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span><span class="mi">2</span><span class="p">)</span>
<span class="p">);</span>
</code></pre></div></div>

<blockquote>
  <p>Tablo tasarımı sonradan tüm sorgu kalitesini etkiler.</p>
</blockquote>

<hr />

<h3 id="37-default">37. DEFAULT</h3>

<p><strong>Ne işe yarar?</strong> Kolon için varsayılan değer tanımlar.</p>

<p><strong>Ne zaman kullanılır?</strong> Kayıt eklerken belirtilmeyen alanlara otomatik değer vermek için kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">CREATE</span> <span class="k">TABLE</span> <span class="n">kullanicilar</span> <span class="p">(</span>
  <span class="n">id</span> <span class="nb">SERIAL</span> <span class="k">PRIMARY</span> <span class="k">KEY</span><span class="p">,</span>
  <span class="n">aktif</span> <span class="nb">BOOLEAN</span> <span class="k">DEFAULT</span> <span class="k">TRUE</span>
<span class="p">);</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">created_at</code> için <code class="language-plaintext highlighter-rouge">DEFAULT now()</code> çok yaygın kullanılır.</p>
</blockquote>

<hr />

<h3 id="38-unique">38. UNIQUE</h3>

<p><strong>Ne işe yarar?</strong> Aynı değerin tekrar girmesini engeller.</p>

<p><strong>Ne zaman kullanılır?</strong> Email, kullanıcı adı, fatura no gibi tekil olması gereken alanlarda kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">CREATE</span> <span class="k">TABLE</span> <span class="n">kullanicilar</span> <span class="p">(</span>
  <span class="n">id</span> <span class="nb">SERIAL</span> <span class="k">PRIMARY</span> <span class="k">KEY</span><span class="p">,</span>
  <span class="n">email</span> <span class="nb">TEXT</span> <span class="k">UNIQUE</span>
<span class="p">);</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">UNIQUE</code> constraint veri kalitesini uygulama koduna bırakmadan veritabanında korur.</p>
</blockquote>

<hr />

<h3 id="39-check">39. CHECK</h3>

<p><strong>Ne işe yarar?</strong> Kolona veya satıra kural koyar.</p>

<p><strong>Ne zaman kullanılır?</strong> Negatif fiyat, geçersiz yaş gibi hatalı verileri engeller.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">CREATE</span> <span class="k">TABLE</span> <span class="n">urunler</span> <span class="p">(</span>
  <span class="n">fiyat</span> <span class="nb">NUMERIC</span> <span class="k">CHECK</span> <span class="p">(</span><span class="n">fiyat</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span>
<span class="p">);</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">CHECK</code>, veri kurallarını merkezi ve güvenli hale getirir.</p>
</blockquote>

<hr />

<h3 id="40-serial--auto-increment">40. SERIAL / AUTO INCREMENT</h3>

<p><strong>Ne işe yarar?</strong> Otomatik artan id üretir.</p>

<p><strong>Ne zaman kullanılır?</strong> Her kayda benzersiz sayısal kimlik vermek için kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">CREATE</span> <span class="k">TABLE</span> <span class="n">musteriler</span> <span class="p">(</span>
  <span class="n">id</span> <span class="nb">SERIAL</span> <span class="k">PRIMARY</span> <span class="k">KEY</span><span class="p">,</span>
  <span class="n">ad</span> <span class="nb">TEXT</span> <span class="k">NOT</span> <span class="k">NULL</span>
<span class="p">);</span>
</code></pre></div></div>

<blockquote>
  <p>PostgreSQL’de modern alternatif <code class="language-plaintext highlighter-rouge">GENERATED AS IDENTITY</code> yapısıdır.</p>
</blockquote>

<hr />

<h2 id="bölüm-2--orta-i̇leri-ve-i̇leri-sql-konuları">Bölüm 2 — Orta-İleri ve İleri SQL Konuları</h2>

<h3 id="41-cte--with">41. CTE — WITH</h3>

<p><strong>Ne işe yarar?</strong> Sorgu içinde geçici isimlendirilmiş sonuç oluşturur.</p>

<p><strong>Ne zaman kullanılır?</strong> Karmaşık sorguları adım adım okunur hale getirir.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">WITH</span> <span class="n">aylik_satis</span> <span class="k">AS</span> <span class="p">(</span>
  <span class="k">SELECT</span> <span class="n">date_trunc</span><span class="p">(</span><span class="s1">'month'</span><span class="p">,</span> <span class="n">created_at</span><span class="p">)</span> <span class="k">AS</span> <span class="n">ay</span><span class="p">,</span> <span class="k">SUM</span><span class="p">(</span><span class="n">toplam_tutar</span><span class="p">)</span> <span class="k">AS</span> <span class="n">ciro</span>
  <span class="k">FROM</span> <span class="n">siparisler</span>
  <span class="k">GROUP</span> <span class="k">BY</span> <span class="mi">1</span>
<span class="p">)</span>
<span class="k">SELECT</span> <span class="o">*</span> <span class="k">FROM</span> <span class="n">aylik_satis</span>
<span class="k">ORDER</span> <span class="k">BY</span> <span class="n">ay</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p>CTE, sorguyu bölümlere ayırmak için harikadır. Bazı veritabanlarında optimizasyon davranışı değişebilir.</p>
</blockquote>

<hr />

<h3 id="42-recursive-cte">42. Recursive CTE</h3>

<p><strong>Ne işe yarar?</strong> Kendi sonucuna tekrar başvuran CTE’dir.</p>

<p><strong>Ne zaman kullanılır?</strong> Kategori ağacı, organizasyon şeması, graph benzeri hiyerarşilerde kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">WITH</span> <span class="k">RECURSIVE</span> <span class="n">kategori_agaci</span> <span class="k">AS</span> <span class="p">(</span>
  <span class="k">SELECT</span> <span class="n">id</span><span class="p">,</span> <span class="n">parent_id</span><span class="p">,</span> <span class="n">ad</span><span class="p">,</span> <span class="mi">1</span> <span class="k">AS</span> <span class="n">seviye</span>
  <span class="k">FROM</span> <span class="n">kategoriler</span> <span class="k">WHERE</span> <span class="n">parent_id</span> <span class="k">IS</span> <span class="k">NULL</span>
  <span class="k">UNION</span> <span class="k">ALL</span>
  <span class="k">SELECT</span> <span class="n">k</span><span class="p">.</span><span class="n">id</span><span class="p">,</span> <span class="n">k</span><span class="p">.</span><span class="n">parent_id</span><span class="p">,</span> <span class="n">k</span><span class="p">.</span><span class="n">ad</span><span class="p">,</span> <span class="n">ka</span><span class="p">.</span><span class="n">seviye</span> <span class="o">+</span> <span class="mi">1</span>
  <span class="k">FROM</span> <span class="n">kategoriler</span> <span class="n">k</span>
  <span class="k">JOIN</span> <span class="n">kategori_agaci</span> <span class="n">ka</span> <span class="k">ON</span> <span class="n">k</span><span class="p">.</span><span class="n">parent_id</span> <span class="o">=</span> <span class="n">ka</span><span class="p">.</span><span class="n">id</span>
<span class="p">)</span>
<span class="k">SELECT</span> <span class="o">*</span> <span class="k">FROM</span> <span class="n">kategori_agaci</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p>Recursive sorgularda sonsuz döngü riskine karşı seviye sınırı veya veri kontrolü düşünülmelidir.</p>
</blockquote>

<hr />

<h3 id="43-window-functions">43. Window Functions</h3>

<p><strong>Ne işe yarar?</strong> Satırları kaybetmeden grup bazlı hesap yapar.</p>

<p><strong>Ne zaman kullanılır?</strong> Sıralama, küme içinde toplam, hareketli ortalama gibi analizlerde kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">musteri_id</span><span class="p">,</span> <span class="n">created_at</span><span class="p">,</span> <span class="n">toplam_tutar</span><span class="p">,</span>
  <span class="k">SUM</span><span class="p">(</span><span class="n">toplam_tutar</span><span class="p">)</span> <span class="n">OVER</span> <span class="p">(</span><span class="k">PARTITION</span> <span class="k">BY</span> <span class="n">musteri_id</span> <span class="k">ORDER</span> <span class="k">BY</span> <span class="n">created_at</span><span class="p">)</span> <span class="k">AS</span> <span class="n">kume_toplam</span>
<span class="k">FROM</span> <span class="n">siparisler</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">GROUP BY</code> satırları özetler; window function satırları korur.</p>
</blockquote>

<hr />

<h3 id="44-row_number">44. ROW_NUMBER</h3>

<p><strong>Ne işe yarar?</strong> Her grup içinde sıralı numara verir.</p>

<p><strong>Ne zaman kullanılır?</strong> Her müşterinin en son siparişini bulmak gibi işlerde kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">WITH</span> <span class="n">sirali</span> <span class="k">AS</span> <span class="p">(</span>
  <span class="k">SELECT</span> <span class="o">*</span><span class="p">,</span> <span class="n">ROW_NUMBER</span><span class="p">()</span> <span class="n">OVER</span> <span class="p">(</span><span class="k">PARTITION</span> <span class="k">BY</span> <span class="n">musteri_id</span> <span class="k">ORDER</span> <span class="k">BY</span> <span class="n">created_at</span> <span class="k">DESC</span><span class="p">)</span> <span class="k">AS</span> <span class="n">rn</span>
  <span class="k">FROM</span> <span class="n">siparisler</span>
<span class="p">)</span>
<span class="k">SELECT</span> <span class="o">*</span> <span class="k">FROM</span> <span class="n">sirali</span> <span class="k">WHERE</span> <span class="n">rn</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p>Aynı sıralama değerlerinde sonuç deterministik olsun diye <code class="language-plaintext highlighter-rouge">ORDER BY</code>‘a ikinci kolon eklenebilir.</p>
</blockquote>

<hr />

<h3 id="45-rank--dense_rank">45. RANK / DENSE_RANK</h3>

<p><strong>Ne işe yarar?</strong> Eşitlik durumunu dikkate alan sıralama fonksiyonlarıdır.</p>

<p><strong>Ne zaman kullanılır?</strong> Puan tablosu, satış liderleri gibi listelerde kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">urun_id</span><span class="p">,</span> <span class="n">toplam_satis</span><span class="p">,</span>
  <span class="n">RANK</span><span class="p">()</span> <span class="n">OVER</span> <span class="p">(</span><span class="k">ORDER</span> <span class="k">BY</span> <span class="n">toplam_satis</span> <span class="k">DESC</span><span class="p">)</span> <span class="k">AS</span> <span class="n">sira</span>
<span class="k">FROM</span> <span class="n">urun_satis_ozet</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">RANK</code> eşitlikte boşluk bırakır; <code class="language-plaintext highlighter-rouge">DENSE_RANK</code> boşluk bırakmaz.</p>
</blockquote>

<hr />

<h3 id="46-lag--lead">46. LAG / LEAD</h3>

<p><strong>Ne işe yarar?</strong> Önceki veya sonraki satırdaki değeri okur.</p>

<p><strong>Ne zaman kullanılır?</strong> Aydan aya değişim, önceki fiyatla karşılaştırma gibi analizlerde kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">ay</span><span class="p">,</span> <span class="n">ciro</span><span class="p">,</span>
  <span class="n">ciro</span> <span class="o">-</span> <span class="n">LAG</span><span class="p">(</span><span class="n">ciro</span><span class="p">)</span> <span class="n">OVER</span> <span class="p">(</span><span class="k">ORDER</span> <span class="k">BY</span> <span class="n">ay</span><span class="p">)</span> <span class="k">AS</span> <span class="n">onceki_aya_gore_fark</span>
<span class="k">FROM</span> <span class="n">aylik_ciro</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p>Zaman serisi analizlerinde çok kullanışlıdır.</p>
</blockquote>

<hr />

<h3 id="47-coalesce">47. COALESCE</h3>

<p><strong>Ne işe yarar?</strong> İlk <code class="language-plaintext highlighter-rouge">NULL</code> olmayan değeri döndürür.</p>

<p><strong>Ne zaman kullanılır?</strong> <code class="language-plaintext highlighter-rouge">NULL</code> değerleri raporda anlamlı varsayılanlarla göstermek için kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">ad</span><span class="p">,</span> <span class="n">COALESCE</span><span class="p">(</span><span class="n">telefon</span><span class="p">,</span> <span class="s1">'Telefon yok'</span><span class="p">)</span> <span class="k">AS</span> <span class="n">telefon</span>
<span class="k">FROM</span> <span class="n">musteriler</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">COALESCE</code> SQL’in en pratik <code class="language-plaintext highlighter-rouge">NULL</code> yönetimi araçlarından biridir.</p>
</blockquote>

<hr />

<h3 id="48-nullif">48. NULLIF</h3>

<p><strong>Ne işe yarar?</strong> İki ifade eşitse <code class="language-plaintext highlighter-rouge">NULL</code> döndürür.</p>

<p><strong>Ne zaman kullanılır?</strong> Sıfıra bölme hatasını önlemek gibi durumlarda kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">toplam_tutar</span> <span class="o">/</span> <span class="k">NULLIF</span><span class="p">(</span><span class="n">urun_adedi</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="k">AS</span> <span class="n">ortalama_birim_tutar</span>
<span class="k">FROM</span> <span class="n">siparisler</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">NULLIF(a,b)</code> → <code class="language-plaintext highlighter-rouge">a = b</code> ise <code class="language-plaintext highlighter-rouge">NULL</code>; değilse <code class="language-plaintext highlighter-rouge">a</code> döndürür.</p>
</blockquote>

<hr />

<h3 id="49-cast--type-conversion">49. CAST / Type Conversion</h3>

<p><strong>Ne işe yarar?</strong> Bir veri tipini başka tipe çevirir.</p>

<p><strong>Ne zaman kullanılır?</strong> Metni sayıya, tarihi metne veya sayıyı metne çevirmek gerekebilir.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="k">CAST</span><span class="p">(</span><span class="s1">'2026-05-07'</span> <span class="k">AS</span> <span class="nb">DATE</span><span class="p">)</span> <span class="k">AS</span> <span class="n">tarih</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p>Yanlış format cast hatası üretir. Veri temizliği önemlidir.</p>
</blockquote>

<hr />

<h3 id="50-date-functions">50. Date Functions</h3>

<p><strong>Ne işe yarar?</strong> Tarihleri parçala, yuvarla veya aralık hesapla.</p>

<p><strong>Ne zaman kullanılır?</strong> Günlük/aylık raporlama ve zaman filtreleri için kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">date_trunc</span><span class="p">(</span><span class="s1">'month'</span><span class="p">,</span> <span class="n">created_at</span><span class="p">)</span> <span class="k">AS</span> <span class="n">ay</span><span class="p">,</span> <span class="k">COUNT</span><span class="p">(</span><span class="o">*</span><span class="p">)</span>
<span class="k">FROM</span> <span class="n">siparisler</span>
<span class="k">GROUP</span> <span class="k">BY</span> <span class="mi">1</span>
<span class="k">ORDER</span> <span class="k">BY</span> <span class="mi">1</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p>Tarih fonksiyonları veritabanına göre değişir; PostgreSQL, MySQL, SQL Server farklıdır.</p>
</blockquote>

<hr />

<h3 id="51-string-functions">51. String Functions</h3>

<p><strong>Ne işe yarar?</strong> Metinleri birleştirme, parçalama, küçültme/büyütme gibi işlemler yapar.</p>

<p><strong>Ne zaman kullanılır?</strong> Arama, temizlik ve raporlama formatları için kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="k">LOWER</span><span class="p">(</span><span class="k">TRIM</span><span class="p">(</span><span class="n">email</span><span class="p">))</span> <span class="k">AS</span> <span class="n">temiz_email</span>
<span class="k">FROM</span> <span class="n">kullanicilar</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p>Metin temizliği yaparken index kullanımı etkilenebilir; expression index gerekebilir.</p>
</blockquote>

<hr />

<h3 id="52-aggregate-filtering">52. Aggregate Filtering</h3>

<p><strong>Ne işe yarar?</strong> Aggregate hesaba koşullu veri dahil eder.</p>

<p><strong>Ne zaman kullanılır?</strong> Aynı sorguda farklı sayım ve toplamları üretmek için kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span>
  <span class="k">COUNT</span><span class="p">(</span><span class="o">*</span><span class="p">)</span> <span class="k">AS</span> <span class="n">toplam</span><span class="p">,</span>
  <span class="k">COUNT</span><span class="p">(</span><span class="o">*</span><span class="p">)</span> <span class="n">FILTER</span> <span class="p">(</span><span class="k">WHERE</span> <span class="n">durum</span> <span class="o">=</span> <span class="s1">'tamamlandi'</span><span class="p">)</span> <span class="k">AS</span> <span class="n">tamamlanan</span>
<span class="k">FROM</span> <span class="n">siparisler</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">FILTER</code> PostgreSQL’de çok temizdir; diğer sistemlerde <code class="language-plaintext highlighter-rouge">CASE</code> ile yazılabilir.</p>
</blockquote>

<hr />

<h3 id="53-conditional-aggregation">53. Conditional Aggregation</h3>

<p><strong>Ne işe yarar?</strong> <code class="language-plaintext highlighter-rouge">SUM</code>/<code class="language-plaintext highlighter-rouge">COUNT</code> içinde <code class="language-plaintext highlighter-rouge">CASE</code> kullanarak koşullu özet üretir.</p>

<p><strong>Ne zaman kullanılır?</strong> Pivot benzeri raporlarda ve dashboard metriklerinde çok kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span>
  <span class="k">SUM</span><span class="p">(</span><span class="k">CASE</span> <span class="k">WHEN</span> <span class="n">durum</span> <span class="o">=</span> <span class="s1">'tamamlandi'</span> <span class="k">THEN</span> <span class="mi">1</span> <span class="k">ELSE</span> <span class="mi">0</span> <span class="k">END</span><span class="p">)</span> <span class="k">AS</span> <span class="n">tamamlanan</span><span class="p">,</span>
  <span class="k">SUM</span><span class="p">(</span><span class="k">CASE</span> <span class="k">WHEN</span> <span class="n">durum</span> <span class="o">=</span> <span class="s1">'iptal'</span> <span class="k">THEN</span> <span class="mi">1</span> <span class="k">ELSE</span> <span class="mi">0</span> <span class="k">END</span><span class="p">)</span> <span class="k">AS</span> <span class="n">iptal</span>
<span class="k">FROM</span> <span class="n">siparisler</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p>Tek sorguda birden fazla metriği hesaplamak için çok pratiktir.</p>
</blockquote>

<hr />

<h3 id="54-union-all">54. UNION ALL</h3>

<p><strong>Ne işe yarar?</strong> İki sonucu tekrar kontrolü yapmadan birleştirir.</p>

<p><strong>Ne zaman kullanılır?</strong> Log, arşiv ve canlı tabloyu birlikte okumak gibi durumlarda kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">id</span><span class="p">,</span> <span class="n">created_at</span> <span class="k">FROM</span> <span class="n">siparisler_2025</span>
<span class="k">UNION</span> <span class="k">ALL</span>
<span class="k">SELECT</span> <span class="n">id</span><span class="p">,</span> <span class="n">created_at</span> <span class="k">FROM</span> <span class="n">siparisler_2026</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">UNION ALL</code> genelde <code class="language-plaintext highlighter-rouge">UNION</code>‘dan daha hızlıdır çünkü tekrar silme maliyeti yoktur.</p>
</blockquote>

<hr />

<h3 id="55-intersect--except">55. INTERSECT / EXCEPT</h3>

<p><strong>Ne işe yarar?</strong> Kesişim ve fark işlemleri yapar.</p>

<p><strong>Ne zaman kullanılır?</strong> İki liste arasında ortak veya eksik kayıtları bulmak için kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">-- Kesişim</span>
<span class="k">SELECT</span> <span class="n">email</span> <span class="k">FROM</span> <span class="n">liste_a</span>
<span class="k">INTERSECT</span>
<span class="k">SELECT</span> <span class="n">email</span> <span class="k">FROM</span> <span class="n">liste_b</span><span class="p">;</span>

<span class="c1">-- Fark</span>
<span class="k">SELECT</span> <span class="n">email</span> <span class="k">FROM</span> <span class="n">liste_a</span>
<span class="k">EXCEPT</span>
<span class="k">SELECT</span> <span class="n">email</span> <span class="k">FROM</span> <span class="n">liste_b</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p>Veri karşılaştırma ve mutabakat işlerinde çok kullanışlıdır.</p>
</blockquote>

<hr />

<h3 id="56-upsert">56. UPSERT</h3>

<p><strong>Ne işe yarar?</strong> Kayıt varsa güncelle, yoksa ekle mantığıdır.</p>

<p><strong>Ne zaman kullanılır?</strong> Tekil anahtara göre tekrarlı veri girişini yönetir.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">INSERT</span> <span class="k">INTO</span> <span class="n">urun_stok</span><span class="p">(</span><span class="n">urun_id</span><span class="p">,</span> <span class="n">adet</span><span class="p">)</span>
<span class="k">VALUES</span> <span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span>
<span class="k">ON</span> <span class="n">CONFLICT</span> <span class="p">(</span><span class="n">urun_id</span><span class="p">)</span>
<span class="k">DO</span> <span class="k">UPDATE</span> <span class="k">SET</span> <span class="n">adet</span> <span class="o">=</span> <span class="n">urun_stok</span><span class="p">.</span><span class="n">adet</span> <span class="o">+</span> <span class="n">EXCLUDED</span><span class="p">.</span><span class="n">adet</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p>PostgreSQL’de <code class="language-plaintext highlighter-rouge">ON CONFLICT</code> kullanılır. SQL Server’da <code class="language-plaintext highlighter-rouge">MERGE</code> alternatif olabilir.</p>
</blockquote>

<hr />

<h3 id="57-stored-procedure">57. Stored Procedure</h3>

<p><strong>Ne işe yarar?</strong> Veritabanında saklanan işlem bloklarıdır.</p>

<p><strong>Ne zaman kullanılır?</strong> Tekrarlanan iş kurallarını veritabanında çalıştırmak için kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">CALL</span> <span class="n">siparis_kapat</span><span class="p">(</span><span class="mi">123</span><span class="p">);</span>
</code></pre></div></div>

<blockquote>
  <p>Procedure kullanımı ekip ve mimariye bağlıdır. Aşırı iş mantığı veritabanını karmaşıklaştırabilir.</p>
</blockquote>

<hr />

<h3 id="58-user-defined-function">58. User Defined Function</h3>

<p><strong>Ne işe yarar?</strong> Veritabanında kendi fonksiyonunu tanımlarsın.</p>

<p><strong>Ne zaman kullanılır?</strong> Tekrar eden hesaplamaları merkezi hale getirir.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">CREATE</span> <span class="k">FUNCTION</span> <span class="n">kdvli_fiyat</span><span class="p">(</span><span class="n">fiyat</span> <span class="nb">NUMERIC</span><span class="p">)</span>
<span class="k">RETURNS</span> <span class="nb">NUMERIC</span> <span class="k">AS</span> <span class="err">$$</span>
  <span class="k">SELECT</span> <span class="n">fiyat</span> <span class="o">*</span> <span class="mi">1</span><span class="p">.</span><span class="mi">20</span><span class="p">;</span>
<span class="err">$$</span> <span class="k">LANGUAGE</span> <span class="k">SQL</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p>Fonksiyonlar okunabilirlik sağlar; ama performans ve yan etki konularına dikkat edilir.</p>
</blockquote>

<hr />

<h3 id="59-materialized-view">59. Materialized View</h3>

<p><strong>Ne işe yarar?</strong> View sonucunu fiziksel olarak saklar.</p>

<p><strong>Ne zaman kullanılır?</strong> Ağır raporları hızlandırmak için kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">CREATE</span> <span class="n">MATERIALIZED</span> <span class="k">VIEW</span> <span class="n">aylik_ciro</span> <span class="k">AS</span>
<span class="k">SELECT</span> <span class="n">date_trunc</span><span class="p">(</span><span class="s1">'month'</span><span class="p">,</span> <span class="n">created_at</span><span class="p">)</span> <span class="k">AS</span> <span class="n">ay</span><span class="p">,</span> <span class="k">SUM</span><span class="p">(</span><span class="n">toplam_tutar</span><span class="p">)</span> <span class="k">AS</span> <span class="n">ciro</span>
<span class="k">FROM</span> <span class="n">siparisler</span>
<span class="k">GROUP</span> <span class="k">BY</span> <span class="mi">1</span><span class="p">;</span>

<span class="n">REFRESH</span> <span class="n">MATERIALIZED</span> <span class="k">VIEW</span> <span class="n">aylik_ciro</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p>Normal view her okumada hesaplar; materialized view saklar ama güncelleme ister.</p>
</blockquote>

<hr />

<h3 id="60-normalization">60. Normalization</h3>

<p><strong>Ne işe yarar?</strong> Veriyi tekrar azaltacak şekilde tablolara ayırma prensibidir.</p>

<p><strong>Ne zaman kullanılır?</strong> Müşteri, sipariş, ürün gibi varlıkları doğru modellemek için kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">-- Müşteri bilgisi sipariş tablosunda tekrar tekrar tutulmaz</span>
<span class="c1">-- siparisler.musteri_id -&gt; musteriler.id</span>
</code></pre></div></div>

<blockquote>
  <p>Aşırı normalizasyon sorguları zorlaştırabilir; raporlama için bazen denormalizasyon kullanılır.</p>
</blockquote>

<hr />

<h3 id="61-denormalization">61. Denormalization</h3>

<p><strong>Ne işe yarar?</strong> Performans veya raporlama için bazı verileri bilinçli tekrar tutmaktır.</p>

<p><strong>Ne zaman kullanılır?</strong> Dashboard, analitik tablo, cache tablo gibi yerlerde kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">-- siparis_ozet tablosunda musteri_adi ve toplam_tutar hazır tutulabilir</span>
</code></pre></div></div>

<blockquote>
  <p>Tutarlılık riski vardır; verinin nasıl güncelleneceği net olmalıdır.</p>
</blockquote>

<hr />

<h3 id="62-query-optimization">62. Query Optimization</h3>

<p><strong>Ne işe yarar?</strong> Sorguyu daha hızlı ve az maliyetli çalışacak hale getirmektir.</p>

<p><strong>Ne zaman kullanılır?</strong> Yavaş raporlar, ağır <code class="language-plaintext highlighter-rouge">JOIN</code>‘ler, büyük tablolarla çalışırken gerekir.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">EXPLAIN</span> <span class="k">ANALYZE</span>
<span class="k">SELECT</span> <span class="o">*</span> <span class="k">FROM</span> <span class="n">siparisler</span> <span class="k">WHERE</span> <span class="n">musteri_id</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p>Optimizasyon tahminle değil ölçümle yapılır. <code class="language-plaintext highlighter-rouge">EXPLAIN</code> ana araçtır.</p>
</blockquote>

<hr />

<h3 id="63-execution-plan--explain">63. Execution Plan — EXPLAIN</h3>

<p><strong>Ne işe yarar?</strong> Veritabanının sorguyu nasıl çalıştıracağını gösterir.</p>

<p><strong>Ne zaman kullanılır?</strong> Index kullanıldı mı, full scan mı yapıldı, <code class="language-plaintext highlighter-rouge">JOIN</code> sırası ne gibi sorulara cevap verir.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">EXPLAIN</span> <span class="k">ANALYZE</span>
<span class="k">SELECT</span> <span class="o">*</span>
<span class="k">FROM</span> <span class="n">siparisler</span>
<span class="k">WHERE</span> <span class="n">created_at</span> <span class="o">&gt;=</span> <span class="k">CURRENT_DATE</span> <span class="o">-</span> <span class="n">INTERVAL</span> <span class="s1">'30 days'</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">ANALYZE</code> sorguyu gerçekten çalıştırır; üretimde dikkatli kullanılır.</p>
</blockquote>

<hr />

<h3 id="64-partitioning">64. Partitioning</h3>

<p><strong>Ne işe yarar?</strong> Büyük tabloyu mantıksal/fiziksel parçalara ayırır.</p>

<p><strong>Ne zaman kullanılır?</strong> Yıllık/aylık log veya sipariş tablolarında performans ve bakım kolaylığı sağlar.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">CREATE</span> <span class="k">TABLE</span> <span class="n">siparisler</span> <span class="p">(</span>
  <span class="n">id</span> <span class="nb">BIGINT</span><span class="p">,</span>
  <span class="n">created_at</span> <span class="nb">DATE</span> <span class="k">NOT</span> <span class="k">NULL</span>
<span class="p">)</span> <span class="k">PARTITION</span> <span class="k">BY</span> <span class="k">RANGE</span> <span class="p">(</span><span class="n">created_at</span><span class="p">);</span>
</code></pre></div></div>

<blockquote>
  <p>Doğru partition anahtarı seçilmezse faydası azalır.</p>
</blockquote>

<hr />

<h3 id="65-acid">65. ACID</h3>

<p><strong>Ne işe yarar?</strong> Transaction güvenilirliğinin dört temel ilkesidir.</p>

<p><strong>Ne zaman kullanılır?</strong> Finans, stok, sipariş gibi tutarlılık gereken sistemlerde kritiktir.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Atomicity  : Ya hepsi olur ya hiçbiri
Consistency: Kurallar bozulmaz
Isolation  : İşlemler birbirini bozmaz
Durability : Commit edilen veri kalıcıdır
</code></pre></div></div>

<blockquote>
  <p>ACID mantığını bilmek transaction, lock ve hata yönetimini anlamayı kolaylaştırır.</p>
</blockquote>

<hr />

<h3 id="66-isolation-levels">66. Isolation Levels</h3>

<p><strong>Ne işe yarar?</strong> Aynı anda çalışan transaction’ların birbirini nasıl göreceğini belirler.</p>

<p><strong>Ne zaman kullanılır?</strong> Dirty read, non-repeatable read, phantom read gibi problemleri kontrol eder.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SET</span> <span class="n">TRANSACTION</span> <span class="k">ISOLATION</span> <span class="k">LEVEL</span> <span class="k">READ</span> <span class="k">COMMITTED</span><span class="p">;</span>
<span class="k">BEGIN</span><span class="p">;</span>
<span class="c1">-- islemler</span>
<span class="k">COMMIT</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p>Yüksek izolasyon daha fazla güvenlik ama daha fazla kilit/performans maliyeti getirebilir.</p>
</blockquote>

<hr />

<h3 id="67-locks">67. Locks</h3>

<p><strong>Ne işe yarar?</strong> Veriye aynı anda erişimde tutarlılık için kilit mekanizmasıdır.</p>

<p><strong>Ne zaman kullanılır?</strong> Aynı kaydı iki kişi güncellerken çarpışmayı önler.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">*</span>
<span class="k">FROM</span> <span class="n">hesaplar</span>
<span class="k">WHERE</span> <span class="n">id</span> <span class="o">=</span> <span class="mi">1</span>
<span class="k">FOR</span> <span class="k">UPDATE</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p>Kilitler doğaldır; uzun transaction deadlock ve bekleme sorunu yaratabilir.</p>
</blockquote>

<hr />

<h3 id="68-deadlock">68. Deadlock</h3>

<p><strong>Ne işe yarar?</strong> İki transaction birbirinin kilidini bekleyince oluşur.</p>

<p><strong>Ne zaman kullanılır?</strong> Yoğun güncelleme yapan sistemlerde karşına çıkabilir.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">-- Çözüm prensibi:</span>
<span class="c1">-- Kayıtları her transaction'da aynı sırayla kilitle.</span>
</code></pre></div></div>

<blockquote>
  <p>Deadlock tamamen yok edilemeyebilir; uygulama retry mantığı içermelidir.</p>
</blockquote>

<hr />

<h3 id="69-json-sql">69. JSON SQL</h3>

<p><strong>Ne işe yarar?</strong> JSON alanları içindeki veriyi sorgular.</p>

<p><strong>Ne zaman kullanılır?</strong> Esnek şemalı ek bilgiler, event payload’ları, API cevapları için kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="k">data</span><span class="o">-&gt;&gt;</span><span class="s1">'email'</span> <span class="k">AS</span> <span class="n">email</span>
<span class="k">FROM</span> <span class="n">events</span>
<span class="k">WHERE</span> <span class="k">data</span><span class="o">-&gt;&gt;</span><span class="s1">'type'</span> <span class="o">=</span> <span class="s1">'signup'</span><span class="p">;</span>
</code></pre></div></div>

<blockquote>
  <p>JSON esneklik sağlar ama her şeyi JSON yapmak relational gücü azaltır.</p>
</blockquote>

<hr />

<h3 id="70-full-text-search">70. Full Text Search</h3>

<p><strong>Ne işe yarar?</strong> Metin içinde kelime bazlı etkili arama yapar.</p>

<p><strong>Ne zaman kullanılır?</strong> Makale, ürün açıklaması, destek kaydı gibi alanlarda kullanılır.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">*</span>
<span class="k">FROM</span> <span class="n">makaleler</span>
<span class="k">WHERE</span> <span class="n">to_tsvector</span><span class="p">(</span><span class="s1">'simple'</span><span class="p">,</span> <span class="n">baslik</span> <span class="o">||</span> <span class="s1">' '</span> <span class="o">||</span> <span class="n">icerik</span><span class="p">)</span> <span class="o">@@</span> <span class="n">plainto_tsquery</span><span class="p">(</span><span class="s1">'sql'</span><span class="p">);</span>
</code></pre></div></div>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">LIKE '%kelime%'</code> basit arama için yeterli olabilir; ciddi arama için full text search düşünülür.</p>
</blockquote>

<hr />

<h2 id="mini-cheat-sheet">Mini Cheat Sheet</h2>

<table>
  <thead>
    <tr>
      <th>İhtiyaç</th>
      <th>Kullanılacak konu</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Satır filtreleme</td>
      <td><code class="language-plaintext highlighter-rouge">WHERE</code></td>
    </tr>
    <tr>
      <td>Grup filtreleme</td>
      <td><code class="language-plaintext highlighter-rouge">HAVING</code></td>
    </tr>
    <tr>
      <td>Eşleşenleri getir</td>
      <td><code class="language-plaintext highlighter-rouge">INNER JOIN</code></td>
    </tr>
    <tr>
      <td>Eşleşmeyenleri de koru</td>
      <td><code class="language-plaintext highlighter-rouge">LEFT JOIN</code> / <code class="language-plaintext highlighter-rouge">FULL OUTER JOIN</code></td>
    </tr>
    <tr>
      <td>Tekrarları kaldır</td>
      <td><code class="language-plaintext highlighter-rouge">DISTINCT</code> / <code class="language-plaintext highlighter-rouge">UNION</code></td>
    </tr>
    <tr>
      <td>Tüm tekrarlarla birleştir</td>
      <td><code class="language-plaintext highlighter-rouge">UNION ALL</code></td>
    </tr>
    <tr>
      <td>Grup özetleri</td>
      <td><code class="language-plaintext highlighter-rouge">GROUP BY</code> + <code class="language-plaintext highlighter-rouge">COUNT</code>/<code class="language-plaintext highlighter-rouge">SUM</code>/<code class="language-plaintext highlighter-rouge">AVG</code></td>
    </tr>
    <tr>
      <td>Satırları kaybetmeden analiz</td>
      <td>Window Functions</td>
    </tr>
    <tr>
      <td>Karmaşık sorguyu okunur yap</td>
      <td>CTE</td>
    </tr>
    <tr>
      <td>Performans incele</td>
      <td><code class="language-plaintext highlighter-rouge">EXPLAIN ANALYZE</code></td>
    </tr>
    <tr>
      <td>Kayıt varsa güncelle</td>
      <td><code class="language-plaintext highlighter-rouge">UPSERT</code></td>
    </tr>
    <tr>
      <td>Güvenli çoklu işlem</td>
      <td><code class="language-plaintext highlighter-rouge">TRANSACTION</code> + <code class="language-plaintext highlighter-rouge">COMMIT</code>/<code class="language-plaintext highlighter-rouge">ROLLBACK</code></td>
    </tr>
  </tbody>
</table>

<hr />

<blockquote>
  <p><strong>Çalışma önerisi:</strong> Her konu için önce örneği çalıştır, sonra tablo ve kolon adlarını kendi verine göre değiştir. En hızlı öğrenme yolu, aynı kavramı farklı senaryolarda tekrar yazmaktır.</p>
</blockquote>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="sql" /><category term="veritabanı" /><category term="select" /><category term="join" /><category term="window-functions" /><category term="cte" /><category term="transaction" /><category term="index" /><category term="postgresql" /><category term="sorgu" /><category term="programlama" /><category term="veri" /><summary type="html"><![CDATA[SQL temellerini bilen ama sorguları daha bilinçli yazmak isteyenler için 70 konu, açıklama, örnek ve pratik notlarla hazırlanmış kapsamlı bir çalışma rehberi.]]></summary></entry><entry><title type="html">Rekabetçi Programcı Çizgi Süpürme Algoritmaları</title><link href="https://sonsuzus.github.io/posts/rekabetci-programci-cizgi-supurme/" rel="alternate" type="text/html" title="Rekabetçi Programcı Çizgi Süpürme Algoritmaları" /><published>2026-05-06T00:00:00+00:00</published><updated>2026-05-06T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/rekabetci-programci-cizgi-supurme</id><content type="html" xml:base="https://sonsuzus.github.io/posts/rekabetci-programci-cizgi-supurme/"><![CDATA[<p><strong>Çizgi süpürme algoritmaları</strong>, geometrik problemleri düzlemdeki noktaları temsil eden <strong>olaylar</strong> kümesine dönüştürerek çözer. Olaylar $x$ veya $y$ koordinatına göre sıralanır ve soldan sağa (ya da aşağıdan yukarıya) sırayla işlenir; böylece iki boyutlu problem tek boyutlu bir taramaya indirgenir.</p>

<p><strong>Motivasyon örneği:</strong> $n$ çalışanı olan bir ofiste her çalışanın giriş ve çıkış saatleri bilinmektedir. Herhangi bir anda ofiste bulunan en fazla çalışan sayısını bul.</p>

<p>Her çalışan iki olay üretir: <strong>giriş (+1)</strong> ve <strong>çıkış (−1)</strong>. Olaylar zamana göre sıralanır ve bir sayaç tutulur:
``</p>

<table>
  <thead>
    <tr>
      <th>Kişi</th>
      <th>Giriş</th>
      <th>Çıkış</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>John</td>
      <td>10</td>
      <td>15</td>
    </tr>
    <tr>
      <td>Maria</td>
      <td>6</td>
      <td>12</td>
    </tr>
    <tr>
      <td>Peter</td>
      <td>14</td>
      <td>16</td>
    </tr>
    <tr>
      <td>Lisa</td>
      <td>5</td>
      <td>13</td>
    </tr>
  </tbody>
</table>

<p>Olaylar soldan sağa işlendiğinde sayaç değerleri:</p>

<p>\(+\ +\quad +\quad -\ -\ +\ -\ -\)
\(1\ \ 2\quad 3\quad 2\ \ 1\ \ 2\ \ 1\ \ 0\)</p>

<p>Maksimum değer <strong>3</strong> olup John’un gelişi ile Maria’nın çıkışı arasındaki aralıktır.</p>

<p><strong>Karmaşıklık:</strong> Olayları sıralamak $O(n \log n)$, tarama $O(n)$ → <strong>toplam $O(n \log n)$</strong>.</p>

<h2 id="301-kesişim-noktaları">30.1 Kesişim Noktaları</h2>

<p>$n$ yatay veya dikey çizginin toplam kesişim noktası sayısını bul.</p>

<p>Kaba kuvvetle tüm çift çiftler $O(n^2)$’de incelenebilir. Çizgi süpürme + aralık sorgu veri yapısıyla bu <strong>$O(n \log n)$</strong>‘e iner.</p>

<h3 id="olay-türleri">Olay Türleri</h3>

<p>Her çizgi en fazla iki olay üretir:</p>

<table>
  <thead>
    <tr>
      <th>Olay</th>
      <th>Açıklama</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>(1) Yatay çizgi başlıyor</strong></td>
      <td>Bu çizginin $y$ koordinatını aktif kümeye <strong>ekle</strong></td>
    </tr>
    <tr>
      <td><strong>(2) Yatay çizgi bitiyor</strong></td>
      <td>Bu çizginin $y$ koordinatını aktif kümeden <strong>çıkar</strong></td>
    </tr>
    <tr>
      <td><strong>(3) Dikey çizgi</strong></td>
      <td>Aktif kümede $[y_1, y_2]$ aralığında kaç $y$ koordinatı var? → bu sayı kesişim sayısına eklenir</td>
    </tr>
  </tbody>
</table>

<h3 id="algoritmanın-i̇şleyişi">Algoritmanın İşleyişi</h3>

<p>Olaylar $x$ koordinatına göre soldan sağa sıralanır. Aktif yatay çizgilerin $y$ koordinatları <strong>sıralı bir veri yapısında</strong> (ikili indeksli ağaç veya segment ağacı) tutulur.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Dikey çizgi geldiğinde:
  → [y1, y2] aralığındaki aktif y koordinatlarını say
  → Bu sayıyı toplam kesişim sayısına ekle
</code></pre></div></div>

<p><strong>İndis sıkıştırması:</strong> $y$ koordinatları $[0, m]$ aralığına eşlenerek segment ağacı verimli kullanılır.</p>

<p>Her olayı işlemek $O(\log n)$ → <strong>toplam $O(n \log n)$</strong>.</p>

<p><strong>Görsel örnek:</strong></p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>      |          |
------+----------+------   ← yatay çizgi 1
      |          |
      |    ------+------   ← yatay çizgi 2
      |          |
  dikey 1    dikey 2
</code></pre></div></div>

<ul>
  <li>Dikey 1 geldiğinde aktif kümede yatay çizgi 1 var → 1 kesişim</li>
  <li>Dikey 2 geldiğinde aktif kümede yatay çizgi 1 ve 2 var → 2 kesişim</li>
  <li><strong>Toplam: 3 kesişim</strong> ✓</li>
</ul>

<h2 id="302-en-yakın-çift-problemi">30.2 En Yakın Çift Problemi</h2>

<p>$n$ nokta arasında <strong>Öklid uzaklığı en küçük</strong> olan iki noktayı bul.</p>

<p>Kaba kuvvetle tüm çiftler $O(n^2)$’de incelenebilir. Çizgi süpürme ile <strong>$O(n \log n)$</strong> mümkündür (böl ve yönet yöntemi de aynı karmaşıklığı verir).</p>

<h3 id="algoritma">Algoritma</h3>

<p><strong>Değişkenler:</strong></p>
<ul>
  <li>Noktalar $x$ koordinatına göre soldan sağa sıralanır.</li>
  <li>$d$: şu ana kadar bulunan minimum mesafe.</li>
  <li>Aktif küme: $x$ koordinatı $[x - d, x]$ aralığında olan noktalar (y’ye göre sıralı tutulur).</li>
</ul>

<p><strong>Her yeni $p = (x, y)$ noktası için:</strong></p>

<ol>
  <li>Aktif kümeden $x$ koordinatı $x - d$’den küçük olanları çıkar.</li>
  <li>Aktif kümede $y$ koordinatı $[y - d,\ y + d]$ aralığındaki noktaları tara; hepsine uzaklığı hesapla.</li>
  <li>$d$ güncellendi mi? Güncellendiyse aktif küme yeniden ayarlanır.</li>
  <li>$p$’yi aktif kümeye ekle.</li>
</ol>

<h3 id="neden-verimli">Neden Verimli?</h3>

<p>Kilit gözlem: Taranan $d \times 2d$’lik dikdörtgen bölge her zaman <strong>$O(1)$ nokta</strong> içerir.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>     2d
   ┌────────────┐
 d │            │
   │    p →     │
 d │            │
   └────────────┘
       ← d →
</code></pre></div></div>

<p>Bu bölgede $d$ eşiği nedeniyle noktalar birbirinden en az $d$ uzaklıktadır; dolayısıyla $2d \times d$’lik alana sığabilecek maksimum nokta sayısı sabittir (yaklaşık 6–8).</p>

<p>Noktalar $y$’ye göre sıralı kümede tutulduğundan $[y-d, y+d]$ aralığı $O(\log n)$’de sorgulanır.</p>

<p><strong>Toplam karmaşıklık:</strong> $n$ nokta × $O(\log n)$ sorgu = <strong>$O(n \log n)$</strong></p>

<h3 id="c-i̇skeleti">C++ İskeleti</h3>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">set</span><span class="o">&lt;</span><span class="n">pair</span><span class="o">&lt;</span><span class="kt">long</span> <span class="kt">long</span><span class="p">,</span><span class="kt">long</span> <span class="kt">long</span><span class="o">&gt;&gt;</span> <span class="n">active</span><span class="p">;</span> <span class="c1">// {y, x} sıralı küme</span>
<span class="n">sort</span><span class="p">(</span><span class="n">points</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">points</span><span class="p">.</span><span class="n">end</span><span class="p">());</span>    <span class="c1">// x'e göre sırala</span>
<span class="kt">long</span> <span class="kt">long</span> <span class="n">d</span> <span class="o">=</span> <span class="n">INF</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

<span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="p">[</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">]</span> <span class="o">:</span> <span class="n">points</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// Sola çok uzaklaşanları çıkar</span>
    <span class="k">while</span> <span class="p">(</span><span class="n">points</span><span class="p">[</span><span class="n">left</span><span class="p">].</span><span class="n">x</span> <span class="o">&lt;</span> <span class="n">x</span> <span class="o">-</span> <span class="n">d</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">active</span><span class="p">.</span><span class="n">erase</span><span class="p">({</span><span class="n">points</span><span class="p">[</span><span class="n">left</span><span class="p">].</span><span class="n">y</span><span class="p">,</span> <span class="n">points</span><span class="p">[</span><span class="n">left</span><span class="p">].</span><span class="n">x</span><span class="p">});</span>
        <span class="n">left</span><span class="o">++</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="c1">// [y-d, y+d] aralığını tara</span>
    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">it</span>  <span class="o">=</span> <span class="n">active</span><span class="p">.</span><span class="n">lower_bound</span><span class="p">({</span><span class="n">y</span> <span class="o">-</span> <span class="n">d</span><span class="p">,</span> <span class="n">LLONG_MIN</span><span class="p">});</span>
              <span class="n">it</span> <span class="o">!=</span> <span class="n">active</span><span class="p">.</span><span class="n">end</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="n">it</span><span class="o">-&gt;</span><span class="n">first</span> <span class="o">&lt;=</span> <span class="n">y</span> <span class="o">+</span> <span class="n">d</span><span class="p">;</span> <span class="o">++</span><span class="n">it</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">d</span> <span class="o">=</span> <span class="n">min</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">dist</span><span class="p">({</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">},</span> <span class="p">{</span><span class="n">it</span><span class="o">-&gt;</span><span class="n">second</span><span class="p">,</span> <span class="n">it</span><span class="o">-&gt;</span><span class="n">first</span><span class="p">}));</span>
    <span class="p">}</span>
    <span class="n">active</span><span class="p">.</span><span class="n">insert</span><span class="p">({</span><span class="n">y</span><span class="p">,</span> <span class="n">x</span><span class="p">});</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="303-convex-hull">30.3 Convex Hull</h2>

<p><strong>Convex hull</strong> (dışbükey zarf), bir nokta kümesindeki tüm noktaları kapsayan <strong>en küçük dışbükey çokgendir</strong>. Dışbükeylik: çokgendeki herhangi iki nokta arasındaki doğru parçası tamamen çokgenin içinde kalır.</p>

<p><strong>Andrew’in Algoritması</strong> $O(n \log n)$’de convex hull oluşturur.</p>

<h3 id="fikir-i̇ki-yarı">Fikir: İki Yarı</h3>

<p>Convex hull <strong>üst hull</strong> ve <strong>alt hull</strong> olmak üzere iki parçaya ayrılır. Her iki parça da benzer şekilde hesaplanır; burada yalnızca <strong>üst hull</strong> ele alınır.</p>

<h3 id="algoritma-adımları">Algoritma Adımları</h3>

<ol>
  <li>Noktaları önce $x$’e göre, eşit $x$’lerde $y$’ye göre <strong>sırala</strong>.</li>
  <li>Sıralı noktalardan geçerek her noktayı hull’a ekle.</li>
  <li>Her eklemede <strong>son üç nokta sola mı dönüyor?</strong> Kontrol et:
    <ul>
      <li>Sola dönüş varsa → ortadaki noktayı hull’dan <strong>sil</strong> (dışbükey değil).</li>
      <li>Ta ki sola dönüş kalmayana dek tekrarla.</li>
    </ul>
  </li>
</ol>

<p><strong>Yön kontrolü:</strong> Vektörel çarpımla yapılır. $A$, $B$, $C$ üç noktasında:</p>

\[(B - A) \times (C - A) &gt; 0 \implies \text{sola dönüş (hull'a almama)}\]

<h3 id="adım-adım-görselleştirme">Adım Adım Görselleştirme</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Başlangıç noktaları (x'e göre sıralı):
  1   2   3   4   5   6   7
  ·   ·   ·   ·   ·   ·   ·

Üst hull oluşturma (sola dönen noktalar elenir):
  Adım 1: [1]
  Adım 2: [1, 2]
  Adım 3: [1, 2, 3]  → 2 sola dönüş yaratıyor mu? Evet → sil
           [1, 3]
  Adım 4: [1, 3, 4]  → kontrol et...
  ...
  Son: [1, 5, 7]  (üst hull)
</code></pre></div></div>

<h3 id="karmaşıklık">Karmaşıklık</h3>

<table>
  <thead>
    <tr>
      <th>Adım</th>
      <th>Süre</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Sıralama</td>
      <td>$O(n \log n)$</td>
    </tr>
    <tr>
      <td>Hull oluşturma</td>
      <td>$O(n)$ (her nokta en fazla bir kez eklenir/çıkarılır)</td>
    </tr>
    <tr>
      <td><strong>Toplam</strong></td>
      <td><strong>$O(n \log n)$</strong></td>
    </tr>
  </tbody>
</table>

<h3 id="c-kodu-üst-hull">C++ Kodu (Üst Hull)</h3>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Noktalar x'e göre sıralanmış varsayılır</span>
<span class="n">vector</span><span class="o">&lt;</span><span class="n">P</span><span class="o">&gt;</span> <span class="n">upper_hull</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">P</span><span class="o">&gt;&amp;</span> <span class="n">pts</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">vector</span><span class="o">&lt;</span><span class="n">P</span><span class="o">&gt;</span> <span class="n">h</span><span class="p">;</span>
    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">p</span> <span class="o">:</span> <span class="n">pts</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">// Son iki nokta ile p sola dönüyor mu?</span>
        <span class="k">while</span> <span class="p">(</span><span class="n">h</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&gt;=</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">P</span> <span class="n">a</span> <span class="o">=</span> <span class="n">h</span><span class="p">[</span><span class="n">h</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="o">-</span><span class="mi">2</span><span class="p">],</span> <span class="n">b</span> <span class="o">=</span> <span class="n">h</span><span class="p">[</span><span class="n">h</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="o">-</span><span class="mi">1</span><span class="p">];</span>
            <span class="c1">// Vektörel çarpım: (b-a) × (p-a)</span>
            <span class="k">if</span> <span class="p">((</span><span class="n">conj</span><span class="p">(</span><span class="n">b</span><span class="o">-</span><span class="n">a</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">p</span><span class="o">-</span><span class="n">a</span><span class="p">)).</span><span class="n">Y</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span>
                <span class="n">h</span><span class="p">.</span><span class="n">pop_back</span><span class="p">();</span>  <span class="c1">// sola dönüş yok → sil</span>
            <span class="k">else</span> <span class="k">break</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="n">h</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">p</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="n">h</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Alt hull için noktaları ters sırada işle; iki hull birleştirilince tam convex hull elde edilir.</p>

<hr />

<blockquote>
  <p><strong>Özet Tablo</strong></p>
</blockquote>

<table>
  <thead>
    <tr>
      <th>Problem</th>
      <th>Kaba Kuvvet</th>
      <th>Çizgi Süpürme</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Maks. eş zamanlı çalışan</td>
      <td>$O(n^2)$</td>
      <td>$O(n \log n)$</td>
    </tr>
    <tr>
      <td>Çizgi kesişim sayısı</td>
      <td>$O(n^2)$</td>
      <td>$O(n \log n)$</td>
    </tr>
    <tr>
      <td>En yakın çift</td>
      <td>$O(n^2)$</td>
      <td>$O(n \log n)$</td>
    </tr>
    <tr>
      <td>Convex hull</td>
      <td>$O(n^2)$</td>
      <td>$O(n \log n)$</td>
    </tr>
  </tbody>
</table>

<p>Tüm problemlerde ortak yapı aynıdır: <strong>olayları sırala, veri yapısıyla tara</strong>.</p>

<hr />

<blockquote>
  <p><strong>Kaynak:</strong> <em>Rekabetçi Programcı</em> (Competitive Programmer’s Handbook — Antti Laaksonen), Bölüm 30.</p>
</blockquote>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="çizgi-süpürme" /><category term="sweep-line" /><category term="kesişim-noktaları" /><category term="en-yakın-çift" /><category term="convex-hull" /><category term="andrew-algoritması" /><category term="segment-ağacı" /><category term="ikili-indeksli-ağaç" /><category term="geometri" /><category term="olay-tabanlı" /><category term="c" /><category term="programlama" /><category term="algoritma" /><category term="olimpiyat" /><category term="yarışma" /><category term="kodlama" /><category term="matematik" /><category term="kitap" /><summary type="html"><![CDATA[Çizgi süpürme algoritmaları, geometrik problemleri düzlemdeki noktaları temsil eden olaylar kümesine dönüştürerek çözer. Olaylar $x$ veya $y$ koordinatına göre sıralanır ve soldan sağa (ya da aşağıdan yukarıya) sırayla işlenir; böylece iki boyutlu problem tek boyutlu bir taramaya indirgenir. Motivasyon örneği: $n$ çalışanı olan bir ofiste her çalışanın giriş ve çıkış saatleri bilinmektedir. Herhangi bir anda ofiste bulunan en fazla çalışan sayısını bul. Her çalışan iki olay üretir: giriş (+1) ve çıkış (−1). Olaylar zamana göre sıralanır ve bir sayaç tutulur:]]></summary></entry><entry><title type="html">Rekabetçi Programcı Geometri</title><link href="https://sonsuzus.github.io/posts/rekabetci-programci-geometri/" rel="alternate" type="text/html" title="Rekabetçi Programcı Geometri" /><published>2026-05-02T00:00:00+00:00</published><updated>2026-05-02T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/rekabetci-programci-geometri</id><content type="html" xml:base="https://sonsuzus.github.io/posts/rekabetci-programci-geometri/"><![CDATA[<p>Geometri problemlerinde kolay koda dökülebilecek bir çözüm bulmak genellikle zordur; özel durum sayısı fazladır. İyi bir yaklaşım, özel durumları minimize eden matematiksel araçlar seçmektir. Bu bölümdeki temel araçlar <strong>karmaşık sayılar</strong> ve <strong>vektörel çarpım</strong> olacaktır.</p>

<p><strong>Örnek:</strong> Bir dörtgenin alanı, köşeleri $s = (a+b+c)/2$ olmak üzere Heron Formülü ile iki üçgene bölerek hesaplanabilir; ama hangi köşegen seçileceği özel durumlar doğurur. Bunun yerine doğrudan genel formül:</p>

\[\text{Alan} = \frac{|x_1 y_2 - x_2 y_1 + x_2 y_3 - x_3 y_2 + x_3 y_4 - x_4 y_3 + x_4 y_1 - x_1 y_4|}{2}\]

<p>Bu formülün avantajı <strong>hiç özel durum içermemesi</strong> ve tüm çokgenlere genellenebilmesidir.
``</p>

<h2 id="291-karmaşık-sayılar">29.1 Karmaşık Sayılar</h2>

<p>Bir <strong>karmaşık sayı</strong> $x + yi$ formundadır ($i = \sqrt{-1}$). Geometrik olarak $(x, y)$ noktasına ya da orijinden o noktaya uzanan vektöre karşılık gelir.</p>

<p>C++’ta <code class="language-plaintext highlighter-rouge">complex</code> sınıfı geometri problemlerini çözmek için güçlü bir araçtır:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">typedef</span> <span class="kt">long</span> <span class="kt">long</span> <span class="n">C</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">complex</span><span class="o">&lt;</span><span class="n">C</span><span class="o">&gt;</span> <span class="n">P</span><span class="p">;</span>
<span class="cp">#define X real()
#define Y imag()
</span>
<span class="n">P</span> <span class="n">p</span> <span class="o">=</span> <span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">};</span>
<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">p</span><span class="p">.</span><span class="n">X</span> <span class="o">&lt;&lt;</span> <span class="s">" "</span> <span class="o">&lt;&lt;</span> <span class="n">p</span><span class="p">.</span><span class="n">Y</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span> <span class="c1">// 4 2</span>

<span class="n">P</span> <span class="n">v</span> <span class="o">=</span> <span class="p">{</span><span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">},</span> <span class="n">u</span> <span class="o">=</span> <span class="p">{</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">};</span>
<span class="n">P</span> <span class="n">s</span> <span class="o">=</span> <span class="n">v</span> <span class="o">+</span> <span class="n">u</span><span class="p">;</span>
<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">X</span> <span class="o">&lt;&lt;</span> <span class="s">" "</span> <span class="o">&lt;&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">Y</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span> <span class="c1">// 5 3</span>
</code></pre></div></div>

<p><strong>Koordinat tipi seçimi:</strong></p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">long long</code> → tam sayı koordinatlar; hesaplamalar <strong>kesin</strong>tir, tercih edilir.</li>
  <li>
    <table>
      <tbody>
        <tr>
          <td><code class="language-plaintext highlighter-rouge">long double</code> → reel koordinatlar; kayan nokta hatalarına dikkat! Eşitlik kontrolü için $</td>
          <td>a - b</td>
          <td>&lt; \varepsilon$ kullanılır ($\varepsilon = 10^{-9}$ gibi).</td>
        </tr>
      </tbody>
    </table>
  </li>
</ul>

<h3 id="hazır-fonksiyonlar">Hazır Fonksiyonlar</h3>

<table>
  <thead>
    <tr>
      <th>Fonksiyon</th>
      <th>Açıklama</th>
      <th>Örnek</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">abs(v)</code></td>
      <td>$v = (x,y)$ vektörünün uzunluğu $\sqrt{x^2+y^2}$</td>
      <td><code class="language-plaintext highlighter-rouge">abs({3,-1} - {4,2})</code> $\approx 3.162$</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">arg(v)</code></td>
      <td>$v$’nin $x$ eksenine olan açısı (radyan)</td>
      <td><code class="language-plaintext highlighter-rouge">arg({4,2})</code> $\approx 0.4636$</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">polar(s, a)</code></td>
      <td>Uzunluğu $s$, açısı $a$ olan vektör</td>
      <td><code class="language-plaintext highlighter-rouge">polar(1.0, 0.5)</code></td>
    </tr>
  </tbody>
</table>

<p><strong>Döndürme:</strong> Bir vektörü $a$ radyan saat yönünün tersine döndürmek için $\text{polar}(1, a)$ ile çarpmak yeterlidir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">P</span> <span class="n">v</span> <span class="o">=</span> <span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">};</span>
<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">arg</span><span class="p">(</span><span class="n">v</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>   <span class="c1">// 0.463648</span>
<span class="n">v</span> <span class="o">*=</span> <span class="n">polar</span><span class="p">(</span><span class="mf">1.0</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">);</span>
<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">arg</span><span class="p">(</span><span class="n">v</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>   <span class="c1">// 0.963648</span>
</code></pre></div></div>

<h2 id="292-noktalar-ve-çizgiler">29.2 Noktalar ve Çizgiler</h2>

<h3 id="vektörel-çarpım-cross-product">Vektörel Çarpım (Cross Product)</h3>

<p>$a = (x_1, y_1)$ ve $b = (x_2, y_2)$ vektörlerinin <strong>vektörel çarpımı</strong>:</p>

\[a \times b = x_1 y_2 - x_2 y_1\]

<p>Bu değer, $a$’dan sonra $b$’nin hangi yöne döndüğünü söyler:</p>

<table>
  <thead>
    <tr>
      <th>Değer</th>
      <th>Anlam</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>$a \times b &gt; 0$</td>
      <td>$b$, $a$’nın <strong>soluna</strong> döner</td>
    </tr>
    <tr>
      <td>$a \times b = 0$</td>
      <td>$a$ ve $b$ <strong>aynı doğrultuda</strong></td>
    </tr>
    <tr>
      <td>$a \times b &lt; 0$</td>
      <td>$b$, $a$’nın <strong>sağına</strong> döner</td>
    </tr>
  </tbody>
</table>

<p>C++ ile <code class="language-plaintext highlighter-rouge">complex</code> sınıfı kullanarak hesaplama:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">P</span> <span class="n">a</span> <span class="o">=</span> <span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">};</span>
<span class="n">P</span> <span class="n">b</span> <span class="o">=</span> <span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">};</span>
<span class="n">C</span> <span class="n">cross</span> <span class="o">=</span> <span class="p">(</span><span class="n">conj</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">*</span> <span class="n">b</span><span class="p">).</span><span class="n">Y</span><span class="p">;</span> <span class="c1">// 4*2 - 1*2 = 6</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">conj(a)</code> → $(x_1, -y_1)$; bununla $b = (x_2, y_2)$ çarpılınca sonucun $Y$ bileşeni $x_1 y_2 - x_2 y_1$ verir.</p>

<h3 id="nokta-lokasyonu">Nokta Lokasyonu</h3>

<p>$s_1$ ve $s_2$ noktalarından geçen doğruya göre $p$ noktasının konumu:</p>

\[\text{Konum} = (p - s_1) \times (p - s_2)\]

<ul>
  <li><strong>Pozitif</strong> → $p$ çizginin <strong>sol</strong> tarafındadır</li>
  <li><strong>Negatif</strong> → $p$ çizginin <strong>sağ</strong> tarafındadır</li>
  <li><strong>Sıfır</strong> → $p$ çizgi üzerindedir</li>
</ul>

<h3 id="çizgi-kesişimi">Çizgi Kesişimi</h3>

<p>$ab$ ve $cd$ parçalarının kesişip kesişmediğini kontrol etmek için <strong>üç durum</strong> vardır:</p>

<p><strong>1. Durum — Aynı doğru üzerinde:</strong> Vektörel çarpım ile tüm noktaların aynı doğruda olduğu kontrol edilir; ardından çakışma sıra karşılaştırmasıyla belirlenir.</p>

<p><strong>2. Durum — Ortak köşe noktası:</strong> Sadece 4 olasılık: $a=c$, $a=d$, $b=c$ veya $b=d$.</p>

<p><strong>3. Durum — İç kesişim:</strong> $c$ ve $d$ noktaları, $a$’dan $b$’ye çizilen doğrunun farklı taraflarındaysa parçalar kesişir. Vektörel çarpımın işaretleri kontrol edilir.</p>

<h3 id="çizgiye-nokta-mesafesi">Çizgiye Nokta Mesafesi</h3>

<p>$s_1$ ve $s_2$’den geçen doğruya $p$ noktasının en kısa mesafesi:</p>

\[d = \frac{|(s_1 - p) \times (s_2 - p)|}{|s_2 - s_1|}\]

<p><strong>Kanıt:</strong> $s_1$, $s_2$, $p$ köşeli üçgenin alanı iki şekilde yazılabilir:</p>
<ul>
  <li>
    <table>
      <tbody>
        <tr>
          <td>$\frac{1}{2}</td>
          <td>s_2 - s_1</td>
          <td>\cdot d$</td>
        </tr>
      </tbody>
    </table>
  </li>
  <li>
    <table>
      <tbody>
        <tr>
          <td>$\frac{1}{2}</td>
          <td>(s_1 - p) \times (s_2 - p)</td>
          <td>$</td>
        </tr>
      </tbody>
    </table>
  </li>
</ul>

<p>Bunlar eşitlenerek $d$ elde edilir.</p>

<h3 id="çokgen-i̇çinde-nokta">Çokgen İçinde Nokta</h3>

<p>Bir $p$ noktasının çokgenin içinde mi dışında mı olduğunu bulmak için <strong>ışın atma</strong> yöntemi kullanılır:</p>

<ol>
  <li>$p$’den rastgele bir yöne ışın gönder.</li>
  <li>Işının çokgenin kenarlarıyla kaç kez kesiştiğini say.</li>
  <li><strong>Tekse</strong> → içeride; <strong>çiftse</strong> → dışarıda.</li>
</ol>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>b (dışarıda) → ışın 0 veya 2 kez kesişir
a (içeride)  → ışın 1 veya 3 kez kesişir
</code></pre></div></div>

<h2 id="293-çokgen-alanı">29.3 Çokgen Alanı</h2>

<h3 id="ayakkabı-bağı-formülü-shoelace-formula">Ayakkabı Bağı Formülü (Shoelace Formula)</h3>

<p>Köşeleri sırasıyla $p_1 = (x_1, y_1), p_2 = (x_2, y_2), \ldots, p_n = (x_n, y_n)$ olan bir çokgenin alanı:</p>

\[\text{Alan} = \frac{1}{2} \left| \sum_{i=1}^{n-1} (x_i y_{i+1} - x_{i+1} y_i) \right|\]

<p>($p_1 = p_n$ yani ilk ve son köşe aynıdır.)</p>

<p><strong>Örnek:</strong> Köşeleri $(2,4), (5,5), (7,3), (4,1), (4,3)$ olan çokgen için:</p>

\[\text{Alan} = \frac{|(2 \cdot 5 - 5 \cdot 4) + (5 \cdot 3 - 7 \cdot 5) + (7 \cdot 1 - 4 \cdot 3) + (4 \cdot 3 - 4 \cdot 1) + (4 \cdot 4 - 2 \cdot 3)|}{2} = \frac{17}{2}\]

<p><strong>Formülün fikri:</strong> Her kenar için $y = 0$ çizgisine uzanan bir yamuk düşünülür. Yamuğun işaretli alanı:</p>

\[(x_{i+1} - x_i)\frac{y_i + y_{i+1}}{2}\]

<p>Tüm yamuklardan bu alanlar toplandığında eşdeğer formül elde edilir. Mutlak değer alınmasının nedeni: toplam, köşelerin dolaşım yönüne göre (saat/saat tersi) pozitif ya da negatif olabilir.</p>

<h3 id="pickin-teoremi">Pick’in Teoremi</h3>

<p>Tüm köşeleri <strong>tamsayı koordinatlarda</strong> olan bir çokgenin alanı:</p>

\[\text{Alan} = a + \frac{b}{2} - 1\]

<ul>
  <li>$a$: Çokgenin <strong>içindeki</strong> tamsayı nokta sayısı</li>
  <li>$b$: Çokgenin <strong>sınırındaki</strong> tamsayı nokta sayısı</li>
</ul>

<p><strong>Örnek:</strong> Önceki çokgen için $a = 6$, $b = 7$:</p>

\[\text{Alan} = 6 + \frac{7}{2} - 1 = \frac{17}{2} \checkmark\]

<blockquote>
  <p>Pick Teoremi, ayakkabı bağı formülünün tamsayı koordinatlardaki özel halidir ve ikisi her zaman aynı sonucu verir.</p>
</blockquote>

<h2 id="294-uzaklık-fonksiyonları">29.4 Uzaklık Fonksiyonları</h2>

<h3 id="öklid-ve-manhattan-uzaklığı">Öklid ve Manhattan Uzaklığı</h3>

<p>İki nokta $(x_1, y_1)$ ve $(x_2, y_2)$ arasında:</p>

\[d_{\text{Öklid}} = \sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2}\]

\[d_{\text{Manhattan}} = |x_1 - x_2| + |y_1 - y_2|\]

<p><strong>Örnek:</strong> $(2, 1)$ ve $(5, 2)$ noktaları için:</p>

\[d_{\text{Öklid}} = \sqrt{3^2 + 1^2} = \sqrt{10} \approx 3.162\]

\[d_{\text{Manhattan}} = |2-5| + |1-2| = 4\]

<p>Geometrik yorum: Öklid uzaklığındaki “1 birim bölge” bir <strong>daire</strong>, Manhattan uzaklığında ise 45° döndürülmüş bir <strong>kare</strong> (elmas) şeklindedir.</p>

<h3 id="koordinat-döndürme-ile-manhattan--çebyşev">Koordinat Döndürme ile Manhattan → Çebyşev</h3>

<p>Bazı problemler Manhattan uzaklığı ile çalışırken koordinatları 45° döndürmek işleri basitleştirir. Dönüşüm:</p>

\[(x, y) \;\longrightarrow\; (x + y,\; y - x)\]

<p>Bu dönüşümün temel özelliği:</p>

\[|x_1 - x_2| + |y_1 - y_2| = \max\bigl(|x_1' - x_2'|,\; |y_1' - y_2'|\bigr)\]

<p>Yani <strong>Manhattan uzaklığı</strong>, döndürülmüş koordinatlarda <strong>Çebyşev uzaklığına</strong> dönüşür. Bu sayede $x$ ve $y$ koordinatları birbirinden bağımsız ele alınabilir.</p>

<p><strong>Örnek — Maksimum Manhattan Uzaklığı:</strong></p>

<p>$n$ nokta arasındaki maksimum Manhattan uzaklığını bulmak:</p>

<ol>
  <li>Her $(x, y)$ noktasını $(x+y, y-x)$’e dönüştür.</li>
  <li>
    <table>
      <tbody>
        <tr>
          <td>$\max(</td>
          <td>x_1’ - x_2’</td>
          <td>,</td>
          <td>y_1’ - y_2’</td>
          <td>)$ değerini bul.</td>
        </tr>
      </tbody>
    </table>
  </li>
  <li>Bu değer ya $x’$ koordinatlarının, ya da $y’$ koordinatlarının maksimum farkından gelir.</li>
  <li>Her eksen için fark $(\max - \min)$ olarak hesaplanır → <strong>$O(n)$</strong>.</li>
</ol>

<p>Örneğin $p_1 = (1, 0)$ ve $p_2 = (3, 3)$: Döndürülmüş koordinatlar $p_1’ = (1, -1)$, $p_2’ = (6, 0)$:</p>

\[|1-3| + |0-3| = \max(|1-6|, |-1-0|) = 5\]

<hr />

<blockquote>
  <p><strong>Özet Tablo</strong></p>
</blockquote>

<table>
  <thead>
    <tr>
      <th>Kavram</th>
      <th>Formül / Yöntem</th>
      <th>Karmaşıklık</th>
      <th> </th>
      <th> </th>
      <th> </th>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Vektörel çarpım</td>
      <td>$x_1 y_2 - x_2 y_1$</td>
      <td>$O(1)$</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>Nokta lokasyonu</td>
      <td>$(p-s_1) \times (p-s_2)$ işareti</td>
      <td>$O(1)$</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>Çizgiye mesafe</td>
      <td>$</td>
      <td>(s_1-p)\times(s_2-p)</td>
      <td>/</td>
      <td>s_2-s_1</td>
      <td>$</td>
      <td>$O(1)$</td>
    </tr>
    <tr>
      <td>Çokgen içinde nokta</td>
      <td>Işın atma, kesişim sayısı</td>
      <td>$O(n)$</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>Çokgen alanı</td>
      <td>Ayakkabı bağı formülü</td>
      <td>$O(n)$</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>Çokgen alanı (tamsayı)</td>
      <td>Pick Teoremi: $a + b/2 - 1$</td>
      <td>$O(n)$</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>Max Manhattan mesafesi</td>
      <td>45° döndür + Çebyşev</td>
      <td>$O(n)$</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
  </tbody>
</table>

<hr />

<blockquote>
  <p><strong>Kaynak:</strong> <em>Rekabetçi Programcı</em> (Competitive Programmer’s Handbook — Antti Laaksonen), Bölüm 29.</p>
</blockquote>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="geometri" /><category term="geometry" /><category term="karmaşık-sayılar" /><category term="complex-numbers" /><category term="vektörel-çarpım" /><category term="cross-product" /><category term="çokgen-alanı" /><category term="shoelace-formula" /><category term="pick-teoremi" /><category term="manhattan-uzaklığı" /><category term="oklid-uzaklığı" /><category term="convex-hull" /><category term="nokta-lokasyonu" /><category term="çizgi-kesişimi" /><category term="c" /><category term="programlama" /><category term="algoritma" /><category term="olimpiyat" /><category term="yarışma" /><category term="kodlama" /><category term="matematik" /><category term="kitap" /><summary type="html"><![CDATA[Geometri problemlerinde kolay koda dökülebilecek bir çözüm bulmak genellikle zordur; özel durum sayısı fazladır. İyi bir yaklaşım, özel durumları minimize eden matematiksel araçlar seçmektir. Bu bölümdeki temel araçlar karmaşık sayılar ve vektörel çarpım olacaktır. Örnek: Bir dörtgenin alanı, köşeleri $s = (a+b+c)/2$ olmak üzere Heron Formülü ile iki üçgene bölerek hesaplanabilir; ama hangi köşegen seçileceği özel durumlar doğurur. Bunun yerine doğrudan genel formül: \[\text{Alan} = \frac{|x_1 y_2 - x_2 y_1 + x_2 y_3 - x_3 y_2 + x_3 y_4 - x_4 y_3 + x_4 y_1 - x_1 y_4|}{2}\] Bu formülün avantajı hiç özel durum içermemesi ve tüm çokgenlere genellenebilmesidir.]]></summary></entry><entry><title type="html">Rekabetçi Programcı Karekök Algoritmaları</title><link href="https://sonsuzus.github.io/posts/rekabetci-programci-karekok-algoritmalari/" rel="alternate" type="text/html" title="Rekabetçi Programcı Karekök Algoritmaları" /><published>2026-04-28T00:00:00+00:00</published><updated>2026-04-28T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/rekabetci-programci-karekok-algoritmalari</id><content type="html" xml:base="https://sonsuzus.github.io/posts/rekabetci-programci-karekok-algoritmalari/"><![CDATA[<p><strong>Karekök algoritmaları</strong>, zaman karmaşıklığı $O(\sqrt{n})$ bileşeni içeren algoritmalardır. Karekök, “fakir adamın logaritması” olarak nitelendirilebilir:</p>

\[O(\log n) \;&lt;\; O(\sqrt{n}) \;&lt;\; O(n)\]

<p>Pratikte karekök algoritmaları hem yeterince hızlı hem de uygulaması görece basittir. Temel fikir, bir diziyi $\sqrt{n}$ büyüklüğündeki <strong>bloklara</strong> ayırmaktır.
``</p>

<h2 id="temel-yapı-blok-ayrıştırma">Temel Yapı: Blok Ayrıştırma</h2>

<p>$n$ elemanlı bir dizi üzerinde iki işlem desteklenmek istensin:</p>

<ul>
  <li><strong>Güncelleme:</strong> Belirli bir pozisyondaki elemanı değiştir.</li>
  <li><strong>Toplam sorgusu:</strong> $[a, b]$ aralığındaki elemanların toplamını bul.</li>
</ul>

<p>Dizi $\sqrt{n}$ büyüklüğünde bloklara ayrılır; her blok kendi toplamını tutar.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>5 | 8 | 20 | 17 ||  6 | 3 | 2 | 7 || 13 | 1 | 5 | 6 || 3 | 2 | 2 | ?
       50          ||      18        ||       25        ||       7
</code></pre></div></div>

<ul>
  <li><strong>Güncelleme:</strong> Elemanı değiştir, yalnızca o bloğun toplamını güncelle → $O(1)$</li>
  <li><strong>Toplam sorgusu:</strong> Aralığı üç parçaya böl — sol kenardaki tek elemanlar + tam kaplanan bloklar + sağ kenardaki tek elemanlar → $O(\sqrt{n})$</li>
</ul>

<p>Blok büyüklüğü $k$ seçilirse güncelleme $O(1)$, sorgu $O(k + n/k)$ zaman alır. $k = \sqrt{n}$ bu ikisini dengeler. Pratikte tam $\sqrt{n}$ yerine dengelemeye göre farklı $k$ değerleri kullanılabilir.</p>

<h2 id="271-algoritmaları-birleştirme">27.1 Algoritmaları Birleştirme</h2>

<p>Karekök eşiği iki farklı algoritmayı birleştirir: küçük durumlar için biri, büyük durumlar için diğeri. Her iki algoritma da tek başına $O(n^2)$ iken birleşince $O(n\sqrt{n})$’e iner.</p>

<h3 id="durum-i̇şleme-case-processing">Durum İşleme (Case Processing)</h3>

<p>$n$ hücreli iki boyutlu bir yapıda her hücrede bir harf var. Aynı harfe sahip, aralarındaki <strong>Manhattan mesafesi</strong> en kısa iki hücreyi bul.</p>

<p>İki algoritma:</p>

<ol>
  <li><strong>1. Algoritma:</strong> $c$ harfine sahip $k$ hücrenin tüm çiftlerini tara → $O(k^2)$</li>
  <li><strong>2. Algoritma:</strong> $c$ harfine sahip tüm hücrelerden aynı anda BFS başlat → $O(n)$</li>
</ol>

<p><strong>Karekök birleştirmesi:</strong></p>

\[\text{Eğer } k \leq \sqrt{n}: \text{ 1. Algoritma} \quad\mid\quad \text{Eğer } k &gt; \sqrt{n}: \text{ 2. Algoritma}\]

<ul>
  <li>$k \leq \sqrt{n}$ olan harfler: her hücre en fazla $\sqrt{n}$ kez karşılaştırılır → toplam $O(n\sqrt{n})$</li>
  <li>$k &gt; \sqrt{n}$ olan harfler: en fazla $\sqrt{n}$ çeşit böyle harf olabilir → toplam $O(n\sqrt{n})$</li>
</ul>

<p><strong>Genel toplam:</strong> $O(n\sqrt{n})$</p>

<h3 id="grup-i̇şleme-batch-processing">Grup İşleme (Batch Processing)</h3>

<p>$n$ hücreli yapıda başta bir hücre siyah, geri kalanı beyaz. $n-1$ işlem yapılır: her işlemde beyaz bir hücreden en yakın siyah hücreye mesafe bulunur, ardından o hücre siyaha boyanır.</p>

<p>İki algoritma:</p>

<ol>
  <li><strong>1. Algoritma:</strong> Tüm siyah hücrelerden BFS yap → $O(n)$; ardından herhangi bir hücreden en yakın siyah hücreye mesafe $O(1)$’de bulunur.</li>
  <li><strong>2. Algoritma:</strong> Siyah hücreleri listede tut; her işlemde listeden geç → $O(k)$ ($k$: liste uzunluğu)</li>
</ol>

<p><strong>Karekök birleştirmesi:</strong> İşlemleri $\sqrt{n}$ büyüklüğünde gruplara böl.</p>

<ul>
  <li>Her grubun başında <strong>1. Algoritma</strong> uygulanır → $O(n)$, toplam $O(n\sqrt{n})$</li>
  <li>Grup içinde <strong>2. Algoritma</strong> kullanılır; liste $\sqrt{n}$’den büyümez (her grup başında temizlenir) → her işlem $O(\sqrt{n})$, toplam $O(n\sqrt{n})$</li>
</ul>

<p><strong>Genel toplam:</strong> $O(n\sqrt{n})$</p>

<h2 id="272-tamsayı-bölmesi">27.2 Tamsayı Bölmesi</h2>

<p><strong>Gözlem:</strong> $n$ pozitif tamsayısı, farklı pozitif tamsayıların toplamı olarak yazılırsa bu toplam en fazla $O(\sqrt{n})$ terim içerir.</p>

<p><strong>Kanıt:</strong> En fazla terim sayısı için $1 + 2 + \cdots + k = \frac{k(k+1)}{2} \leq n$ olmalı, buradan $k = O(\sqrt{n})$.</p>

<p>Bu gözlem bazı algoritmalarda $O(n\sqrt{n})$ sınırı elde etmek için kullanılır.</p>

<h3 id="sırt-çantası-knapsack">Sırt Çantası (Knapsack)</h3>

<p>Toplamları $n$ olan tamsayı ağırlıklar verilsin; bu ağırlıklarla oluşturulabilecek tüm toplamları bul.</p>

<ul>
  <li><strong>Klasik DP yaklaşımı:</strong> $O(n^2)$</li>
  <li><strong>Karekök iyileştirmesi:</strong> Aynı ağırlıktan en fazla $O(\sqrt{n})$ farklı değer olduğu bilindiğinden, aynı ağırlıklıları gruplar hâlinde işle. Her grup $O(n)$’de, toplam $O(n\sqrt{n})$’de çözülür.</li>
</ul>

<p>Fikir: $n$ elemanlık bir “ulaşılabilir toplam” dizisi tutulur (1: ulaşılabilir, 0: ulaşılamaz). Grupları soldan sağa işlerken yeni ulaşılabilir değerler kaydedilir.</p>

<h3 id="yazı-oluşturma-string-construction">Yazı Oluşturma (String Construction)</h3>

<p>$n$ uzunluğundaki $s$ yazısı ile toplam uzunluğu $m$ olan $D$ yazı kümesi verilsin. $D$’deki yazıları birleştirerek $s$’yi kaç farklı şekilde oluşturabiliriz?</p>

<p><strong>DP tanımı:</strong> $\text{count}(k)$ = $s[0 \ldots k]$’yı $D$’den yazılarla oluşturma yolu sayısı.</p>

<ul>
  <li><strong>Trie ile:</strong> $O(n^2)$</li>
  <li><strong>Hash + karekök:</strong> $D$’de en fazla $O(\sqrt{m})$ farklı yazı uzunluğu vardır. Her $\text{count}(k)$ hesaplanırken bu uzunluklar taranır; her adım $O(\sqrt{m})$, toplam $O(n\sqrt{m})$.</li>
</ul>

<h2 id="273-monun-algoritması">27.3 Mo’nun Algoritması</h2>

<p><strong>Mo’nun Algoritması</strong>, <strong>sabit</strong> (sorgu sırasında değişmeyen) diziler üzerindeki aralık sorgularını verimli işler. Her sorgu $[a, b]$ aralığındaki elemanlardan bir değer ister.</p>

<p>Dizi sabit olduğu için sorgular <strong>istenen sırada</strong> işlenebilir; Mo’nun Algoritması bu sırayı akıllıca seçerek toplam işlem sayısını minimize eder.</p>

<h3 id="temel-fikir">Temel Fikir</h3>

<p>Algoritma bir <strong>aktif aralık</strong> $[l, r]$ tutar. Her sorgu için bu aralığın sınırları eleman ekleyerek veya çıkararak kaydırılır. Her kaydırma adımı $O(f(n))$ zaman alırsa toplam karmaşıklık:</p>

\[O\!\left(n\sqrt{n}\cdot f(n)\right)\]

<h3 id="sıralama-stratejisi">Sıralama Stratejisi</h3>

<p>Dizi $k = O(\sqrt{n})$ büyüklüğünde bloklara ayrılır. $[a_1, b_1]$ sorgusu $[a_2, b_2]$’den <strong>önce</strong> işlenir; eğer:</p>

<p>\(\lfloor a_1 / k \rfloor &lt; \lfloor a_2 / k \rfloor \qquad\text{veya}\)
\(\lfloor a_1 / k \rfloor = \lfloor a_2 / k \rfloor \text{ ve } b_1 &lt; b_2\)</p>

<p>Yani: <strong>Aynı blokta</strong> olanlar sağ bitiş noktasına göre artan sırada; farklı bloklar soldan sağa işlenir.</p>

<h3 id="hareket-analizi">Hareket Analizi</h3>

<p>Bu sıralama ile:</p>

<ul>
  <li><strong>Sol bitiş noktası:</strong> Her blok geçişinde en fazla $O(\sqrt{n})$ hareket eder. $O(\sqrt{n})$ blok vardır → toplam $O(n\sqrt{n})$ hareket.</li>
  <li><strong>Sağ bitiş noktası:</strong> Her blok içinde monoton artar, o blok bitince sıfırlanır. Her blok $O(n)$ hareket → toplam $O(n\sqrt{n})$ hareket.</li>
</ul>

<p><strong>Her iki bitiş noktası toplamda $O(n\sqrt{n})$ adım atar.</strong></p>

<h3 id="örnek-aralıkta-farklı-eleman-sayısı">Örnek: Aralıkta Farklı Eleman Sayısı</h3>

<p>Her $[a, b]$ sorgusunda aralıkta kaç farklı eleman olduğu bulunacak.</p>

<p><strong>Veri yapısı:</strong> <code class="language-plaintext highlighter-rouge">count[x]</code> → $x$ elemanının aktif aralıkta kaç kez geçtiği.</p>

<ul>
  <li><strong>Eleman ekle ($x$):</strong> <code class="language-plaintext highlighter-rouge">count[x]++</code>; eğer <code class="language-plaintext highlighter-rouge">count[x] == 1</code> oldu ise cevabı 1 artır.</li>
  <li><strong>Eleman çıkar ($x$):</strong> <code class="language-plaintext highlighter-rouge">count[x]--</code>; eğer <code class="language-plaintext highlighter-rouge">count[x] == 0</code> oldu ise cevabı 1 azalt.</li>
</ul>

<p>Her adım $O(1)$ → toplam $O(n\sqrt{n})$.</p>

<p><strong>Örnek geçiş:</strong></p>

<table>
  <thead>
    <tr>
      <th>Aktif aralık</th>
      <th>Sonraki aralık</th>
      <th>Sol kayma</th>
      <th>Sağ kayma</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>$[3, 7]$</td>
      <td>$[4, 9]$</td>
      <td>1 adım sağ</td>
      <td>2 adım sağ</td>
    </tr>
  </tbody>
</table>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>4  2  5  4  2  4  3  3  4
         [3..7]
            [4..9]
</code></pre></div></div>

<hr />

<blockquote>
  <p><strong>Kaynak:</strong> <em>Rekabetçi Programcı</em> (Competitive Programmer’s Handbook — Antti Laaksonen), Bölüm 27.</p>
</blockquote>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="karekök-algoritmaları" /><category term="square-root" /><category term="mo-algoritması" /><category term="blok-ayrıştırma" /><category term="aralık-sorgusu" /><category term="knapsack" /><category term="tam-sayı-bölmesi" /><category term="yazı-oluşturma" /><category term="durum-işleme" /><category term="grup-işleme" /><category term="c" /><category term="programlama" /><category term="algoritma" /><category term="olimpiyat" /><category term="yarışma" /><category term="kodlama" /><category term="matematik" /><category term="kitap" /><summary type="html"><![CDATA[Karekök algoritmaları, zaman karmaşıklığı $O(\sqrt{n})$ bileşeni içeren algoritmalardır. Karekök, “fakir adamın logaritması” olarak nitelendirilebilir: \[O(\log n) \;&lt;\; O(\sqrt{n}) \;&lt;\; O(n)\] Pratikte karekök algoritmaları hem yeterince hızlı hem de uygulaması görece basittir. Temel fikir, bir diziyi $\sqrt{n}$ büyüklüğündeki bloklara ayırmaktır.]]></summary></entry><entry><title type="html">Rekabetçi Programcı Yazı Algoritmaları</title><link href="https://sonsuzus.github.io/posts/rekabetci-programci-yazi-algoritmalari/" rel="alternate" type="text/html" title="Rekabetçi Programcı Yazı Algoritmaları" /><published>2026-04-27T00:00:00+00:00</published><updated>2026-04-27T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/rekabetci-programci-yazi-algoritmalari</id><content type="html" xml:base="https://sonsuzus.github.io/posts/rekabetci-programci-yazi-algoritmalari/"><![CDATA[<p><strong>Yazı algoritmaları</strong>, metinleri verimli şekilde işlemek için kullanılır. Pek çok yazı problemi $O(n^2)$’de kolayca çözülse de asıl hedef $O(n)$ veya $O(n \log n)$’e inmektir. Temel örnek <strong>örüntü bulma</strong> problemidir: $n$ uzunluğundaki yazıda $m$ uzunluğundaki örüntü nerede geçiyor?
``</p>

<h2 id="261-yazı-terminolojisi">26.1 Yazı Terminolojisi</h2>

<p>$n$ uzunluğundaki $s$ yazısı <strong>sıfır tabanlı</strong> indislenir: $s[0], s[1], \ldots, s[n-1]$.</p>

<table>
  <thead>
    <tr>
      <th>Kavram</th>
      <th>Tanım</th>
      <th>Örnek (<code class="language-plaintext highlighter-rouge">ABCD</code>)</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Alt dize</strong> (substring)</td>
      <td>Ardışık karakterler; $s[a \ldots b]$</td>
      <td><code class="language-plaintext highlighter-rouge">A</code>, <code class="language-plaintext highlighter-rouge">AB</code>, <code class="language-plaintext highlighter-rouge">ABC</code>, <code class="language-plaintext highlighter-rouge">ABCD</code>, …</td>
    </tr>
    <tr>
      <td><strong>Alt dizi</strong> (subsequence)</td>
      <td>Ardışık olmak zorunda değil</td>
      <td><code class="language-plaintext highlighter-rouge">A</code>, <code class="language-plaintext highlighter-rouge">AC</code>, <code class="language-plaintext highlighter-rouge">BD</code>, …</td>
    </tr>
    <tr>
      <td><strong>Ön ek</strong> (prefix)</td>
      <td>Baştan başlayan alt dize</td>
      <td><code class="language-plaintext highlighter-rouge">A</code>, <code class="language-plaintext highlighter-rouge">AB</code>, <code class="language-plaintext highlighter-rouge">ABC</code>, <code class="language-plaintext highlighter-rouge">ABCD</code></td>
    </tr>
    <tr>
      <td><strong>Son ek</strong> (suffix)</td>
      <td>Sonla biten alt dize</td>
      <td><code class="language-plaintext highlighter-rouge">D</code>, <code class="language-plaintext highlighter-rouge">CD</code>, <code class="language-plaintext highlighter-rouge">BCD</code>, <code class="language-plaintext highlighter-rouge">ABCD</code></td>
    </tr>
    <tr>
      <td><strong>Rotasyon</strong></td>
      <td>Karakterleri sağa/sola kaydırma</td>
      <td><code class="language-plaintext highlighter-rouge">ABCD</code>, <code class="language-plaintext highlighter-rouge">BCDA</code>, <code class="language-plaintext highlighter-rouge">CDAB</code>, <code class="language-plaintext highlighter-rouge">DABC</code></td>
    </tr>
    <tr>
      <td><strong>Periyot</strong> (period)</td>
      <td>Yazıyı tekrarla oluşturan ön ek</td>
      <td><code class="language-plaintext highlighter-rouge">ABCABCA</code>‘nın en kısa periyodu <code class="language-plaintext highlighter-rouge">ABC</code></td>
    </tr>
    <tr>
      <td><strong>Sınır</strong> (border)</td>
      <td>Hem ön ek hem son ek olan alt dize</td>
      <td><code class="language-plaintext highlighter-rouge">ABACABA</code>‘nın sınırları: <code class="language-plaintext highlighter-rouge">A</code>, <code class="language-plaintext highlighter-rouge">ABA</code>, <code class="language-plaintext highlighter-rouge">ABACABA</code></td>
    </tr>
  </tbody>
</table>

<p>Sözlük sıralaması (lexicographical order): $x &lt; y$ için ya $x \neq y$ ve $x$, $y$’nin ön ekidir; ya da $x[k] &lt; y[k]$ olan ilk $k$ pozisyonu vardır.</p>

<h2 id="262-trie-yapısı">26.2 Trie Yapısı</h2>

<p><strong>Trie</strong>, bir yazı kümesini tutan köklü ağaçtır. Ortak ön ekli yazılar aynı dalı paylaşır.</p>

<p>Örnek: ${\text{CANAL, CANDY, THE, THERE}}$ kümesi için trie:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(kök)
├── C → A → N → A → L *
│             └── D → Y *
└── T → H → E *
               └── R → E *
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">*</code> o noktada bir yazının bittiğini gösterir (THE, THERE gibi iç içe yazılar için gereklidir).</p>

<p><strong>İşlemler:</strong></p>
<ul>
  <li>$n$ uzunluğunda yazı <strong>arama:</strong> $O(n)$</li>
  <li>$n$ uzunluğunda yazı <strong>ekleme:</strong> $O(n)$</li>
  <li>Bir yazının <strong>en uzun ön eki</strong> kümede mi? → $O(n)$</li>
  <li>Her düğümde sayaç tutularak ön eke sahip yazı sayısı da bulunabilir</li>
</ul>

<p><strong>Dizi temsili:</strong></p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">trie</span><span class="p">[</span><span class="n">N</span><span class="p">][</span><span class="n">A</span><span class="p">];</span>
<span class="c1">// N: maksimum düğüm sayısı, A: alfabe büyüklüğü</span>
<span class="c1">// trie[s][c]: s düğümünden c karakteriyle gidilen sonraki düğüm</span>
<span class="c1">// Kök düğüm: 0</span>
</code></pre></div></div>

<h2 id="263-yazı-hashleme">26.3 Yazı Hashleme</h2>

<p><strong>Yazı hashleme</strong>, iki yazının aynı olup olmadığını verimli şekilde belirler: karakterleri tek tek karşılaştırmak yerine <strong>hash değerlerini</strong> karşılaştırırız.</p>

<h3 id="hash-değeri-hesaplama-polinom-hashleme">Hash Değeri Hesaplama (Polinom Hashleme)</h3>

<p>$n$ uzunluğundaki $s$ yazısının hash değeri:</p>

\[H(s) = \Bigl(s[0] \cdot A^{n-1} + s[1] \cdot A^{n-2} + \cdots + s[n-1] \cdot A^0\Bigr) \bmod B\]

<p>$A$ ve $B$ önceden seçilen sabitlerdir. Örneğin <code class="language-plaintext highlighter-rouge">ALLEY</code> için karakter kodları $65, 76, 76, 69, 89$; $A=3$, $B=97$ ile:</p>

\[H = (65 \cdot 3^4 + 76 \cdot 3^3 + 76 \cdot 3^2 + 69 \cdot 3^1 + 89 \cdot 3^0) \bmod 97 = 52\]

<h3 id="ön-i̇şleme-ile-o1-alt-dize-hashi">Ön İşleme ile $O(1)$ Alt Dize Hashi</h3>

<p>$h[k] = H(s[0 \ldots k])$ ve $p[k] = A^k \bmod B$ dizileri $O(n)$’de oluşturulur:</p>

<p>\(h[0] = s[0], \qquad h[k] = (h[k-1] \cdot A + s[k]) \bmod B\)
\(p[0] = 1, \qquad p[k] = (p[k-1] \cdot A) \bmod B\)</p>

<p>$a &gt; 0$ için $s[a \ldots b]$ alt dizesinin hash değeri $O(1)$’de:</p>

\[H(s[a \ldots b]) = \bigl(h[b] - h[a-1] \cdot p[b-a+1]\bigr) \bmod B\]

<p>Bu sayede kaba kuvvet örüntü eşleştirme $O(n^2)$’den $O(n)$’e iner.</p>

<p><strong>Ek uygulama:</strong> Hashleme + ikili arama ile iki yazının sözlük sırası $O(\log n)$’de bulunur (ortak ön ek uzunluğu ikili aramayla bulunur).</p>

<h3 id="çarpışmalar-ve-parametre-seçimi">Çarpışmalar ve Parametre Seçimi</h3>

<p>Farklı iki yazının aynı hash değerini almasına <strong>çarpışma</strong> denir ve yanlış sonuç üretir.</p>

<p>Üç senaryo ($n = 10^5$ için çarpışma olasılıkları):</p>

<table>
  <thead>
    <tr>
      <th>$B$ sabiti</th>
      <th>1 karşılaştırma</th>
      <th>$x$ vs $y_1 \ldots y_n$</th>
      <th>Tüm çiftler</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>$10^3$</td>
      <td>0.001</td>
      <td>1.000</td>
      <td>1.000</td>
    </tr>
    <tr>
      <td>$10^6$</td>
      <td>0.000001</td>
      <td>0.632</td>
      <td>1.000</td>
    </tr>
    <tr>
      <td>$10^9$</td>
      <td>$\approx 0$</td>
      <td>$\approx 0$</td>
      <td><strong>0.393</strong></td>
    </tr>
    <tr>
      <td>$10^{12}$</td>
      <td>$\approx 0$</td>
      <td>$\approx 0$</td>
      <td>0.0005</td>
    </tr>
  </tbody>
</table>

<ol>
  <li>senaryo <strong>doğum günü paradoksudur</strong>: Tüm çiftler karşılaştırıldığında $B \approx 10^9$ ile çarpışma olasılığı yaklaşık %39’dur!</li>
</ol>

<p><strong>Önerilen sabitler:</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>A = 911382323
B = 972663749
</code></pre></div></div>

<p><strong>Güvenli kullanım:</strong> İki farklı $(A, B)$ çiftiyle paralel hash — çarpışma ihtimali $\approx 10^{-18}$.</p>

<blockquote>
  <p>⚠️ $B = 2^{32}$ veya $B = 2^{64}$ gibi 2’nin kuvvetlerini <strong>kullanmayın</strong>; bu parametrelerle her zaman çarpışma üretebilen girdiler oluşturmak mümkündür.</p>
</blockquote>

<h2 id="264-z-algoritması">26.4 Z-Algoritması</h2>

<p>$n$ uzunluğundaki $s$ yazısının <strong>Z-dizisi</strong> $z$, her $k$ için $k$ pozisyonundan başlayan ve aynı zamanda $s$’nin ön eki olan en uzun alt dizenin uzunluğunu verir:</p>

\[z[k] = p \iff s[0 \ldots p-1] = s[k \ldots k+p-1]\]

<p><strong>Örnek:</strong> <code class="language-plaintext highlighter-rouge">ACBACDACBACBACDA</code> için Z-dizisi:</p>

<table>
  <thead>
    <tr>
      <th>0</th>
      <th>1</th>
      <th>2</th>
      <th>3</th>
      <th>4</th>
      <th>5</th>
      <th>6</th>
      <th>7</th>
      <th>8</th>
      <th>9</th>
      <th>10</th>
      <th>11</th>
      <th>12</th>
      <th>13</th>
      <th>14</th>
      <th>15</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>A</td>
      <td>C</td>
      <td>B</td>
      <td>A</td>
      <td>C</td>
      <td>D</td>
      <td>A</td>
      <td>C</td>
      <td>B</td>
      <td>A</td>
      <td>C</td>
      <td>B</td>
      <td>A</td>
      <td>C</td>
      <td>D</td>
      <td>A</td>
    </tr>
    <tr>
      <td>–</td>
      <td>0</td>
      <td>0</td>
      <td>2</td>
      <td>0</td>
      <td>0</td>
      <td><strong>5</strong></td>
      <td>0</td>
      <td>0</td>
      <td><strong>7</strong></td>
      <td>0</td>
      <td>0</td>
      <td>2</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
    </tr>
  </tbody>
</table>

<p>Örneğin $z[6] = 5$ çünkü <code class="language-plaintext highlighter-rouge">ACBAC</code> ($= s[6 \ldots 10]$) yazının ön ekidir ama <code class="language-plaintext highlighter-rouge">ACBACB</code> değil.</p>

<h3 id="algoritmanın-çalışması">Algoritmanın Çalışması</h3>

<p>Z-algoritması bir $[x, y]$ aralığı tutar: $s[x \ldots y]$, $s$’nin bir ön ekidir ve $y$ mümkün olduğunca büyük tutulur.</p>

<p>Her $k$ pozisyonu için:</p>
<ol>
  <li>$z[k-x]$ değerine bakılır.
    <ul>
      <li>$k + z[k-x] &lt; y$ ise → $z[k] = z[k-x]$ (karaktere bakmaya gerek yok).</li>
      <li>$k + z[k-x] \geq y$ ise → $y$’den devam ederek karakter karakter karşılaştır.</li>
    </ul>
  </li>
  <li>Gerekirse $[x, y]$ güncellenir.</li>
</ol>

<p>Her karakter en fazla bir kez yeni karşılaştırmaya girer → <strong>toplam süre $O(n)$</strong>.</p>

<h3 id="örüntü-bulma-ile-kullanım">Örüntü Bulma ile Kullanım</h3>

<p>$p$ örüntüsünün $s$ yazısında geçtiği yerleri bulmak için:</p>

\[t = p \# s\]

<table>
  <tbody>
    <tr>
      <td>oluşturulur; <code class="language-plaintext highlighter-rouge">#</code> karakteri ne $p$’de ne $s$’de geçer. $t$’nin Z-dizisinde $</td>
      <td>p</td>
      <td>$ değerine eşit olan pozisyonlar örüntünün başlangıç noktalarıdır.</td>
    </tr>
  </tbody>
</table>

<p><strong>Örnek:</strong> $s = \text{HATTIVATTI}$, $p = \text{ATT}$</p>

<table>
  <thead>
    <tr>
      <th>0</th>
      <th>1</th>
      <th>2</th>
      <th>3</th>
      <th>4</th>
      <th>5</th>
      <th>6</th>
      <th>7</th>
      <th>8</th>
      <th>9</th>
      <th>10</th>
      <th>11</th>
      <th>12</th>
      <th>13</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>A</td>
      <td>T</td>
      <td>T</td>
      <td>#</td>
      <td>H</td>
      <td>A</td>
      <td>T</td>
      <td>T</td>
      <td>I</td>
      <td>V</td>
      <td>A</td>
      <td>T</td>
      <td>T</td>
      <td>I</td>
    </tr>
    <tr>
      <td>–</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td><strong>3</strong></td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td><strong>3</strong></td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
  </tbody>
</table>

<ol>
  <li>
    <table>
      <tbody>
        <tr>
          <td>ve 10. pozisyonlar $z = 3 =</td>
          <td>p</td>
          <td>$ → <code class="language-plaintext highlighter-rouge">ATT</code>, <code class="language-plaintext highlighter-rouge">HATTIVATTI</code>‘da 1. ve 6. indislerde geçer.</td>
        </tr>
      </tbody>
    </table>
  </li>
</ol>

<h3 id="implementasyon">Implementasyon</h3>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">z</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>
    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">z</span><span class="p">(</span><span class="n">n</span><span class="p">);</span>
    <span class="kt">int</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">z</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">min</span><span class="p">(</span><span class="n">z</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="n">x</span><span class="p">],</span> <span class="n">y</span><span class="o">-</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">));</span>
        <span class="k">while</span> <span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="n">z</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">[</span><span class="n">z</span><span class="p">[</span><span class="n">i</span><span class="p">]]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="n">z</span><span class="p">[</span><span class="n">i</span><span class="p">]])</span> <span class="p">{</span>
            <span class="n">x</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span> <span class="n">y</span> <span class="o">=</span> <span class="n">i</span><span class="o">+</span><span class="n">z</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> <span class="n">z</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">++</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="n">z</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="hashleme-vs-z-algoritması">Hashleme vs Z-Algoritması</h3>

<table>
  <thead>
    <tr>
      <th> </th>
      <th>Yazı Hashleme</th>
      <th>Z-Algoritması</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Hız</strong></td>
      <td>$O(n)$ ön işleme, $O(1)$ sorgu</td>
      <td>$O(n)$ tek geçiş</td>
    </tr>
    <tr>
      <td><strong>Güvenlik</strong></td>
      <td>Çarpışma riski var</td>
      <td>Her zaman doğru</td>
    </tr>
    <tr>
      <td><strong>Kod kolaylığı</strong></td>
      <td>Daha basit</td>
      <td>Daha karmaşık</td>
    </tr>
    <tr>
      <td><strong>Esneklik</strong></td>
      <td>İkili arama ile sözlük sırası</td>
      <td>Yalnızca ön ek eşleşmeleri</td>
    </tr>
  </tbody>
</table>

<hr />

<blockquote>
  <p><strong>Kaynak:</strong> <em>Rekabetçi Programcı</em> (Competitive Programmer’s Handbook — Antti Laaksonen), Bölüm 26.</p>
</blockquote>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="yazı-algoritmaları" /><category term="string-algorithms" /><category term="trie" /><category term="z-algoritması" /><category term="string-hashing" /><category term="polinom-hashleme" /><category term="örüntü-bulma" /><category term="çarpışma" /><category term="doğum-günü-paradoksu" /><category term="c" /><category term="programlama" /><category term="algoritma" /><category term="olimpiyat" /><category term="yarışma" /><category term="kodlama" /><category term="matematik" /><category term="kitap" /><summary type="html"><![CDATA[Yazı algoritmaları, metinleri verimli şekilde işlemek için kullanılır. Pek çok yazı problemi $O(n^2)$’de kolayca çözülse de asıl hedef $O(n)$ veya $O(n \log n)$’e inmektir. Temel örnek örüntü bulma problemidir: $n$ uzunluğundaki yazıda $m$ uzunluğundaki örüntü nerede geçiyor?]]></summary></entry><entry><title type="html">Rekabetçi Programcı Oyun Teorisi</title><link href="https://sonsuzus.github.io/posts/rekabetci-programci-oyun-teorisi/" rel="alternate" type="text/html" title="Rekabetçi Programcı Oyun Teorisi" /><published>2026-04-25T00:00:00+00:00</published><updated>2026-04-25T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/rekabetci-programci-oyun-teorisi</id><content type="html" xml:base="https://sonsuzus.github.io/posts/rekabetci-programci-oyun-teorisi/"><![CDATA[<p><strong>Oyun teorisi</strong>, rastgele eleman içermeyen iki kişilik oyunları analiz eder. Amaç; rakip ne yaparsa yapsın, eğer varsa oyunu kesinlikle kazandıracak bir strateji bulmaktır. Bu oyunlar <strong>nim teorisi</strong> ile analiz edilir.
``</p>

<h2 id="251-oyun-durumları">25.1 Oyun Durumları</h2>

<p>Örnek oyun: $n$ çubukluk bir öbek var; $A$ ve $B$ oyuncuları sırayla oynar, $A$ başlar. Her hamlede oyuncu 1, 2 veya 3 çubuk çıkarır; <strong>son çubuğu çıkaran kazanır.</strong></p>

<p>$n = 10$ için örnek oynanış:</p>

<ul>
  <li>A, 2 çıkarır → 8 kaldı</li>
  <li>B, 3 çıkarır → 5 kaldı</li>
  <li>A, 1 çıkarır → 4 kaldı</li>
  <li>B, 2 çıkarır → 2 kaldı</li>
  <li>A, 2 çıkarır → <strong>A kazanır</strong></li>
</ul>

<h3 id="kazanan-ve-kaybeden-durumlar">Kazanan ve Kaybeden Durumlar</h3>

<ul>
  <li><strong>Kazanan durum (W):</strong> Mevcut oyuncu optimal oynarsa kazanır.</li>
  <li><strong>Kaybeden durum (L):</strong> Rakip optimal oynarsa mevcut oyuncu kaybeder.</li>
</ul>

<p><strong>Temel kural:</strong></p>
<ul>
  <li>Şu anki durumdan bir <strong>kaybeden</strong> duruma geçiş yapılabiliyorsa → <strong>kazanan durum</strong></li>
  <li>Şu anki durumdan yalnızca <strong>kazanan</strong> durumlara geçilebiliyorsa → <strong>kaybeden durum</strong></li>
</ul>

<p>Başka hamle olmayan son durum her zaman <strong>kaybedendir</strong> (0 çubuk: hamle yok).</p>

<p>1–2–3 çubuk çıkarma oyununda 0–15 durumlarının sınıflandırması:</p>

<table>
  <thead>
    <tr>
      <th>0</th>
      <th>1</th>
      <th>2</th>
      <th>3</th>
      <th>4</th>
      <th>5</th>
      <th>6</th>
      <th>7</th>
      <th>8</th>
      <th>9</th>
      <th>10</th>
      <th>11</th>
      <th>12</th>
      <th>13</th>
      <th>14</th>
      <th>15</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>L</td>
      <td>W</td>
      <td>W</td>
      <td>W</td>
      <td>L</td>
      <td>W</td>
      <td>W</td>
      <td>W</td>
      <td>L</td>
      <td>W</td>
      <td>W</td>
      <td>W</td>
      <td>L</td>
      <td>W</td>
      <td>W</td>
      <td>W</td>
    </tr>
  </tbody>
</table>

<p><strong>Kalıp:</strong> $k$ durumu, $4 \mid k$ ise kaybeden; aksi hâlde kazanandır. Optimal strateji her hamlede kalan çubuk sayısını 4’ün katı tutmaktır.</p>

<h3 id="durum-çizgesi">Durum Çizgesi</h3>

<p>Daha karmaşık oyunlarda (örneğin $k$. durumda $k$’yi bölen kadar çubuk alınabilir) durum çizgesi kurulur: düğümler durumları, kenarlar geçişleri gösterir. 1–9 durumları için:</p>

<table>
  <thead>
    <tr>
      <th>1</th>
      <th>2</th>
      <th>3</th>
      <th>4</th>
      <th>5</th>
      <th>6</th>
      <th>7</th>
      <th>8</th>
      <th>9</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>L</td>
      <td>W</td>
      <td>L</td>
      <td>W</td>
      <td>L</td>
      <td>W</td>
      <td>L</td>
      <td>W</td>
      <td>L</td>
    </tr>
  </tbody>
</table>

<p>Bu oyunda tüm tek sayılı durumlar kaybedendir.</p>

<h2 id="252-nim-oyunu">25.2 Nim Oyunu</h2>

<p><strong>Nim</strong>, oyun teorisinin temel taşıdır; çünkü çoğu oyun aynı stratejiyle analiz edilebilir.</p>

<p><strong>Kurallar:</strong></p>
<ul>
  <li>$n$ öbek vardır, $k$. öbekte $x_k$ çubuk bulunur.</li>
  <li>Sıradaki oyuncu bir öbek seçer ve istediği kadar çubuk çıkarır.</li>
  <li>Son çubuğu çıkaran kazanır.</li>
  <li>Durum $[0, 0, \ldots, 0]$ kaybedendir.</li>
</ul>

<h3 id="analiz-nim-toplamı">Analiz: Nim Toplamı</h3>

<p>Herhangi bir nim durumu <strong>nim toplamı</strong> ile sınıflandırılır:</p>

\[s = x_1 \oplus x_2 \oplus \cdots \oplus x_n\]

<p>$\oplus$ XOR operatörüdür. <strong>Nim toplamı 0 olan durum kaybedendir; diğerleri kazanandır.</strong></p>

<p>Örnek: $[10, 12, 5]$ durumunda $s = 10 \oplus 12 \oplus 5 = 3 \neq 0$ → kazanan durum.</p>

<p><strong>Neden işe yarar?</strong></p>

<ul>
  <li><strong>Kaybeden durumlar:</strong> $[0,0,\ldots,0]$’ın nim toplamı 0’dır. Herhangi bir $x_k$’yı değiştirmek nim toplamını 0’dan farklı yapar → kazanan duruma geçilir.</li>
  <li><strong>Kazanan durumlar:</strong> $x_k \oplus s &lt; x_k$ olan bir $k$ her zaman mevcuttur (nim toplamının en soldaki bitine karşılık gelen öbek). Bu öbeği $x_k \oplus s$ büyüklüğüne düşürmek nim toplamını 0 yapar → kaybeden duruma geçilir.</li>
</ul>

<p><strong>Örnek hamle:</strong> $[10, 12, 5]$, nim toplamı $s = 3$:</p>

\[10 = 1010_2, \quad 12 = 1100_2, \quad 5 = 0101_2, \quad s = 0011_2\]

<p>$s$’nin en soldaki biti 10’un 2. bitine denk gelir. Yeni öbek boyutu: $10 \oplus 3 = 9$.
Hamle: 10’lu öbekten 1 çubuk çıkar → $[9, 12, 5]$, nim toplamı $9 \oplus 12 \oplus 5 = 0$ → <strong>kaybeden durum</strong>.</p>

<h3 id="misère-nim">Misère Nim</h3>

<p><strong>Misère</strong> versiyonunda son çubuğu alan <strong>kaybeder</strong>. Strateji:</p>

<ul>
  <li>Tüm öbeklerde en fazla 1 çubuk kalana dek <strong>standart nim</strong> gibi oyna.</li>
  <li>Bu eşiğe gelindiğinde taktiği değiştir:
    <ul>
      <li><strong>Standart nim’de</strong> tek çubuklu öbek sayısını <strong>çift</strong> tut.</li>
      <li><strong>Misère’de</strong> tek çubuklu öbek sayısını <strong>tek</strong> tut.</li>
    </ul>
  </li>
</ul>

<p>Bu eşik durumu her zaman <strong>kazanan</strong> bir durumdur (birden fazla çubuklu tek öbek mevcuttur, nim toplamı 0 değildir).</p>

<h2 id="253-spraguegrundy-teoremi">25.3 Sprague–Grundy Teoremi</h2>

<p><strong>Sprague–Grundy Teoremi</strong>, nim stratejisini aşağıdaki şartları sağlayan tüm oyunlara genelleştirir (Sprague 1935, Grundy 1939 — bağımsız olarak):</p>

<ul>
  <li>İki oyuncu sırayla hamle yapar.</li>
  <li>Olası hamleler kimin sırasında olduğuna bağlı değildir.</li>
  <li>Hamle yapamayan oyuncu kaybeder.</li>
  <li>Oyun sonlu durumda biter.</li>
  <li>Oyuncuların tam bilgisi vardır; rastgelelik yoktur.</li>
</ul>

<p><strong>Temel fikir:</strong> Her oyun durumuna bir <strong>Grundy sayısı</strong> atanır. Bu sayı bir nim öbeğindeki çubuk sayısına karşılık gelir; böylece oyun standart nim gibi oynanabilir.</p>

<h3 id="grundy-sayısı-mex">Grundy Sayısı (mex)</h3>

<p>Bir durumun Grundy sayısı:</p>

\[G = \text{mex}(\{g_1, g_2, \ldots, g_n\})\]

<p>$g_1, g_2, \ldots, g_n$ gidilebilecek durumların Grundy sayıları; <strong>mex</strong> ise kümede bulunmayan en küçük negatif olmayan tam sayıdır.</p>

<p>Örnek: $\text{mex}({0, 1, 3}) = 2$. Hamle olmayan durumda $\text{mex}(\emptyset) = 0$.</p>

<p><strong>Özellikler:</strong></p>
<ul>
  <li>Grundy sayısı <strong>0</strong> → kaybeden durum</li>
  <li>Grundy sayısı <strong>pozitif</strong> → kazanan durum</li>
  <li>Grundy sayısı $x &gt; 0$ olan durumdan $0, 1, \ldots, x-1$ Grundy sayılı tüm durumlara gidilebilir</li>
</ul>

<p><strong>Labirent oyunu örneği:</strong> Oyuncular figürü sol veya yukarı hareket ettiriyor; son hamleyi yapan kazanıyor. Sol alt köşenin Grundy sayısı 2 → kazanan durum. Kaybeden duruma ya iki adım yukarı ya dört adım sola gidilerek varılır.</p>

<blockquote>
  <p>Standart nim’den farklı olarak Grundy sayısı daha büyük bir duruma geçmek mümkündür; fakat rakip her zaman bu hamleyi nötrleyebilir.</p>
</blockquote>

<h3 id="alt-oyunlar">Alt Oyunlar</h3>

<p>Oyun birden fazla bağımsız alt oyundan oluşuyorsa ve her hamlede yalnızca bir alt oyunda hareket ediliyorsa, <strong>tüm oyunun Grundy sayısı alt oyunların Grundy sayılarının nim toplamıdır:</strong></p>

\[G = G_1 \oplus G_2 \oplus \cdots \oplus G_k\]

<p><strong>Örnek:</strong> 3 labirentten oluşan oyun; başlangıç Grundy sayıları 2, 3, 3 ise:</p>

\[G = 2 \oplus 3 \oplus 3 = 2 \neq 0 \implies \text{kazanan durum}\]

<p>Optimal hamle: ilk labirentte iki adım yukarı git → $0 \oplus 3 \oplus 3 = 0$ (kaybeden durum).</p>

<h3 id="grundynin-oyunu">Grundy’nin Oyunu</h3>

<p>Bazen bir hamle oyunu bağımsız <strong>alt oyunlara böler</strong>. Bu durumda:</p>

\[G = \text{mex}(\{g_1, g_2, \ldots, g_n\}), \quad g_k = a_{k,1} \oplus a_{k,2} \oplus \cdots \oplus a_{k,m}\]

<p><strong>Grundy’nin Oyunu:</strong> Tek bir öbek var; her hamlede oyuncu seçtiği öbeği <strong>farklı büyüklükte</strong> iki boş olmayan öbeğe böler. Son hamleyi yapan kazanır.</p>

<p>$f(n)$, $n$ çubuklu öbeğin Grundy sayısı olsun. Örneğin $n = 8$:</p>

\[f(8) = \text{mex}(\{f(1) \oplus f(7),\ f(2) \oplus f(6),\ f(3) \oplus f(5)\})\]

<p>1 ve 2 çubuklu öbekler bölünemez; dolayısıyla $f(1) = f(2) = 0$. İlk Grundy sayıları:</p>

<table>
  <thead>
    <tr>
      <th>$n$</th>
      <th>1</th>
      <th>2</th>
      <th>3</th>
      <th>4</th>
      <th>5</th>
      <th>6</th>
      <th>7</th>
      <th>8</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>$f(n)$</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>2</td>
      <td>1</td>
      <td>0</td>
      <td>2</td>
    </tr>
  </tbody>
</table>

<p>$f(8) = 2 \neq 0$ → kazanan durum. Kazanan hamle: $1 + 7$ olarak böl, çünkü $f(1) \oplus f(7) = 0 \oplus 0 = 0$.</p>

<hr />

<blockquote>
  <p><strong>Kaynak:</strong> <em>Rekabetçi Programcı</em> (Competitive Programmer’s Handbook — Antti Laaksonen), Bölüm 25.</p>
</blockquote>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="oyun-teorisi" /><category term="game-theory" /><category term="nim" /><category term="sprague-grundy" /><category term="grundy-sayısı" /><category term="misère" /><category term="kazanan-durum" /><category term="kaybeden-durum" /><category term="xor" /><category term="mex" /><category term="c" /><category term="programlama" /><category term="algoritma" /><category term="olimpiyat" /><category term="yarışma" /><category term="kodlama" /><category term="matematik" /><category term="kitap" /><summary type="html"><![CDATA[Oyun teorisi, rastgele eleman içermeyen iki kişilik oyunları analiz eder. Amaç; rakip ne yaparsa yapsın, eğer varsa oyunu kesinlikle kazandıracak bir strateji bulmaktır. Bu oyunlar nim teorisi ile analiz edilir.]]></summary></entry><entry><title type="html">Rekabetçi Programcı Olasılık</title><link href="https://sonsuzus.github.io/posts/rekabetci-programci-olasilik/" rel="alternate" type="text/html" title="Rekabetçi Programcı Olasılık" /><published>2026-04-24T00:00:00+00:00</published><updated>2026-04-24T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/rekabetci-programci-olasilik</id><content type="html" xml:base="https://sonsuzus.github.io/posts/rekabetci-programci-olasilik/"><![CDATA[<p><strong>Olasılık</strong>, rastgele bir sürecin sonuçlarını sayısal olarak ifade eder. $0$ ile $1$ arasında bir değer olan $P(A)$, $A$ olayının gerçekleşme ihtimalini verir; $P(A) = 0$ imkânsızı, $P(A) = 1$ kesinliği temsil eder.</p>

<p>Zar atma örneğiyle:</p>

<ul>
  <li>$P(\text{“sonuç 4”}) = 1/6$</li>
  <li>$P(\text{“sonuç 6 değil”}) = 5/6$</li>
  <li>$P(\text{“sonuç çift”}) = 1/2$
``</li>
</ul>

<h2 id="241-hesaplama">24.1 Hesaplama</h2>

<p>Bir olayın olasılığını hesaplamak için iki temel yöntem kullanılır.</p>

<p><strong>1. Yöntem — Kombinatorik:</strong> Olasılık şu formülle bulunur:</p>

\[P(A) = \frac{\text{istenen durum sayısı}}{\text{toplam olası durum sayısı}}\]

<p>Örneğin karıştırılmış 52 kartlık desteden aynı değerde 3 kart seçme olasılığı:</p>

\[\frac{13 \cdot \binom{4}{3}}{\binom{52}{3}} = \frac{1}{425}\]

<p>çünkü 13 kart değeri vardır, her değerden 4 kart arasından 3 seçilir ve toplamda 52 karttan 3 seçilir.</p>

<p><strong>2. Yöntem — Simülasyon (Adım adım çarpım):</strong> Her adımı sırayla düşünürüz:</p>

<ul>
  <li>
    <ol>
      <li>kart: herhangi bir kart → olasılık $1$</li>
    </ol>
  </li>
  <li>
    <ol>
      <li>kart: kalan 51 kart arasında aynı değerde 3 kart → olasılık $3/51$</li>
    </ol>
  </li>
  <li>
    <ol>
      <li>kart: kalan 50 kart arasında aynı değerde 2 kart → olasılık $2/50$</li>
    </ol>
  </li>
</ul>

\[1 \cdot \frac{3}{51} \cdot \frac{2}{50} = \frac{1}{425}\]

<h2 id="242-olaylar">24.2 Olaylar</h2>

<p>Olasılık teorisinde bir <strong>olay</strong> $A$, tüm olası durumlar kümesi $X$’in bir alt kümesidir: $A \subset X$.</p>

<p>Zar örneğinde $X = {1,2,3,4,5,6}$ ve “çift sayı gelme” olayı $A = {2,4,6}$’dır. Her $x$ durumuna bir $p(x)$ olasılığı atanır; olayın olasılığı:</p>

\[P(A) = \sum_{x \in A} p(x)\]

<p>Tüm olası durumların olasılıkları toplamı her zaman $P(X) = 1$ olmalıdır.</p>

<h3 id="temel-i̇şlemler">Temel İşlemler</h3>

<p>Olaylar birer küme olduğundan standart küme işlemleri uygulanır:</p>

<ul>
  <li><strong>Tümleyen</strong> $\bar{A}$: “$A$ gerçekleşmeyecek”. $P(\bar{A}) = 1 - P(A)$</li>
  <li><strong>Birleşim</strong> $A \cup B$: “$A$ veya $B$ gerçekleşecek”. $P(A \cup B) = P(A) + P(B) - P(A \cap B)$</li>
  <li><strong>Kesişim</strong> $A \cap B$: “$A$ ve $B$ birlikte gerçekleşecek”. $P(A \cap B) = P(A)\,P(B \mid A)$</li>
</ul>

<p><strong>Tümleyen ile zıt problem çözme:</strong> 10 defa zar attığımızda en az bir kez 6 gelme olasılığı doğrudan hesaplamak yerine tümleyenle bulunur:</p>

\[P(\text{en az bir 6}) = 1 - \left(\frac{5}{6}\right)^{10}\]

<p><strong>Birleşim örneği:</strong> Zar atarken $A = $ “çift sayı” ve $B = $ “4’ten küçük” olayları için:</p>

\[P(A \cup B) = \frac{1}{2} + \frac{1}{2} - \frac{1}{6} = \frac{5}{6}\]

<p>Eğer $A \cap B = \emptyset$ (ayrık olaylar) ise $P(A \cup B) = P(A) + P(B)$.</p>

<h3 id="koşullu-olasılık">Koşullu Olasılık</h3>

<p>$B$ olayının gerçekleşeceği bilindiğinde $A$’nın olasılığı:</p>

\[P(A \mid B) = \frac{P(A \cap B)}{P(B)}\]

<h3 id="bağımsız-olaylar">Bağımsız Olaylar</h3>

<p>$A$ ve $B$ olayları, birinin gerçekleşmesi diğerini etkilemiyorsa <strong>bağımsızdır</strong>: $P(A \mid B) = P(A)$ ve $P(B \mid A) = P(B)$. Bu durumda:</p>

\[P(A \cap B) = P(A)\,P(B)\]

<p>Örneğin desteden kart çekerken $A = $ “sinek” ve $B = $ “değeri 4” bağımsızdır:</p>

\[P(\text{sinek 4}) = \frac{1}{4} \cdot \frac{1}{13} = \frac{1}{52}\]

<h2 id="243-rastgele-değişkenler">24.3 Rastgele Değişkenler</h2>

<p><strong>Rastgele değişken</strong>, rastgele bir süreçten üretilen sayısal değerdir. $P(X = x)$ ifadesi $X$’in $x$ değerini alma olasılığını verir.</p>

<p>Örneğin iki zar atıldığında $X = $ “toplamları” için $P(X = 10) = 3/36$; zira [4,6], [5,5] ve [6,4] kombinasyonları 10 toplamını verir.</p>

<h3 id="beklenen-değer">Beklenen Değer</h3>

<p><strong>Beklenen değer</strong> $E[X]$, $X$’in ağırlıklı ortalamasıdır:</p>

\[E[X] = \sum_{x} P(X = x) \cdot x\]

<p>Tek zar için: $E[X] = \frac{1}{6}(1+2+3+4+5+6) = \frac{7}{2}$</p>

<p><strong>Beklenen değerin doğrusallığı:</strong> Değişkenler bağımlı olsa bile:</p>

\[E[X_1 + X_2 + \cdots + X_n] = E[X_1] + E[X_2] + \cdots + E[X_n]\]

<p>İki zar için: $E[X_1 + X_2] = 7/2 + 7/2 = 7$.</p>

<p><strong>Uygulama:</strong> $n$ topun rastgele $n$ kutuya yerleştirildiğinde boş kutu sayısının beklenen değeri nedir? Tek bir kutunun boş kalma olasılığı $\left(\frac{n-1}{n}\right)^n$ olduğundan, doğrusallık ile:</p>

\[E[\text{boş kutu sayısı}] = n \cdot \left(\frac{n-1}{n}\right)^n\]

<h3 id="dağılımlar">Dağılımlar</h3>

<p>Bir rastgele değişkenin <strong>dağılımı</strong>, alabileceği her değerin olasılığını gösterir. Önemli dağılımlar:</p>

<p><strong>Sürekli (Uniform) dağılım:</strong> $a, a+1, \ldots, b$ arasındaki $n$ değerden her birinin olasılığı $1/n$’dir.</p>

\[E[X] = \frac{a+b}{2}\]

<p>Zar için: $E[X] = (1+6)/2 = 7/2$.</p>

<p><strong>Binom dağılım:</strong> $n$ denemeden her birinin başarı olasılığı $p$ iken tam $x$ başarının olasılığı:</p>

\[P(X = x) = \binom{n}{x} p^x (1-p)^{n-x}, \qquad E[X] = pn\]

<p>Örneğin 10 zar atışında tam 3 kez 6 gelme olasılığı: $\binom{10}{3}(1/6)^3(5/6)^7$.</p>

<p><strong>Geometrik dağılım:</strong> İlk başarıya ulaşmak için gereken deneme sayısı ($p$ başarı olasılığı):</p>

\[P(X = x) = (1-p)^{x-1} p, \qquad E[X] = \frac{1}{p}\]

<p>Örneğin 6 gelene kadar zar atarken 4 denemede başarı olasılığı: $(5/6)^3 \cdot 1/6$.</p>

<h2 id="244-markov-zincirleri">24.4 Markov Zincirleri</h2>

<p><strong>Markov zinciri</strong>, durumlar ve aralarındaki geçiş olasılıklarından oluşan rastgele bir süreçtir. Bir çizge olarak gösterilir: düğümler durumları, kenarlar geçişleri temsil eder.</p>

<p><strong>Örnek:</strong> $n$ katlı binada her adımda bir kat yukarı ya da aşağı yürünüyor (1. kattan sadece yukarı, $n$. kattan sadece aşağı). $n = 5$ için çizge:</p>

\[1 \xrightarrow{1} 2 \underset{1/2}{\overset{1/2}{\rightleftharpoons}} 3 \underset{1/2}{\overset{1/2}{\rightleftharpoons}} 4 \underset{1/2}{\overset{1/2}{\rightleftharpoons}} 5 \xrightarrow{1} 4 \quad \cdots\]

<p><strong>Olasılık dağılımı</strong> $[p_1, p_2, \ldots, p_n]$ vektörü ile tutulur; $p_k$ şu anki durumun $k$ olma ihtimalidir, $\sum p_k = 1$.</p>

<ol>
  <li>kattan başlayınca ilk dağılım $[1, 0, 0, 0, 0]$, sonraki $[0, 1, 0, 0, 0]$, ondan sonra $[1/2, 0, 1/2, 0, 0]$ şeklinde ilerler.</li>
</ol>

<p><strong>Hesaplama yöntemleri:</strong></p>

<ul>
  <li><strong>Dinamik programlama:</strong> Dağılım vektörünü adım adım güncelleyerek $O(n^2 m)$ sürede $m$ adım hesaplanır.</li>
  <li><strong>Matris kuvveti:</strong> Geçişler bir $n \times n$ geçiş matrisi $T$ ile ifade edilir. $m$ adım sonraki dağılım $T^m \cdot [p_1, \ldots, p_n]^T$ ile bulunur ve $O(n^3 \log m)$ sürer.</li>
</ul>

<p>$n = 5$ için geçiş matrisi:</p>

\[T = \begin{pmatrix} 0 &amp; 1/2 &amp; 0 &amp; 0 &amp; 0 \\ 1 &amp; 0 &amp; 1/2 &amp; 0 &amp; 0 \\ 0 &amp; 1/2 &amp; 0 &amp; 1/2 &amp; 0 \\ 0 &amp; 0 &amp; 1/2 &amp; 0 &amp; 1 \\ 0 &amp; 0 &amp; 0 &amp; 1/2 &amp; 0 \end{pmatrix}\]

<h2 id="245-rastgele-algoritmalar">24.5 Rastgele Algoritmalar</h2>

<p><strong>Rastgele algoritma</strong>, probleme özgü rastgelelik olmasa bile kendi iç rastgeleliğini kullanan algoritmadır. İki ana türü vardır:</p>

<ul>
  <li><strong>Monte Carlo algoritması:</strong> Kesin doğru cevap garantisi yoktur, küçük bir hata olasılığı kabul edilir; buna karşın çalışma süresi deterministiktir.</li>
  <li><strong>Las Vegas algoritması:</strong> Her zaman doğru cevabı verir; çalışma süresi rastgeledir ama beklenen süre verimlidir.</li>
</ul>

<h3 id="sıra-i̇statistikleri-quickselect">Sıra İstatistikleri (Quickselect)</h3>

<p>$n$ elemanlı bir dizinin $k$. en küçük elemanını bulmak için diziyi tamamen sıralamak şart değildir. <strong>Hızlı Seçme (Quickselect)</strong> bir Las Vegas algoritmasıdır:</p>

<ol>
  <li>Diziden rastgele bir $x$ öğesi (pivot) seç.</li>
  <li>$x$’ten küçükleri sola, büyükleri sağa yerleştir ($O(n)$ sürer).</li>
  <li>Sol kısımda $a$ eleman varsa:
    <ul>
      <li>$a = k-1$ ise $x$ cevaptır.</li>
      <li>$a \geq k$ ise sol kısımda ara.</li>
      <li>$a &lt; k-1$ ise sağ kısımda $(k-a-1)$. sırayı ara.</li>
    </ul>
  </li>
</ol>

<p>Beklenen süre:</p>

\[n + n/2 + n/4 + \cdots &lt; 2n = O(n)\]

<p>En kötü durum $O(n^2)$ olmakla birlikte pratikte bu durum son derece nadirdir.</p>

<h3 id="matris-çarpımını-doğrulama-freivalds-algoritması">Matris Çarpımını Doğrulama (Freivalds Algoritması)</h3>

<p>$n \times n$ boyutlu $A$, $B$, $C$ matrisleri için $AB = C$ mi sorusunu $O(n^2)$’de doğrulamak mümkündür (doğrudan $AB$ çarpmak $O(n^3)$ sürer):</p>

<ol>
  <li>Rastgele bir $n$ boyutlu $X$ vektörü seç.</li>
  <li>$A(BX)$ ve $CX$ matrislerini hesapla (her biri $O(n^2)$).</li>
  <li>$A(BX) = CX$ ise $AB = C$ de; değilse $AB \neq C$ de.</li>
</ol>

<p>Algoritma (Freivalds, 1977) $AB \neq C$ olduğu hâlde yanlış “eşit” diyebilir; fakat bu olasılık çok küçüktür ve testi farklı rastgele $X$’lerle tekrarlamak hata ihtimalini üstel hızda azaltır.</p>

<h3 id="çizge-boyaması">Çizge Boyaması</h3>

<p>$n$ düğüm ve $m$ kenardan oluşan bir çizgeyi iki renkle öyle boyamak istiyoruz ki en az $m/2$ kenarda uç noktaların renkleri farklı olsun.</p>

<p><strong>Las Vegas yaklaşımı:</strong> Her düğümü $1/2$ olasılıkla bağımsız olarak renklendir. Tek bir kenarın uç noktalarının farklı renkli olma olasılığı $1/2$’dir. Doğrusallık gereği beklenen “farklı uçlu kenar” sayısı $m/2$’dir. Yani rastgele bir boyama beklenen değerde geçerlidir; dolayısıyla geçerli bir boyama genellikle hızla bulunur.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="olasılık" /><category term="probability" /><category term="kombinatorik" /><category term="beklenen-değer" /><category term="markov-zinciri" /><category term="monte-carlo" /><category term="las-vegas" /><category term="rastgele-algoritma" /><category term="quickselect" /><category term="dağılım" /><category term="c" /><category term="programlama" /><category term="algoritma" /><category term="olimpiyat" /><category term="yarışma" /><category term="kodlama" /><category term="matematik" /><category term="kitap" /><summary type="html"><![CDATA[Olasılık, rastgele bir sürecin sonuçlarını sayısal olarak ifade eder. $0$ ile $1$ arasında bir değer olan $P(A)$, $A$ olayının gerçekleşme ihtimalini verir; $P(A) = 0$ imkânsızı, $P(A) = 1$ kesinliği temsil eder. Zar atma örneğiyle: $P(\text{“sonuç 4”}) = 1/6$ $P(\text{“sonuç 6 değil”}) = 5/6$ $P(\text{“sonuç çift”}) = 1/2$]]></summary></entry><entry><title type="html">Rekabetçi Programcı Matris</title><link href="https://sonsuzus.github.io/posts/rekabetci-programci-matris/" rel="alternate" type="text/html" title="Rekabetçi Programcı Matris" /><published>2026-04-21T00:00:00+00:00</published><updated>2026-04-21T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/rekabetci-programci-matris</id><content type="html" xml:base="https://sonsuzus.github.io/posts/rekabetci-programci-matris/"><![CDATA[<p><strong>Matris</strong>, programlamadaki iki boyutlu dizinin matematikteki karşılığıdır. $m \times n$ büyüklüğündeki bir matris $m$ satır ve $n$ sütundan oluşur; $A[i, j]$ gösterimi $i$. satır ve $j$. sütundaki elemanı verir. Özel bir durum olarak $n \times 1$ büyüklüğündeki matrise <strong>vektör</strong> denir.</p>

<p>$A$ matrisinin <strong>transpozu</strong> $A^T$, satırlar ile sütunların yer değiştirmesinden elde edilir: $A^T[i, j] = A[j, i]$. Satır ve sütun sayısı eşit olan matris <strong>kare matristir</strong>.
``</p>

<h2 id="231-operasyonlar">23.1 Operasyonlar</h2>

<h3 id="toplama-ve-skaler-çarpma">Toplama ve Skaler Çarpma</h3>

<p>Aynı boyuttaki $A$ ve $B$ matrislerinin toplamı $A + B$, karşılıklı elemanların toplamından oluşur:</p>

\[\begin{bmatrix} 6 &amp; 1 &amp; 4 \\ 3 &amp; 9 &amp; 2 \end{bmatrix}
+
\begin{bmatrix} 4 &amp; 9 &amp; 3 \\ 8 &amp; 1 &amp; 3 \end{bmatrix}
=
\begin{bmatrix} 10 &amp; 10 &amp; 7 \\ 11 &amp; 10 &amp; 5 \end{bmatrix}\]

<p>Bir matrisi $x$ skaleriyle çarpmak, her elemanı $x$ ile çarpar:</p>

\[2 \cdot \begin{bmatrix} 6 &amp; 1 &amp; 4 \\ 3 &amp; 9 &amp; 2 \end{bmatrix}
=
\begin{bmatrix} 12 &amp; 2 &amp; 8 \\ 6 &amp; 18 &amp; 4 \end{bmatrix}\]

<h3 id="matris-çarpımı">Matris Çarpımı</h3>

<p>$A$ matrisi $a \times n$, $B$ matrisi $n \times b$ boyutunda ise $AB$ çarpımı tanımlıdır ve $a \times b$ boyutunda bir matris üretir:</p>

\[AB[i, j] = \sum_{k=1}^{n} A[i, k] \cdot B[k, j]\]

<p>Her eleman, $A$’nın ilgili satırı ile $B$’nin ilgili sütununun nokta çarpımına eşittir. Örneğin:</p>

\[\begin{bmatrix} 1 &amp; 4 \\ 3 &amp; 9 \\ 8 &amp; 6 \end{bmatrix}
\cdot
\begin{bmatrix} 1 &amp; 6 \\ 2 &amp; 9 \end{bmatrix}
=
\begin{bmatrix} 9 &amp; 42 \\ 21 &amp; 99 \\ 20 &amp; 102 \end{bmatrix}\]

<p>Matris çarpımı <strong>birleşme</strong> özelliğine sahiptir ($A(BC) = (AB)C$) ama <strong>değişme</strong> özelliğine sahip değildir ($AB \neq BA$ olabilir).</p>

<p><strong>Birim matris</strong> $I$, köşegenleri 1, diğer tüm elemanları 0 olan kare matristir. Herhangi bir $A$ için $AI = IA = A$ geçerlidir.</p>

<p>$n \times n$ iki matrisin çarpımı düz algoritmada $O(n^3)$ zamanda hesaplanır. Strassen (1969) gibi daha verimli algoritmalar teorik açıdan ilginç olmakla birlikte rekabetçi programlamada genellikle gerekli değildir.</p>

<h3 id="matris-kuvveti">Matris Kuvveti</h3>

<p>$A$ kare matrisi ise $A^k$, $A$’nın kendisiyle $k$ defa çarpılmasıdır; $A^0 = I$. Modüler üs almanın analogu olan hızlı kuvvet yöntemiyle $A^k$, $O(n^3 \log k)$ zamanda hesaplanır:</p>

\[A^8 = A^4 \cdot A^4, \qquad A^4 = A^2 \cdot A^2, \quad \ldots\]

<p>Örneğin:</p>

\[\begin{bmatrix} 2 &amp; 5 \\ 1 &amp; 4 \end{bmatrix}^3
=
\begin{bmatrix} 48 &amp; 165 \\ 33 &amp; 114 \end{bmatrix}\]

<h3 id="determinant">Determinant</h3>

<p>$A$ kare matrisi için <strong>determinant</strong> $\det(A)$, özyinelemeli olarak hesaplanır. $1 \times 1$ matris için $\det(A) = A[1,1]$. Daha büyük matrisler için:</p>

\[\det(A) = \sum_{j=1}^{n} A[1, j] \cdot C[1, j]\]

<p>Burada $C[i, j] = (-1)^{i+j} \det(M[i,j])$ <strong>kofaktördür</strong> ve $M[i,j]$, $A$’dan $i$. satır ile $j$. sütun çıkarılarak elde edilir. Örneğin:</p>

\[\det\begin{pmatrix} 3 &amp; 4 \\ 1 &amp; 6 \end{pmatrix} = 3 \cdot 6 - 4 \cdot 1 = 14\]

\[\det\begin{pmatrix} 2 &amp; 4 &amp; 3 \\ 5 &amp; 1 &amp; 6 \\ 7 &amp; 2 &amp; 4 \end{pmatrix}
= 2 \det\begin{pmatrix}1&amp;6\\2&amp;4\end{pmatrix}
- 4 \det\begin{pmatrix}5&amp;6\\7&amp;4\end{pmatrix}
+ 3 \det\begin{pmatrix}5&amp;1\\7&amp;2\end{pmatrix}
= 81\]

<h3 id="ters-matris">Ters Matris</h3>

<p>$\det(A) \neq 0$ ise $A \cdot A^{-1} = I$ koşulunu sağlayan <strong>ters matris</strong> $A^{-1}$ mevcuttur:</p>

\[A^{-1}[i, j] = \frac{C[j, i]}{\det(A)}\]

<p>Örneğin:</p>

\[\begin{pmatrix} 2 &amp; 4 &amp; 3 \\ 5 &amp; 1 &amp; 6 \\ 7 &amp; 2 &amp; 4 \end{pmatrix}
\cdot
\frac{1}{81}\begin{pmatrix} -8 &amp; -10 &amp; 21 \\ 22 &amp; -13 &amp; 3 \\ 3 &amp; 24 &amp; -18 \end{pmatrix}
=
\begin{pmatrix} 1 &amp; 0 &amp; 0 \\ 0 &amp; 1 &amp; 0 \\ 0 &amp; 0 &amp; 1 \end{pmatrix}\]

<h2 id="232-lineer-tekrar-linear-recurrences">23.2 Lineer Tekrar (Linear Recurrences)</h2>

<p><strong>Lineer tekrar</strong>, $f(n)$ fonksiyonunun ilk $k$ değeriyle tanımlandığı ve büyük değerlerin şu formülle hesaplandığı bir yapıdır:</p>

\[f(n) = c_1 f(n-1) + c_2 f(n-2) + \cdots + c_k f(n-k)\]

<p>Dinamik programlamayla tüm değerleri soldan sağa hesaplamak $O(kn)$ zaman alır. Ancak $k$ küçükse matris işlemleriyle $f(n)$, $O(k^3 \log n)$ zamanda hesaplanabilir.</p>

<h3 id="fibonacci-sayıları">Fibonacci Sayıları</h3>

<p>Fibonacci tekrarı $k = 2$, $c_1 = c_2 = 1$ olan özel bir lineer tekrardır:</p>

\[f(0) = 0, \quad f(1) = 1, \quad f(n) = f(n-1) + f(n-2)\]

<p>$2 \times 2$ boyutundaki $X$ matrisiyle şu ilişki kurulur:</p>

\[X \cdot \begin{bmatrix} f(i) \\ f(i+1) \end{bmatrix} = \begin{bmatrix} f(i+1) \\ f(i+2) \end{bmatrix}\]

<p>Bu dönüşümü gerçekleştiren matris:</p>

\[X = \begin{bmatrix} 0 &amp; 1 \\ 1 &amp; 1 \end{bmatrix}\]

<p>Dolayısıyla:</p>

\[\begin{bmatrix} f(n) \\ f(n+1) \end{bmatrix} = X^n \cdot \begin{bmatrix} 0 \\ 1 \end{bmatrix}\]

<p>$X^n$ matrisi $O(\log n)$ zamanda hesaplandığından $f(n)$ de $O(\log n)$ zamanda bulunur. Örneğin:</p>

\[\begin{bmatrix} 0 &amp; 1 \\ 1 &amp; 1 \end{bmatrix} \cdot \begin{bmatrix} 5 \\ 8 \end{bmatrix} = \begin{bmatrix} 8 \\ 13 \end{bmatrix}\]

<h3 id="genel-durum">Genel Durum</h3>

<p>Genel $k$’lı lineer tekrar için $k \times k$ boyutundaki dönüşüm matrisi:</p>

\[X = \begin{bmatrix}
0 &amp; 1 &amp; 0 &amp; 0 &amp; \cdots &amp; 0 \\
0 &amp; 0 &amp; 1 &amp; 0 &amp; \cdots &amp; 0 \\
0 &amp; 0 &amp; 0 &amp; 1 &amp; \cdots &amp; 0 \\
\vdots &amp; \vdots &amp; \vdots &amp; \vdots &amp; \ddots &amp; \vdots \\
0 &amp; 0 &amp; 0 &amp; 0 &amp; \cdots &amp; 1 \\
c_k &amp; c_{k-1} &amp; c_{k-2} &amp; c_{k-3} &amp; \cdots &amp; c_1
\end{bmatrix}\]

<p>İlk $k-1$ satır her değeri bir sonrakiyle kaydırır; son satır tekrarın katsayılarını taşır. Bu matrisle:</p>

\[\begin{bmatrix} f(n) \\ f(n+1) \\ \vdots \\ f(n+k-1) \end{bmatrix} = X^n \cdot \begin{bmatrix} f(0) \\ f(1) \\ \vdots \\ f(k-1) \end{bmatrix}\]

<p>Bu formül $O(k^3 \log n)$ zamanda çalışır.</p>

<h2 id="233-çizgeler-ve-matrisler">23.3 Çizgeler ve Matrisler</h2>

<h3 id="yolları-saymak">Yolları Saymak</h3>

<p>Ağırlıksız bir çizgenin <strong>komşuluk matrisi</strong> $V$ için, $V^n$ matrisinin $V^n[i,j]$ elemanı $i$’den $j$’ye tam $n$ kenarlık yolların sayısını verir.</p>

<p>Örneğin 6 düğümlü bir çizgenin komşuluk matrisi $V$’yi hesaplayıp $V^4$’ü bulursak:</p>

\[V^4[2,5] = 2\]

<p>Bu, 2. düğümden 5. düğüme 4 kenarlı iki farklı yol bulunduğunu söyler: $2 \to 1 \to 4 \to 2 \to 5$ ve $2 \to 6 \to 3 \to 2 \to 5$.</p>

<h3 id="en-kısa-yollar">En Kısa Yollar</h3>

<p>Aynı fikir ağırlıklı çizgelerde <strong>en kısa yol</strong> bulmak için de kullanılabilir. Standart matris çarpımındaki toplam ve çarpım işlemleri aşağıdaki gibi değiştirilir:</p>

\[AB[i,j] = \min_{k=1}^{n} \bigl(A[i,k] + B[k,j]\bigr)\]

<p>Başlangıç değerleri olarak komşuluk matrisinde kenar ağırlıkları, kenar olmayan yerlerde $\infty$ kullanılır. Bu yapıyla $V^n[i,j]$, $i$’den $j$’ye tam $n$ kenarlık yolların en kısa uzunluğuna eşittir.</p>

<p>Örneğin ağırlıklı bir çizgede:</p>

\[V^4[2,5] = 8\]

<p>Bu değer, $2 \to 1 \to 4 \to 2 \to 5$ yoluna karşılık gelir.</p>

<h3 id="kirchhoffun-teoremi">Kirchhoff’un Teoremi</h3>

<p><strong>Kirchhoff’un Teoremi</strong>, bir çizgenin toplam kapsayan ağaç sayısını <strong>Laplacian matrisin</strong> determinantı yardımıyla hesaplar.</p>

<p><strong>Laplacian matris</strong> $L$ şöyle tanımlanır:</p>

\[L[i, j] = \begin{cases} \deg(i) &amp; i = j \\ -1 &amp; i \neq j \text{ ve } (i,j) \text{ kenarı var} \\ 0 &amp; \text{aksi hâlde} \end{cases}\]

<p>Toplam kapsayan ağaç sayısı, $L$’den herhangi bir satır ve sütun çıkarıldıktan sonra kalan matrisin determinantına eşittir; hangi satır-sütun çıkarılırsa çıkarılsın sonuç değişmez.</p>

<p><strong>Örnek:</strong> 4 düğümlü tam çizgede (her düğüm çifti arasında kenar var) kapsayan ağaçların sayısını bulalım. Laplacian matris:</p>

\[L = \begin{pmatrix} 3 &amp; -1 &amp; -1 &amp; -1 \\ -1 &amp; 1 &amp; 0 &amp; 0 \\ -1 &amp; 0 &amp; 2 &amp; -1 \\ -1 &amp; 0 &amp; -1 &amp; 2 \end{pmatrix}\]

<p>İlk satır ve sütun çıkarıldıktan sonra:</p>

\[\det\begin{pmatrix} 1 &amp; 0 &amp; 0 \\ 0 &amp; 2 &amp; -1 \\ 0 &amp; -1 &amp; 2 \end{pmatrix} = 3\]

<p>Gerçekten bu çizgenin 3 farklı kapsayan ağacı vardır.</p>

<p><strong>Cayley’in Formülüyle bağlantı:</strong> $n$ düğümlü tam çizgenin Laplacian matrisinin herhangi bir $(n-1) \times (n-1)$ alt determinantı $n^{n-2}$ olduğundan, Cayley’in Formülü Kirchhoff’un Teoreminin özel bir durumudur.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="matris" /><category term="matrix" /><category term="matris-çarpımı" /><category term="matris-kuvveti" /><category term="determinant" /><category term="ters-matris" /><category term="linear-tekrar" /><category term="fibonacci" /><category term="komşuluk-matrisi" /><category term="kirchhoff" /><category term="laplacian" /><category term="kapsayan-ağaç" /><category term="c" /><category term="programlama" /><category term="algoritma" /><category term="olimpiyat" /><category term="yarışma" /><category term="kodlama" /><category term="matematik" /><category term="kitap" /><summary type="html"><![CDATA[Matris, programlamadaki iki boyutlu dizinin matematikteki karşılığıdır. $m \times n$ büyüklüğündeki bir matris $m$ satır ve $n$ sütundan oluşur; $A[i, j]$ gösterimi $i$. satır ve $j$. sütundaki elemanı verir. Özel bir durum olarak $n \times 1$ büyüklüğündeki matrise vektör denir. $A$ matrisinin transpozu $A^T$, satırlar ile sütunların yer değiştirmesinden elde edilir: $A^T[i, j] = A[j, i]$. Satır ve sütun sayısı eşit olan matris kare matristir.]]></summary></entry><entry><title type="html">Rekabetçi Programcı Kombinatorik</title><link href="https://sonsuzus.github.io/posts/rekabetci-programci-kombinatorik/" rel="alternate" type="text/html" title="Rekabetçi Programcı Kombinatorik" /><published>2026-04-18T00:00:00+00:00</published><updated>2026-04-18T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/rekabetci-programci-kombinatorik</id><content type="html" xml:base="https://sonsuzus.github.io/posts/rekabetci-programci-kombinatorik/"><![CDATA[<p>Kombinatorik, nesnelerin kombinasyonlarını sayma yöntemlerini araştırır. Genelde amaç her kombinasyonu ayrı ayrı oluşturmadan toplam sayıyı hesaplamaktır.</p>

<p>Örneğin toplamı $n$ olan tam sayı dizisi sayısı gibi problemler özyinelemeli formüllerle ele alınır. $f(n)$, $n$’yi toplam olarak yazma yollarının sayısı olsun:</p>

\[f(n) = \begin{cases} 1 &amp; n = 0 \\ f(0) + f(1) + \cdots + f(n-1) &amp; n &gt; 0 \end{cases}\]

<p>İlk değerler: $f(0)=1,\ f(1)=1,\ f(2)=2,\ f(3)=4,\ f(4)=8$. Bu durumda kapalı form $f(n) = 2^{n-1}$’dir; çünkü $n-1$ boşluktan istediğimizi seçip $+$ ya da hiç koyabiliriz.
``</p>

<h2 id="221-binom-katsayıları">22.1 Binom Katsayıları</h2>

<p>$\binom{n}{k}$, $n$ elemanlı bir kümeden $k$ elemanlı alt küme seçme sayısıdır. Örneğin $\binom{5}{3} = 10$ çünkü ${1,2,3,4,5}$ kümesinin 3 elemanlı alt kümeleri şunlardır:</p>

\[\{1,2,3\},\ \{1,2,4\},\ \{1,2,5\},\ \{1,3,4\},\ \{1,3,5\},\ \{1,4,5\},\ \{2,3,4\},\ \{2,3,5\},\ \{2,4,5\},\ \{3,4,5\}\]

<h3 id="1-formül-özyineleme">1. Formül: Özyineleme</h3>

<p>Kümedeki bir $x$ elemanı sabitlenir. $x$ alt kümede ya var ya yoktur:</p>

\[\binom{n}{k} = \binom{n-1}{k-1} + \binom{n-1}{k}\]

<p>Temel durumlar:</p>

\[\binom{n}{0} = \binom{n}{n} = 1\]

<h3 id="2-formül-faktöriyel">2. Formül: Faktöriyel</h3>

<p>$n$ elemanın $n!$ permütasyonu arasından ilk $k$’sını alt kümeye eklersek, sıralama önemli olmadığından $k!$ ve $(n-k)!$’e böleriz:</p>

\[\binom{n}{k} = \frac{n!}{k!\,(n-k)!}\]

<h3 id="özellikler">Özellikler</h3>

\[\binom{n}{k} = \binom{n}{n-k}\]

<p>Tüm binom katsayılarının toplamı:</p>

\[\sum_{k=0}^{n} \binom{n}{k} = 2^n\]

<p>Binom teoremi:</p>

\[(a+b)^n = \sum_{k=0}^{n} \binom{n}{k} a^{n-k} b^k\]

<p><strong>Pascal’ın Üçgeni:</strong> Her değer, üstündeki iki değerin toplamıdır:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>            1
          1   1
        1   2   1
      1   3   3   1
    1   4   6   4   1
   ...  ...  ... ...  ...
</code></pre></div></div>

<h3 id="kutular-ve-toplar">Kutular ve Toplar</h3>

<p>$k$ topu $n$ kutuya yerleştirme probleminin üç farklı varyantı vardır:</p>

<p><strong>1. Durum — Her kutu en fazla 1 top alır:</strong> Çözüm sayısı doğrudan $\dbinom{n}{k}$’dır.</p>

<p><strong>2. Durum — Bir kutu birden fazla top alabilir:</strong> Topları “o” ve kutu geçişlerini “→” ile sembolize edersek her çözüm $k$ adet “o” ve $n-1$ adet “→” içeren bir diziye karşılık gelir:</p>

\[\binom{k + n - 1}{k}\]

<p><strong>3. Durum — Her kutu en fazla 1 top alır ve ardışık iki kutu aynı anda dolu olamaz:</strong> $k$ topu önce $k$ ayrı kutuya yerleştirip aralarına birer boş kutu koyarız; kalan $n - 2k + 1$ kutuyu dağıtmak için 2. senaryonun formülünü uygularız:</p>

\[\binom{n - k + 1}{k}\]

<h3 id="çok-terimli-katsayılar">Çok Terimli Katsayılar</h3>

<p>$n$ nesneyi $k_1, k_2, \ldots, k_m$ büyüklüklü gruplara ayırma sayısı:</p>

\[\binom{n}{k_1, k_2, \ldots, k_m} = \frac{n!}{k_1!\, k_2!\, \cdots\, k_m!}\]

<p>Bu, binom katsayısının $m = 2$ özel durumudur.</p>

<h2 id="222-katalan-sayıları">22.2 Katalan Sayıları</h2>

<p>$C_n$, $n$ sol ve $n$ sağ parantezden oluşan <strong>geçerli parantez ifadelerinin</strong> sayısıdır. Örneğin $C_3 = 5$:</p>

\[()()(), \quad (())(), \quad ()(()),\quad ((())),\quad (()())\]

<h3 id="geçerli-parantez-i̇fadesi">Geçerli Parantez İfadesi</h3>

<p>Bir ifade geçerlidir ancak ve ancak:</p>
<ul>
  <li>Her ön ekinde sağ parantez sayısı sol parantez sayısını geçmiyorsa,</li>
  <li>Toplam sol ve sağ parantez sayıları eşitse.</li>
</ul>

<h3 id="1-formül-özyineleme-1">1. Formül: Özyineleme</h3>

<p>İfadeyi iki parçaya böleriz; ilk parça mümkün olduğunca küçük tutulur:</p>

\[C_n = \sum_{i=0}^{n-1} C_i \cdot C_{n-i-1}, \qquad C_0 = 1\]

<p>Herhangi bir $i$ için ilk bölüm $i+1$ parantez çifti, ikinci bölüm $n-i-1$ parantez çifti içerir.</p>

<h3 id="2-formül-binom-katsayısı">2. Formül: Binom Katsayısı</h3>

\[C_n = \frac{1}{n+1}\binom{2n}{n}\]

<p><strong>Türetme:</strong> $n$ sol ve $n$ sağ parantezden oluşan toplam $\binom{2n}{n}$ dizi vardır. Bunlardan geçersiz olanlar, ilk geçersizleştiği noktadan sonraki kısmın sembollerini ters çevirince $n+1$ sol ve $n-1$ sağ parantezli bir diziye dönüşür; bu tür dizi sayısı $\binom{2n}{n+1}$’dir. Dolayısıyla:</p>

\[C_n = \binom{2n}{n} - \binom{2n}{n+1} = \frac{1}{n+1}\binom{2n}{n}\]

<h3 id="ağaçlarla-bağlantı">Ağaçlarla Bağlantı</h3>

<p>Katalan sayıları ağaç sayma problemlerinde de ortaya çıkar:</p>

<ul>
  <li>$n$ düğümden oluşan <strong>ikili ağaç</strong> sayısı $C_n$’dir.</li>
  <li>$n$ düğümden oluşan <strong>köklü ağaç</strong> sayısı $C_{n-1}$’dir.</li>
</ul>

<p>Örneğin $C_3 = 5$ için 5 farklı ikili ağaç ve $C_2 = 2$ için 2 farklı köklü ağaç vardır.</p>

<h2 id="223-i̇çerme-dışarma">22.3 İçerme-Dışarma</h2>

<p><strong>İçerme-dışarma ilkesi</strong>, kesişim büyüklüklerini kullanarak birleşim büyüklüğünü (ya da tersini) hesaplamamızı sağlar.</p>

<p>İki küme için:</p>

\[|A \cup B| = |A| + |B| - |A \cap B|\]

<p>Üç küme için:</p>

\[|A \cup B \cup C| = |A| + |B| + |C| - |A \cap B| - |A \cap C| - |B \cap C| + |A \cap B \cap C|\]

<p>Genel kural: Tek sayıda kümenin kesişimi <strong>eklenir</strong>, çift sayıda kümenin kesişimi <strong>çıkarılır</strong>.</p>

<p>Simetrik olarak kesişim büyüklükleri de birleşimden hesaplanabilir. Örneğin:</p>

\[|A \cap B| = |A| + |B| - |A \cup B|\]

\[|A \cap B \cap C| = |A| + |B| + |C| - |A \cup B| - |A \cup C| - |B \cup C| + |A \cup B \cup C|\]

<h3 id="düzensizlikler-derangements">Düzensizlikler (Derangements)</h3>

<p>${1, 2, \ldots, n}$ elemanlarının <strong>düzensizliği</strong>, hiçbir elemanın kendi konumunda bulunmadığı permütasyondur. Örneğin $n = 3$ için $(2,3,1)$ ve $(3,1,2)$ olmak üzere yalnızca 2 düzensizlik vardır.</p>

<p><strong>İçerme-dışarma ile:</strong> $X_k$, $k$. pozisyonda $k$ elemanını içeren permütasyon kümesi olsun. Düzensizlik sayısı:</p>

\[n! - |X_1 \cup X_2 \cup \cdots \cup X_n|\]

<p>$n = 3$ için:</p>

\[|X_1 \cup X_2 \cup X_3| = 2 + 2 + 2 - 1 - 1 - 1 + 1 = 4\]

<p>Düzensizlik sayısı $= 3! - 4 = 2$.</p>

<p><strong>Özyineleme ile:</strong> $f(n)$, $n$ elemanlı kümenin düzensizlik sayısı olsun. 1. elemanın hangi $x$ ile yer değiştirdiğine göre iki seçenek vardır:</p>

<ol>
  <li>$x$ de 1. elemanın konumuna geçer → $n-2$ elemanlık düzensizlik: $f(n-2)$ yol.</li>
  <li>$x$, 1. elemana değil başka bir konuma geçer → $n-1$ elemanlık düzensizlik: $f(n-1)$ yol.</li>
</ol>

\[f(n) = \begin{cases} 0 &amp; n = 1 \\ 1 &amp; n = 2 \\ (n-1)\bigl(f(n-2) + f(n-1)\bigr) &amp; n &gt; 2 \end{cases}\]

<h2 id="224-burnsideın-lemması">22.4 Burnside’ın Lemma’sı</h2>

<p><strong>Burnside’ın Lemma’sı</strong>, simetriler dikkate alındığında birbirinden gerçekten farklı kombinasyon sayısını hesaplamamızı sağlar. $n$ farklı dönüşüm (pozisyon değiştirme yolu) varsa ve $k$. dönüşüm uygulandığında $c(k)$ kombinasyon değişmeden kalıyorsa, toplam farklı kombinasyon sayısı:</p>

\[\frac{1}{n} \sum_{k=1}^{n} c(k)\]

<h3 id="örnek-renkli-kolye">Örnek: Renkli Kolye</h3>

<p>$n$ inciden oluşan, her incinin $m$ farklı rengi olabileceği bir kolyede, döndürme simetrileri dikkate alındığında kaç farklı kolye vardır?</p>

<p>Kolyeyi $0, 1, \ldots, n-1$ adım döndürebiliriz ($n$ farklı dönüşüm). $k$ adım döndürüldüğünde sabit kalan kolye sayısı:</p>

\[m^{\gcd(k, n)}\]

<p>Bunun nedeni $\gcd(k,n)$ büyüklüğündeki inci bloklarının birbirinin yerine geçmesidir. Burnside’ın Lemma’sına göre farklı kolye sayısı:</p>

\[\frac{1}{n} \sum_{i=0}^{n-1} m^{\gcd(i,n)}\]

<p><strong>Örnek:</strong> $n = 4$, $m = 3$ için:</p>

\[\frac{3^4 + 3^1 + 3^2 + 3^1}{4} = \frac{81 + 3 + 9 + 3}{4} = \frac{96}{4} = 24\]

<h2 id="225-cayleyin-formülü">22.5 Cayley’in Formülü</h2>

<p><strong>Cayley’in Formülü</strong>, $n$ etiketli düğüm üzerinde oluşturulabilecek farklı ağaç sayısının $n^{n-2}$ olduğunu söyler. Düğümler $1, 2, \ldots, n$ ile etiketlenir; hem yapısı hem etiketi farklı olan ağaçlar sayılır.</p>

<p>Örneğin $n = 4$ için toplam etiketli ağaç sayısı $4^{4-2} = 16$’dır.</p>

<h3 id="prüfer-kodu">Prüfer Kodu</h3>

<p>Cayley’in Formülü, <strong>Prüfer kodu</strong> ile kanıtlanır. Prüfer kodu, etiketli bir ağacı $n-2$ sayıdan oluşan bir diziye dönüştürür.</p>

<p><strong>Kodlama algoritması:</strong> $n-2$ kez tekrarlanır:</p>
<ol>
  <li>Ağaçtaki en küçük etiketli yaprak kaldırılır.</li>
  <li>Bu yaprağın tek komşusunun etiketi koda eklenir.</li>
</ol>

<p><strong>Örnek:</strong> 5 düğümlü bir ağaçta adımlar şöyle ilerler:</p>

<ul>
  <li>
    <ol>
      <li>düğüm (yaprak) kaldırılır → komşu 4 koda eklenir: <code class="language-plaintext highlighter-rouge">[4]</code></li>
    </ol>
  </li>
  <li>
    <ol>
      <li>düğüm (yaprak) kaldırılır → komşu 4 koda eklenir: <code class="language-plaintext highlighter-rouge">[4, 4]</code></li>
    </ol>
  </li>
  <li>
    <ol>
      <li>düğüm (yaprak) kaldırılır → komşu 2 koda eklenir: <code class="language-plaintext highlighter-rouge">[4, 4, 2]</code></li>
    </ol>
  </li>
</ul>

<p>Prüfer kodu: $[4, 4, 2]$.</p>

<p><strong>Neden $n^{n-2}$?</strong> Her etiketli ağacın benzersiz bir Prüfer kodu vardır ve her Prüfer kodundan orijinal ağaç benzersiz biçimde yeniden oluşturulabilir. ${1, 2, \ldots, n}$ üzerindeki $n-2$ uzunluklu dizi sayısı $n^{n-2}$ olduğundan etiketli ağaç sayısı da $n^{n-2}$’dir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="kombinatorik" /><category term="combinatorics" /><category term="binom-katsayısı" /><category term="binomial-coefficient" /><category term="katalan-sayısı" /><category term="pascal-üçgeni" /><category term="içerme-dışarma" /><category term="inclusion-exclusion" /><category term="düzensizlik" /><category term="derangement" /><category term="burnside" /><category term="cayley" /><category term="prüfer-kodu" /><category term="multinomial" /><category term="c" /><category term="programlama" /><category term="algoritma" /><category term="olimpiyat" /><category term="yarışma" /><category term="kodlama" /><category term="matematik" /><category term="kitap" /><summary type="html"><![CDATA[Kombinatorik, nesnelerin kombinasyonlarını sayma yöntemlerini araştırır. Genelde amaç her kombinasyonu ayrı ayrı oluşturmadan toplam sayıyı hesaplamaktır. Örneğin toplamı $n$ olan tam sayı dizisi sayısı gibi problemler özyinelemeli formüllerle ele alınır. $f(n)$, $n$’yi toplam olarak yazma yollarının sayısı olsun: \[f(n) = \begin{cases} 1 &amp; n = 0 \\ f(0) + f(1) + \cdots + f(n-1) &amp; n &gt; 0 \end{cases}\] İlk değerler: $f(0)=1,\ f(1)=1,\ f(2)=2,\ f(3)=4,\ f(4)=8$. Bu durumda kapalı form $f(n) = 2^{n-1}$’dir; çünkü $n-1$ boşluktan istediğimizi seçip $+$ ya da hiç koyabiliriz.]]></summary></entry><entry><title type="html">Rekabetçi Programcı Sayılar Teorisi</title><link href="https://sonsuzus.github.io/posts/rekabetci-programci-sayilar-teorisi/" rel="alternate" type="text/html" title="Rekabetçi Programcı Sayılar Teorisi" /><published>2026-04-17T00:00:00+00:00</published><updated>2026-04-17T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/rekabetci-programci-sayilar-teorisi</id><content type="html" xml:base="https://sonsuzus.github.io/posts/rekabetci-programci-sayilar-teorisi/"><![CDATA[<p>Sayılar teorisi, matematiğin tam sayılarla ilgilenen alt dalıdır. İlginç bir konudur; çünkü tam sayı içeren pek çok soru ilk bakışta kolay görünse de çözümü son derece zor olabilir. Örneğin $x^3 + y^3 + z^3 = 33$ eşitliğini sağlayan üç tam sayı bulmak hâlâ açık bir matematik problemidir.</p>

<p>Bu bölümde sayılar teorisinin rekabetçi programlamada sık karşılaşılan temel kavramları ve algoritmaları ele alınmaktadır.
``</p>

<h2 id="211-asal-sayılar-ve-bölenler">21.1 Asal Sayılar ve Bölenler</h2>

<p>$a$ sayısı $b$ sayısını bölüyorsa $a$, $b$’nin <strong>böleni</strong> ya da <strong>çarpanı</strong> olarak adlandırılır; $a \mid b$ ile gösterilir. Örneğin 24’ün bölenleri $1, 2, 3, 4, 6, 8, 12, 24$’tür.</p>

<p>$n &gt; 1$ olan bir sayı yalnızca $1$ ve kendisine bölünebiliyorsa <strong>asal sayıdır</strong>. Her $n &gt; 1$ için <strong>tekil bir asal çarpanlara ayrılma</strong> mevcuttur:</p>

\[n = p_1^{\alpha_1} p_2^{\alpha_2} \cdots p_k^{\alpha_k}\]

<p>Örneğin $84 = 2^2 \cdot 3^1 \cdot 7^1$.</p>

<h3 id="çarpan-sayısı-toplamı-ve-çarpımı">Çarpan Sayısı, Toplamı ve Çarpımı</h3>

<p>$n$’nin <strong>çarpan sayısı:</strong></p>

\[\tau(n) = \prod_{i=1}^{k} (\alpha_i + 1)\]

<p>Örneğin $\tau(84) = 3 \cdot 2 \cdot 2 = 12$.</p>

<p>$n$’nin <strong>çarpanlarının toplamı:</strong></p>

\[\sigma(n) = \prod_{i=1}^{k} \frac{p_i^{\alpha_i + 1} - 1}{p_i - 1}\]

<p>Örneğin $\sigma(84) = \dfrac{2^3 - 1}{2-1} \cdot \dfrac{3^2 - 1}{3-1} \cdot \dfrac{7^2 - 1}{7-1} = 7 \cdot 4 \cdot 8 = 224$.</p>

<p>$n$’nin <strong>çarpanlarının çarpımı:</strong></p>

\[\mu(n) = n^{\tau(n)/2}\]

<p>Çarpanlar $\tau(n)/2$ çift oluşturur. Örneğin $84$’ün çarpanları $1 \cdot 84,\ 2 \cdot 42,\ 3 \cdot 28, \ldots$ çiftlerini oluşturur ve $\mu(84) = 84^6$.</p>

<p>Bir sayı $n = \sigma(n) - n$ ise <strong>mükemmel sayıdır</strong>; yani 1’den $n-1$’e kadar olan çarpanlarının toplamına eşittir. Örneğin $28 = 1 + 2 + 4 + 7 + 14$.</p>

<h3 id="asal-sayıların-sayısı-ve-yoğunluğu">Asal Sayıların Sayısı ve Yoğunluğu</h3>

<p>Sonsuz sayıda asal sayı vardır. Bunu çelişkiyle kanıtlayabiliriz: sonlu sayıda asal olsaydı $p_1 p_2 \cdots p_n + 1$ bu listenin hiçbir elemanına bölünemeyecek yeni bir asal oluştururdu.</p>

<p>$\pi(n)$, 1 ile $n$ arasındaki asal sayı adedini gösterir. Asal sayıların yoğunluğu için şu yaklaşım geçerlidir:</p>

\[\pi(n) \approx \frac{n}{\ln n}\]

<p>Örneğin $\pi(10^6) = 78498$ iken $10^6 / \ln 10^6 \approx 72382$.</p>

<h3 id="ünlü-konjektürler">Ünlü Konjektürler</h3>

<p>Kanıtlanamamış fakat doğru olduğu güçlü biçimde düşünülen açık problemler:</p>

<ul>
  <li><strong>Goldbach’ın Konjektürü:</strong> Her $n &gt; 2$ çift sayısı iki asal sayının toplamı olarak yazılabilir.</li>
  <li><strong>İkiz Asal Konjektürü:</strong> $p$ ve $p+2$’nin her ikisinin de asal olduğu sonsuz sayıda ${p, p+2}$ çifti vardır.</li>
  <li><strong>Legendre’nin Konjektürü:</strong> Her pozitif $n$ için $n^2$ ile $(n+1)^2$ arasında en az bir asal sayı bulunur.</li>
</ul>

<h3 id="asal-sayı-testi-ve-çarpanlara-ayırma">Asal Sayı Testi ve Çarpanlara Ayırma</h3>

<p>$n$ asal değilse $a \cdot b = n$ çarpımında $a \leq \sqrt{n}$ ya da $b \leq \sqrt{n}$ olmak zorundadır. Bu gözlem $O(\sqrt{n})$ zamanlı basit algoritmaların temelini oluşturur.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">bool</span> <span class="nf">prime</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">)</span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> <span class="n">x</span> <span class="o">*</span> <span class="n">x</span> <span class="o">&lt;=</span> <span class="n">n</span><span class="p">;</span> <span class="n">x</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="n">x</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">factors</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">f</span><span class="p">;</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> <span class="n">x</span> <span class="o">*</span> <span class="n">x</span> <span class="o">&lt;=</span> <span class="n">n</span><span class="p">;</span> <span class="n">x</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">while</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="n">x</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">f</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">x</span><span class="p">);</span>
            <span class="n">n</span> <span class="o">/=</span> <span class="n">x</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">)</span> <span class="n">f</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">n</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">f</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Örneğin $24 = 2^3 \cdot 3$ için <code class="language-plaintext highlighter-rouge">factors(24)</code> sonucu <code class="language-plaintext highlighter-rouge">[2, 2, 2, 3]</code> olur.</p>

<h3 id="eratosten-kalburu">Eratosten Kalburu</h3>

<p><strong>Eratosten Kalburu (Sieve of Eratosthenes)</strong>, $2 \ldots n$ arasındaki her sayının asal olup olmadığını ve değilse bir asal çarpanını $O(n \log \log n)$ zamanda bulan ön işleme algoritmasıdır.</p>

<p><code class="language-plaintext highlighter-rouge">sieve[k] = 0</code> ise $k$ asaldır; <code class="language-plaintext highlighter-rouge">sieve[k] != 0</code> ise <code class="language-plaintext highlighter-rouge">sieve[k]</code>, $k$’nın asal çarpanlarından biridir.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> <span class="n">x</span> <span class="o">&lt;=</span> <span class="n">n</span><span class="p">;</span> <span class="n">x</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">sieve</span><span class="p">[</span><span class="n">x</span><span class="p">])</span> <span class="k">continue</span><span class="p">;</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">u</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">x</span><span class="p">;</span> <span class="n">u</span> <span class="o">&lt;=</span> <span class="n">n</span><span class="p">;</span> <span class="n">u</span> <span class="o">+=</span> <span class="n">x</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">sieve</span><span class="p">[</span><span class="n">u</span><span class="p">]</span> <span class="o">=</span> <span class="n">x</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Örneğin $n = 20$ için dizi:</p>

<table>
  <thead>
    <tr>
      <th style="text-align: center">2</th>
      <th style="text-align: center">3</th>
      <th style="text-align: center">4</th>
      <th style="text-align: center">5</th>
      <th style="text-align: center">6</th>
      <th style="text-align: center">7</th>
      <th style="text-align: center">8</th>
      <th style="text-align: center">9</th>
      <th style="text-align: center">10</th>
      <th style="text-align: center">11</th>
      <th style="text-align: center">12</th>
      <th style="text-align: center">13</th>
      <th style="text-align: center">14</th>
      <th style="text-align: center">15</th>
      <th style="text-align: center">16</th>
      <th style="text-align: center">17</th>
      <th style="text-align: center">18</th>
      <th style="text-align: center">19</th>
      <th style="text-align: center">20</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: center">0</td>
      <td style="text-align: center">0</td>
      <td style="text-align: center">2</td>
      <td style="text-align: center">0</td>
      <td style="text-align: center">3</td>
      <td style="text-align: center">0</td>
      <td style="text-align: center">2</td>
      <td style="text-align: center">3</td>
      <td style="text-align: center">5</td>
      <td style="text-align: center">0</td>
      <td style="text-align: center">3</td>
      <td style="text-align: center">0</td>
      <td style="text-align: center">7</td>
      <td style="text-align: center">5</td>
      <td style="text-align: center">2</td>
      <td style="text-align: center">0</td>
      <td style="text-align: center">3</td>
      <td style="text-align: center">0</td>
      <td style="text-align: center">5</td>
    </tr>
  </tbody>
</table>

<p>İç döngü yalnızca $x$ asal olduğunda çalıştığından gerçek karmaşıklık $O(n \log \log n)$’dir; bu değer $O(n)$’e çok yakındır.</p>

<h3 id="öklidin-algoritması">Öklid’in Algoritması</h3>

<p>$\gcd(a, b)$, hem $a$ hem $b$’yi bölen en büyük sayıdır. $\text{lcm}(a, b)$ ise her ikisi tarafından bölünebilen en küçük sayıdır. İkisi arasındaki ilişki:</p>

\[\text{lcm}(a, b) = \frac{ab}{\gcd(a, b)}\]

<p>Öklid’in Algoritması M.Ö. 300’lere uzanan, bilinen en eski algoritmalardan biridir:</p>

\[\gcd(a, b) = \begin{cases} a &amp; b = 0 \\ \gcd(b,\ a \bmod b) &amp; b \neq 0 \end{cases}\]

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">gcd</span><span class="p">(</span><span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">b</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="n">a</span><span class="p">;</span>
    <span class="k">return</span> <span class="n">gcd</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">a</span> <span class="o">%</span> <span class="n">b</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Algoritma $O(\log \min(a, b))$ zamanda çalışır. En kötü durum ardışık Fibonacci sayılarının girdi olarak verilmesidir; örneğin $\gcd(13, 8) = \gcd(8, 5) = \gcd(5, 3) = \cdots = 1$.</p>

<h3 id="eulerin-totient-fonksiyonu">Euler’in Totient Fonksiyonu</h3>

<p>$\gcd(a, b) = 1$ ise $a$ ve $b$ <strong>aralarında asaldır</strong>. <strong>Euler’in Totient Fonksiyonu</strong> $\varphi(n)$, $1$’den $n$’e kadar $n$ ile aralarında asal olan sayıların adedini verir. Asal çarpanlardan hesaplama formülü:</p>

\[\varphi(n) = \prod_{i=1}^{k} p_i^{\alpha_i - 1}(p_i - 1)\]

<p>Örneğin $\varphi(12) = 2^1 \cdot (2-1) \cdot 3^0 \cdot (3-1) = 4$. $n$ asal ise $\varphi(n) = n - 1$.</p>

<h2 id="212-modüler-aritmetik">21.2 Modüler Aritmetik</h2>

<p>Modüler aritmetikte sayılar $0, 1, 2, \ldots, m-1$ aralığına sıkıştırılır; her $x$ sayısı $x \bmod m$ ile temsil edilir. Temel işlem özellikleri:</p>

\[\begin{aligned}
(x + y) \bmod m &amp;= (x \bmod m + y \bmod m) \bmod m \\
(x - y) \bmod m &amp;= (x \bmod m - y \bmod m) \bmod m \\
(x \cdot y) \bmod m &amp;= (x \bmod m \cdot y \bmod m) \bmod m \\
x^n \bmod m &amp;= (x \bmod m)^n \bmod m
\end{aligned}\]

<h3 id="modüler-üs-alma">Modüler Üs Alma</h3>

<p>$x^n \bmod m$ değerini $O(\log n)$ zamanda hesaplamak için hızlı kuvvet alma kullanılır:</p>

\[x^n = \begin{cases} 1 &amp; n = 0 \\ x^{n/2} \cdot x^{n/2} &amp; n \text{ çift} \\ x^{n-1} \cdot x &amp; n \text{ tek} \end{cases}\]

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">modpow</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">,</span> <span class="kt">int</span> <span class="n">m</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="mi">1</span> <span class="o">%</span> <span class="n">m</span><span class="p">;</span>
    <span class="kt">long</span> <span class="kt">long</span> <span class="n">u</span> <span class="o">=</span> <span class="n">modpow</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">2</span><span class="p">,</span> <span class="n">m</span><span class="p">);</span>
    <span class="n">u</span> <span class="o">=</span> <span class="p">(</span><span class="n">u</span> <span class="o">*</span> <span class="n">u</span><span class="p">)</span> <span class="o">%</span> <span class="n">m</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="n">u</span> <span class="o">=</span> <span class="p">(</span><span class="n">u</span> <span class="o">*</span> <span class="n">x</span><span class="p">)</span> <span class="o">%</span> <span class="n">m</span><span class="p">;</span>
    <span class="k">return</span> <span class="n">u</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="fermatın-teoremi-ve-eulerin-teoremi">Fermat’ın Teoremi ve Euler’in Teoremi</h3>

<p>$m$ asal ve $\gcd(x, m) = 1$ iken <strong>Fermat’ın Küçük Teoremi</strong>:</p>

\[x^{m-1} \bmod m = 1\]

<p>Bu aynı zamanda $x^k \bmod m = x^{k \bmod (m-1)} \bmod m$ bağıntısını verir. Daha genel haliyle <strong>Euler’in Teoremi</strong>, $\gcd(x, m) = 1$ iken:</p>

\[x^{\varphi(m)} \bmod m = 1\]

<p>Fermat’ın Teoremi bu sonucun $m$ asal olduğundaki özel durumudur çünkü $\varphi(m) = m - 1$.</p>

<h3 id="modüler-çarpımsal-ters">Modüler Çarpımsal Ters</h3>

<p>$x$ sayısının $m$ modülündeki <strong>çarpımsal tersi</strong> $x^{-1}$, şu koşulu sağlayan sayıdır:</p>

\[x \cdot x^{-1} \bmod m = 1\]

<p>Bu ters, $x$ ile $m$ aralarında asal olduğunda her zaman mevcuttur. Örneğin $x = 6$, $m = 17$ için $x^{-1} = 3$ çünkü $6 \cdot 3 \bmod 17 = 1$. Modüler ters, modüler aritmetikte bölme işlemini mümkün kılar: $x$’e bölmek $x^{-1}$ ile çarpmaya eşdeğerdir.</p>

<p>Euler’in Teoreminden çarpımsal ters şöyle türetilir:</p>

\[x^{-1} = x^{\varphi(m) - 1}\]

<p>$m$ asal ise $x^{-1} = x^{m-2}$ olur. <code class="language-plaintext highlighter-rouge">modpow</code> ile verimli hesaplanır:</p>

\[6^{-1} \bmod 17 = 6^{15} \bmod 17 = 3\]

<p><strong>C++ notu:</strong> <code class="language-plaintext highlighter-rouge">unsigned int</code> türü $2^{32}$ ile doğal sarılma yapar; bu özellik bilinçli olarak modüler aritmetik hesaplamalarda kullanılabilir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">123456789</span><span class="p">;</span>
<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">x</span> <span class="o">*</span> <span class="n">x</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>  <span class="c1">// 123456789^2 mod 2^32 = 2537071545</span>
</code></pre></div></div>

<h2 id="213-eşitlikleri-çözmek">21.3 Eşitlikleri Çözmek</h2>

<h3 id="diyofantus-eşitlikleri">Diyofantus Eşitlikleri</h3>

<p><strong>Diyofantus eşitliği</strong>, tam sayı çözüm aranan $ax + by = c$ biçimindeki denklemdir. Çözülebilmesi için gerekli ve yeterli koşul $\gcd(a, b) \mid c$’dir.</p>

<p>Çözüm <strong>genişletilmiş Öklid algoritması</strong> ile bulunur: önce $ax + by = \gcd(a, b)$ formu çözülür, ardından $c / \gcd(a, b)$ ile ölçeklenir.</p>

<p><strong>Örnek:</strong> $39x + 15y = 12$. $\gcd(39, 15) = 3$ ve $3 \mid 12$ olduğundan çözülebilir. Öklid adımları:</p>

\[39 - 2 \cdot 15 = 9, \quad 15 - 1 \cdot 9 = 6, \quad 9 - 1 \cdot 6 = 3\]

<p>Geri izleyerek $39 \cdot 2 + 15 \cdot (-5) = 3$ elde edilir; $4$ ile çarpılırsa:</p>

\[39 \cdot 8 + 15 \cdot (-20) = 12\]

<p>Bir çözüm bulunduğunda sonsuz çözüm elde edilir. $(x, y)$ bir çözümse, her tam sayı $k$ için şu çift de çözümdür:</p>

\[\left(x + \frac{kb}{\gcd(a,b)},\quad y - \frac{ka}{\gcd(a,b)}\right)\]

<h3 id="çin-kalan-teoremi">Çin Kalan Teoremi</h3>

<p><strong>Çin Kalan Teoremi (CRT)</strong>, ikili aralarında asal modüllere sahip eşitlik sistemini çözer:</p>

\[x \equiv a_1 \pmod{m_1}, \quad x \equiv a_2 \pmod{m_2}, \quad \ldots, \quad x \equiv a_n \pmod{m_n}\]

<p>$X_k = m_1 m_2 \cdots m_n / m_k$ ve $X_k^{-1}$, $X_k$’nın $m_k$ modülündeki çarpımsal tersi olmak üzere çözüm:</p>

\[x = a_1 X_1 X_1^{-1} + a_2 X_2 X_2^{-1} + \cdots + a_n X_n X_n^{-1}\]

<p><strong>Örnek:</strong></p>

\[x \equiv 3 \pmod{5}, \quad x \equiv 4 \pmod{7}, \quad x \equiv 2 \pmod{3}\]

\[x = 3 \cdot 21 \cdot 1 + 4 \cdot 15 \cdot 1 + 2 \cdot 35 \cdot 2 = 263\]

<p>Bir çözüm bulunduğunda $x + m_1 m_2 \cdots m_n$ biçimindeki tüm sayılar da çözümdür.</p>

<h2 id="214-diğer-sonuçlar">21.4 Diğer Sonuçlar</h2>

<h3 id="lagrangeın-teoremi">Lagrange’ın Teoremi</h3>

<p>Her pozitif tam sayı en fazla <strong>dört tam karenin toplamı</strong> olarak ifade edilebilir:</p>

\[n = a^2 + b^2 + c^2 + d^2\]

<p>Örneğin $123 = 8^2 + 5^2 + 5^2 + 3^2$.</p>

<h3 id="zeckendorfun-teoremi">Zeckendorf’un Teoremi</h3>

<p>Her pozitif tam sayı, birbirini takip etmeyen <strong>farklı Fibonacci sayılarının toplamı</strong> olarak tek türlü yazılabilir. Örneğin $74 = 55 + 13 + 5 + 1$.</p>

<h3 id="pisagor-üçlüleri">Pisagor Üçlüleri</h3>

<p>$a^2 + b^2 = c^2$ bağıntısını sağlayan $(a, b, c)$ tam sayı üçlüsüne <strong>Pisagor üçlüsü</strong> denir. $(a, b, c)$ Pisagor üçlüsüyse her $k &gt; 1$ için $(ka, kb, kc)$ de Pisagor üçlüsüdür. $a$, $b$ ve $c$ aralarında asal ise üçlü <strong>basittir</strong> (primitive). Tüm basit Pisagor üçlüleri <strong>Öklid’in formülü</strong> ile oluşturulur:</p>

\[\left(n^2 - m^2,\ 2nm,\ n^2 + m^2\right)\]

<p>Burada $0 &lt; m &lt; n$, $n$ ve $m$ aralarında asal ve en az biri çifttir. Örneğin $m = 1$, $n = 2$ için $(3, 4, 5)$ elde edilir.</p>

<h3 id="wilsonun-teoremi">Wilson’un Teoremi</h3>

<p>$n$ sayısı asal olmak ve ancak olmak üzere:</p>

\[(n-1)! \bmod n = n - 1\]

<p>Örneğin $10! \bmod 11 = 10$ olduğundan 11 asaldır; $11! \bmod 12 = 0 \neq 11$ olduğundan 12 asal değildir. Pratikte $(n-1)!$ büyük $n$ için hesaplanamaz; bu nedenle asal testi açısından teorik önemi büyük olsa da pratik kullanımı sınırlıdır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="sayılar-teorisi" /><category term="number-theory" /><category term="asal-sayı" /><category term="prime" /><category term="eratosten-kalburu" /><category term="sieve-of-eratosthenes" /><category term="öklid" /><category term="gcd" /><category term="lcm" /><category term="euler-totient" /><category term="modüler-aritmetik" /><category term="modular-exponentiation" /><category term="fermat" /><category term="çin-kalan-teoremi" /><category term="diyofantus" /><category term="pisagor" /><category term="wilson" /><category term="c" /><category term="programlama" /><category term="algoritma" /><category term="olimpiyat" /><category term="yarışma" /><category term="kodlama" /><category term="matematik" /><category term="kitap" /><summary type="html"><![CDATA[Sayılar teorisi, matematiğin tam sayılarla ilgilenen alt dalıdır. İlginç bir konudur; çünkü tam sayı içeren pek çok soru ilk bakışta kolay görünse de çözümü son derece zor olabilir. Örneğin $x^3 + y^3 + z^3 = 33$ eşitliğini sağlayan üç tam sayı bulmak hâlâ açık bir matematik problemidir. Bu bölümde sayılar teorisinin rekabetçi programlamada sık karşılaşılan temel kavramları ve algoritmaları ele alınmaktadır.]]></summary></entry></feed>