<?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-11T12:05:34+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">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">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">Mastermind Çözücüsü: Sınırlı Tahminle Gizli Kodu Bulan Algoritma</title><link href="https://program.sonsuz.us/posts/mastermind-cozucusu-sinirli-tahminle-gizli-kodu-bulan-algoritma/" rel="alternate" type="text/html" title="Mastermind Çözücüsü: Sınırlı Tahminle Gizli Kodu Bulan Algoritma" /><published>2026-10-11T00:00:00+00:00</published><updated>2026-10-11T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/mastermind-cozucusu-sinirli-tahminle-gizli-kodu-bulan-algoritma</id><content type="html" xml:base="https://program.sonsuz.us/posts/mastermind-cozucusu-sinirli-tahminle-gizli-kodu-bulan-algoritma/"><![CDATA[<p>Mastermind, birkaç renkli pimin masum görünümü altında ciddi bir arama problemi saklar. Oyuncunun amacı, sınırlı sayıdaki tahminle gizli kodu bulmaktır. Her tahminden sonra alınan “doğru renk ve doğru konum” ile “doğru renk, yanlış konum” ipuçları, olası kodları adım adım elemeyi sağlar. Gelin bu mantığı bilgisayara öğretelim ve şansa güvenmek yerine sistematik düşünen bir çözücü geliştirelim.
``</p>

<h2 id="problemi-matematiksel-olarak-tanımlayalım">Problemi matematiksel olarak tanımlayalım</h2>

<p>Kod uzunluğu $n$, kullanılabilecek renk sayısı ise $k$ olsun. Renk tekrarına izin verildiğinde toplam olası kod sayısı:</p>

\[N = k^n\]

<p>Örneğin klasik bir oyunda $n=4$ ve $k=6$ ise:</p>

\[N = 6^4 = 1296\]

<p>Bu sayı bilgisayar için oldukça küçüktür. Dolayısıyla bütün kodları üretip her ipucundan sonra uyumsuz olanları silmek mümkündür. Algoritmanın temel fikri şöyledir:</p>

<ol>
  <li>Bütün olası kodları oluştur.</li>
  <li>Bir tahmin seç.</li>
  <li>Tahmine verilen geri bildirimi al.</li>
  <li>Aynı geri bildirimi üretmeyecek adayları ele.</li>
  <li>Tek aday kalana veya kod bulunana kadar tekrarla.</li>
</ol>

<h2 id="geri-bildirim-nasıl-hesaplanır">Geri bildirim nasıl hesaplanır?</h2>

<p>Mastermind değerlendirmesinde iki değer bulunur:</p>

<table>
  <thead>
    <tr>
      <th>İpucu</th>
      <th>Anlamı</th>
      <th>Örnek</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Siyah pim</td>
      <td>Renk ve konum doğru</td>
      <td>Gizli <code class="language-plaintext highlighter-rouge">1234</code>, tahmin <code class="language-plaintext highlighter-rouge">1536</code>: <code class="language-plaintext highlighter-rouge">1</code> doğru</td>
    </tr>
    <tr>
      <td>Beyaz pim</td>
      <td>Renk doğru, konum yanlış</td>
      <td>Gizli <code class="language-plaintext highlighter-rouge">1234</code>, tahmin <code class="language-plaintext highlighter-rouge">2416</code>: <code class="language-plaintext highlighter-rouge">2</code> ve <code class="language-plaintext highlighter-rouge">4</code> yanlış yerde</td>
    </tr>
    <tr>
      <td>Boş</td>
      <td>Renk kodda yok</td>
      <td>Gizli <code class="language-plaintext highlighter-rouge">1234</code>, tahmindeki <code class="language-plaintext highlighter-rouge">6</code></td>
    </tr>
  </tbody>
</table>

<p><img src="/img/mastermind-cozucusu-sinirli-32.svg" alt="mastermind-cozucusu-sinirli-32" /></p>

<p>Önce tam eşleşmeleri saymak önemlidir. Ardından bu konumlar değerlendirme dışı bırakılarak kalan renklerin ortak miktarı hesaplanır. Aksi hâlde tekrarlanan renkler iki kez sayılabilir; algoritmik muz kabuğu tam olarak burada duruyor!</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="n">collections</span> <span class="kn">import</span> <span class="n">Counter</span>
<span class="kn">from</span> <span class="n">itertools</span> <span class="kn">import</span> <span class="n">product</span>

<span class="k">def</span> <span class="nf">puanla</span><span class="p">(</span><span class="n">gizli</span><span class="p">,</span> <span class="n">tahmin</span><span class="p">):</span>
    <span class="n">tam</span> <span class="o">=</span> <span class="nf">sum</span><span class="p">(</span><span class="n">a</span> <span class="o">==</span> <span class="n">b</span> <span class="k">for</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="ow">in</span> <span class="nf">zip</span><span class="p">(</span><span class="n">gizli</span><span class="p">,</span> <span class="n">tahmin</span><span class="p">))</span>

    <span class="n">kalan_gizli</span> <span class="o">=</span> <span class="p">[</span><span class="n">a</span> <span class="k">for</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="ow">in</span> <span class="nf">zip</span><span class="p">(</span><span class="n">gizli</span><span class="p">,</span> <span class="n">tahmin</span><span class="p">)</span> <span class="k">if</span> <span class="n">a</span> <span class="o">!=</span> <span class="n">b</span><span class="p">]</span>
    <span class="n">kalan_tahmin</span> <span class="o">=</span> <span class="p">[</span><span class="n">b</span> <span class="k">for</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="ow">in</span> <span class="nf">zip</span><span class="p">(</span><span class="n">gizli</span><span class="p">,</span> <span class="n">tahmin</span><span class="p">)</span> <span class="k">if</span> <span class="n">a</span> <span class="o">!=</span> <span class="n">b</span><span class="p">]</span>

    <span class="n">cg</span> <span class="o">=</span> <span class="nc">Counter</span><span class="p">(</span><span class="n">kalan_gizli</span><span class="p">)</span>
    <span class="n">ct</span> <span class="o">=</span> <span class="nc">Counter</span><span class="p">(</span><span class="n">kalan_tahmin</span><span class="p">)</span>
    <span class="n">yanlis_yer</span> <span class="o">=</span> <span class="nf">sum</span><span class="p">((</span><span class="n">cg</span> <span class="o">&amp;</span> <span class="n">ct</span><span class="p">).</span><span class="nf">values</span><span class="p">())</span>
    <span class="k">return</span> <span class="n">tam</span><span class="p">,</span> <span class="n">yanlis_yer</span>
</code></pre></div></div>

<p>Bu fonksiyon, iki kod arasındaki ilişkiyi <code class="language-plaintext highlighter-rouge">(tam, yanlış_yer)</code> biçiminde döndürür. <code class="language-plaintext highlighter-rouge">Counter</code> kesişimi, her rengin yalnızca iki tarafta bulunan en küçük adedi kadar sayılmasını sağlar.</p>

<h2 id="adayları-filtreleyen-çözücü">Adayları filtreleyen çözücü</h2>

<p>Her turda yalnızca alınan ipucuyla uyumlu kodları tutabiliriz:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">tum_kodlar</span><span class="p">(</span><span class="n">renkler</span><span class="p">,</span> <span class="n">uzunluk</span><span class="p">):</span>
    <span class="k">return</span> <span class="nf">list</span><span class="p">(</span><span class="nf">product</span><span class="p">(</span><span class="n">renkler</span><span class="p">,</span> <span class="n">repeat</span><span class="o">=</span><span class="n">uzunluk</span><span class="p">))</span>

<span class="k">def</span> <span class="nf">adaylari_filtrele</span><span class="p">(</span><span class="n">adaylar</span><span class="p">,</span> <span class="n">tahmin</span><span class="p">,</span> <span class="n">cevap</span><span class="p">):</span>
    <span class="k">return</span> <span class="p">[</span><span class="n">kod</span> <span class="k">for</span> <span class="n">kod</span> <span class="ow">in</span> <span class="n">adaylar</span> <span class="k">if</span> <span class="nf">puanla</span><span class="p">(</span><span class="n">kod</span><span class="p">,</span> <span class="n">tahmin</span><span class="p">)</span> <span class="o">==</span> <span class="n">cevap</span><span class="p">]</span>

<span class="n">renkler</span> <span class="o">=</span> <span class="nf">range</span><span class="p">(</span><span class="mi">6</span><span class="p">)</span>
<span class="n">adaylar</span> <span class="o">=</span> <span class="nf">tum_kodlar</span><span class="p">(</span><span class="n">renkler</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>

<span class="n">tahmin</span> <span class="o">=</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">cevap</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>  <span class="c1"># Oyundan veya kullanıcıdan alınır
</span><span class="n">adaylar</span> <span class="o">=</span> <span class="nf">adaylari_filtrele</span><span class="p">(</span><span class="n">adaylar</span><span class="p">,</span> <span class="n">tahmin</span><span class="p">,</span> <span class="n">cevap</span><span class="p">)</span>

<span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">Kalan aday:</span><span class="sh">"</span><span class="p">,</span> <span class="nf">len</span><span class="p">(</span><span class="n">adaylar</span><span class="p">))</span>
</code></pre></div></div>

<p>Filtreleme neden doğrudur? Gerçek gizli kod, yapılan tahmin karşısında verilen cevabı üretmek zorundadır. Bir aday farklı puan üretiyorsa onun gizli kod olması mantıksal olarak imkânsızdır.</p>

<h2 id="tahmin-seçme-stratejileri">Tahmin seçme stratejileri</h2>

<table>
  <thead>
    <tr>
      <th>Strateji</th>
      <th>Avantaj</th>
      <th>Dezavantaj</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>İlk adayı seç</td>
      <td>Çok kolay ve hızlı</td>
      <td>Gereksiz fazla tur sürebilir</td>
    </tr>
    <tr>
      <td>Rastgele aday</td>
      <td>Basit ve eğlenceli</td>
      <td>Başarı kararlı değildir</td>
    </tr>
    <tr>
      <td>En çok renk çeşitliliği</td>
      <td>Başlangıçta bilgi toplar</td>
      <td>Her durumda en iyi değildir</td>
    </tr>
    <tr>
      <td>Minimax</td>
      <td>En kötü durumu küçültür</td>
      <td>Daha fazla hesaplama ister</td>
    </tr>
  </tbody>
</table>

<p>Minimax yaklaşımı, her olası tahminin adayları hangi cevap gruplarına böleceğini inceler. En büyük grubun boyutu $G(t)$ olsun. Seçilecek tahmin:</p>

\[t^* = \arg\min_t G(t)\]

<p>Böylece algoritma, rakibin verebileceği en az yardımcı cevapta bile mümkün olduğunca az aday bırakmaya çalışır. Bu, “Umarım şansım yaver gider” yerine “En kötü ihtimale hazırım” demektir.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">minimax_tahmin</span><span class="p">(</span><span class="n">adaylar</span><span class="p">):</span>
    <span class="n">en_iyi</span><span class="p">,</span> <span class="n">en_kotu_boyut</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="nf">float</span><span class="p">(</span><span class="sh">"</span><span class="s">inf</span><span class="sh">"</span><span class="p">)</span>

    <span class="k">for</span> <span class="n">tahmin</span> <span class="ow">in</span> <span class="n">adaylar</span><span class="p">:</span>
        <span class="n">gruplar</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="k">for</span> <span class="n">gizli</span> <span class="ow">in</span> <span class="n">adaylar</span><span class="p">:</span>
            <span class="n">sonuc</span> <span class="o">=</span> <span class="nf">puanla</span><span class="p">(</span><span class="n">gizli</span><span class="p">,</span> <span class="n">tahmin</span><span class="p">)</span>
            <span class="n">gruplar</span><span class="p">[</span><span class="n">sonuc</span><span class="p">]</span> <span class="o">=</span> <span class="n">gruplar</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="n">sonuc</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="n">en_buyuk_grup</span> <span class="o">=</span> <span class="nf">max</span><span class="p">(</span><span class="n">gruplar</span><span class="p">.</span><span class="nf">values</span><span class="p">())</span>
        <span class="k">if</span> <span class="n">en_buyuk_grup</span> <span class="o">&lt;</span> <span class="n">en_kotu_boyut</span><span class="p">:</span>
            <span class="n">en_iyi</span> <span class="o">=</span> <span class="n">tahmin</span>
            <span class="n">en_kotu_boyut</span> <span class="o">=</span> <span class="n">en_buyuk_grup</span>

    <span class="k">return</span> <span class="n">en_iyi</span>
</code></pre></div></div>

<p>Bu sürüm öğretici ve orta ölçekli oyunlar için yeterlidir. Daha büyük problemlerde önbellekleme, örnekleme veya bilgi entropisi kullanılabilir. Entropi yaklaşımı, beklenen bilgi kazancını yükseltmeye çalışır:</p>

\[H = -\sum_i p_i \log_2 p_i\]

<p>Sonuç olarak Mastermind çözücüsü; kombinatorik arama, kısıt yayılımı ve karar teorisini tek projede buluşturur. Aynı yaklaşım parola benzeri bulmacalara, test optimizasyonuna ve hata teşhisine de uyarlanabilir. Renkli pimlerle başlayan macera, küçük ama oldukça şık bir yapay zekâ uygulamasına dönüşür.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Proje" /><category term="mastermind" /><category term="python" /><category term="algoritma" /><category term="minimax" /><category term="mantık" /><category term="yapay zeka" /><summary type="html"><![CDATA[Mastermind, birkaç renkli pimin masum görünümü altında ciddi bir arama problemi saklar. Oyuncunun amacı, sınırlı sayıdaki tahminle gizli kodu bulmaktır. Her tahminden sonra alınan “doğru renk ve doğru konum” ile “doğru renk, yanlış konum” ipuçları, olası kodları adım adım elemeyi sağlar. Gelin bu mantığı bilgisayara öğretelim ve şansa güvenmek yerine sistematik düşünen bir çözücü geliştirelim.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/mastermind-cozucusu-sinirli-32.png" /><media:content medium="image" url="https://program.sonsuz.us/img/mastermind-cozucusu-sinirli-32.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Modüler Aritmetik ve Hızlı Üs Alma: Kriptografinin Matematik Motoru</title><link href="https://program.sonsuz.us/posts/moduler-aritmetik-ve-hizli-us-alma-kriptografinin-matematik-motoru/" rel="alternate" type="text/html" title="Modüler Aritmetik ve Hızlı Üs Alma: Kriptografinin Matematik Motoru" /><published>2026-10-11T00:00:00+00:00</published><updated>2026-10-11T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/moduler-aritmetik-ve-hizli-us-alma-kriptografinin-matematik-motoru</id><content type="html" xml:base="https://program.sonsuz.us/posts/moduler-aritmetik-ve-hizli-us-alma-kriptografinin-matematik-motoru/"><![CDATA[<p><img src="/img/moduler-aritmetik-ve-31.svg" alt="moduler-aritmetik-ve-31" /></p>

<p>Günlük matematikte sayılar büyüdükçe hesaplar zorlaşır; kriptografide ise sayılar yalnızca büyümez, adeta gökdelen olur. Binlerce bitlik anahtarlarla çalışırken sıradan üs alma yöntemleri bilgisayarı terletebilir. Modüler aritmetik ve hızlı üs alma, bu devasa işlemleri yönetilebilir parçalara ayırarak RSA ve Diffie–Hellman gibi sistemlerin çalışmasını sağlayan temel araçlardır.</p>

<p>``</p>

<h2 id="modüler-aritmetik-sayıların-saat-düzeni">Modüler aritmetik: Sayıların saat düzeni</h2>

<p>Modüler aritmetiği anlamanın en kolay yolu bir saat düşünmektir. Saat 10 iken beş saat ilerlerseniz 15 değil, 3 sonucuna ulaşırsınız. Çünkü saat üzerindeki değerler 12’ye göre döngüseldir:</p>

\[10 + 5 ≡ 3 \pmod{12}\]

<p>Genel olarak iki sayı, bir $m$ modülüne bölündüklerinde aynı kalanı veriyorsa eşdeğerdir:</p>

\[a ≡ b \pmod{m}\]

<p>Bu yaklaşımın önemli avantajı, ara sonuçların sürekli küçültülebilmesidir. Örneğin çarpma için şu özellik geçerlidir:</p>

\[(a \cdot b) \bmod m = ((a \bmod m)(b \bmod m)) \bmod m\]

<p>Dolayısıyla dev sayıları sonuna kadar taşımak yerine her adımda mod alabiliriz.</p>

<table>
  <thead>
    <tr>
      <th>Normal işlem</th>
      <th>Modüler karşılığı</th>
      <th>Faydası</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>$a+b$</td>
      <td>$(a \bmod m+b \bmod m)\bmod m$</td>
      <td>Toplamı küçük tutar</td>
    </tr>
    <tr>
      <td>$a\cdot b$</td>
      <td>$((a\bmod m)(b\bmod m))\bmod m$</td>
      <td>Büyük çarpımları sınırlar</td>
    </tr>
    <tr>
      <td>$a^n$</td>
      <td>Tekrarlı kare alma</td>
      <td>Üs hesabını hızlandırır</td>
    </tr>
    <tr>
      <td>Bölme</td>
      <td>Modüler ters ile çarpma</td>
      <td>Alan yapısında bölmeyi mümkün kılar</td>
    </tr>
  </tbody>
</table>

<h2 id="neden-doğrudan-üs-almıyoruz">Neden doğrudan üs almıyoruz?</h2>

<p>$7^{13} \bmod 11$ gibi küçük bir işlem doğrudan hesaplanabilir. Ancak kriptografide üsler yüzlerce veya binlerce bitten oluşabilir. Önce $a^n$ değerini üretip sonra mod almak, bellekte gereksiz büyüklükte bir sayı oluşturur.</p>

<p>Ayrıca üssü kadar çarpma yapan basit yöntem $O(n)$ zaman karmaşıklığına sahiptir. Hızlı üs alma, üssün ikili gösteriminden yararlanarak bu maliyeti $O(\log n)$ seviyesine indirir. Aradaki fark, bisikletle kıtalar arası yolculuk yapmak ile hızlı trene binmek gibidir.</p>

<h2 id="hızlı-üs-alma-nasıl-çalışır">Hızlı üs alma nasıl çalışır?</h2>

<p>Temel fikir, üssü sürekli ikiye bölmek ve tabanı karelemektir. Örneğin:</p>

\[a^{13}=a^{8}a^{4}a^{1}\]

<p>Çünkü $13$ sayısının ikili gösterimi $1101_2$ biçimindedir. İkili gösterimdeki her <code class="language-plaintext highlighter-rouge">1</code>, sonuca hangi kuvvetin katılacağını belirtir. Her aşamada mod alındığı için ara değerler kontrol altında kalır.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">moduler_us</span><span class="p">(</span><span class="n">taban</span><span class="p">,</span> <span class="n">us</span><span class="p">,</span> <span class="n">modul</span><span class="p">):</span>
    <span class="n">sonuc</span> <span class="o">=</span> <span class="mi">1</span>
    <span class="n">taban</span> <span class="o">%=</span> <span class="n">modul</span>

    <span class="k">while</span> <span class="n">us</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
        <span class="c1"># Üs tekse mevcut tabanı sonuca dahil et.
</span>        <span class="k">if</span> <span class="n">us</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
            <span class="n">sonuc</span> <span class="o">=</span> <span class="p">(</span><span class="n">sonuc</span> <span class="o">*</span> <span class="n">taban</span><span class="p">)</span> <span class="o">%</span> <span class="n">modul</span>

        <span class="c1"># Sonraki ikili basamak için tabanı karele.
</span>        <span class="n">taban</span> <span class="o">=</span> <span class="p">(</span><span class="n">taban</span> <span class="o">*</span> <span class="n">taban</span><span class="p">)</span> <span class="o">%</span> <span class="n">modul</span>
        <span class="n">us</span> <span class="o">//=</span> <span class="mi">2</span>

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

<span class="nf">print</span><span class="p">(</span><span class="nf">moduler_us</span><span class="p">(</span><span class="mi">7</span><span class="p">,</span> <span class="mi">13</span><span class="p">,</span> <span class="mi">11</span><span class="p">))</span>  <span class="c1"># 2
</span></code></pre></div></div>

<p>Bu fonksiyon yalnızca birkaç çarpma yapar. Python aynı işlemi yerleşik <code class="language-plaintext highlighter-rouge">pow(7, 13, 11)</code> çağrısıyla da gerçekleştirebilir.</p>

<h2 id="kriptografideki-rolü">Kriptografideki rolü</h2>

<p>RSA’da şifreleme kabaca şu denklemle ifade edilir:</p>

\[c = m^e \bmod n\]

<p>Burada $m$ mesajı, $e$ açık üssü, $n$ modülü ve $c$ şifreli metni temsil eder. Şifre çözme ise özel üs $d$ kullanılarak yapılır:</p>

\[m = c^d \bmod n\]

<p>Güvenlik, modüler üs alma işleminin kolay; uygun gizli bilgiler olmadan işlemi tersine çevirmenin ise zor olmasına dayanır. Diffie–Hellman anahtar değişimi ve ElGamal gibi yöntemler de benzer matematiksel yapılardan yararlanır.</p>

<h2 id="uygulamadaki-önemli-ayrıntılar">Uygulamadaki önemli ayrıntılar</h2>

<p>Matematiksel doğruluk tek başına güvenlik anlamına gelmez. Koşullu dallanmalar ve işlem süreleri, yan kanal saldırılarına bilgi sızdırabilir. Gerçek kriptografik uygulamalarda sabit zamanlı algoritmalar, güvenilir kütüphaneler ve yeterince büyük parametreler kullanılmalıdır. Kendi algoritmanızı yazmak öğrenmek için harikadır; üretimde kullanmak ise paraşütü evde dikmeye biraz benzer.</p>

<p>Özetle modüler aritmetik sayıları döngüsel bir alana hapseder, hızlı üs alma da bu alandaki dev kuvvetleri az sayıda adımla hesaplar. İkisi birleştiğinde modern açık anahtarlı kriptografinin sessiz ama son derece güçlü matematik motoru ortaya çıkar.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="modüler aritmetik" /><category term="hızlı üs alma" /><category term="kriptografi" /><category term="algoritma" /><category term="python" /><category term="matematik" /><summary type="html"><![CDATA[Günlük matematikte sayılar büyüdükçe hesaplar zorlaşır; kriptografide ise sayılar yalnızca büyümez, adeta gökdelen olur. Binlerce bitlik anahtarlarla çalışırken sıradan üs alma yöntemleri bilgisayarı terletebilir. Modüler aritmetik ve hızlı üs alma, bu devasa işlemleri yönetilebilir parçalara ayırarak RSA ve Diffie–Hellman gibi sistemlerin çalışmasını sağlayan temel araçlardır.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/moduler-aritmetik-ve-31.png" /><media:content medium="image" url="https://program.sonsuz.us/img/moduler-aritmetik-ve-31.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Nesneler Kutulara Nasıl Dağıtılır? Dört Temel Kombinatorik Senaryo</title><link href="https://program.sonsuz.us/posts/nesneler-kutulara-nasil-dagitilir-dort-temel-kombinatorik-senaryo/" rel="alternate" type="text/html" title="Nesneler Kutulara Nasıl Dağıtılır? Dört Temel Kombinatorik Senaryo" /><published>2026-10-11T00:00:00+00:00</published><updated>2026-10-11T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/nesneler-kutulara-nasil-dagitilir-dort-temel-kombinatorik-senaryo</id><content type="html" xml:base="https://program.sonsuz.us/posts/nesneler-kutulara-nasil-dagitilir-dort-temel-kombinatorik-senaryo/"><![CDATA[<p><img src="/img/nesneler-kutulara-nasil-44.svg" alt="nesneler-kutulara-nasil-44" /></p>

<p>Bir çekmecedeki çorapları bölmelere, sunucudaki görevleri işlemcilere veya şekerleri çocuklara dağıttığımızı düşünelim. Bu örneklerin hepsi aynı soruya dönüşür: $n$ nesne, $m$ kutuya kaç farklı biçimde yerleştirilebilir? Ancak cevabı bulmadan önce nesnelerin ve kutuların ayırt edilip edilmediğini bilmeliyiz. Küçük bir ayrıntı gibi görünen bu özellik, sonucu üstel sayılardan bölüşüm sayılarına kadar değiştirebilir.
``</p>
<h2 id="problemin-iki-kritik-sorusu">Problemin iki kritik sorusu</h2>

<p>Bir nesnenin ayırt edilebilir olması, ona bir kimlik verebilmemiz demektir. Örneğin Ali’nin kitabı ile Ece’nin kitabı farklıdır. Özdeş bilyeler ise ayırt edilemez. Benzer biçimde numaralandırılmış dolaplar ayırt edilebilirken aynı türden isimsiz kutular ayırt edilemez.</p>

<p>İkinci karar, boş kutulara izin verilip verilmediğidir. “Her kutuda en az bir nesne bulunmalı” koşulu, özellikle dahil etme–hariç tutma ve Stirling sayıları gibi araçları sahneye çıkarır.</p>

<table>
  <thead>
    <tr>
      <th>Nesneler</th>
      <th>Kutular</th>
      <th style="text-align: right">Boş kutu serbestse</th>
      <th style="text-align: right">Boş kutu yasaksa</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Ayırt edilebilir</td>
      <td>Ayırt edilebilir</td>
      <td style="text-align: right">$m^n$</td>
      <td style="text-align: right">$m!S(n,m)$</td>
    </tr>
    <tr>
      <td>Ayırt edilemez</td>
      <td>Ayırt edilebilir</td>
      <td style="text-align: right">$\binom{n+m-1}{m-1}$</td>
      <td style="text-align: right">$\binom{n-1}{m-1}$</td>
    </tr>
    <tr>
      <td>Ayırt edilebilir</td>
      <td>Ayırt edilemez</td>
      <td style="text-align: right">$\sum_{k=1}^{m}S(n,k)$</td>
      <td style="text-align: right">$S(n,m)$</td>
    </tr>
    <tr>
      <td>Ayırt edilemez</td>
      <td>Ayırt edilemez</td>
      <td style="text-align: right">En fazla $m$ parçalı tamsayı bölüşümü</td>
      <td style="text-align: right">Tam $m$ parçalı tamsayı bölüşümü</td>
    </tr>
  </tbody>
</table>

<p>Buradaki $S(n,m)$, ikinci tür Stirling sayısıdır.</p>

<h2 id="her-şeyin-etiketi-varsa">Her şeyin etiketi varsa</h2>

<p>Nesneler ve kutular ayırt edilebiliyorsa her nesnenin önünde $m$ bağımsız seçim bulunur. Çarpma ilkesiyle sonuç:</p>

\[m \cdot m \cdots m=m^n\]

<p>Örneğin üç farklı dosyayı iki farklı sunucuya dağıtmanın $2^3=8$ yolu vardır. Her sunucunun en az bir dosya alması istenirse, boş kalan kutuları çıkarmalıyız:</p>

\[\sum_{i=0}^{m}(-1)^i\binom{m}{i}(m-i)^n=m!S(n,m)\]

<p>Bu ifade örten fonksiyonların sayısıdır. Ayrıca $n&lt;m$ ise bütün kutuları doldurmak imkânsızdır ve sonuç sıfır olur.</p>

<h2 id="yıldızlar-ve-çubuklar">Yıldızlar ve çubuklar</h2>

<p>Nesneler özdeş, kutular etiketliyse dağılım şu denklemin negatif olmayan tam sayı çözümlerini saymaya dönüşür:</p>

\[x_1+x_2+\cdots+x_m=n\]

<p>Nesneleri yıldız, kutu sınırlarını çubuk olarak gösteririz. $n$ yıldız ile $m-1$ çubuğun sıralanması sonucu $\binom{n+m-1}{m-1}$ elde edilir. Her kutu dolu olacaksa önce her kutuya birer nesne koyarız; kalan $n-m$ nesne dağıtılır ve sonuç $\binom{n-1}{m-1}$ olur.</p>

<h2 id="kutuların-etiketi-kaybolursa">Kutuların etiketi kaybolursa</h2>

<p>Farklı nesneleri isimsiz ve boş olmayan kutulara ayırmak, bir kümenin $m$ gruba bölünmesidir. Bu nedenle cevap $S(n,m)$ olur. Stirling sayıları şu bağıntıyla hesaplanabilir:</p>

\[S(n,m)=mS(n-1,m)+S(n-1,m-1)\]

<p>İlk terim yeni nesnenin mevcut gruplardan birine girmesini, ikinci terim tek başına yeni bir grup oluşturmasını temsil eder.</p>

<p>Hem nesneler hem kutular özdeşse artık sıradan kombinasyon formülleri yetmez. Örneğin dört bilyeyi en fazla iki kutuya dağıtmak, $4$ ve $3+1$ ile $2+2$ bölüşümlerini verir. Kutuların yerini değiştirmek yeni sonuç üretmez. Bu alan, tamsayı bölüşümleriyle ilgilidir.</p>

<h2 id="python-ile-stirling-hesabı">Python ile Stirling hesabı</h2>

<p>Aşağıdaki dinamik programlama kodu, farklı nesnelerin isimsiz ve boş olmayan kutulara dağılımını hesaplar:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">stirling</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">m</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">m</span> <span class="o">+</span> <span class="mi">1</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">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="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>

    <span class="k">for</span> <span class="n">objects</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">boxes</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="nf">min</span><span class="p">(</span><span class="n">objects</span><span class="p">,</span> <span class="n">m</span><span class="p">)</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="n">objects</span><span class="p">][</span><span class="n">boxes</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span>
                <span class="n">boxes</span> <span class="o">*</span> <span class="n">dp</span><span class="p">[</span><span class="n">objects</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="n">boxes</span><span class="p">]</span>
                <span class="o">+</span> <span class="n">dp</span><span class="p">[</span><span class="n">objects</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="n">boxes</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</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="n">m</span><span class="p">]</span>

<span class="nf">print</span><span class="p">(</span><span class="nf">stirling</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span>  <span class="c1"># 25
</span></code></pre></div></div>

<p>Dağıtım sorularında altın kural formül ezberlemek değil, önce “Kimlerin etiketi var?” ve “Boş kutu mümkün mü?” sorularını sormaktır. Doğru model seçildiğinde kutuların içindeki kombinatorik karmaşa hızla düzene girer.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="kombinatorik" /><category term="matematik" /><category term="sayma" /><category term="algoritma" /><category term="python" /><category term="olasılık" /><summary type="html"><![CDATA[Bir çekmecedeki çorapları bölmelere, sunucudaki görevleri işlemcilere veya şekerleri çocuklara dağıttığımızı düşünelim. Bu örneklerin hepsi aynı soruya dönüşür: $n$ nesne, $m$ kutuya kaç farklı biçimde yerleştirilebilir? Ancak cevabı bulmadan önce nesnelerin ve kutuların ayırt edilip edilmediğini bilmeliyiz. Küçük bir ayrıntı gibi görünen bu özellik, sonucu üstel sayılardan bölüşüm sayılarına kadar değiştirebilir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/nesneler-kutulara-nasil-44.png" /><media:content medium="image" url="https://program.sonsuz.us/img/nesneler-kutulara-nasil-44.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Stirling ve Bell Sayılarıyla Küme Parçalanmasının Matematiği</title><link href="https://program.sonsuz.us/posts/stirling-ve-bell-sayilariyla-kume-parcalanmasinin-matematigi/" rel="alternate" type="text/html" title="Stirling ve Bell Sayılarıyla Küme Parçalanmasının Matematiği" /><published>2026-10-11T00:00:00+00:00</published><updated>2026-10-11T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/stirling-ve-bell-sayilariyla-kume-parcalanmasinin-matematigi</id><content type="html" xml:base="https://program.sonsuz.us/posts/stirling-ve-bell-sayilariyla-kume-parcalanmasinin-matematigi/"><![CDATA[<p>Bir sınıftaki öğrencileri takımlara, sunucuları kümelere veya görevleri bağımsız gruplara ayırdığınızı düşünün. Grupların sırası önemli değilse ve her eleman tam olarak bir gruba katılacaksa karşımıza <strong>küme parçalanması</strong> çıkar. Bu parçalanmaları belirli sayıda grup için Stirling, toplam olarak ise Bell sayılarıyla hesaplayabiliriz.</p>

<p>``</p>

<h2 id="küme-parçalanması-nedir">Küme parçalanması nedir?</h2>

<p>Bir kümenin parçalanması; boş olmayan, birbirinden ayrık alt kümelerden oluşan ve birleşimleri başlangıç kümesini veren bir koleksiyondur. Örneğin $A={a,b,c}$ kümesinin bazı parçalanmaları şunlardır:</p>

<ul>
  <li>${{a,b,c}}$</li>
  <li>${{a},{b,c}}$</li>
  <li>${{a,b},{c}}$</li>
  <li>${{a},{b},{c}}$</li>
</ul>

<p>Burada grupların sırası önemli değildir. Dolayısıyla ${{a},{b,c}}$ ile ${{b,c},{a}}$ aynı parçalanmadır. Kombinatorikteki küçük ama kritik ayrıntı budur; aksi hâlde gereksiz yere aynı sonucu birkaç kez sayarız.</p>

<h2 id="i̇kinci-tür-stirling-sayıları">İkinci tür Stirling sayıları</h2>

<p>$n$ elemanlı bir kümeyi tam olarak $k$ tane boş olmayan gruba ayırma sayısı <strong>ikinci tür Stirling sayısı</strong> olarak adlandırılır ve $S(n,k)$ biçiminde gösterilir.</p>

<table>
  <thead>
    <tr>
      <th>İfade</th>
      <th>Anlamı</th>
      <th style="text-align: right">Değeri</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>$S(3,1)$</td>
      <td>Üç elemanı tek gruba ayırma</td>
      <td style="text-align: right">1</td>
    </tr>
    <tr>
      <td>$S(3,2)$</td>
      <td>Üç elemanı iki gruba ayırma</td>
      <td style="text-align: right">3</td>
    </tr>
    <tr>
      <td>$S(3,3)$</td>
      <td>Her elemanı ayrı gruba koyma</td>
      <td style="text-align: right">1</td>
    </tr>
    <tr>
      <td>$S(n,0)$</td>
      <td>Pozitif sayıda elemanı sıfır gruba ayırma</td>
      <td style="text-align: right">0</td>
    </tr>
    <tr>
      <td>$S(0,0)$</td>
      <td>Boş kümeyi sıfır gruba ayırma</td>
      <td style="text-align: right">1</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/stirling-ve-bell-71.svg" alt="stirling-ve-bell-71" /></p>

<p>Bu sayıların temel bağıntısı şöyledir:</p>

\[S(n,k)=kS(n-1,k)+S(n-1,k-1)\]

<p>Bağıntının mantığını anlamak için yeni eklenen $n$’inci elemana odaklanalım. Bu eleman mevcut $k$ gruptan birine yerleşirse $kS(n-1,k)$ olasılık elde edilir. Tek başına yeni bir grup oluşturursa geriye kalan elemanların $k-1$ gruba ayrılması gerekir; bu da $S(n-1,k-1)$ seçenektir.</p>

<p>Kapalı form da kullanılabilir:</p>

\[S(n,k)=\frac{1}{k!}\sum_{i=0}^{k}(-1)^{k-i}\binom{k}{i}i^n\]

<p>Ancak programlamada özyinelemeli bağıntıyı dinamik programlamayla uygulamak çoğu zaman daha kolay ve güvenlidir.</p>

<h2 id="bell-sayıları-kaç-grup-olduğunu-bilmiyorsak">Bell sayıları: Kaç grup olduğunu bilmiyorsak</h2>

<p>Grup sayısı önceden belirtilmiyorsa tüm olası $k$ değerlerini toplarız. Elde edilen sonuç <strong>Bell sayısı</strong>dır:</p>

\[B_n=\sum_{k=0}^{n}S(n,k)\]

<p>Örneğin $B_3=1+3+1=5$ olur. Yani üç elemanlı bir küme toplam beş farklı biçimde parçalanabilir. İlk değerler $B_0=1$, $B_1=1$, $B_2=2$, $B_3=5$, $B_4=15$ ve $B_5=52$ şeklindedir. Sayılar hızlı büyür; kümeler kalabalıklaştıkça kombinatorik parti kontrolden çıkar!</p>

<table>
  <thead>
    <tr>
      <th>Dizi</th>
      <th>Sabit grup sayısı var mı?</th>
      <th>Hesaplanan şey</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Stirling $S(n,k)$</td>
      <td>Evet, $k$ grup</td>
      <td>Belirli sayıdaki parçalanmalar</td>
    </tr>
    <tr>
      <td>Bell $B_n$</td>
      <td>Hayır</td>
      <td>Bütün parçalanmaların toplamı</td>
    </tr>
  </tbody>
</table>

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

<p>Aşağıdaki fonksiyon bir tablo oluşturarak Stirling sayılarını hesaplar, ardından ilgili satırı toplayıp Bell sayısını verir:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">stirling_ve_bell</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="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nf">range</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="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>

    <span class="k">for</span> <span class="n">eleman</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">grup</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">eleman</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="n">eleman</span><span class="p">][</span><span class="n">grup</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span>
                <span class="n">grup</span> <span class="o">*</span> <span class="n">dp</span><span class="p">[</span><span class="n">eleman</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="n">grup</span><span class="p">]</span>
                <span class="o">+</span> <span class="n">dp</span><span class="p">[</span><span class="n">eleman</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="n">grup</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</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">sum</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">n</span><span class="p">])</span>

<span class="n">stirling_satiri</span><span class="p">,</span> <span class="n">bell</span> <span class="o">=</span> <span class="nf">stirling_ve_bell</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
<span class="nf">print</span><span class="p">(</span><span class="n">stirling_satiri</span><span class="p">)</span>  <span class="c1"># [0, 1, 15, 25, 10, 1]
</span><span class="nf">print</span><span class="p">(</span><span class="n">bell</span><span class="p">)</span>             <span class="c1"># 52
</span></code></pre></div></div>

<p>Algoritma $O(n^2)$ zamanda ve $O(n^2)$ bellekte çalışır. Yalnızca Bell sayısı veya son satır gerekiyorsa bellek kullanımı iki satır saklanarak $O(n)$ seviyesine indirilebilir.</p>

<p>Bu diziler yalnızca teorik oyuncaklar değildir. Veri kümeleme, eşdeğerlik sınıfları, ağ bölümlendirme, görev gruplama ve dağıtık sistem tasarımı gibi alanlarda ortaya çıkar. Stirling sayıları “tam kaç grup?”, Bell sayıları ise “toplam kaç farklı düzen?” sorusunun zarif cevabıdır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="stirling sayıları" /><category term="bell sayıları" /><category term="kombinatorik" /><category term="küme teorisi" /><category term="dinamik programlama" /><summary type="html"><![CDATA[Bir sınıftaki öğrencileri takımlara, sunucuları kümelere veya görevleri bağımsız gruplara ayırdığınızı düşünün. Grupların sırası önemli değilse ve her eleman tam olarak bir gruba katılacaksa karşımıza küme parçalanması çıkar. Bu parçalanmaları belirli sayıda grup için Stirling, toplam olarak ise Bell sayılarıyla hesaplayabiliriz.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/stirling-ve-bell-71.png" /><media:content medium="image" url="https://program.sonsuz.us/img/stirling-ve-bell-71.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Tekrarlı Permütasyon ve Kombinasyon: Aynı Elemanlar Oyuna Girerse</title><link href="https://program.sonsuz.us/posts/tekrarli-permutasyon-ve-kombinasyon-ayni-elemanlar-oyuna-girerse/" rel="alternate" type="text/html" title="Tekrarlı Permütasyon ve Kombinasyon: Aynı Elemanlar Oyuna Girerse" /><published>2026-10-11T00:00:00+00:00</published><updated>2026-10-11T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/tekrarli-permutasyon-ve-kombinasyon-ayni-elemanlar-oyuna-girerse</id><content type="html" xml:base="https://program.sonsuz.us/posts/tekrarli-permutasyon-ve-kombinasyon-ayni-elemanlar-oyuna-girerse/"><![CDATA[<p><img src="/img/tekrarli-permutasyon-ve-37.svg" alt="tekrarli-permutasyon-ve-37" /></p>

<p>Bir çekmecede birbirinden ayırt edilemeyen çoraplar, bir şifrede tekrar kullanılabilen rakamlar veya dağıtılmayı bekleyen özdeş şekerler varsa klasik sayma formülleri tek başına yeterli olmayabilir. Çünkü tekrar eden elemanlar bazı düzenlemeleri aynı hâle getirirken, tekrar seçimine izin verilmesi yeni olasılıklar doğurur. İsimleri benzese de <strong>tekrarlı permütasyon</strong> ile <strong>tekrarlı kombinasyon</strong> farklı problemlere cevap verir.
``</p>
<h2 id="önce-klasik-durumu-hatırlayalım">Önce klasik durumu hatırlayalım</h2>

<p>Birbirinden farklı $n$ elemanın tamamı sıralanıyorsa klasik permütasyon formülü şöyledir:</p>

\[P(n)=n!\]

<p>Örneğin A, B ve C harfleri $3!=6$ farklı şekilde sıralanabilir. Sıra önemli değilse ve bu elemanlardan $r$ tanesi seçilecekse kombinasyon kullanılır:</p>

\[\binom{n}{r}=\frac{n!}{r!(n-r)!}\]

<p>Buradaki gizli kahraman, elemanların <strong>ayırt edilebilir</strong> olmasıdır. Elemanlar aynı görünmeye veya seçim sırasında yeniden kullanılmaya başladığında hikâye değişir.</p>

<h2 id="tekrarlı-permütasyon-aynı-elemanlar-yer-değiştirirse">Tekrarlı permütasyon: Aynı elemanlar yer değiştirirse</h2>

<p>$ n $ elemanlı bir dizide bazı elemanlar özdeşse, bunların kendi aralarındaki yer değişimleri yeni bir düzen üretmez. Birinci türden $n_1$, ikinci türden $n_2$ ve devamında $n_k$ adet aynı eleman bulunduğunda:</p>

\[\frac{n!}{n_1!n_2!\cdots n_k!}\]

<p>Örneğin <strong>KAKAO</strong> kelimesinde 5 harf vardır; K ve A ikişer kez, O ise bir kez geçer. Bütün harfleri farklı saysaydık $5!$ düzen bulurduk. Ancak iki K’nin ve iki A’nın yer değiştirmesi sonucu değiştirmez:</p>

\[\frac{5!}{2!2!}=30\]

<p>Paydadaki faktöriyeller, yanlışlıkla birden fazla saydığımız özdeş düzenlemeleri temizleyen birer matematik süpürgesi gibidir.</p>

<blockquote>
  <p>Dikkat: Şifre oluştururken aynı karakterin yeniden kullanılabilmesi farklı bir durumdur. $n$ seçenekle $r$ basamaklı ve sıralı bir kod oluşturuluyorsa sonuç $n^r$ olur. Bu da bazen “tekrarlı permütasyon” diye adlandırılır; fakat özdeş elemanların dizilmesinden kavramsal olarak ayrılır.</p>
</blockquote>

<h2 id="tekrarlı-kombinasyon-seç-istersen-yine-seç">Tekrarlı kombinasyon: Seç, istersen yine seç</h2>

<p>Sıranın önemsiz olduğu ve aynı türün birden fazla seçilebildiği problemlerde tekrarlı kombinasyon kullanılır. $n$ farklı türden toplam $r$ seçim yapmanın sayısı:</p>

\[\binom{n+r-1}{r}=\binom{n+r-1}{n-1}\]

<p>Örneğin çikolata, vanilya ve çilek olmak üzere 3 dondurma çeşidinden 4 top seçelim. Dört topun tamamı çikolata olabilir; tekrar serbesttir. Sonuç:</p>

\[\binom{3+4-1}{4}=\binom{6}{4}=15\]

<p>Bu formülün arkasında <strong>yıldız ve çubuklar</strong> yöntemi bulunur. Dört topu yıldızlarla, üç çeşidi ayıran iki sınırı çubuklarla gösteririz: <code class="language-plaintext highlighter-rouge">**|*|*</code>. Toplam altı konumdan iki çubuğun yerlerini seçmek, dağılımı belirlemeye yeterlidir.</p>

<table>
  <thead>
    <tr>
      <th>Problem türü</th>
      <th style="text-align: right">Sıra önemli mi?</th>
      <th style="text-align: right">Tekrar var mı?</th>
      <th style="text-align: right">Formül</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Klasik permütasyon</td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">Hayır</td>
      <td style="text-align: right">$n!$</td>
    </tr>
    <tr>
      <td>Özdeş elemanlı permütasyon</td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">Elemanlar zaten tekrar eder</td>
      <td style="text-align: right">$\frac{n!}{n_1!\cdots n_k!}$</td>
    </tr>
    <tr>
      <td>Klasik kombinasyon</td>
      <td style="text-align: right">Hayır</td>
      <td style="text-align: right">Hayır</td>
      <td style="text-align: right">$\binom{n}{r}$</td>
    </tr>
    <tr>
      <td>Tekrarlı kombinasyon</td>
      <td style="text-align: right">Hayır</td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">$\binom{n+r-1}{r}$</td>
    </tr>
    <tr>
      <td>Tekrarlı sıralı seçim</td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">$n^r$</td>
    </tr>
  </tbody>
</table>

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

<p>Aşağıdaki fonksiyonlar özdeş elemanlı permütasyonu ve tekrarlı kombinasyonu doğrudan 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">factorial</span><span class="p">,</span> <span class="n">comb</span>

<span class="k">def</span> <span class="nf">ozdes_perm</span><span class="p">(</span><span class="o">*</span><span class="n">adetler</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="n">adetler</span><span class="p">)</span>
    <span class="n">sonuc</span> <span class="o">=</span> <span class="nf">factorial</span><span class="p">(</span><span class="n">toplam</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">adet</span> <span class="ow">in</span> <span class="n">adetler</span><span class="p">:</span>
        <span class="n">sonuc</span> <span class="o">//=</span> <span class="nf">factorial</span><span class="p">(</span><span class="n">adet</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">sonuc</span>

<span class="k">def</span> <span class="nf">tekrarli_kombinasyon</span><span class="p">(</span><span class="n">tur_sayisi</span><span class="p">,</span> <span class="n">secim_sayisi</span><span class="p">):</span>
    <span class="k">return</span> <span class="nf">comb</span><span class="p">(</span><span class="n">tur_sayisi</span> <span class="o">+</span> <span class="n">secim_sayisi</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">secim_sayisi</span><span class="p">)</span>

<span class="nf">print</span><span class="p">(</span><span class="nf">ozdes_perm</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">))</span>          <span class="c1"># KAKAO: 30
</span><span class="nf">print</span><span class="p">(</span><span class="nf">tekrarli_kombinasyon</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">))</span>   <span class="c1"># Dondurma seçimi: 15
</span></code></pre></div></div>

<p>İlk fonksiyon toplam eleman sayısının faktöriyelini hesaplayıp her özdeş grubun faktöriyeline böler. İkinci fonksiyon ise Python’ın <code class="language-plaintext highlighter-rouge">comb</code> aracılığıyla yıldız ve çubuklar formülünü uygular.</p>

<p>Bir soruda formüle atlamadan önce üç soru sorun: <strong>Sıra önemli mi, elemanlar ayırt edilebilir mi, tekrar seçimine izin var mı?</strong> Bu küçük kontrol listesi, benzer görünen sayma problemlerini birbirinden ayırır ve faktöriyeller arasında kaybolmanızı önler.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="matematik" /><category term="permütasyon" /><category term="kombinasyon" /><category term="algoritma" /><category term="python" /><summary type="html"><![CDATA[Bir çekmecede birbirinden ayırt edilemeyen çoraplar, bir şifrede tekrar kullanılabilen rakamlar veya dağıtılmayı bekleyen özdeş şekerler varsa klasik sayma formülleri tek başına yeterli olmayabilir. Çünkü tekrar eden elemanlar bazı düzenlemeleri aynı hâle getirirken, tekrar seçimine izin verilmesi yeni olasılıklar doğurur. İsimleri benzese de tekrarlı permütasyon ile tekrarlı kombinasyon farklı problemlere cevap verir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/tekrarli-permutasyon-ve-37.png" /><media:content medium="image" url="https://program.sonsuz.us/img/tekrarli-permutasyon-ve-37.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>