<?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://program.sonsuz.us/feed.xml" rel="self" type="application/atom+xml" /><link href="https://program.sonsuz.us/" rel="alternate" type="text/html" /><updated>2026-10-12T00:05:47+00:00</updated><id>https://program.sonsuz.us/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">Antik Dünyadan Rönesans’a: Caesar, Polybius ve Vigenère Şifreleri</title><link href="https://program.sonsuz.us/posts/antik-dunyadan-ronesansa-caesar-polybius-ve-vigen%C3%A8re-sifreleri/" rel="alternate" type="text/html" title="Antik Dünyadan Rönesans’a: Caesar, Polybius ve Vigenère Şifreleri" /><published>2026-10-11T00:00:00+00:00</published><updated>2026-10-11T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/antik-dunyadan-ronesansa-caesar-polybius-ve-vigen%C3%A8re-sifreleri</id><content type="html" xml:base="https://program.sonsuz.us/posts/antik-dunyadan-ronesansa-caesar-polybius-ve-vigen%C3%A8re-sifreleri/"><![CDATA[<p>Günümüzde şifreleme denince akla devasa asal sayılar ve karmaşık algoritmalar geliyor. Oysa kriptografinin temelleri, harfleri kaydırmak veya bir tabloya yerleştirmek kadar basit fikirlerle atıldı. Caesar, Polybius ve Vigenère şifreleri yalnızca tarihî merak konusu değildir; modern şifrelemenin neden anahtar, anahtar uzayı ve istatistiksel direnç gibi kavramlara ihtiyaç duyduğunu gösteren harika laboratuvarlardır.</p>

<p><img src="/img/antik-dunyadan-ronesansa-25.svg" alt="antik-dunyadan-ronesansa-25" /></p>

<p>``</p>
<h2 id="caesar-şifresi-alfabeyi-biraz-kaydıralım">Caesar şifresi: Alfabeyi biraz kaydıralım</h2>

<p>Adını Roma lideri Julius Caesar’dan alan bu yöntemin askerî yazışmalarda kullanıldığı anlatılır. Her harf, alfabede sabit miktarda ileri kaydırılır. Harfleri $0$ ile $25$ arasında numaralandırırsak şifreleme işlemi şöyle gösterilir:</p>

\[E_k(x) = (x + k) \bmod 26\]

<p>Şifreyi çözmek için kaydırma geri alınır:</p>

\[D_k(x) = (x - k) \bmod 26\]

<p>Örneğin $k=3$ olduğunda <code class="language-plaintext highlighter-rouge">ABC</code>, <code class="language-plaintext highlighter-rouge">DEF</code> olur. Fikir zarif olsa da yalnızca 26 olası anahtar vardır. Saldırgan bütün kaydırmaları deneyerek anlamlı sonucu birkaç saniyede bulabilir. Buna <strong>kaba kuvvet saldırısı</strong> denir. Uzun metinlerde en sık görülen harfi dildeki yaygın harflerle karşılaştıran frekans analizi de kullanılabilir.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">caesar</span><span class="p">(</span><span class="n">metin</span><span class="p">,</span> <span class="n">kaydirma</span><span class="p">):</span>
    <span class="n">sonuc</span> <span class="o">=</span> <span class="sh">""</span>
    <span class="k">for</span> <span class="n">karakter</span> <span class="ow">in</span> <span class="n">metin</span><span class="p">.</span><span class="nf">upper</span><span class="p">():</span>
        <span class="k">if</span> <span class="sh">"</span><span class="s">A</span><span class="sh">"</span> <span class="o">&lt;=</span> <span class="n">karakter</span> <span class="o">&lt;=</span> <span class="sh">"</span><span class="s">Z</span><span class="sh">"</span><span class="p">:</span>
            <span class="n">kod</span> <span class="o">=</span> <span class="p">(</span><span class="nf">ord</span><span class="p">(</span><span class="n">karakter</span><span class="p">)</span> <span class="o">-</span> <span class="nf">ord</span><span class="p">(</span><span class="sh">"</span><span class="s">A</span><span class="sh">"</span><span class="p">)</span> <span class="o">+</span> <span class="n">kaydirma</span><span class="p">)</span> <span class="o">%</span> <span class="mi">26</span>
            <span class="n">sonuc</span> <span class="o">+=</span> <span class="nf">chr</span><span class="p">(</span><span class="n">kod</span> <span class="o">+</span> <span class="nf">ord</span><span class="p">(</span><span class="sh">"</span><span class="s">A</span><span class="sh">"</span><span class="p">))</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">sonuc</span> <span class="o">+=</span> <span class="n">karakter</span>
    <span class="k">return</span> <span class="n">sonuc</span>

<span class="nf">print</span><span class="p">(</span><span class="nf">caesar</span><span class="p">(</span><span class="sh">"</span><span class="s">KRIPTOGRAFI</span><span class="sh">"</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span>
</code></pre></div></div>

<p>Bu kod, yalnızca Latin alfabesindeki harfleri kaydırır; boşluk ve noktalama işaretlerini korur. Negatif kaydırma verilerek şifre çözme işlemi de yapılabilir.</p>

<h2 id="polybius-karesi-harfler-koordinata-dönüşüyor">Polybius karesi: Harfler koordinata dönüşüyor</h2>

<p>MÖ 2. yüzyılda yaşamış Yunan tarihçi Polybius, karakterleri bir tablo üzerindeki koordinatlarla temsil etti. Klasik $5 \times 5$ karede I ve J aynı hücreyi paylaşır. Örneğin A <code class="language-plaintext highlighter-rouge">11</code>, B <code class="language-plaintext highlighter-rouge">12</code>, F ise <code class="language-plaintext highlighter-rouge">21</code> olarak yazılır.</p>

<p>Bu yaklaşımın önemli özelliği, harfleri sayısal çiftlere dönüştürmesidir. Böylece mesajlar meşale, ses veya işaret kombinasyonlarıyla iletilebilir. Ancak standart kare gizli değilse saldırgan koordinatları doğrudan geri çevirebilir. Karışık anahtarlı bir alfabe kullanılsa bile tek bir harf daima aynı çifte dönüştüğü için frekans analizi hâlâ etkilidir.</p>

<h2 id="vigenère-tek-kaydırma-yetmezse">Vigenère: Tek kaydırma yetmezse</h2>

<ol>
  <li>yüzyılda Blaise de Vigenère ile özdeşleşen bu yöntem, tekrar eden bir anahtar kelime kullanarak her karaktere farklı Caesar kaydırması uygular. Matematiksel olarak:</li>
</ol>

\[C_i = (P_i + K_i) \bmod 26\]

<p><code class="language-plaintext highlighter-rouge">ANAHTAR</code> gibi bir anahtar, mesaj uzunluğunca tekrarlanır. Böylece aynı düz metin harfi farklı konumlarda farklı şifreli harflere dönüşebilir. Bu nedenle Vigenère uzun süre <strong>çözülemez şifre</strong> olarak ün kazandı.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">vigenere_sifrele</span><span class="p">(</span><span class="n">metin</span><span class="p">,</span> <span class="n">anahtar</span><span class="p">):</span>
    <span class="n">metin</span> <span class="o">=</span> <span class="n">metin</span><span class="p">.</span><span class="nf">upper</span><span class="p">()</span>
    <span class="n">anahtar</span> <span class="o">=</span> <span class="n">anahtar</span><span class="p">.</span><span class="nf">upper</span><span class="p">()</span>
    <span class="n">sonuc</span><span class="p">,</span> <span class="n">sira</span> <span class="o">=</span> <span class="sh">""</span><span class="p">,</span> <span class="mi">0</span>

    <span class="k">for</span> <span class="n">harf</span> <span class="ow">in</span> <span class="n">metin</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">harf</span><span class="p">.</span><span class="nf">isalpha</span><span class="p">()</span> <span class="ow">and</span> <span class="sh">"</span><span class="s">A</span><span class="sh">"</span> <span class="o">&lt;=</span> <span class="n">harf</span> <span class="o">&lt;=</span> <span class="sh">"</span><span class="s">Z</span><span class="sh">"</span><span class="p">:</span>
            <span class="n">kaydirma</span> <span class="o">=</span> <span class="nf">ord</span><span class="p">(</span><span class="n">anahtar</span><span class="p">[</span><span class="n">sira</span> <span class="o">%</span> <span class="nf">len</span><span class="p">(</span><span class="n">anahtar</span><span class="p">)])</span> <span class="o">-</span> <span class="nf">ord</span><span class="p">(</span><span class="sh">"</span><span class="s">A</span><span class="sh">"</span><span class="p">)</span>
            <span class="n">sonuc</span> <span class="o">+=</span> <span class="nf">chr</span><span class="p">((</span><span class="nf">ord</span><span class="p">(</span><span class="n">harf</span><span class="p">)</span> <span class="o">-</span> <span class="nf">ord</span><span class="p">(</span><span class="sh">"</span><span class="s">A</span><span class="sh">"</span><span class="p">)</span> <span class="o">+</span> <span class="n">kaydirma</span><span class="p">)</span> <span class="o">%</span> <span class="mi">26</span> <span class="o">+</span> <span class="nf">ord</span><span class="p">(</span><span class="sh">"</span><span class="s">A</span><span class="sh">"</span><span class="p">))</span>
            <span class="n">sira</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">sonuc</span> <span class="o">+=</span> <span class="n">harf</span>
    <span class="k">return</span> <span class="n">sonuc</span>
</code></pre></div></div>

<p>Şifrenin zayıf noktası anahtarın tekrarlanmasıdır. <strong>Kasiski incelemesi</strong>, şifreli metindeki yinelenen diziler arasındaki uzaklıkları ölçerek muhtemel anahtar uzunluğunu bulur. Friedman testi ise harflerin çakışma olasılığından yararlanır. Uzunluk belirlendikten sonra metin sütunlara ayrılır ve her sütun ayrı bir Caesar şifresi gibi frekans analiziyle çözülür.</p>

<h2 id="hızlı-karşılaştırma">Hızlı karşılaştırma</h2>

<table>
  <thead>
    <tr>
      <th>Teknik</th>
      <th>Temel fikir</th>
      <th style="text-align: right">Anahtar uzayı</th>
      <th>Başlıca kırılma yöntemi</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Caesar</td>
      <td>Sabit harf kaydırma</td>
      <td style="text-align: right">Çok küçük</td>
      <td>Kaba kuvvet, frekans analizi</td>
    </tr>
    <tr>
      <td>Polybius</td>
      <td>Harfi koordinata çevirme</td>
      <td style="text-align: right">Kare düzenine bağlı</td>
      <td>Eşleme ve frekans analizi</td>
    </tr>
    <tr>
      <td>Vigenère</td>
      <td>Tekrarlanan çoklu kaydırma</td>
      <td style="text-align: right">Anahtara bağlı</td>
      <td>Kasiski, Friedman, frekans analizi</td>
    </tr>
  </tbody>
</table>

<p>Bu üç yöntem bize önemli bir ders verir: Bir algoritmanın karmaşık görünmesi güvenli olduğu anlamına gelmez. Küçük anahtar uzayı, tekrar eden desenler ve dilin istatistiksel yapısı saldırgana ipucu verir. Yine de bu klasikler, modern kriptografideki saldırı modelini anlamak ve kendi şifre analiz araçlarımızı geliştirmek için vazgeçilmez başlangıç noktalarıdır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="kriptografi" /><category term="caesar" /><category term="polybius" /><category term="vigenère" /><category term="şifreleme" /><category term="siber güvenlik" /><summary type="html"><![CDATA[Günümüzde şifreleme denince akla devasa asal sayılar ve karmaşık algoritmalar geliyor. Oysa kriptografinin temelleri, harfleri kaydırmak veya bir tabloya yerleştirmek kadar basit fikirlerle atıldı. Caesar, Polybius ve Vigenère şifreleri yalnızca tarihî merak konusu değildir; modern şifrelemenin neden anahtar, anahtar uzayı ve istatistiksel direnç gibi kavramlara ihtiyaç duyduğunu gösteren harika laboratuvarlardır.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/antik-dunyadan-ronesansa-25.png" /><media:content medium="image" url="https://program.sonsuz.us/img/antik-dunyadan-ronesansa-25.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Armstrong Sayıları: Basamaklardan Doğan Matematiksel Sihir</title><link href="https://program.sonsuz.us/posts/armstrong-sayilari-basamaklardan-dogan-matematiksel-sihir/" rel="alternate" type="text/html" title="Armstrong Sayıları: Basamaklardan Doğan Matematiksel Sihir" /><published>2026-10-11T00:00:00+00:00</published><updated>2026-10-11T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/armstrong-sayilari-basamaklardan-dogan-matematiksel-sihir</id><content type="html" xml:base="https://program.sonsuz.us/posts/armstrong-sayilari-basamaklardan-dogan-matematiksel-sihir/"><![CDATA[<p>Bazı sayılar sıradan görünürken basamaklarına ayrıldıklarında küçük bir matematik gösterisi yapar. Armstrong sayıları da tam olarak bu gruptadır: Her basamağın belirli bir kuvvetini alıp topladığımızda sayının kendisine geri döneriz. Bu özellik hem basamak işlemlerini öğrenmek hem de döngü, fonksiyon ve algoritma karmaşıklığı pratiği yapmak için harika bir bahanedir.
``
Bir sayının Armstrong sayısı olup olmadığını anlamadan önce tanımı netleştirelim. Pozitif bir $n$ sayısının basamak sayısı $k$ ve basamakları $d_1,d_2,\ldots,d_k$ olsun. Eğer</p>

\[n = \sum_{i=1}^{k} d_i^k\]

<p>eşitliği sağlanıyorsa bu sayı bir Armstrong sayısıdır. Bu sayılara <strong>narsistik sayılar</strong> da denir. Buradaki önemli ayrıntı, her basamağın kuvvetinin sayının toplam basamak sayısına eşit olmasıdır.</p>

<p>Örneğin $153$ üç basamaklıdır. Dolayısıyla her basamağın üçüncü kuvveti alınır:</p>

\[1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153\]

<p>Sonuç yine $153$ olduğundan sayı Armstrong özelliği taşır. Buna karşılık $123$ için aynı işlem $1+8+27=36$ sonucunu verir; yani sihir gerçekleşmez.</p>

<table>
  <thead>
    <tr>
      <th style="text-align: right">Sayı</th>
      <th style="text-align: right">Basamak sayısı</th>
      <th style="text-align: right">Kuvvetler toplamı</th>
      <th style="text-align: center">Armstrong mı?</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: right">153</td>
      <td style="text-align: right">3</td>
      <td style="text-align: right">$1^3+5^3+3^3=153$</td>
      <td style="text-align: center">Evet</td>
    </tr>
    <tr>
      <td style="text-align: right">370</td>
      <td style="text-align: right">3</td>
      <td style="text-align: right">$3^3+7^3+0^3=370$</td>
      <td style="text-align: center">Evet</td>
    </tr>
    <tr>
      <td style="text-align: right">9474</td>
      <td style="text-align: right">4</td>
      <td style="text-align: right">$9^4+4^4+7^4+4^4=9474$</td>
      <td style="text-align: center">Evet</td>
    </tr>
    <tr>
      <td style="text-align: right">123</td>
      <td style="text-align: right">3</td>
      <td style="text-align: right">$1^3+2^3+3^3=36$</td>
      <td style="text-align: center">Hayır</td>
    </tr>
  </tbody>
</table>

<h2 id="python-ile-tek-sayı-kontrolü">Python ile tek sayı kontrolü</h2>

<p>Sayıyı metne dönüştürmek, basamaklara erişmenin en okunabilir yollarından biridir:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">armstrong_mu</span><span class="p">(</span><span class="n">sayi</span><span class="p">):</span>
    <span class="n">basamaklar</span> <span class="o">=</span> <span class="nf">str</span><span class="p">(</span><span class="n">sayi</span><span class="p">)</span>
    <span class="n">kuvvet</span> <span class="o">=</span> <span class="nf">len</span><span class="p">(</span><span class="n">basamaklar</span><span class="p">)</span>

    <span class="n">toplam</span> <span class="o">=</span> <span class="nf">sum</span><span class="p">(</span><span class="nf">int</span><span class="p">(</span><span class="n">basamak</span><span class="p">)</span> <span class="o">**</span> <span class="n">kuvvet</span>
                 <span class="k">for</span> <span class="n">basamak</span> <span class="ow">in</span> <span class="n">basamaklar</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">toplam</span> <span class="o">==</span> <span class="n">sayi</span>

<span class="k">for</span> <span class="n">sayi</span> <span class="ow">in</span> <span class="p">[</span><span class="mi">153</span><span class="p">,</span> <span class="mi">123</span><span class="p">,</span> <span class="mi">370</span><span class="p">,</span> <span class="mi">9474</span><span class="p">]:</span>
    <span class="nf">print</span><span class="p">(</span><span class="n">sayi</span><span class="p">,</span> <span class="nf">armstrong_mu</span><span class="p">(</span><span class="n">sayi</span><span class="p">))</span>
</code></pre></div></div>

<p>Fonksiyon önce basamak sayısını belirler. Ardından her karakteri tekrar tam sayıya çevirir, uygun kuvveti hesaplar ve sonuçları toplar. Son satırda toplam ile başlangıçtaki sayı karşılaştırılır. Böylece kontrol mantığı yeniden kullanılabilir küçük bir fonksiyona dönüşür.</p>

<p>Metin dönüşümü kullanmadan, yalnızca aritmetik işlemlerle de basamakları ayırabiliriz. $n \bmod 10$ son basamağı verirken, $n // 10$ son basamağı sayıdan çıkarır:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">aralikta_armstrong</span><span class="p">(</span><span class="n">baslangic</span><span class="p">,</span> <span class="n">bitis</span><span class="p">):</span>
    <span class="n">bulunanlar</span> <span class="o">=</span> <span class="p">[]</span>

    <span class="k">for</span> <span class="n">sayi</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">baslangic</span><span class="p">,</span> <span class="n">bitis</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
        <span class="n">kuvvet</span> <span class="o">=</span> <span class="nf">len</span><span class="p">(</span><span class="nf">str</span><span class="p">(</span><span class="n">sayi</span><span class="p">))</span>
        <span class="n">gecici</span> <span class="o">=</span> <span class="n">sayi</span>
        <span class="n">toplam</span> <span class="o">=</span> <span class="mi">0</span>

        <span class="k">while</span> <span class="n">gecici</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">basamak</span> <span class="o">=</span> <span class="n">gecici</span> <span class="o">%</span> <span class="mi">10</span>
            <span class="n">toplam</span> <span class="o">+=</span> <span class="n">basamak</span> <span class="o">**</span> <span class="n">kuvvet</span>
            <span class="n">gecici</span> <span class="o">//=</span> <span class="mi">10</span>

        <span class="k">if</span> <span class="n">toplam</span> <span class="o">==</span> <span class="n">sayi</span><span class="p">:</span>
            <span class="n">bulunanlar</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">sayi</span><span class="p">)</span>

    <span class="k">return</span> <span class="n">bulunanlar</span>

<span class="nf">print</span><span class="p">(</span><span class="nf">aralikta_armstrong</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">10000</span><span class="p">))</span>
</code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">gecici</code> değişkeni önemlidir; doğrudan <code class="language-plaintext highlighter-rouge">sayi</code> üzerinde bölme yapsaydık karşılaştıracağımız özgün değeri kaybederdik. Algoritma, verilen aralıktaki her sayıyı tek tek inceler.</p>

<h2 id="karmaşıklık-ve-optimizasyon">Karmaşıklık ve optimizasyon</h2>

<p>Üst sınır $N$, sayıların ortalama basamak sayısı da $k$ ise yaklaşık zaman karmaşıklığı $O(Nk)$ olur. Küçük aralıklarda bu son derece yeterlidir. Daha büyük aramalarda $0^k$ ile $9^k$ arasındaki sonuçları önceden bir tabloda saklamak, aynı kuvvet hesaplarını tekrar yapmayı önler.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Avantaj</th>
      <th>Dezavantaj</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Metne dönüştürme</td>
      <td>Kısa ve okunabilir</td>
      <td>Karakter dönüşümü yapar</td>
    </tr>
    <tr>
      <td>Mod ve bölme</td>
      <td>Sayısal mantığı öğretir</td>
      <td>Biraz daha uzun kodlanır</td>
    </tr>
    <tr>
      <td>Kuvvetleri önbellekleme</td>
      <td>Büyük aralıklarda hız kazandırır</td>
      <td>Ek hazırlık ve bellek ister</td>
    </tr>
  </tbody>
</table>

<p>Aynı şablon; mutlu sayılar, mükemmel sayılar ve rakamları toplamına bölünebilen Harshad sayıları gibi özel sayı problemlerine de uyarlanabilir. Değişen şey çoğunlukla basamaklara uygulanan kuraldır. Kısacası Armstrong sayıları yalnızca matematiksel bir merak değil, problemi parçalama ve temiz fonksiyon tasarlama konusunda eğlenceli bir algoritma laboratuvarıdır.</p>

<p><img src="/img/armstrong-sayilari-basamaklardan-27.svg" alt="armstrong-sayilari-basamaklardan-27" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="armstrong sayıları" /><category term="python" /><category term="algoritma" /><category term="matematik" /><category term="basamak işlemleri" /><category term="özel sayılar" /><summary type="html"><![CDATA[Bazı sayılar sıradan görünürken basamaklarına ayrıldıklarında küçük bir matematik gösterisi yapar. Armstrong sayıları da tam olarak bu gruptadır: Her basamağın belirli bir kuvvetini alıp topladığımızda sayının kendisine geri döneriz. Bu özellik hem basamak işlemlerini öğrenmek hem de döngü, fonksiyon ve algoritma karmaşıklığı pratiği yapmak için harika bir bahanedir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/armstrong-sayilari-basamaklardan-27.png" /><media:content medium="image" url="https://program.sonsuz.us/img/armstrong-sayilari-basamaklardan-27.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Bölünebilme Kurallarının Ardındaki Matematik: Kalanlarla Hızlı Hesap</title><link href="https://program.sonsuz.us/posts/bolunebilme-kurallarinin-ardindaki-matematik-kalanlarla-hizli-hesap/" rel="alternate" type="text/html" title="Bölünebilme Kurallarının Ardındaki Matematik: Kalanlarla Hızlı Hesap" /><published>2026-10-11T00:00:00+00:00</published><updated>2026-10-11T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/bolunebilme-kurallarinin-ardindaki-matematik-kalanlarla-hizli-hesap</id><content type="html" xml:base="https://program.sonsuz.us/posts/bolunebilme-kurallarinin-ardindaki-matematik-kalanlarla-hizli-hesap/"><![CDATA[<p>Uzun bir sayının 3’e, 7’ye veya 11’e tam bölünüp bölünmediğini anlamak için hemen hesap makinesine uzanmanız gerekmez. Bölünebilme kuralları sihirli kestirmeler gibi görünse de aslında basamak değerleri ve kalanlar üzerine kuruludur. Gelin, ezberlenen kuralların matematik motorunun kapağını açalım.</p>

<p><img src="/img/bolunebilme-kurallarinin-ardindaki-13.svg" alt="bolunebilme-kurallarinin-ardindaki-13" /></p>

<p>``</p>

<h2 id="bölünebilmek-ne-demektir">Bölünebilmek ne demektir?</h2>

<p>Bir $N$ tam sayısı, $d$ sayısına bölündüğünde kalan sıfırsa $d$ ile tam bölünür. Modüler aritmetik dilinde bunu şöyle yazarız:</p>

\[N ≡ 0 \pmod d\]

<p>Örneğin $42 ≡ 0 \pmod 7$ olduğundan 42, 7’ye tam bölünür. Bir sayının ondalık gösterimi ise basamak değerleri kullanılarak açılabilir:</p>

\[N = a_0 + 10a_1 + 10^2a_2 + \cdots + 10^ka_k\]

<p>Bölünebilme kuralları, buradaki $10$, $100$ ve diğer kuvvetlerin ilgili bölen karşısındaki kalanlarını kullanır. Yani mesele rakamları rastgele toplamak değil, onluk sistemin davranışını değerlendirmektir.</p>

<h2 id="yaygın-kurallar-ve-nedenleri">Yaygın kurallar ve nedenleri</h2>

<table>
  <thead>
    <tr>
      <th style="text-align: right">Bölen</th>
      <th>Hızlı kontrol</th>
      <th>Matematiksel fikir</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: right">2</td>
      <td>Son rakam çifttir.</td>
      <td>$10 ≡ 0 \pmod 2$</td>
    </tr>
    <tr>
      <td style="text-align: right">3</td>
      <td>Rakamlar toplamı 3’ün katıdır.</td>
      <td>$10 ≡ 1 \pmod 3$</td>
    </tr>
    <tr>
      <td style="text-align: right">4</td>
      <td>Son iki basamak 4’ün katıdır.</td>
      <td>$100 ≡ 0 \pmod 4$</td>
    </tr>
    <tr>
      <td style="text-align: right">5</td>
      <td>Son rakam 0 veya 5’tir.</td>
      <td>Onun katlarının son basamağı belirleyicidir.</td>
    </tr>
    <tr>
      <td style="text-align: right">6</td>
      <td>Sayı hem 2’ye hem 3’e bölünür.</td>
      <td>$6 = 2 \times 3$ ve bölenler aralarında asaldır.</td>
    </tr>
    <tr>
      <td style="text-align: right">8</td>
      <td>Son üç basamak 8’in katıdır.</td>
      <td>$1000 ≡ 0 \pmod 8$</td>
    </tr>
    <tr>
      <td style="text-align: right">9</td>
      <td>Rakamlar toplamı 9’un katıdır.</td>
      <td>$10 ≡ 1 \pmod 9$</td>
    </tr>
    <tr>
      <td style="text-align: right">10</td>
      <td>Son rakam 0’dır.</td>
      <td>$10 ≡ 0 \pmod {10}$</td>
    </tr>
    <tr>
      <td style="text-align: right">11</td>
      <td>Tek ve çift sıralı rakam toplamlarının farkı 11’in katıdır.</td>
      <td>$10 ≡ -1 \pmod {11}$</td>
    </tr>
  </tbody>
</table>

<h3 id="neden-rakamları-topluyoruz">Neden rakamları topluyoruz?</h3>

<p>$5832$ sayısını ele alalım. Çünkü $10 ≡ 1 \pmod 3$ olduğundan, 10’un bütün pozitif kuvvetleri de 3’e göre 1 kalanını verir:</p>

\[5832 ≡ 5 + 8 + 3 + 2 = 18 ≡ 0 \pmod 3\]

<p>Dolayısıyla sayı 3’e bölünür. Aynı mantık 9 için de geçerlidir. Bu nedenle rakamlar toplamı yöntemi yalnızca pratik bir numara değil, basamak açılımının doğrudan sonucudur.</p>

<h2 id="11-kuralındaki-işaret-değiştirme">11 kuralındaki işaret değiştirme</h2>

<p>$10 ≡ -1 \pmod {11}$ olduğu için kuvvetler sırayla $1, -1, 1, -1$ biçiminde ilerler. Örneğin 2728 için dönüşümlü toplamı hesaplayalım:</p>

\[8 - 2 + 7 - 2 = 11\]

<p>Sonuç 11’in katı olduğu için 2728 de 11’e tam bölünür. Bir bakıma rakamlar matematiksel bir tahterevalliye oturur; denge 11’in katında kurulursa test başarıyla tamamlanır.</p>

<h2 id="peki-ya-7">Peki ya 7?</h2>

<p>7 kuralı biraz daha afacan görünür: Son rakamın iki katını, kalan sayıdan çıkarın. Elde edilen sonuç 7’nin katıysa başlangıçtaki sayı da 7’nin katıdır. Örneğin 203 için:</p>

\[20 - 2 \times 3 = 14\]

<p>14, 7’ye bölündüğünden 203 de bölünür. Bu işlem gerekirse sonuç küçülene kadar tekrarlanabilir.</p>

<h2 id="kuralları-kodlamak">Kuralları kodlamak</h2>

<p>Aşağıdaki Python fonksiyonu, seçilen bölen için anlaşılır kontroller uygular. Böylece kuralların bir algoritmaya nasıl dönüştüğünü görebiliriz:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">bolunur_mu</span><span class="p">(</span><span class="n">sayi</span><span class="p">,</span> <span class="n">bolen</span><span class="p">):</span>
    <span class="n">rakamlar</span> <span class="o">=</span> <span class="p">[</span><span class="nf">int</span><span class="p">(</span><span class="n">rakam</span><span class="p">)</span> <span class="k">for</span> <span class="n">rakam</span> <span class="ow">in</span> <span class="nf">str</span><span class="p">(</span><span class="nf">abs</span><span class="p">(</span><span class="n">sayi</span><span class="p">))]</span>

    <span class="k">if</span> <span class="n">bolen</span> <span class="ow">in</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">9</span><span class="p">):</span>
        <span class="k">return</span> <span class="nf">sum</span><span class="p">(</span><span class="n">rakamlar</span><span class="p">)</span> <span class="o">%</span> <span class="n">bolen</span> <span class="o">==</span> <span class="mi">0</span>
    <span class="k">if</span> <span class="n">bolen</span> <span class="o">==</span> <span class="mi">4</span><span class="p">:</span>
        <span class="k">return</span> <span class="nf">abs</span><span class="p">(</span><span class="n">sayi</span><span class="p">)</span> <span class="o">%</span> <span class="mi">100</span> <span class="o">%</span> <span class="mi">4</span> <span class="o">==</span> <span class="mi">0</span>
    <span class="k">if</span> <span class="n">bolen</span> <span class="o">==</span> <span class="mi">8</span><span class="p">:</span>
        <span class="k">return</span> <span class="nf">abs</span><span class="p">(</span><span class="n">sayi</span><span class="p">)</span> <span class="o">%</span> <span class="mi">1000</span> <span class="o">%</span> <span class="mi">8</span> <span class="o">==</span> <span class="mi">0</span>
    <span class="k">if</span> <span class="n">bolen</span> <span class="o">==</span> <span class="mi">11</span><span class="p">:</span>
        <span class="n">fark</span> <span class="o">=</span> <span class="nf">sum</span><span class="p">(</span><span class="n">rakamlar</span><span class="p">[::</span><span class="mi">2</span><span class="p">])</span> <span class="o">-</span> <span class="nf">sum</span><span class="p">(</span><span class="n">rakamlar</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="k">return</span> <span class="n">fark</span> <span class="o">%</span> <span class="mi">11</span> <span class="o">==</span> <span class="mi">0</span>

    <span class="k">return</span> <span class="n">sayi</span> <span class="o">%</span> <span class="n">bolen</span> <span class="o">==</span> <span class="mi">0</span>

<span class="nf">print</span><span class="p">(</span><span class="nf">bolunur_mu</span><span class="p">(</span><span class="mi">2728</span><span class="p">,</span> <span class="mi">11</span><span class="p">))</span>  <span class="c1"># True
</span></code></pre></div></div>

<p>Kod, 3 ve 9 için rakamları toplar; 4 ve 8 için yalnızca gerekli son basamakları inceler. Genel durumda ise doğrudan kalan operatörünü kullanır.</p>

<p>Bölünebilme kuralları, zihinden hesaplamayı hızlandırmanın ötesinde modüler aritmetiği somutlaştırır. Kuralları ezberlemek işe yarar; fakat neden çalıştıklarını bilmek, yeni bölenler için kendi yöntemlerinizi geliştirmenizi sağlar.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="matematik" /><category term="bölünebilme" /><category term="modüler aritmetik" /><category term="algoritma" /><category term="python" /><summary type="html"><![CDATA[Uzun bir sayının 3’e, 7’ye veya 11’e tam bölünüp bölünmediğini anlamak için hemen hesap makinesine uzanmanız gerekmez. Bölünebilme kuralları sihirli kestirmeler gibi görünse de aslında basamak değerleri ve kalanlar üzerine kuruludur. Gelin, ezberlenen kuralların matematik motorunun kapağını açalım.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/bolunebilme-kurallarinin-ardindaki-13.png" /><media:content medium="image" url="https://program.sonsuz.us/img/bolunebilme-kurallarinin-ardindaki-13.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Catalan Sayıları: Parantezlerden İkili Ağaçlara Uzanan Sayma Macerası</title><link href="https://program.sonsuz.us/posts/catalan-sayilari-parantezlerden-ikili-agaclara-uzanan-sayma-macerasi/" rel="alternate" type="text/html" title="Catalan Sayıları: Parantezlerden İkili Ağaçlara Uzanan Sayma Macerası" /><published>2026-10-11T00:00:00+00:00</published><updated>2026-10-11T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/catalan-sayilari-parantezlerden-ikili-agaclara-uzanan-sayma-macerasi</id><content type="html" xml:base="https://program.sonsuz.us/posts/catalan-sayilari-parantezlerden-ikili-agaclara-uzanan-sayma-macerasi/"><![CDATA[<p>Bazı sayı dizileri matematiğin gizli aktörleri gibidir: Farklı görünen problemlerde tekrar tekrar sahneye çıkarlar. Catalan sayıları da dengeli parantezlerden çokgenlere, ikili arama ağaçlarından dağ yollarına kadar şaşırtıcı sayıda yapıyı sayar. İlk terimleri $1, 1, 2, 5, 14, 42, 132$ olan bu dizi, “Kaç farklı geçerli yapı oluşturabilirim?” sorusunun en renkli cevaplarından biridir.
``</p>

<h2 id="catalan-sayısının-matematiksel-tanımı">Catalan sayısının matematiksel tanımı</h2>

<p>Sıfırıncı Catalan sayısı $C_0=1$ kabul edilir. Genel formül şöyledir:</p>

\[C_n = \frac{1}{n+1}\binom{2n}{n} = \frac{(2n)!}{(n+1)!n!}\]

<p>Buradaki merkezi binom katsayısı, $2n$ konum içinden $n$ tanesini seçer. Ancak seçilen her dizilim geçerli değildir. Örneğin açılan parantez sayısının hiçbir noktada kapanan parantez sayısından az olmaması gerekir. Formüldeki $n+1$ bölümü, bu geçersiz düzenlemeleri ayıklayan kombinatorik düzeltmedir.</p>

<p>Catalan sayıları özyinelemeli olarak da hesaplanabilir:</p>

\[C_{n+1}=\sum_{i=0}^{n} C_iC_{n-i}\]

<p>Bu bağıntının arkasındaki fikir bölüp birleştirmedir. Bir yapı kökünden iki parçaya ayrılıyorsa sol tarafta $i$, sağ tarafta $n-i$ eleman bulunabilir. Olasılıkların çarpılması ve bütün bölünmelerin toplanması Catalan sonucunu verir.</p>

<table>
  <thead>
    <tr>
      <th style="text-align: right">$n$</th>
      <th style="text-align: right">$C_n$</th>
      <th style="text-align: right">Dengeli parantez çifti sayısı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: right">0</td>
      <td style="text-align: right">1</td>
      <td style="text-align: right">Boş dizi</td>
    </tr>
    <tr>
      <td style="text-align: right">1</td>
      <td style="text-align: right">1</td>
      <td style="text-align: right"><code class="language-plaintext highlighter-rouge">()</code></td>
    </tr>
    <tr>
      <td style="text-align: right">2</td>
      <td style="text-align: right">2</td>
      <td style="text-align: right"><code class="language-plaintext highlighter-rouge">(())</code>, <code class="language-plaintext highlighter-rouge">()()</code></td>
    </tr>
    <tr>
      <td style="text-align: right">3</td>
      <td style="text-align: right">5</td>
      <td style="text-align: right">Beş farklı dizilim</td>
    </tr>
    <tr>
      <td style="text-align: right">4</td>
      <td style="text-align: right">14</td>
      <td style="text-align: right">On dört farklı dizilim</td>
    </tr>
  </tbody>
</table>

<h2 id="dengeli-parantezler-neden-catalan-sayısıdır">Dengeli parantezler neden Catalan sayısıdır?</h2>

<p>$n$ çift açma ve kapama parantezi içeren bir dizide toplam $2n$ karakter vardır. Geçerli bir dizilim iki kurala uyar:</p>

<ol>
  <li>Toplam açma ve kapama parantezi sayıları eşittir.</li>
  <li>Soldan sağa ilerlerken kapanan parantez sayısı, açılanlardan fazla olamaz.</li>
</ol>

<p>Örneğin <code class="language-plaintext highlighter-rouge">(()())</code> geçerliyken <code class="language-plaintext highlighter-rouge">())(()</code> geçersizdir. İkinci dizi toplamda eşit sayıda parantez içerse bile üçüncü karakterde henüz açılmamış bir parantezi kapatmaya çalışır. Matematik bile “Önce aç, sonra kapat!” der.</p>

<h2 id="i̇kili-ağaçlarla-bağlantısı">İkili ağaçlarla bağlantısı</h2>

<p>$n$ düğümlü farklı ikili ağaç biçimlerinin sayısı da $C_n$ değeridir. Kök düğümü seçtikten sonra kalan düğümler sol ve sağ alt ağaçlar arasında dağıtılır. Sol alt ağaçta $i$ düğüm varsa sağ tarafta $n-1-i$ düğüm bulunur.</p>

<table>
  <thead>
    <tr>
      <th>Problem</th>
      <th>Ayrıştırma biçimi</th>
      <th style="text-align: right">Sonuç</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Dengeli parantez</td>
      <td>Dış parantezin içi ve sonrası</td>
      <td style="text-align: right">$C_n$</td>
    </tr>
    <tr>
      <td>İkili ağaç</td>
      <td>Sol ve sağ alt ağaç</td>
      <td style="text-align: right">$C_n$</td>
    </tr>
    <tr>
      <td>Çokgen üçgenleme</td>
      <td>Seçilen üçgenin iki yanı</td>
      <td style="text-align: right">$C_{n-2}$</td>
    </tr>
    <tr>
      <td>Izgara yolu</td>
      <td>Köşegeni aşmayan yollar</td>
      <td style="text-align: right">$C_n$</td>
    </tr>
  </tbody>
</table>

<p>Aynı sayıların ortaya çıkmasının nedeni, bu problemlerin yüzeyde farklı olsa da aynı özyinelemeli bölünme yapısını taşımasıdır.</p>

<h2 id="python-ile-hesaplama">Python ile hesaplama</h2>

<p>Aşağıdaki dinamik programlama yaklaşımı, özyinelemeli bağıntıyı kullanır. <code class="language-plaintext highlighter-rouge">dp[k]</code>, $k$ boyutundaki yapıların sayısını saklar:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">catalan</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
    <span class="n">dp</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
    <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>

    <span class="k">for</span> <span class="n">boyut</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
        <span class="k">for</span> <span class="n">sol</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">boyut</span><span class="p">):</span>
            <span class="n">sag</span> <span class="o">=</span> <span class="n">boyut</span> <span class="o">-</span> <span class="mi">1</span> <span class="o">-</span> <span class="n">sol</span>
            <span class="n">dp</span><span class="p">[</span><span class="n">boyut</span><span class="p">]</span> <span class="o">+=</span> <span class="n">dp</span><span class="p">[</span><span class="n">sol</span><span class="p">]</span> <span class="o">*</span> <span class="n">dp</span><span class="p">[</span><span class="n">sag</span><span class="p">]</span>

    <span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="n">n</span><span class="p">]</span>

<span class="nf">print</span><span class="p">([</span><span class="nf">catalan</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="mi">8</span><span class="p">)])</span>
<span class="c1"># [1, 1, 2, 5, 14, 42, 132, 429]
</span></code></pre></div></div>

<p>Algoritmanın zaman karmaşıklığı $O(n^2)$, alan karmaşıklığı ise $O(n)$ olur. Yalnızca tek bir $C_n$ değeri gerekiyorsa faktöriyel formülü daha hızlı olabilir; dinamik programlama ise dizinin tüm ara terimlerini üretmek ve mantığı görmek için daha öğreticidir.</p>

<p>Catalan sayıları, farklı problemlerin ortak matematiksel iskeletini fark etmenin harika bir örneğidir. Bir soruda dengeli parantez, ikili ağaç, köşegeni aşmayan yol veya çokgen üçgenleme görürseniz, sahne arkasında bir Catalan sayısının kostümünü giymekte olabileceğini unutmayın.</p>

<p><img src="/img/catalan-sayilari-parantezlerden-39.svg" alt="catalan-sayilari-parantezlerden-39" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="catalan sayıları" /><category term="kombinatorik" /><category term="algoritma" /><category term="dinamik programlama" /><category term="ikili ağaç" /><category term="python" /><summary type="html"><![CDATA[Bazı sayı dizileri matematiğin gizli aktörleri gibidir: Farklı görünen problemlerde tekrar tekrar sahneye çıkarlar. Catalan sayıları da dengeli parantezlerden çokgenlere, ikili arama ağaçlarından dağ yollarına kadar şaşırtıcı sayıda yapıyı sayar. İlk terimleri $1, 1, 2, 5, 14, 42, 132$ olan bu dizi, “Kaç farklı geçerli yapı oluşturabilirim?” sorusunun en renkli cevaplarından biridir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/catalan-sayilari-parantezlerden-39.png" /><media:content medium="image" url="https://program.sonsuz.us/img/catalan-sayilari-parantezlerden-39.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Çinlilerin Kalan Teoremi: Parçalı Bilgiden Tek Bir Sayıya</title><link href="https://program.sonsuz.us/posts/cinlilerin-kalan-teoremi-parcali-bilgiden-tek-bir-sayiya/" rel="alternate" type="text/html" title="Çinlilerin Kalan Teoremi: Parçalı Bilgiden Tek Bir Sayıya" /><published>2026-10-11T00:00:00+00:00</published><updated>2026-10-11T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/cinlilerin-kalan-teoremi-parcali-bilgiden-tek-bir-sayiya</id><content type="html" xml:base="https://program.sonsuz.us/posts/cinlilerin-kalan-teoremi-parcali-bilgiden-tek-bir-sayiya/"><![CDATA[<p>Bir sayıyı doğrudan bilmiyor, fakat farklı sayılara bölündüğünde bıraktığı kalanları biliyor olabilirsiniz. İlk bakışta bu bilgiler ayrı yapboz parçaları gibi görünür. Çinlilerin Kalan Teoremi, modüller uygun olduğunda bütün parçaları birleştirerek tek ve tutarlı bir çözüm üretir. Üstelik bu çözüm yalnızca teorik bir merak değildir; kriptografi, takvim hesapları, paralel işlem ve bilgisayar aritmetiğinde karşımıza çıkar.</p>

<p>``</p>

<h2 id="temel-fikir-aynı-sayı-farklı-saatler">Temel fikir: Aynı sayı, farklı saatler</h2>

<p>Modüler aritmetiği farklı büyüklüklerde çalışan saatlere benzetebiliriz. Örneğin</p>

\[x \equiv 2 \pmod{3}\]

<p>ifadesi, $x$ sayısının 3’e bölündüğünde 2 kalanını verdiğini söyler. Benzer biçimde şu sistemi ele alalım:</p>

\[x \equiv 2 \pmod{3}, \qquad
x \equiv 3 \pmod{5}, \qquad
x \equiv 2 \pmod{7}\]

<p>Burada aynı $x$, üç farklı modüler saatte belirli konumlara gelmektedir. Modüller olan 3, 5 ve 7 ikişer ikişer aralarında asaldır. Yani her farklı çift için $\gcd(m_i,m_j)=1$ koşulu sağlanır.</p>

<p>Çinlilerin Kalan Teoremi şunu garanti eder: Modüller ikişer ikişer aralarında asalsa sistemin, modüllerin çarpımına göre tek bir çözüm sınıfı vardır.</p>

\[M=m_1m_2\cdots m_k\]

<p>Başka bir deyişle çözüm $M$ aralığında benzersizdir; fakat tam sayılarda sonsuz kez tekrar eder.</p>

<table>
  <thead>
    <tr>
      <th>Kavram</th>
      <th>Anlamı</th>
      <th style="text-align: right">Örnekteki değeri</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>$a_i$</td>
      <td>İstenen kalan</td>
      <td style="text-align: right">2, 3, 2</td>
    </tr>
    <tr>
      <td>$m_i$</td>
      <td>Modül</td>
      <td style="text-align: right">3, 5, 7</td>
    </tr>
    <tr>
      <td>$M$</td>
      <td>Tüm modüllerin çarpımı</td>
      <td style="text-align: right">105</td>
    </tr>
    <tr>
      <td>Çözüm sınıfı</td>
      <td>Eşdeğer bütün sayılar</td>
      <td style="text-align: right">$23+105k$</td>
    </tr>
  </tbody>
</table>

<h2 id="çözüm-nasıl-inşa-edilir">Çözüm nasıl inşa edilir?</h2>

<p>Her denklem için toplam çarpımdan ilgili modülü çıkaran bir parça oluşturulur:</p>

\[M_i=\frac{M}{m_i}\]

<p>Ardından $M_i$ sayısının $m_i$ modülündeki çarpımsal tersi bulunur. Bu ters $y_i$ ile gösterilirse</p>

\[M_i y_i \equiv 1 \pmod{m_i}\]

<p>olmalıdır. Son çözüm şu formülle birleştirilir:</p>

\[x \equiv \sum_{i=1}^{k} a_iM_iy_i \pmod{M}\]

<p>Örneğimizde $M=105$ olur. Parçalar sırasıyla 35, 21 ve 15’tir. Bunların ilgili modüllerdeki tersleri 2, 1 ve 1 olarak bulunur. Dolayısıyla</p>

\[x \equiv 2\cdot35\cdot2+3\cdot21\cdot1+2\cdot15\cdot1=233 \pmod{105}\]

<p>elde edilir. $233$ sayısının 105’e göre kalanı 23 olduğundan en küçük pozitif çözüm $x=23$’tür. Gerçekten de 23; 3’e bölününce 2, 5’e bölününce 3 ve 7’ye bölününce 2 kalanını verir.</p>

<h2 id="python-ile-genel-çözüm">Python ile genel çözüm</h2>

<p>Aşağıdaki fonksiyon, modüllerin bağımsızlığını kontrol eder ve yapıcı formülü uygular. <code class="language-plaintext highlighter-rouge">pow(Mi, -1, mi)</code> ifadesi Python’da modüler tersi hesaplar.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="n">math</span> <span class="kn">import</span> <span class="n">gcd</span><span class="p">,</span> <span class="n">prod</span>

<span class="k">def</span> <span class="nf">crt</span><span class="p">(</span><span class="n">kalanlar</span><span class="p">,</span> <span class="n">moduller</span><span class="p">):</span>
    <span class="c1"># Modüllerin ikişer ikişer aralarında asal olduğunu doğrula.
</span>    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="nf">len</span><span class="p">(</span><span class="n">moduller</span><span class="p">)):</span>
        <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nf">len</span><span class="p">(</span><span class="n">moduller</span><span class="p">)):</span>
            <span class="k">if</span> <span class="nf">gcd</span><span class="p">(</span><span class="n">moduller</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">moduller</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">:</span>
                <span class="k">raise</span> <span class="nc">ValueError</span><span class="p">(</span><span class="sh">'</span><span class="s">Modüller aralarında asal değil</span><span class="sh">'</span><span class="p">)</span>

    <span class="n">M</span> <span class="o">=</span> <span class="nf">prod</span><span class="p">(</span><span class="n">moduller</span><span class="p">)</span>
    <span class="n">toplam</span> <span class="o">=</span> <span class="mi">0</span>

    <span class="k">for</span> <span class="n">ai</span><span class="p">,</span> <span class="n">mi</span> <span class="ow">in</span> <span class="nf">zip</span><span class="p">(</span><span class="n">kalanlar</span><span class="p">,</span> <span class="n">moduller</span><span class="p">):</span>
        <span class="n">Mi</span> <span class="o">=</span> <span class="n">M</span> <span class="o">//</span> <span class="n">mi</span>
        <span class="n">ters</span> <span class="o">=</span> <span class="nf">pow</span><span class="p">(</span><span class="n">Mi</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">mi</span><span class="p">)</span>
        <span class="n">toplam</span> <span class="o">+=</span> <span class="n">ai</span> <span class="o">*</span> <span class="n">Mi</span> <span class="o">*</span> <span class="n">ters</span>

    <span class="k">return</span> <span class="n">toplam</span> <span class="o">%</span> <span class="n">M</span><span class="p">,</span> <span class="n">M</span>

<span class="n">cozum</span><span class="p">,</span> <span class="n">periyot</span> <span class="o">=</span> <span class="nf">crt</span><span class="p">([</span><span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">],</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">7</span><span class="p">])</span>
<span class="nf">print</span><span class="p">(</span><span class="n">cozum</span><span class="p">,</span> <span class="n">periyot</span><span class="p">)</span>  <span class="c1"># 23 105
</span></code></pre></div></div>

<p>Fonksiyon <code class="language-plaintext highlighter-rouge">(23, 105)</code> döndürür. Bu sonuç yalnızca 23’ü değil, $x=23+105k$ biçimindeki bütün çözümleri temsil eder.</p>

<h2 id="modüller-aralarında-asal-değilse">Modüller aralarında asal değilse</h2>

<p>Teoremin klasik biçimi doğrudan uygulanamaz; ancak sistem mutlaka çözümsüz değildir. İki denklem için kalanların $\gcd(m_1,m_2)$ modülünde uyumlu olması gerekir. Örneğin $x\equiv1\pmod4$ ve $x\equiv3\pmod6$ sistemi uyumludur; fakat $x\equiv1\pmod4$ ve $x\equiv2\pmod6$ değildir. Kısacası CRT, farklı modüler dünyaların aynı sayıda buluşabilmesi için güçlü ve zarif bir köprü kurar.</p>

<p><img src="/img/cinlilerin-kalan-teoremi-86.svg" alt="cinlilerin-kalan-teoremi-86" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="çinlilerin kalan teoremi" /><category term="modüler aritmetik" /><category term="sayı teorisi" /><category term="matematik" /><category term="python" /><category term="algoritma" /><summary type="html"><![CDATA[Bir sayıyı doğrudan bilmiyor, fakat farklı sayılara bölündüğünde bıraktığı kalanları biliyor olabilirsiniz. İlk bakışta bu bilgiler ayrı yapboz parçaları gibi görünür. Çinlilerin Kalan Teoremi, modüller uygun olduğunda bütün parçaları birleştirerek tek ve tutarlı bir çözüm üretir. Üstelik bu çözüm yalnızca teorik bir merak değildir; kriptografi, takvim hesapları, paralel işlem ve bilgisayar aritmetiğinde karşımıza çıkar.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/cinlilerin-kalan-teoremi-86.png" /><media:content medium="image" url="https://program.sonsuz.us/img/cinlilerin-kalan-teoremi-86.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Collatz Problemi: 3n+1 ile Sonsuzluğa Açılan Matematik Bilmecesi</title><link href="https://program.sonsuz.us/posts/collatz-problemi-3n1-ile-sonsuzluga-acilan-matematik-bilmecesi/" rel="alternate" type="text/html" title="Collatz Problemi: 3n+1 ile Sonsuzluğa Açılan Matematik Bilmecesi" /><published>2026-10-11T00:00:00+00:00</published><updated>2026-10-11T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/collatz-problemi-3n1-ile-sonsuzluga-acilan-matematik-bilmecesi</id><content type="html" xml:base="https://program.sonsuz.us/posts/collatz-problemi-3n1-ile-sonsuzluga-acilan-matematik-bilmecesi/"><![CDATA[<p>Bir pozitif tam sayı seçin. Çiftse ikiye bölün, tekse üçle çarpıp bir ekleyin ve aynı işlemi tekrarlayın. Çocuk oyuncağı kadar basit görünen bu tarif, matematikçilerin onlarca yıldır çözemediği Collatz varsayımını oluşturur. Bilgisayarlar akıl almaz büyüklükte sayıları sınamış olsa da her başlangıç değerinin sonunda 1’e ulaşacağını kanıtlayan genel bir ispat hâlâ bulunamamıştır.</p>

<p>``</p>

<h2 id="kural-tam-olarak-nedir">Kural tam olarak nedir?</h2>

<p>1937 yılında Alman matematikçi Lothar Collatz tarafından ortaya atılan problem, pozitif tam sayılar üzerinde çalışan bir fonksiyonla tanımlanır:</p>

\[C(n)=
\begin{cases}
n/2, &amp; n \text{ çiftse} \\
3n+1, &amp; n \text{ tekse}
\end{cases}\]

<p>Elde edilen sonuç tekrar aynı fonksiyona verilir. Varsayım, hangi pozitif $n$ değeriyle başlanırsa başlansın dizinin sonunda $1$ sayısına ulaşacağını söyler. Bir kez 1’e gelindiğinde $1 \rightarrow 4 \rightarrow 2 \rightarrow 1$ döngüsü oluşur.</p>

<table>
  <thead>
    <tr>
      <th>Başlangıç türü</th>
      <th style="text-align: right">Uygulanan işlem</th>
      <th>İlk sonucun özelliği</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Çift $n$</td>
      <td style="text-align: right">$n/2$</td>
      <td>Sayı kesinlikle küçülür</td>
    </tr>
    <tr>
      <td>Tek $n$</td>
      <td style="text-align: right">$3n+1$</td>
      <td>Sonuç çift ve genellikle daha büyüktür</td>
    </tr>
    <tr>
      <td>$n=1$</td>
      <td style="text-align: right">$3(1)+1=4$</td>
      <td>Ana döngü başlar</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/collatz-problemi-3n1-78.svg" alt="collatz-problemi-3n1-78" /></p>

<p>Tek sayıdan sonra sonucun çift olması önemlidir. Çünkü $3n+1$ ifadesinde hem $3n$ hem de $n$ tek olduğundan sonuç çifttir; böylece sonraki adımda bölme işlemi garanti edilir.</p>

<h2 id="küçük-sayı-uzun-macera">Küçük sayı, uzun macera</h2>

<p>Örneğin $n=6$ ile başlayalım:</p>

\[6 \rightarrow 3 \rightarrow 10 \rightarrow 5 \rightarrow 16 \rightarrow 8 \rightarrow 4 \rightarrow 2 \rightarrow 1\]

<p>Daha şaşırtıcı bir örnek 27’dir. Dizi hızla küçülmek yerine 9232’ye kadar yükselir ve 1’e ulaşması 111 adım sürer. Yani başlangıç sayısının küçük olması, yolculuğun kısa olacağı anlamına gelmez.</p>

<table>
  <thead>
    <tr>
      <th style="text-align: right">Başlangıç</th>
      <th style="text-align: right">1’e ulaşma adımı</th>
      <th style="text-align: right">Yolculuktaki en büyük değer</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: right">6</td>
      <td style="text-align: right">8</td>
      <td style="text-align: right">16</td>
    </tr>
    <tr>
      <td style="text-align: right">12</td>
      <td style="text-align: right">9</td>
      <td style="text-align: right">16</td>
    </tr>
    <tr>
      <td style="text-align: right">27</td>
      <td style="text-align: right">111</td>
      <td style="text-align: right">9232</td>
    </tr>
  </tbody>
</table>

<p>Bu düzensiz davranış, problemi kaotik bir labirente dönüştürür. Bazı adımlar sayıyı küçültürken bazıları aniden büyütür; yerel hareketlere bakarak uzun vadeli sonucu kestirmek kolay değildir.</p>

<h2 id="neden-ispatlamak-bu-kadar-zor">Neden ispatlamak bu kadar zor?</h2>

<p>Deneysel doğrulama ile matematiksel ispat aynı şey değildir. Bir bilgisayar ilk trilyonlarca başlangıç değerini kontrol edebilir; ancak pozitif tam sayılar sonsuzdur. Kontrol edilmeyen tek bir sayı bile sonsuza kaçabilir veya 1’i içermeyen farklı bir döngüye girebilir.</p>

<p>Sezgisel olarak tek bir adımdan ziyade, tek sayıdan sonraki bölmeleri birlikte düşünebiliriz. $3n+1$ sonucu bazen 2’ye, bazen $4$, $8$ veya daha büyük bir iki kuvvetine bölünür. Kabaca rastgelelik varsayılırsa bölmelerin uzun vadede büyümeyi dengelemesi beklenir. Fakat “beklenir” sözcüğü ispat değildir; adımlar birbirinden bağımsız rastgele olaylar değildir.</p>

<h2 id="python-ile-collatz-yolculuğu">Python ile Collatz yolculuğu</h2>

<p>Aşağıdaki fonksiyon diziyi üretir, tekrar eden bir değer görürse durur. Böylece hem 1 döngüsü hem de varsayımsal başka döngüler yakalanabilir:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">collatz_sequence</span><span class="p">(</span><span class="n">start</span><span class="p">,</span> <span class="n">limit</span><span class="o">=</span><span class="mi">10_000</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">start</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">raise</span> <span class="nc">ValueError</span><span class="p">(</span><span class="sh">'</span><span class="s">Pozitif bir tam sayı girilmeli.</span><span class="sh">'</span><span class="p">)</span>

    <span class="n">sequence</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="n">seen</span> <span class="o">=</span> <span class="nf">set</span><span class="p">()</span>
    <span class="n">n</span> <span class="o">=</span> <span class="n">start</span>

    <span class="k">while</span> <span class="n">n</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">seen</span> <span class="ow">and</span> <span class="nf">len</span><span class="p">(</span><span class="n">sequence</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">limit</span><span class="p">:</span>
        <span class="n">sequence</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
        <span class="n">seen</span><span class="p">.</span><span class="nf">add</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>

        <span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
            <span class="k">break</span>
        <span class="n">n</span> <span class="o">=</span> <span class="n">n</span> <span class="o">//</span> <span class="mi">2</span> <span class="k">if</span> <span class="n">n</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span> <span class="k">else</span> <span class="mi">3</span> <span class="o">*</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">1</span>

    <span class="k">return</span> <span class="n">sequence</span>

<span class="n">path</span> <span class="o">=</span> <span class="nf">collatz_sequence</span><span class="p">(</span><span class="mi">27</span><span class="p">)</span>
<span class="nf">print</span><span class="p">(</span><span class="sh">'</span><span class="s">Adım sayısı:</span><span class="sh">'</span><span class="p">,</span> <span class="nf">len</span><span class="p">(</span><span class="n">path</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="nf">print</span><span class="p">(</span><span class="sh">'</span><span class="s">En büyük değer:</span><span class="sh">'</span><span class="p">,</span> <span class="nf">max</span><span class="p">(</span><span class="n">path</span><span class="p">))</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">seen</code> kümesi daha önce ziyaret edilen değerleri hızlıca denetler. <code class="language-plaintext highlighter-rouge">limit</code> ise beklenmedik derecede uzun bir yürüyüşün programı süresiz çalıştırmasını engeller. Bu kod örnekleri test eder, fakat genel bir kanıt üretmez.</p>

<h2 id="basitlik-neden-yanıltıcıdır">Basitlik neden yanıltıcıdır?</h2>

<p>Collatz problemi, kolay ifade edilmenin kolay çözülmek anlamına gelmediğini gösterir. Ortada yalnızca çarpma, toplama ve bölme vardır; buna rağmen işlemlerin birleşimi öngörülmesi güç küresel bir davranış doğurur. Belki bütün diziler 1’e iner, belki erişilmesi inanılmaz zor bir karşı örnek vardır. İşte bu belirsizlik, $3n+1$ bilmecesini sayı teorisinin en eğlenceli ve inatçı problemlerinden biri yapar.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="collatz" /><category term="matematik" /><category term="algoritma" /><category term="python" /><category term="sayı teorisi" /><category term="varsayım" /><summary type="html"><![CDATA[Bir pozitif tam sayı seçin. Çiftse ikiye bölün, tekse üçle çarpıp bir ekleyin ve aynı işlemi tekrarlayın. Çocuk oyuncağı kadar basit görünen bu tarif, matematikçilerin onlarca yıldır çözemediği Collatz varsayımını oluşturur. Bilgisayarlar akıl almaz büyüklükte sayıları sınamış olsa da her başlangıç değerinin sonunda 1’e ulaşacağını kanıtlayan genel bir ispat hâlâ bulunamamıştır.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/collatz-problemi-3n1-78.png" /><media:content medium="image" url="https://program.sonsuz.us/img/collatz-problemi-3n1-78.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Derangement Problemi: Herkes Yanlış Sandalyeye Otursun!</title><link href="https://program.sonsuz.us/posts/derangement-problemi-herkes-yanlis-sandalyeye-otursun/" rel="alternate" type="text/html" title="Derangement Problemi: Herkes Yanlış Sandalyeye Otursun!" /><published>2026-10-11T00:00:00+00:00</published><updated>2026-10-11T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/derangement-problemi-herkes-yanlis-sandalyeye-otursun</id><content type="html" xml:base="https://program.sonsuz.us/posts/derangement-problemi-herkes-yanlis-sandalyeye-otursun/"><![CDATA[<p><img src="/img/derangement-problemi-herkes-70.svg" alt="derangement-problemi-herkes-70" /></p>

<p>Bir davette herkes şapkasını vestiyere bırakıyor ve çıkışta şapkalar rastgele dağıtılıyor. Acaba hiç kimsenin kendi şapkasını almadığı kaç farklı dağıtım vardır? Kombinatorikte <strong>derangement</strong>, Türkçede düzensizleştirme olarak bilinen problem tam olarak bunu sorar. İlk bakışta yalnızca permütasyon üretip kontrol etmek yeterli görünse de teorik yaklaşım çok daha hızlı ve öğreticidir.</p>

<p>``</p>

<h2 id="problemin-matematiksel-tanımı">Problemin matematiksel tanımı</h2>

<p>$n$ farklı elemanın bir permütasyonunu düşünelim. Bir eleman başlangıçtaki konumunda kalıyorsa buna <strong>sabit nokta</strong> denir. Derangement, sabit noktası bulunmayan permütasyondur.</p>

<p>Derangement sayısı genellikle $!n$, $D_n$ veya $d(n)$ ile gösterilir:</p>

\[D_n = \left\vert \{\pi \in S_n : \pi(i) \neq i \text{, her } i \text{ için}\}\right\vert\]

<p>Küçük değerler problemi somutlaştırır:</p>

<table>
  <thead>
    <tr>
      <th style="text-align: right">$n$</th>
      <th style="text-align: right">Toplam permütasyon $n!$</th>
      <th style="text-align: right">Derangement $D_n$</th>
      <th>Örnek</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: right">0</td>
      <td style="text-align: right">1</td>
      <td style="text-align: right">1</td>
      <td>Boş düzenleme</td>
    </tr>
    <tr>
      <td style="text-align: right">1</td>
      <td style="text-align: right">1</td>
      <td style="text-align: right">0</td>
      <td>İmkânsız</td>
    </tr>
    <tr>
      <td style="text-align: right">2</td>
      <td style="text-align: right">2</td>
      <td style="text-align: right">1</td>
      <td><code class="language-plaintext highlighter-rouge">[2, 1]</code></td>
    </tr>
    <tr>
      <td style="text-align: right">3</td>
      <td style="text-align: right">6</td>
      <td style="text-align: right">2</td>
      <td><code class="language-plaintext highlighter-rouge">[2, 3, 1]</code>, <code class="language-plaintext highlighter-rouge">[3, 1, 2]</code></td>
    </tr>
    <tr>
      <td style="text-align: right">4</td>
      <td style="text-align: right">24</td>
      <td style="text-align: right">9</td>
      <td>Dokuz farklı düzenleme</td>
    </tr>
  </tbody>
</table>

<p>$D_0=1$ tanımı ilk anda garip gelebilir. Ancak boş kümeyi düzenlemenin tek bir yolu vardır ve ortada kendi yerinde kalan eleman bulunmaz. Bu kabul, formüllerin düzgün çalışmasını sağlar.</p>

<h2 id="dahil-etmehariç-tutma-ilkesi">Dahil etme–hariç tutma ilkesi</h2>

<p>Toplam $n!$ permütasyon vardır. $A_i$, $i$ numaralı elemanın kendi yerinde kaldığı permütasyonlar kümesi olsun. İstenen sonuç, hiçbir $A_i$ kümesine girmeyen permütasyonların sayısıdır.</p>

<p>Bir elemanı sabitlersek kalanlar $(n-1)!$ şekilde, iki elemanı sabitlersek $(n-2)!$ şekilde dizilir. Dahil etme–hariç tutma ilkesi uygulandığında:</p>

\[D_n=n!-\binom{n}{1}(n-1)!+\binom{n}{2}(n-2)!-\cdots+(-1)^n\]

<p>$\binom{n}{k}(n-k)!=\frac{n!}{k!}$ olduğundan daha kısa formül şöyledir:</p>

\[D_n=n!\sum_{k=0}^{n}\frac{(-1)^k}{k!}\]

<p>Bu toplam, $e^{-1}$ sayısının Taylor açılımını andırır. Dolayısıyla:</p>

\[D_n \approx \frac{n!}{e}\]

<p>Hatta tam sayı sonucu en yakın tam sayıya yuvarlayarak bulabiliriz:</p>

\[D_n=\left\lfloor\frac{n!}{e}+\frac{1}{2}\right\rfloor\]

<p>Bunun ilginç sonucu şudur: $n$ büyüdükçe rastgele bir permütasyonda hiç sabit nokta bulunmama olasılığı yaklaşık $1/e$, yani yüzde $36{,}79$ olur.</p>

<h2 id="daha-kullanışlı-bağıntı">Daha kullanışlı bağıntı</h2>

<p>Derangement sayıları aşağıdaki yinelemeli bağıntıyla da hesaplanabilir:</p>

\[D_n=(n-1)(D_{n-1}+D_{n-2})\]

<p>İlk eleman başka bir konuma gönderilir. O konumdaki eleman ya ilk elemanın yerine gelir ya da üçüncü bir konuma gider. Bu iki durum sırasıyla daha küçük derangement problemlerine dönüşür.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th style="text-align: right">Zaman karmaşıklığı</th>
      <th style="text-align: right">Bellek</th>
      <th>Özellik</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Tüm permütasyonları denemek</td>
      <td style="text-align: right">$O(n!\cdot n)$</td>
      <td style="text-align: right">Yüksek</td>
      <td>Yalnızca küçük $n$ için</td>
    </tr>
    <tr>
      <td>Dahil etme–hariç tutma</td>
      <td style="text-align: right">$O(n)$</td>
      <td style="text-align: right">$O(1)$</td>
      <td>Faktöriyel takibi gerekir</td>
    </tr>
    <tr>
      <td>Yinelemeli dinamik çözüm</td>
      <td style="text-align: right">$O(n)$</td>
      <td style="text-align: right">$O(1)$</td>
      <td>Tam sayı hesabı için pratik</td>
    </tr>
  </tbody>
</table>

<h2 id="python-ile-hesaplama">Python ile hesaplama</h2>

<p>Aşağıdaki fonksiyon bağıntıyı kullanır. Yalnızca son iki değeri sakladığı için ek diziye ihtiyaç duymaz:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">derangement</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">n</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">raise</span> <span class="nc">ValueError</span><span class="p">(</span><span class="sh">"</span><span class="s">n negatif olamaz</span><span class="sh">"</span><span class="p">)</span>
    <span class="k">if</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="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
        <span class="k">return</span> <span class="mi">0</span>

    <span class="n">onceki_iki</span><span class="p">,</span> <span class="n">onceki</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span>  <span class="c1"># D0 ve D1
</span>
    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
        <span class="n">simdiki</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">onceki</span> <span class="o">+</span> <span class="n">onceki_iki</span><span class="p">)</span>
        <span class="n">onceki_iki</span><span class="p">,</span> <span class="n">onceki</span> <span class="o">=</span> <span class="n">onceki</span><span class="p">,</span> <span class="n">simdiki</span>

    <span class="k">return</span> <span class="n">onceki</span>

<span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">9</span><span class="p">):</span>
    <span class="nf">print</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nf">derangement</span><span class="p">(</span><span class="n">n</span><span class="p">))</span>
</code></pre></div></div>

<p>Program sırasıyla <code class="language-plaintext highlighter-rouge">0, 1, 2, 9, 44, 265, 1854, 14833</code> değerlerini üretir. Python tam sayıları otomatik büyüttüğü için büyük sonuçlarda taşma yaşanmaz.</p>

<p>Derangement; görev atama, gizli hediye çekilişi, test sorularını karıştırma ve kimsenin önceki eşleşmesini almaması gereken planlama problemlerinde kullanılır. Kısacası matematiğin düzen kurmak için bazen herkesi özellikle yanlış yere koyduğu eğlenceli örneklerden biridir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="derangement" /><category term="permütasyon" /><category term="kombinatorik" /><category term="python" /><category term="algoritma" /><category term="matematik" /><summary type="html"><![CDATA[Bir davette herkes şapkasını vestiyere bırakıyor ve çıkışta şapkalar rastgele dağıtılıyor. Acaba hiç kimsenin kendi şapkasını almadığı kaç farklı dağıtım vardır? Kombinatorikte derangement, Türkçede düzensizleştirme olarak bilinen problem tam olarak bunu sorar. İlk bakışta yalnızca permütasyon üretip kontrol etmek yeterli görünse de teorik yaklaşım çok daha hızlı ve öğreticidir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/derangement-problemi-herkes-70.png" /><media:content medium="image" url="https://program.sonsuz.us/img/derangement-problemi-herkes-70.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Güvercin Yuvası İlkesi: Basit Bir Fikirle Şaşırtıcı Kanıtlar</title><link href="https://program.sonsuz.us/posts/guvercin-yuvasi-ilkesi-basit-bir-fikirle-sasirtici-kanitlar/" rel="alternate" type="text/html" title="Güvercin Yuvası İlkesi: Basit Bir Fikirle Şaşırtıcı Kanıtlar" /><published>2026-10-11T00:00:00+00:00</published><updated>2026-10-11T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/guvercin-yuvasi-ilkesi-basit-bir-fikirle-sasirtici-kanitlar</id><content type="html" xml:base="https://program.sonsuz.us/posts/guvercin-yuvasi-ilkesi-basit-bir-fikirle-sasirtici-kanitlar/"><![CDATA[<p>Bir kümesteki yuvalardan daha fazla güvercin varsa en az bir yuvayı paylaşmak zorunda kalırlar. Kulağa çocuk oyuncağı gibi gelen bu gözlem; sayı teorisinden çizge kuramına, algoritma analizinden günlük yaşam problemlerine kadar şaşırtıcı derecede güçlü sonuçlar üretir. Matematikte buna <strong>Güvercin Yuvası İlkesi</strong> denir ve çoğu zaman aranan nesneyi göstermeden, yalnızca onun var olmak zorunda olduğunu kanıtlar.</p>

<p><img src="/img/guvercin-yuvasi-ilkesi-57.svg" alt="guvercin-yuvasi-ilkesi-57" /></p>

<p>``</p>

<h2 id="i̇lkenin-matematiksel-temeli">İlkenin matematiksel temeli</h2>

<p>Elimizde $n$ adet yuva ve bu yuvalara dağıtılan $n+1$ adet güvercin olsun. Her yuvada en fazla bir güvercin bulunduğunu varsayarsak yerleştirilebilecek toplam güvercin sayısı en fazla $n$ olur. Oysa elimizde $n+1$ güvercin vardır. Varsayımımız çelişkiye ulaştığı için en az bir yuvada iki veya daha fazla güvercin bulunmalıdır.</p>

<p>İlkenin genelleştirilmiş biçimi daha kullanışlıdır: $N$ nesne $k$ kutuya dağıtılırsa kutulardan en az biri en az</p>

\[ceil(N/k)\]

<p>nesne içerir. Buradaki $ceil(x)$, sonucu yukarıdaki en yakın tam sayıya yuvarlar. Örneğin 100 dosya 9 sunucuya dağıtılırsa en az bir sunucuda en az $ceil(100/9)=12$ dosya bulunur.</p>

<table>
  <thead>
    <tr>
      <th>Durum</th>
      <th style="text-align: right">Güvercinler</th>
      <th style="text-align: right">Yuvalar</th>
      <th>Zorunlu sonuç</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Klasik ilke</td>
      <td style="text-align: right">$n+1$</td>
      <td style="text-align: right">$n$</td>
      <td>Bir yuvada en az 2 nesne</td>
    </tr>
    <tr>
      <td>Genelleştirilmiş ilke</td>
      <td style="text-align: right">$N$</td>
      <td style="text-align: right">$k$</td>
      <td>Bir yuvada en az $ceil(N/k)$ nesne</td>
    </tr>
    <tr>
      <td>Ters bakış</td>
      <td style="text-align: right">En fazla $r$ nesne/yuvada</td>
      <td style="text-align: right">$k$</td>
      <td>Toplam en fazla $rk$ nesne</td>
    </tr>
  </tbody>
</table>

<h2 id="doğum-günü-örneği">Doğum günü örneği</h2>

<p>Bir okulda 367 öğrenci olduğunu düşünelim. Yılın 366 gün sürebileceğini hesaba katsak bile en az iki öğrencinin doğum günü aynıdır. Öğrenciler güvercin, takvim günleri ise yuva rolündedir.</p>

<p>Daha güçlü bir soru soralım: 100 öğrenciden kaçının aynı ayda doğmuş olması garanti edilir? Aylar 12 yuva olduğuna göre:</p>

\[ceil(100/12)=9\]

<p>Dolayısıyla hangi aylarda doğduklarını bilmeden, en az 9 öğrencinin aynı doğum ayını paylaştığını söyleyebiliriz. İlkenin büyüsü burada ortaya çıkar: Dağılımı hesaplamaz, kaçınılmaz sonucu yakalarız.</p>

<h2 id="sayı-teorisinden-şaşırtıcı-bir-kanıt">Sayı teorisinden şaşırtıcı bir kanıt</h2>

<p>Herhangi $n+1$ tam sayı seçelim. Bu sayıları $n$ ile böldüğümüzde kalanlar yalnızca</p>

\[0,1,2,...,n-1\]

<p>olabilir. Yani $n$ farklı kalan yuvası vardır. Ancak $n+1$ sayı bulunduğu için iki sayı aynı kalanı verir. Bu sayılara $a$ ve $b$ dersek:</p>

\[a mod n = b mod n\]

<p>Buradan $a-b$ farkının $n$ ile tam bölündüğü sonucu çıkar. Sayıların değerlerini hiç bilmeden, aralarında $n$’nin katı olan bir fark bulunacağını kanıtladık.</p>

<h2 id="bilgisayar-bilimindeki-karşılığı">Bilgisayar bilimindeki karşılığı</h2>

<p>Hash tablolarında çok sayıda anahtar, sınırlı sayıdaki indekse eşlenir. Anahtar sayısı indeks sayısından fazlaysa çakışma kaçınılmazdır. İyi bir hash fonksiyonu çakışmayı yok etmez; dengeli dağıtmaya çalışır.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">pigeonhole_groups</span><span class="p">(</span><span class="n">values</span><span class="p">,</span> <span class="n">bucket_count</span><span class="p">):</span>
    <span class="c1"># Sayıları kalanlarına göre sınıflandırır.
</span>    <span class="n">buckets</span> <span class="o">=</span> <span class="p">[[]</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">bucket_count</span><span class="p">)]</span>

    <span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">values</span><span class="p">:</span>
        <span class="n">index</span> <span class="o">=</span> <span class="n">value</span> <span class="o">%</span> <span class="n">bucket_count</span>
        <span class="n">buckets</span><span class="p">[</span><span class="n">index</span><span class="p">].</span><span class="nf">append</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>

    <span class="k">return</span> <span class="nf">max</span><span class="p">(</span><span class="n">buckets</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="nb">len</span><span class="p">)</span>

<span class="n">numbers</span> <span class="o">=</span> <span class="p">[</span><span class="mi">14</span><span class="p">,</span> <span class="mi">27</span><span class="p">,</span> <span class="mi">35</span><span class="p">,</span> <span class="mi">42</span><span class="p">,</span> <span class="mi">58</span><span class="p">,</span> <span class="mi">63</span><span class="p">]</span>
<span class="nf">print</span><span class="p">(</span><span class="nf">pigeonhole_groups</span><span class="p">(</span><span class="n">numbers</span><span class="p">,</span> <span class="mi">5</span><span class="p">))</span>
</code></pre></div></div>

<p>Kod, sayıları beş kalan sınıfına yerleştirir ve en kalabalık sınıfı döndürür. Altı sayı beş sınıfa dağıtıldığı için sınıflardan birinde en az iki sayı bulunacağı daha program çalışmadan garantidir.</p>

<table>
  <thead>
    <tr>
      <th>Matematiksel kavram</th>
      <th>Programlamadaki karşılığı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Güvercin</td>
      <td>Anahtar, veri veya istek</td>
    </tr>
    <tr>
      <td>Yuva</td>
      <td>Hash indeksi, sunucu veya bellek bölgesi</td>
    </tr>
    <tr>
      <td>Aynı yuvaya düşme</td>
      <td>Çakışma ya da kaynak paylaşımı</td>
    </tr>
    <tr>
      <td>Genelleştirilmiş sınır</td>
      <td>En kötü durum yükü</td>
    </tr>
  </tbody>
</table>

<h2 id="kanıtlarda-nasıl-fark-edilir">Kanıtlarda nasıl fark edilir?</h2>

<p>Bir problemde “en az iki tanesi”, “mutlaka aynı”, “garanti edilen minimum” veya “kaçınılmaz çakışma” ifadeleri geçiyorsa güvercin yuvası ilkesini düşünmek yararlıdır. Asıl ustalık, güvercinleri ve yuvaları doğru seçmektir. Bazen yuvalar aylar, bazen kalan sınıfları, bazen de geometrik bölgelerdir.</p>

<p>Bu ilke bize önemli bir matematiksel alışkanlık kazandırır: Her şeyi tek tek bulmak zorunda değiliz. Kapasite ile nesne sayısını karşılaştırmak, karmaşık görünen bir varlık kanıtını birkaç satırlık kaçınılmazlık argümanına dönüştürebilir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="matematik" /><category term="güvercin-yuvası-ilkesi" /><category term="algoritma" /><category term="kombinatorik" /><category term="ispat" /><category term="python" /><summary type="html"><![CDATA[Bir kümesteki yuvalardan daha fazla güvercin varsa en az bir yuvayı paylaşmak zorunda kalırlar. Kulağa çocuk oyuncağı gibi gelen bu gözlem; sayı teorisinden çizge kuramına, algoritma analizinden günlük yaşam problemlerine kadar şaşırtıcı derecede güçlü sonuçlar üretir. Matematikte buna Güvercin Yuvası İlkesi denir ve çoğu zaman aranan nesneyi göstermeden, yalnızca onun var olmak zorunda olduğunu kanıtlar.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/guvercin-yuvasi-ilkesi-57.png" /><media:content medium="image" url="https://program.sonsuz.us/img/guvercin-yuvasi-ilkesi-57.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">K-Elemanlı Alt Kümeleri Sistematik Olarak Üretme</title><link href="https://program.sonsuz.us/posts/k-elemanli-alt-kumeleri-sistematik-olarak-uretme/" rel="alternate" type="text/html" title="K-Elemanlı Alt Kümeleri Sistematik Olarak Üretme" /><published>2026-10-11T00:00:00+00:00</published><updated>2026-10-11T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/k-elemanli-alt-kumeleri-sistematik-olarak-uretme</id><content type="html" xml:base="https://program.sonsuz.us/posts/k-elemanli-alt-kumeleri-sistematik-olarak-uretme/"><![CDATA[<p>Bir kümeden tam olarak $k$ eleman seçmenin kaç farklı yolu olduğunu bilmek kolaydır; asıl eğlence, bu seçimlerin tamamını eksiksiz, tekrarsız ve belirli bir sırada üretmekle başlar. Kombinasyon üretimi; arama algoritmalarından test verisi hazırlamaya, takım oluşturmadan özellik seçimine kadar pek çok alanda karşımıza çıkar. Bu yazıda k-elemanlı alt kümeleri üretmenin üç sistematik yöntemini inceleyeceğiz.</p>

<p>``</p>

<h2 id="önce-matematik-kaç-sonuç-bekliyoruz">Önce matematik: Kaç sonuç bekliyoruz?</h2>

<p>$n$ elemanlı bir kümenin $k$ elemanlı alt kümelerinin sayısı binom katsayısıyla hesaplanır:</p>

\[{n \choose k}=\frac{n!}{k!(n-k)!}\]

<p>Örneğin $A={a,b,c,d}$ ve $k=2$ için toplam sonuç sayısı</p>

\[{4 \choose 2}=6\]

<p>olur. Üretilecek alt kümeler şunlardır: ${a,b}$, ${a,c}$, ${a,d}$, ${b,c}$, ${b,d}$ ve ${c,d}$.</p>

<p>Bir algoritmanın doğru olduğunu sınarken bu formül iyi bir kontrol mekanizmasıdır. Algoritma tam olarak ${n \choose k}$ sonuç vermeli ve hiçbir sonucu iki kez üretmemelidir.</p>

<h2 id="1-özyinelemeli-geri-izleme">1. Özyinelemeli geri izleme</h2>

<p>En anlaşılır yaklaşım, her adımda bir elemanı seçip seçmemeye karar vermektir. Ancak yalnızca seçme dalını açıkça dolaşarak gereksiz adımları azaltabiliriz.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">kombinasyonlar</span><span class="p">(</span><span class="n">elemanlar</span><span class="p">,</span> <span class="n">k</span><span class="p">):</span>
    <span class="n">sonuc</span> <span class="o">=</span> <span class="p">[]</span>

    <span class="k">def</span> <span class="nf">ara</span><span class="p">(</span><span class="n">baslangic</span><span class="p">,</span> <span class="n">secilenler</span><span class="p">):</span>
        <span class="c1"># İstenen büyüklüğe ulaştığımızda kopyayı kaydet.
</span>        <span class="k">if</span> <span class="nf">len</span><span class="p">(</span><span class="n">secilenler</span><span class="p">)</span> <span class="o">==</span> <span class="n">k</span><span class="p">:</span>
            <span class="n">sonuc</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">secilenler</span><span class="p">.</span><span class="nf">copy</span><span class="p">())</span>
            <span class="k">return</span>

        <span class="n">gereken</span> <span class="o">=</span> <span class="n">k</span> <span class="o">-</span> <span class="nf">len</span><span class="p">(</span><span class="n">secilenler</span><span class="p">)</span>
        <span class="n">son_indeks</span> <span class="o">=</span> <span class="nf">len</span><span class="p">(</span><span class="n">elemanlar</span><span class="p">)</span> <span class="o">-</span> <span class="n">gereken</span>

        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">baslangic</span><span class="p">,</span> <span class="n">son_indeks</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
            <span class="n">secilenler</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">elemanlar</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
            <span class="nf">ara</span><span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">secilenler</span><span class="p">)</span>
            <span class="n">secilenler</span><span class="p">.</span><span class="nf">pop</span><span class="p">()</span>  <span class="c1"># Geri dön ve başka adayı dene.
</span>
    <span class="nf">ara</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="p">[])</span>
    <span class="k">return</span> <span class="n">sonuc</span>

<span class="nf">print</span><span class="p">(</span><span class="nf">kombinasyonlar</span><span class="p">([</span><span class="sh">"</span><span class="s">a</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">b</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">c</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">d</span><span class="sh">"</span><span class="p">],</span> <span class="mi">2</span><span class="p">))</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">baslangic</code> değeri, daha önce kullanılan elemanlara geri dönülmesini engeller. Böylece hem tekrar oluşmaz hem de kombinasyonlar sözlük sırasına benzer bir düzende üretilir. <code class="language-plaintext highlighter-rouge">son_indeks</code> hesabı ise geride yeterli eleman kalmadığı bilinen dalları budar.</p>

<h2 id="2-i̇ndeksleri-sözlük-sırasıyla-ilerletmek">2. İndeksleri sözlük sırasıyla ilerletmek</h2>

<p>Bir kombinasyonu elemanların kendisi yerine indeks dizisiyle temsil edebiliriz. Örneğin <code class="language-plaintext highlighter-rouge">[0, 1, 3]</code>, kümenin birinci, ikinci ve dördüncü elemanlarını seçer. Her turda sağdan başlayarak artırılabilecek ilk indeks bulunur.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">sirali_k_alt_kumeler</span><span class="p">(</span><span class="n">veri</span><span class="p">,</span> <span class="n">k</span><span class="p">):</span>
    <span class="n">n</span> <span class="o">=</span> <span class="nf">len</span><span class="p">(</span><span class="n">veri</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="ow">or</span> <span class="n">k</span> <span class="o">&gt;</span> <span class="n">n</span><span class="p">:</span>
        <span class="k">return</span>

    <span class="n">indeksler</span> <span class="o">=</span> <span class="nf">list</span><span class="p">(</span><span class="nf">range</span><span class="p">(</span><span class="n">k</span><span class="p">))</span>

    <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
        <span class="k">yield</span> <span class="p">[</span><span class="n">veri</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">indeksler</span><span class="p">]</span>

        <span class="n">i</span> <span class="o">=</span> <span class="n">k</span> <span class="o">-</span> <span class="mi">1</span>
        <span class="k">while</span> <span class="n">i</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">indeksler</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">i</span> <span class="o">+</span> <span class="n">n</span> <span class="o">-</span> <span class="n">k</span><span class="p">:</span>
            <span class="n">i</span> <span class="o">-=</span> <span class="mi">1</span>

        <span class="k">if</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">return</span>

        <span class="n">indeksler</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">k</span><span class="p">):</span>
            <span class="n">indeksler</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">indeksler</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span>
</code></pre></div></div>

<p>Bu sürüm <code class="language-plaintext highlighter-rouge">yield</code> kullandığı için tüm sonuçları bellekte tutmaz. Büyük veri kümelerinde yalnızca sıradaki kombinasyona ihtiyaç duyulduğunda oldukça kullanışlıdır.</p>

<h2 id="3-bit-maskesi-yaklaşımı">3. Bit maskesi yaklaşımı</h2>

<p>Her elemanı bir bit ile temsil edebiliriz: <code class="language-plaintext highlighter-rouge">1</code> seçildiğini, <code class="language-plaintext highlighter-rouge">0</code> seçilmediğini gösterir. Örneğin <code class="language-plaintext highlighter-rouge">10110</code> maskesi üç eleman seçer. Dolayısıyla yalnızca içinde tam $k$ tane <code class="language-plaintext highlighter-rouge">1</code> bulunan maskeler kabul edilir.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">bitmask_kombinasyonlari</span><span class="p">(</span><span class="n">veri</span><span class="p">,</span> <span class="n">k</span><span class="p">):</span>
    <span class="n">n</span> <span class="o">=</span> <span class="nf">len</span><span class="p">(</span><span class="n">veri</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">maske</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="n">n</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">maske</span><span class="p">.</span><span class="nf">bit_count</span><span class="p">()</span> <span class="o">==</span> <span class="n">k</span><span class="p">:</span>
            <span class="k">yield</span> <span class="p">[</span><span class="n">veri</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="k">if</span> <span class="n">maske</span> <span class="o">&amp;</span> <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="n">i</span><span class="p">)]</span>
</code></pre></div></div>

<p>Kod son derece kısa olsa da $0$ ile $2^n-1$ arasındaki bütün maskeleri inceler. Bu nedenle özellikle $k$, $n$ değerine göre küçükken çok sayıda gereksiz maske kontrol edilir.</p>

<h2 id="yöntemlerin-karşılaştırması">Yöntemlerin karşılaştırması</h2>

<table>
  <thead>
    <tr>
      <th>Yöntem</th>
      <th style="text-align: right">Üretim maliyeti</th>
      <th style="text-align: right">Ek bellek</th>
      <th>Güçlü yönü</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Geri izleme</td>
      <td style="text-align: right">$O(k{n \choose k})$</td>
      <td style="text-align: right">$O(k)$</td>
      <td>Kolay uyarlanır ve budanabilir</td>
    </tr>
    <tr>
      <td>İndeks ilerletme</td>
      <td style="text-align: right">$O(k{n \choose k})$</td>
      <td style="text-align: right">$O(k)$</td>
      <td>Tembel ve sıralı üretim sağlar</td>
    </tr>
    <tr>
      <td>Bit maskesi</td>
      <td style="text-align: right">$O(n2^n)$</td>
      <td style="text-align: right">$O(k)$</td>
      <td>Basit, düşük seviyeli işlemlere uygun</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/k-elemanli-alt-29.svg" alt="k-elemanli-alt-29" /></p>

<p>Pratikte genel amaçlı kullanım için indeks ilerletme yöntemi iyi bir dengedir. Seçimlere özel kurallar eklenecekse geri izleme daha esnektir. Bit maskesi ise küçük kümelerde, bit düzeyindeki temsiller zaten problemin parçasıysa parlamaya başlar. Hangi yolu seçerseniz seçin, sonuç sayısını ${n \choose k}$ ile doğrulamak algoritmik pusulanız olacaktır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="algoritma" /><category term="kombinasyon" /><category term="python" /><category term="bitmask" /><category term="özyineleme" /><summary type="html"><![CDATA[Bir kümeden tam olarak $k$ eleman seçmenin kaç farklı yolu olduğunu bilmek kolaydır; asıl eğlence, bu seçimlerin tamamını eksiksiz, tekrarsız ve belirli bir sırada üretmekle başlar. Kombinasyon üretimi; arama algoritmalarından test verisi hazırlamaya, takım oluşturmadan özellik seçimine kadar pek çok alanda karşımıza çıkar. Bu yazıda k-elemanlı alt kümeleri üretmenin üç sistematik yöntemini inceleyeceğiz.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/k-elemanli-alt-29.png" /><media:content medium="image" url="https://program.sonsuz.us/img/k-elemanli-alt-29.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Luhn Algoritması ile Kart Numarası Doğrulama</title><link href="https://program.sonsuz.us/posts/luhn-algoritmasi-ile-kart-numarasi-dogrulama/" rel="alternate" type="text/html" title="Luhn Algoritması ile Kart Numarası Doğrulama" /><published>2026-10-11T00:00:00+00:00</published><updated>2026-10-11T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/luhn-algoritmasi-ile-kart-numarasi-dogrulama</id><content type="html" xml:base="https://program.sonsuz.us/posts/luhn-algoritmasi-ile-kart-numarasi-dogrulama/"><![CDATA[<p>Bir kart numarasını yanlış yazdığınızda sistemin hatayı ödeme kuruluşuna ulaşmadan fark etmesi sihir değildir. Çoğu kart numarası, basit ama etkili bir sağlama yöntemi olan <strong>Luhn algoritması</strong> ile kontrol edilebilir. Gelin algoritmanın matematiksel mantığını inceleyelim ve JavaScript ile yeniden kullanılabilir bir doğrulayıcı geliştirelim.</p>

<p><img src="/img/luhn-algoritmasi-ile-54.svg" alt="luhn-algoritmasi-ile-54" /></p>

<p>``</p>
<h2 id="luhn-algoritması-ne-işe-yarar">Luhn algoritması ne işe yarar?</h2>

<p>IBM araştırmacısı Hans Peter Luhn tarafından geliştirilen algoritma; kredi kartı numaraları, IMEI kodları ve bazı kimlik numaralarındaki yazım hatalarını yakalamak için kullanılır. Temel amacı bir numaranın gerçekten aktif, kullanılabilir veya bir kişiye ait olduğunu kanıtlamak değildir. Yalnızca rakam dizisinin belirlenen sağlama kuralına uyup uymadığını söyler.</p>

<p>Başka bir ifadeyle Luhn kontrolünden geçen rastgele bir sayı üretilebilir. Bu nedenle algoritma bir güvenlik veya yetkilendirme mekanizması olarak görülmemelidir.</p>

<table>
  <thead>
    <tr>
      <th>Kontrol</th>
      <th style="text-align: right">Luhn yapabilir mi?</th>
      <th>Açıklama</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Eksik veya hatalı rakamı yakalama</td>
      <td style="text-align: right">Genellikle</td>
      <td>Yaygın veri giriş hatalarını belirler</td>
    </tr>
    <tr>
      <td>Kartın bankada kayıtlı olduğunu doğrulama</td>
      <td style="text-align: right">Hayır</td>
      <td>Banka veya ödeme altyapısı gerekir</td>
    </tr>
    <tr>
      <td>Kart sahibini doğrulama</td>
      <td style="text-align: right">Hayır</td>
      <td>Kimlik doğrulama işlemi değildir</td>
    </tr>
    <tr>
      <td>Sunucuya gitmeden ön kontrol yapma</td>
      <td style="text-align: right">Evet</td>
      <td>Tarayıcıda kolayca çalıştırılabilir</td>
    </tr>
  </tbody>
</table>

<h2 id="matematiksel-mantık">Matematiksel mantık</h2>

<p>Numaranın rakamları sağdan sola doğru işlenir. En sağdaki rakam kontrol basamağıdır. Sağdan başlayarak her ikinci rakam ikiyle çarpılır. Çarpım 9’dan büyükse sonuçtan 9 çıkarılır. Elde edilen bütün değerler toplanır.</p>

<p>Toplam $S$ ile gösterilirse numara şu koşul sağlandığında Luhn açısından geçerlidir:</p>

\[S \bmod 10 = 0\]

<p>Örneğin <code class="language-plaintext highlighter-rouge">79927398713</code> sayısını düşünelim. Sağdan sola ilerlerken uygun konumlardaki rakamlar iki katına çıkarılır. <code class="language-plaintext highlighter-rouge">8</code> rakamının iki katı <code class="language-plaintext highlighter-rouge">16</code> olduğunda $16-9=7$ kullanılır. Bu işlem aslında <code class="language-plaintext highlighter-rouge">16</code> sayısının basamaklarını toplamakla, yani $1+6=7$ hesaplamakla aynıdır.</p>

<table>
  <thead>
    <tr>
      <th style="text-align: right">İki katına çıkarılan değer</th>
      <th style="text-align: right">Dönüştürülmüş değer</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: right">4</td>
      <td style="text-align: right">4</td>
    </tr>
    <tr>
      <td style="text-align: right">8</td>
      <td style="text-align: right">8</td>
    </tr>
    <tr>
      <td style="text-align: right">12</td>
      <td style="text-align: right">3</td>
    </tr>
    <tr>
      <td style="text-align: right">16</td>
      <td style="text-align: right">7</td>
    </tr>
  </tbody>
</table>

<p>Dokuz çıkarma kuralı kodu sadeleştirir; iki basamaklı sonuçları ayrıca metne dönüştürmemize gerek kalmaz.</p>

<h2 id="javascript-ile-uygulama">JavaScript ile uygulama</h2>

<p>Aşağıdaki fonksiyon boşluk ve kısa çizgileri temizler, girdinin yalnızca rakamlardan oluştuğunu denetler ve ardından Luhn toplamını hesaplar:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nf">luhnDogrula</span><span class="p">(</span><span class="nx">kartNumarasi</span><span class="p">)</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">temizNumara</span> <span class="o">=</span> <span class="nc">String</span><span class="p">(</span><span class="nx">kartNumarasi</span><span class="p">).</span><span class="nf">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">[\s</span><span class="sr">-</span><span class="se">]</span><span class="sr">/g</span><span class="p">,</span> <span class="dl">''</span><span class="p">);</span>

  <span class="k">if </span><span class="p">(</span><span class="o">!</span><span class="sr">/^</span><span class="se">\d</span><span class="sr">+$/</span><span class="p">.</span><span class="nf">test</span><span class="p">(</span><span class="nx">temizNumara</span><span class="p">)</span> <span class="o">||</span> <span class="nx">temizNumara</span><span class="p">.</span><span class="nx">length</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="kd">let</span> <span class="nx">toplam</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="kd">let</span> <span class="nx">ikiyleCarp</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>

  <span class="k">for </span><span class="p">(</span><span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="nx">temizNumara</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">let</span> <span class="nx">rakam</span> <span class="o">=</span> <span class="nc">Number</span><span class="p">(</span><span class="nx">temizNumara</span><span class="p">[</span><span class="nx">i</span><span class="p">]);</span>

    <span class="k">if </span><span class="p">(</span><span class="nx">ikiyleCarp</span><span class="p">)</span> <span class="p">{</span>
      <span class="nx">rakam</span> <span class="o">*=</span> <span class="mi">2</span><span class="p">;</span>
      <span class="k">if </span><span class="p">(</span><span class="nx">rakam</span> <span class="o">&gt;</span> <span class="mi">9</span><span class="p">)</span> <span class="nx">rakam</span> <span class="o">-=</span> <span class="mi">9</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="nx">toplam</span> <span class="o">+=</span> <span class="nx">rakam</span><span class="p">;</span>
    <span class="nx">ikiyleCarp</span> <span class="o">=</span> <span class="o">!</span><span class="nx">ikiyleCarp</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="k">return</span> <span class="nx">toplam</span> <span class="o">%</span> <span class="mi">10</span> <span class="o">===</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>

<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="nf">luhnDogrula</span><span class="p">(</span><span class="dl">'</span><span class="s1">7992 7398 713</span><span class="dl">'</span><span class="p">));</span> <span class="c1">// true</span>
<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="nf">luhnDogrula</span><span class="p">(</span><span class="dl">'</span><span class="s1">7992 7398 714</span><span class="dl">'</span><span class="p">));</span> <span class="c1">// false</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">ikiyleCarp</code> değişkeni her turda tersine çevrilerek sıradaki rakama hangi işlemin uygulanacağı belirlenir. Döngünün sağdan başlaması önemlidir; çünkü çiftleme düzeni kontrol basamağına göre kurulmuştur. Boşlukların ve kısa çizgilerin temizlenmesi ise kullanıcıların <code class="language-plaintext highlighter-rouge">1234 5678</code> gibi okunabilir biçimler girmesine izin verir.</p>

<h2 id="kullanırken-nelere-dikkat-edilmeli">Kullanırken nelere dikkat edilmeli?</h2>

<p>Gerçek projelerde Luhn kontrolünü form doğrulamasının yalnızca ilk katmanı olarak kullanın. Kart numarasını günlük dosyalarına yazmayın, gereksiz yere saklamayın ve ödeme işlemlerini PCI DSS uyumlu sağlayıcılara bırakın. İstemci tarafındaki kontrol kullanıcı deneyimini iyileştirir; ancak aynı doğrulama sunucuda da yapılmalıdır, çünkü tarayıcıdaki JavaScript değiştirilebilir.</p>

<p>Sonuç olarak Luhn algoritması güçlü bir şifreleme tekniği değil, hızlı bir hata süzgecidir. Birkaç aritmetik işlemle yaygın yazım yanlışlarını yakalaması, küçük algoritmaların gerçek dünyada ne kadar faydalı olabileceğinin harika bir örneğidir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="luhn algoritması" /><category term="javascript" /><category term="kredi kartı" /><category term="veri doğrulama" /><category term="algoritma" /><category term="programlama" /><summary type="html"><![CDATA[Bir kart numarasını yanlış yazdığınızda sistemin hatayı ödeme kuruluşuna ulaşmadan fark etmesi sihir değildir. Çoğu kart numarası, basit ama etkili bir sağlama yöntemi olan Luhn algoritması ile kontrol edilebilir. Gelin algoritmanın matematiksel mantığını inceleyelim ve JavaScript ile yeniden kullanılabilir bir doğrulayıcı geliştirelim.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/luhn-algoritmasi-ile-54.png" /><media:content medium="image" url="https://program.sonsuz.us/img/luhn-algoritmasi-ile-54.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>