Python Programlamaya Giriş yazı dizimizin bu bölümünün konusu, Python’da isimler ve nesnelerin eşleştirilmesinin ayrıntıları, ve bu ayrıntıların bazen nasıl bizi şaşırtabileceği. Dizinin bütün yazılarına erişmek için Python Programlamaya Giriş kategorimize bakabilirsiniz.
Nesneler ve referanslar
Elimizde a isimli bir liste olsun. Diyelim bu listeyi kopyalayıp b isimli ikinci ve eş bir liste yaratmak istiyoruz. İlk aklımıza gelen şeyi yapalım ve basit bir atama yapalım.
In [1]:
Devamı...
Python programlamaya giriş konulu yazı dizimizdeki son birkaç bölümde, Python’da tanımlı temel veri tiplerinin kullanımının ayrıntılarından bahsettik. Bu yazıdaki konumuz, daha önce bahsetmediğimiz bir veri yapısı olan “kümeler”. Dizinin bütün yazılarına erişmek için Python Programlamaya Giriş kategorimize bakabilirsiniz.
Bir küme, listelerden farklı olarak, belli bir sırası bulunmayan bir veri topluluğudur; yani elemanlarına indeksleme ile erişilemez. Ayrıca, matematiksel kümeler gibi, aynı elemandan birden fazla barındıramaz. Python’da bir küme yaratmanın birinci yolu, nesneleri küme parantezinde toplayarak vermektir:
In [1]:
Devamı...
Python Programlamaya Giriş dizimizin bir önceki bölümünde dizelerle yapılabilecek işlemleri ve yaygın dize metodlarını özetledik. Bu yazıda dize metodlarından biri olan format() ile dize biçimlendirmeyi daha ayrıntılı işleyeceğiz. Dizinin bütün yazılarına erişmek için Python Programlamaya Giriş kategorimize bakabilirsiniz.
Birçok durumda bir değişkende barındırılan bir değeri uygun bir biçimde düzenleyerek ekrana basmamız gerekir. Bu düzenlemeler ve biçimlendirmeler örneğin şöyle olabilirler:
- Bir kalıp dize içindeki boşlukları doldurmak,
İsim:...., Yaş:.... gibi.
- Sayıları ondalıktan sonra sabit sayıda basamakla vermek:
9.340, -18.731 gibi.
- Sayıları sıfırlarla doldurmak:
099.45, 001.12 gibi.
- Tablo halinde basılan listeleri hizalı olarak, belli boşluklar ayırarak basmak.
- Tablo içeriklerini sağa veya sola yaslamak, ortalamak.
Bu tür düzenlemeler için Python’da kapsamlı bir mini-dil mevcut. Bu tür düzenlemeler, format() metoduyla beraber şu şekilde kullanılır:
Devamı...
Python programlamaya giriş yazı dizimizin bu bölümünde dizelerin kullanımını daha ayrıntılı inceleyeceğiz ve dize veri tipine ait olan metodların bazılarına örneklerle göz atacağız. Dizinin bütün yazılarına erişmek için Python Programlamaya Giriş kategorimize bakabilirsiniz.
Dize, bir veya daha fazla karakterden bir araya gelmiş bir sıralı veri tipidir. Dizelerle düz metin halindeki veriler alınıp işlenebilir. Veriler pek çok zaman düz metin dosyaları halinde bulunur. HTML, XML, JSON veya CSV gibi standartlardaki veriler de düz metinden oluşur. Bir metin verisini dize halinde aldığımızda, dize metodlarını kullanarak bu verileri işleyebilir, biçimlerini değiştirebilir, parçalayabilir, birleştirebilir, sıralayabilir, değişiklik yapabiliriz.
Temel işlemler
Sıralı nesnelerle kullanılan len, in, not in, +, * gibi işlemler dizelerde de aynı şekilde çalışır:
In [1]:
Devamı...
Daha önceki bir bölümde Python’daki liste, çokuz, dize ve sözlük tiplerinin nasıl kullanıldığını kısaca özetlemiştik. Bu ve bunu izleyen üç yazıda liste, sözlük, dize ve küme veri tiplerine dair daha fazla ayrıntı işleyeceğiz. Dizinin bütün yazılarına erişmek için Python Programlamaya Giriş kategorimize bakabilirsiniz.
Bu yazının konusu sıralı nesne (sequential object) olarak anılan liste, çokuz ve dize tipleriyle ilgili bazı işlemlerdir. Bunlara sıralı nesne denmesinin sebebi, içlerinde barındırdıkları nesnelerin sırasının önemli oluşu. Söz gelişi, "merhaba" dizesi ile "baharem" dizesi farklıdır, aynı harfleri barındırmalarına rağmen. Buna karşılık bir sözlük sıralı nesne değildir, çünkü {"ahmet":123, "ayşe":456} ile {"ayşe":456, "ahmet":123} aynı sözlüğü tanımlarlar.
Bu yazıda göreceklerimiz:
- Dilimleme (slicing)
- Öntanımlı fonksiyonlar:
range, len, del, list, tuple, join, all, any, enumerate, max, min, sorted, sum, zip
- Türkçe alfabeye göre sıralama
Dilimleme
Daha önce, bir L sıralı nesnesinin i indeksli bir elemanına L[i] işlemi ile ulaşabildiğimizi görmüştük. Python’da indeksler sıfırdan başladığı için L[i] listenin i+1‘inci elemanını verir.
In [1]:
Devamı...
Yazı dizimizin önceki bir bölümünde Python’un öntanımlı veri tiplerini yüzeysel bir şekilde işlemiştik. Bu yazıda ve takip eden birkaç yazıda liste, dize, sözlük ve küme veri tiplerini daha ayrıntılı işleyeceğiz ve bu tip verilerle yapılabilecek işlemleri sıralayacağız. Dizinin bütün yazılarına erişmek için Python Programlamaya Giriş kategorimize bakabilirsiniz.
Nesneler ve metodlar
Temel kullanım için bunu bilmek çok gerekmese de, Python nesneye yönelik (object-oriented) bir dildir. Python’da tanımladığınız her şey bir nesnedir. Nesneler özel veri yapılarıdır; içlerinde verilerin yanı sıra, o verilerle yapılabilecek işlemleri tanımlayan fonksiyonlar barındırırlar. Söz gelişi, bir liste nesnesinin içinde elemanların değerleri, elemanların ne tipte olduğu, kaç eleman bulunduğu gibi veriler bulunur. Ayrıca listeye eleman ekleme, eleman çıkarma, sıralama gibi işlemler yapan fonksiyonlar da listeyi tanımlayan kodun içindedir. Veri tipinin (sınıfın) tanımı içinde bulunan fonksiyonlara o nesnenin metodları denir.
Herhangi bir veri tipi içinde tanımlanmış isimleri (veri veya metod) dir fonksiyonuyla görebilirsiniz.
In [1]:
Devamı...
Python Programlamaya Giriş yazı dizimizde Python fonksiyonlarının nasıl tanımlandığını, parametre eşleştirmenin ve varsayılan parametrelerin nasıl işlediğini gördük, çeşitli örnekler ve alıştırmalar işledik. Dizinin bütün yazılarına erişmek için Python Programlamaya Giriş kategorimize bakabilirsiniz.
Fonksiyonların her zaman def komutuyla tanımlanması gerekmez. Başka bir yol, lambda komutunu kullanarak isimsiz (“anonymous” – belli bir isme bağlı olmayan) fonksiyonlar yaratmaktır. İsimsiz fonksiyonlar, def komutuyla üretilen fonksiyonlara göre daha kısıtlıdırlar. Buna karşılık, bir fonksiyon nesnesi gereken yerlerde bazı kolaylıklar sağlarlar.
Fonksiyonların lambda komutuyla üretilmesine basit bir örnek olarak, aşağıdaki ifadeyi ele alalım. Burada, aldığı parametrenin karesini döndüren bir fonksiyon yaratıyoruz ve buna f ismini atıyoruz.
In [1]:
Devamı...
Önceki yazılarda verdiğimiz basit örneklerin ötesine geçip biraz daha elle tutulur fonksiyon örnekleri verelim.
- Asallık testi
- Asal çarpanlar
- Standart sapma
- Collatz dizisi uzunluğu
- Taylor serisiyle üstel fonksiyon
Asallık testi
Döngülerden bahsederken, bir sayının asal olup olmadığını belirleyen bir program yazmıştık. Şimdi bunu bir fonksiyon haline getirelim. Parametre değeri bir asal sayıysa fonksiyonumuz True verecek, değilse False verecek.
In [1]:
Devamı...
Python fonksiyonlarının uygulamalarının ardından, şimdi kendiniz uygulayabileceğiniz birkaç fonksiyon alıştırması verelim. Çözümleri bulmak size ait. Buradaki alıştırmaların ötesinde, daha önceki bölümlerde verdiğimiz örnekleri de bir fonksiyona dönüştürmeyi deneyebilirsiniz. Ayrıca internet kaynaklarında pek çok değişik konuda alıştırma örneği bulabilirsiniz.
Dizinin bütün yazılarına erişmek için Python Programlamaya Giriş kategorimize bakabilirsiniz.
- Fonksiyona verilen en küçük parametreyi bulma
- Fibonacci sayıları
- Satranç atının gidebileceği kareler
- Karekök fonksiyonu
- Machin formülü ile pi’yi bulmak
- İkinci derece denklem kökleri
- Mükemmel sayılar
En küçük parametre değeri
Belirsiz sayıda sayısal parametre alıp, parametreler arasındaki en küçük değeri geri veren bir fonksiyon yazın. (İpucu: Parametre paketlemesi kullandığımızda bütün parametrelerin fonksiyon içinde bir çokuza toplandığını görmüştük. Bu çokuz üzerinde bir döngüyle en küçük değeri bulabilirsiniz.)
Örnekler:
Devamı...
Python Programlamaya Giriş yazı dizimize Python fonksiyonlarının temelleriyle devam ediyoruz.
Bir önceki bölümde Python’da fonksiyonların nasıl yaratıldığından ve nasıl çağrıldığından bahsettik. Bir fonksiyon kapalı bir kutu gibidir: İçinde ne olup bittiğini görmeyiz, parametreler yoluyla bilgi veririz ve cevabı bir değer olarak geri alırız. Bu yazıda parametreleri nasıl kullandığımızı inceleyeceğiz.
Parametre eşleştirme
Aldığı parametreleri ekrana yazan basit bir fonksiyonu ele alalım:
In [1]:
Devamı...
Python Programlamaya Giriş yazı dizimize Python fonksiyonlarının temelleriyle devam ediyoruz. Yazı dizimizin şimdiye kadarki bölümlerinde bir programı inşa etmek için gereken bütün yapı taşlarını gördük. Prosedürel programlama denen paradigma içinde programlar birbiri arkasından işlenir, bir karar verilmesi gerektiğinde program akışı iki yoldan birini seçer, veya bir döngü içindeki bir kod parçası tekrarlanır. Teorik olarak, her türlü programı yazmak için bu yapılar yeterli. Ancak, Yogi Berra’nın dediği gibi: Teoride teori ve pratik arasında fark yoktur, ama pratikte vardır. Kod yazarken işlemleri sık sık farklı yerlerde tekrarlamamız gerekir. Söz gelişi, bir yatırımın belli bir dönem sonunda bileşik faizle ne miktara ulaştığını yazmak için bir döngü yazabiliriz. Bu tür bir işlemi büyük bir program içinde değişik yerlerde (mesela farklı yatırım araçları için) kullanmamız gerekebilir. Programcılar böyle tekrarlanan işler için aynı kodu tekrar tekrar yazmaktansa, bunları bir fonksiyon (prosedür veya yordam olarak da bilinir) olarak paketleyip kullanmayı tercih ederler. Fonksiyon kullanmak sayesinde:
- Aynı kodu defalarca yazmak gerekmez.
- Tekrarlama yüzünden doğacak hatalar ortadan kalkar.
- Bellek (RAM) gereksiz yere dolmaz. Kod parçası onlarca kere tekrarlanmak yerine bir kere yazılır.
- Programcı küçük ayrıntılara tekrar tekrar kafa yormak zorunda kalmaz.
- İşleri küçük birimlere bölmek, programlama hatalarını bulmayı kolaylaştırır.
- Programlama dilinin çekirdek tanımında bulunmayan üst seviye işlemleri tek komutla yapmayı sağlar.
- Fonksiyon kütüphaneleri, uzmanlaşmış programcılar tarafından hızlı ve verimli hale getirilebilir.
Bu faydalar sadece Python değil, her türlü programlama dili için geçerlidir tabii.
Bir fonksiyon bir kara kutu gibi düşünülebilir: Aldığı parametreler onun girdisi, verdiği (“döndürdüğü”) değer ise çıktısıdır. Fonksiyonlara istediğiniz sayıda parametre verebilirsiniz. Parametre almayan ve/veya geriye bir değer vermeyen fonksiyonlar da olabilir.
Kütüphane fonksiyonları kullanma
Bir kütüphane belli bir işlev için hazırlanan fonksiyonların topluluğudur. Bir kütüphane matematik fonksiyonlarını toplarken, başka bir kütüphane kelime işleme, bir başkası ağ iletişimi, bir başkası oyun modülleri barındırıyor olabilir. Kütüphaneler bir dilin resmi tanımına dahil olabilir ve kurulumda beraber gelebilir (bu durumda onlara standart kütüphane denir), veya üçüncü kişiler tarafından hazırlanmış olabilir.
Python dili çok zengin bir standart kütüphaneye sahiptir. Matematik işlemleri, istatistik işlemleri, gün ve saat işlemleri, dosya sıkıştırma, internet protokolleri, HTML, işletim sistemi yönetimi, grafik arayüz oluşturma, ve daha bir çok işlem için gereken hazır fonksiyonlar Python ile birlikte gelir. Bunların dışında yüzlerce başka kütüphane de mevcuttur, istediğinizde bunları sisteminize kurup kullanabilirsiniz. Daha sonraki yazılarda kendi kütüphanelerimizi nasıl oluşturacağımızı da göreceğiz. Bu yazıda sadece matematik fonksiyonları kütüphanesini örnek olarak kullanacağız.
Kütüphaneler diskimize kurulu olarak hazır bekliyor olsalar da, onları kullanmak için önce import komutuyla yorumlayıcıya yüklememiz gerekir.
In [1]:
Devamı...
- En uzun Collatz zinciri
- Üstel fonksiyon Taylor serisi
- Karekök bulma
- Machin formülüyle pi’yi bulma
- Lojistik fonksiyon ve kaos
- SIR salgın modeli
En uzun Collatz zinciri
Collatz dizisinden önceki bölümde bahsetmiştik. Diziyi $n$ sayısıyla başlatırsak, sonraki sayıyı şu bulma kuralla buluruz:
- $n_i$ çift sayıysa: $n_{i+1} = n_i/2$
- $n_i$ tek sayıysa: $n_{i+1} = 3n_i+1$
- $n_i=1$ ise dizi sonlanır.
Meselâ 13 ile başlarsak, on eleman uzunlukta olan 13, 40, 20, 10, 5, 16, 8, 4, 2, 1 dizisini elde ederiz. Bu dizinin uzunluğu 10’dur.
Sorumuz şu: Bir milyonun altındaki bütün başlangıç değerleri içinde hangisi en uzun Collatz dizisini verir? (Başlangıçtan sonraki değerler bir milyonun üzerine çıkabilir.)
(Kaynak: Euler Project, 14. problem)
Üstel fonksiyon için Taylor serisi
Üstel fonksiyonun $x=0$ çevresinde bir sonsuz seri ile gösterilebileceğini temel analiz derslerinden biliyoruz.
\[e^x = \sum_{n=0}^{\infty} \frac {x^n}{n!} = 1 + x + \frac{1}{2}x^2 + \frac{1}{6}x^3 + \cdots\]
Bu seri bütün $x$ değerleri için yakınsar, yani her $x$ değeri için yeterince terim ekleyerek $e^x$ değerini istediğimiz hassasiyette hesaplayabiliriz.
$x$ değerini kullanıcıdan sorarak, yukarıdaki seriyle $e^x$ değerini veren bir program yazın. Programın içinde tol isimli bir tolerans değişkeni tanımlayın ve $10^{-10}$ değeri verin. Bir döngü içinde, son terimin mutlak değeri tol‘den küçük olana kadar seriye yeni terimler ekleyin.
Her terimi sıfırdan hesaplamak gereksiz yük bindirecektir. Eklenecek yeni terimi hesaplarken, bir önceki terimi $x$ ile çarpıp, iterasyon değişkeni olan $n$’ye bölmek daha verimli olur.
Çeşitli $x$ ve tol değerleri kullanarak $e^x$ değerlerini, kaç terim gerektiğini, ve son terimi ekrana bastırın.
Örnek çıktı:
Devamı...
Asal sayıları listelemek
Verilen bir (N) sayısından küçükeşit bütün asalları listeleyen bir program yazalım.
Bir önceki yazıda, belli bir sayının asal olup olmadığını tespit eden bir program yazmıştık. Burada, o programı 2 ile $N$ arasındaki her tamsayı için çalıştıracağız.
Devamı...
Döngüler, daha önce bahsettiğimiz karar yapısı if ile benzer bir yapıya sahiptir. Blok kaydırma yapısı ve mantıksal şartlara aşina değilseniz önce python mantık işlemleri ve karşılaştırmaları okumanız iyi olur.
while döngüsü
while döngüleri, bir mantıksal şart mantıksal “doğru” değerine sahip olduğu sürece tekrarlanır. Döngünün sona ermesi için şartın eninde sonunda yanlış hale gelmesi gerekir. Bunun için döngünün içinde değişkenler uygun şekilde güncellenir. Bu güncellemeyi unutursak sonsuz döngü içine düşeriz ve programımız biz zorla kapatmadıkça durmaz.
Basit bir örnekle başlayalım: 10’a kadar olan sayıları sırayla ekrana yazan bir program yazalım.
In [1]:
Devamı...
En basit programlarda bile sık sık “şu şart doğruysa şöyle yap, yoksa yapma”, veya “doğruysa şöyle yap, yanlışsa öbür türlü yap” şeklinde düzenlemelere ihtiyaç duyarız. Sözgelişi, “cevap doğruysa puanı bir arttır”, veya “yanlış sayısı dördün katıysa puanı bir azalt” gibi. Birçok dil gibi Python’da da seçim yapısı if-else komutlarıyla kurulur.
if komutu
Karar yapılarının en basit hali, bir şartın doğruluğunu yoklamak ve doğruysa belli işlemler yapmaktır. Sözgelişi aşağıdaki programa bakalım. Hücreyi Shift-Enter ile çalıştırdığımızda tahminimizi soran bir kutu ortaya çıkacak. Kutuya bir cevap yazıp Enter’e basın.
In [2]:
Devamı...
Yeni başlayanlar için Python programlamayı anlatan yazı dizimizin ikinci bölümünde sayıları, aritmetik işlemlerini, ve Python’daki temel veri tiplerini (listeler, çokuzlar, dizeler, sözlükler) işliyoruz.
Bu yazıda sadece kısa ve işlevsel bir giriş yapıyoruz. Sonraki bölümlerimizde veri yapılarının kullanımından daha fazla bahsedeceğiz.
Sayılar ve aritmetik
Python’da öntanımlı (built-in) üç çeşit sayı var: Tamsayılar, reel sayılar, ve karmaşık sayılar. Reel sayılar bilgisayarda kayan nokta (floating point) biçiminde temsil edilir. Bilimsel hesaplama yapanlar için kayan nokta temsilini iyi anlamak çok mühim, ama bunu daha sonraya bırakalım.
Bu üç sayı tipiyle öntanımlı olarak yedi aritmetik işlem yapılabilir: Toplama (+), çıkarma (-), çarpma (*), bölme (/), tamsayı bölme (//), kalan (%), ve üs alma (**).
In [1]:
Devamı...
Python programlarını yazmak için gereken şeyler çok az: Sadece bir metin editörüne (text editor) ve Python yorumlayıcısına ihtiyacınız var. Metin editörü ile programı yazarsınız, ve yorumlayıcıya bu dosyayı okuyup çalıştırmasını söylersiniz. Hepsi bu.
Metin editörü olarak notepad, emacs, gedit gibi programlar kullanılabilir. Ancak Word, LibreOffice Writer gibi kelime işlemcileri kullanamazsınız. Bunlar yazıları kendilerine özgü bir biçimde saklarlar ve Python yorumlayıcısı bu dosyaları okuyamaz.
Python yorumlayıcısını Python resmi sayfasından indirip kolayca kurabilirsiniz. Her platformda (Windows, MacOS, Unix, Linux,…) çalışabilen bir Python derleyicisi vardır. Bir makinede yazdığınız bir Python programını, gerekli yorumlayıcının mevcut olduğu başka bir makinede, farklı bir işletim sistemi kullansa bile, çalıştırabilirsiniz.
Python yorumlayıcısı sisteminizde mevcut bile olabilir. Linux kullanıyorsanız zaten kuruludur çünkü birçok sistem programı Python kullanır. Ubuntu, Fedora vs gibi paket yönetim sistemi olan bir dağıtım kullanıyorsanız, paket yöneticisi aracılığıyla kurmanız daha iyi olabilir.
Bir editör ve yorumlayıcı, program yazmanız ve çalıştırmanız için yeterlidir. Gerisi teferruattır, ve başlangıç için şart değildir. Ama Python bazı geliştirme araçları size hız ve kolaylık sağlar. Söz gelişi IDLE, Spyder, PyCharm gibi bir IDE (bütünleşik geliştirme ortamı) kullanmayı tercih edebilirsiniz. Bunlardan daha sonra bahsedeceğiz.
Python kurmak için başka bir yol Anaconda veya Canopy gibi Python dağıtımları. Bunların en büyük avantajı, ileri seviye kullanıcıların ihtiyaç duyduğu modüllerin, sürümleri birbiriyle uyumlu olacak şekilde düzenlenerek bir araya getirilmiş olmaları. Spyder, Jupyter Notebook gibi yazılımlar da bu dağıtımlara dahil. Tabii bu modülleri ayrı ayrı da kurabilirsiniz.
Basit etkileşimli kullanım
Python’u işletim sisteminizin komut yorumlayıcısı ile (DOS command prompt veya shell/terminal) çalıştırıp etkileşimli olarak kullanabilirsiniz. Dolar ($) işareti komut yorumlayıcısının işareti. Aşağıdaki ekran görüntüsünde bazı örnekler görülüyor. >>> işareti Python’un bir komut beklediğini gösteriyor. Komutu yazdıktan sonra işlenmesi için Enter tuşuna basın.
Python etkileşimli halde çalışırken, bir ifadeyi yazıp Enter’a basmanız ifadenin değerinin ekrana yazılmasını sağlar. Meselâ “2+2” yazıp Enter’e bastığımızda “4” yazması sadece etkileşimli modda mümkün. Bir betiğin (programın) içinde “2+2” ifadesinin değeri hesaplanır, ama ekrana basılmaz. Betik içindeki bir ifadenin değerinin ekrana basılmasını istiyorsanız için print() fonksiyonunu kullanmalısınız.
Yorumlayıcıyı kapatmak için quit() yazabilir, ya da Ctrl-D (Linux) veya Ctrl-Z (Windows) tuşlarına basabilirsiniz.
Program çalıştırma
Python programları, bir düz metin dosyasına yazılmış Python ifadelerinden ibarettir. Notepad, emacs, gedit gibi herhangi bir düz metin editörü açın ve aşağıdaki satırları yazın. Dosyayı ortalama.py ismiyle kaydedin.
Devamı...
Ali ile Veli tutukludur. Bir gün gardiyan gelir ve bir oyun oynayacaklarını, eğer kazanırlarsa serbest bırakılacaklarını söyler. Oyunun kuralları şöyle: Gardiyan sabah gelip Ali’yi bir odaya götürecek. Veli başka bir odada bekleyecek. Ali’nin getirildiği odada birden dörde kadar numaralanmış dört adet boş kutu olacak. Ali bu kutuları görürken gardiyan bir kutuya cebinden çıkardığı bir kağıdı koyacak. Ali kağıdın hangi kutuya koyulduğunu bilecek yani. Sonra gardiyan cebinden dört adet hilesiz madeni para çıkaracak ve sırayla yazı tura atıp her bir parayı birer kutunun üzerine koyacak. Ali hangi paranın yazı ya da tura geldiğini ve hangisinin hangi kutu üzerinde olduğunu da bilecek. Sonra gardiyan Ali’ye bir parayı seçmesini söyleyecek. Alinin seçtiği para yazı ise turaya, tura ise de yazıya döndürülecek ve Ali odadan çıkarılacak.
Ardından Veli odaya alınacak. Veli kutuların içini göremeyecek ama üzerindeki paraların durumunu görecek. Veli odaya girdikten sonra bir kutuyu seçecek. Eğer doğru kutuyu seçerse ikisi de serbest bırakılacak, bulamazsa tutukluluk devam edecek.
Ali kutuların olduğu odaya girdikten sonra Veli ile aralarında paralar dışında başka hiçbir iletişim olmayacak. Bütün bu bilgiler doğrultusunda Ali ve Veli oyun başlamadan önce beraberce bir strateji belirleyebilecekler. Serbest kalmalarını garantileyecek strateji nasıl olmalıdır?
Üzerinde birden onikiye kadar sayıları yazılı olduğu oniki tane kartımız var. Bu kartla Anaximander, Boethius, Confucius ve Diogenes arasında eşit olarak paylaştırılıyor, yani her biri üç tane kart alıyor. Sonra sırayla aralarında şöyle bir konuşma geçiyor.
Anaximander: Benim kartların birinde 8 var.
Beothius: Kartlarımın hepsinde asal sayılar var.
Confucius: Benim sayılarımın hiçbiri asal değil. Ayrıca üçünün de ortak bir asal çarpanı var.
Diogenes: O zaman her birinizin hangi kartlara sahip olduğunu biliyorum.
Herkes doğruyu söylemişse Anaximander’in kartlarında hangi sayılar vardır?
Çözüm
Anaximander’in kartlarından birinde 8 sayısı var.
Boethius’un kartlarında sadece asal sayılar varmış. Yani 2, 3, 5, 7, 11.
Confucius’un kartlarında da asal olmayan ve ortak bir asal çarpanı olan üç sayı varmış. Bunlar da 4, 6, 9, 10 ve 12 olabilir. 1’in asal çarpanı olmadığı için listede yok. 8 sayısı Anaximander’in kartlarında ve 2 sayısı da asal olduğundan Confucius’un kartlarında olamaz.
Bu bilgilere bakan Diogenes kimde hangi sayıların olduğunu bulabiliyor.
Şimdi bu bilgilere biraz daha bakalım. Boethius’un kartlarında üç tane asal olduğuna göre kalan iki asal Anaximander’de ve Diogenes’te olmalı, çünkü Confucius’ta hiç asal yok. Peki bu asalların dağılımı nasıl olmalı ki Diogenes kendi kartlarına baktığında kimde hangi sayıların olduğunu görebiliyor?
Dikkat edersek asallarla ilgili Boethius’tan başka bilgi veren yok. Yani eğer Anaximander’de asal sayı varsa, Diogenes hangi asal sayıların Boethius’ta hangi asal sayının veya asal sayıların Anaximander’de olduğunu bilemez. O zaman kalan iki asal sayı da Diogenes de olmalı. Bu şekilde Diogenes Boethius’un üç sayısını da bilebilir.
Şimdi kalan sayılara bakalım. 8 sayısı Anaximander’deydi. O zaman 1, 4, 6, 9, 10, 12 sayıları kaldı. 1 sayısı kimde olmalı?
1 sayısı eğer Diogenes’te olsa, o zaman Diogenes 4, 6, 9, 10 ve 12 sayılarının hangi üçünün Confucius’ta, hangi ikisinin de Anaximander’de olduğunu bulamaz. Olasılıklara bakalım:
Anaximander: 4, 10 Confucius: 6, 9, 12 (ortak asal çarpan 3)
Anaximander: 9, 12 Confucius: 4, 6, 10 (ortak asal çarpan 2)
ve daha başka dağılımlar da bulunabilir.
Demek ki 1 sayısı Diogenes’te olamaz. 1 sayısı Anaximander’de.
Artık dağıtmamız gereken beş sayı kaldı. 4, 6, 9, 10, 12. Bu sayıların biri Anaximander’de, üçü Confucius’ta, sonuncusu da Diogenes’te. Hangi dağılımda Diogenes herkesin sayılarını bilebilir?
Bunun için şöyle bir tablo yapayım:
| |
|
|
| Anaximander |
Confucius |
Diogenes |
| 10 ya da 9 |
(6, 9, 12) ya da (6, 10, 12) |
4 |
| 9 |
4, 10, 12 |
6 |
| 12, 6, 4 ya da 10 |
(4, 6, 10) ya da (4, 10, 12) ya da (6, 10, 12) ya da (4, 6, 12) |
9 |
| 4 ya da 9 |
(6, 9, 12) ya da ((4, 6, 12) |
10 |
| 9 |
(4, 6, 10) |
12 |
Bu tabloyu Diogenes sütunundan okumaya başlayalım. Eğer Diogenes’te 4, 9 ya da 10 sayılarından biri varsa kalan sayıların dağılımı birden fazla şekilde yapılabiliyor. Bu durumda Diogenes diğerlerinin sayılarını bilemez. Buna karşın Diogenes’in sayıları 6 ya da 12 ise kalan sayıların dağılımı tek şekilde yapılabiliyor. Bu dağılımların ikisinde de Anaximander 9 sayısına sahip oluyor.
Sonuçta Diogenes herkesin sayılarını biliyor ama biz problemi çözünce Diogenes’in hiçbir sayısını bilemiyoruz. Elindeki sayıları bilebileceğimiz tek kişi de Anaximander ve soruda da onun sayıları sorulmuş. 1, 8, 9.
Anaximander de diğerlerinin sayılarını bilemez, ne asal sayıların ne de asal olmayan sayıların dağılımı hakkında bir bilgiye sahip değil.
Boethius kalan iki asal sayının Diogenes’te olduğunu bulabilir ama Diogenes’in son sayısını bulamaz.
Aynı şekilde Confucius da Diogenes’in asal olmayan sayısını bilir ama asalların nasıl dağıldığını bulamaz.
Bu oyun iki kişi arasında ve yanyana dizili 13 taşla oynanıyor. İki oyuncu da sırayla aşağıdaki hamlelerden birini yapıyor:
- Herhangi bir taşı almak.
- Aralarında boşluk olmayacak şekilde duran iki taşı almak.
Bir ya da iki taş alındıktan sonra kalan taşlar birbirlerine yaklaştırılmayacak, yani aralarda boşluklar oluşabilecek.
Son taşı ya da taşları alan oyunu kazanır.
Oyunu kazanmak için bir strateji bulun.