Python ile Anagram oluşturma

Merhaba dostlar.

Bugün, akşamüstü vakitlerinde Google’da “Python örnek kodlar” ve “Python örnekleri” diye arattırdım. Sonuçlar içerisinde bir web sitesine denk geldim ve Python ile Anagram (Bkz. Anagram Nedir?) oluşturduğunu iddia eden bir makale okudum. Mantık olarak çok az doğru gidilse de istenilen sonuca ulaşması imkansızdı iddia edilen makalede. Çünkü pek çok detay atlanmış ve düzensiz bir değer ortaya çıkıyordu. Bende emin olmak için kendim yapmaya karar verdim.

Yazının sonlarına doğru, Anagram tekniğinin doğru algoritmasını ve bunun kodlarını göreceksiniz. Ama “Ben hepsini okuyamam, kodu görsem anlarım arkadaş! Sen sadece kodları ver” diyorsan, tıkla bakalım.

Şimdi bahsettiğim web sitesini ve yukarıda yazdıklarımı bir kenara bırakıp; TÜBİTAK’ın yayınlamış olduğu aşağıdaki soruları nasıl cevaplarız, buna odaklanalım.

Görüntü 011
(Kaynak: TÜBİTAK UEKAE)

 

Önce algoritmayı ele alalım ve neyin ne ifade ettiğini bir kavrayalım.

Anagram tekniğinde; belirtilen cümle veya kelime içerisinde kaç adet harf olduğu tespit edilir ve ardından boşluk karakterler dikkate alınmaksızın, bulunan sonuç alfabetik sıraya alınarak yazılır. Örneğin “merhaba” kelimesini ele alalım. Kelime içerisindeki harfleri, adetleri ile beraber vermiş olduğumuz kelime bazında sıralayacak olursak şu sonuçları elde ederiz (Tablo 1).

Tablo 1: "merhaba" kelimesindeki harfler ve kaç adet olduğunun gösterilmesi
Tablo 1

Yukarıda Anagram için bulunan harf ve adetlerde alfabetik sıralama yaptığından da bahsetmiştik. Tablo 1’deki verileri alfabetik sıralamaya alacak olursak şöyle bir sonuç alacağız, “2a1b1e1h1m1r”.

Peki bu sonuç yeterli mi? Cevap kesinlikle hayır! Çünkü Anagram tekniğinde kodlanacak olan kelime veya cümle içerisindeki harflerden sadece bir tane varsa, sayısal değeri yazılmaz. Haliyle sonucumuz “2abehmr” şeklinde olmalıdır.

Bu nereden anlıyoruz?
TÜBİTAK’ın vermiş olduğu örneği tekrar inceleyelim. “Dünya güneşin etrafında döner” cümlesini ele alalım. İçerisindeki harfleri alfabetik bazında sıralayacak olursak, sonuç aşağıdaki gibi olacaktır (Tablo 2).

Tablo 2: "Dünya güneşin etrafında döner" kelimesindeki harfler ve kaç adet olduğunun gösterilmesi
Tablo 2

Tablo 2’yi tek satırlık bir düzene sokacak olursak bizim bulduğumuz sonuç “3a3D3e1f1g1ı1i5n1ö2r1ş1t2ü1y” şeklinde olacaktır. Peki TÜBİTAK’ın bu soruya vermiş olduğu cevap neydi? Sayfanın en başına gelerek bakıyoruz, bize verdiği cevap, “3a3d3efgıi5nö2rşt2üy” olarak belirtilmiş. Buradan iki sonuç çıkar:

  1. Dikkat ederseniz kelime içerisindeki f,g,ı,i,ş,y harflerinin başında 1 yazmamaktadır, yani sayısal değerini belirtmemiştir. Bu demek oluyor ki, kelime veya cümle içerisindeki tek harfler için sayısal değerini yazmamalıyız.
  2. Bulduğumuz sonuç ile TÜBİTAK’ın bulduğu sonuç arasında bir harf farkı vardır. “Dünya güneşin etrafında döner” cümlesindeki “D” harfi büyüktür. Bulduğumuz sonuç içerisinde “D” büyük iken, TÜBİTAK’ın verdiği sonuç içerisindeki “d” harfi küçüktür. Bu demek oluyor ki, kelime veya cümle içerisindeki harflerin hepsini küçük harf olarak dikkate almalıyız.

 

Buraya kadar Anagram tekniğinin inceliklerini fark etmişsinizdir.

Şimdi, Python’da yazdığım kodları ve bulduğu sonuçları paylaşıyorum. Detaylı anlatım devam edecektir..

Python ile TÜBİTAK sorusunun cevabını bulan kod.

# -*- coding: cp1254 -*-
__author__ = 'EnisKurtay'
import locale
locale.setlocale(locale.LC_ALL, "Turkish_Turkey.1254")
 
def anagram(cumle):
    cumle = cumle.lower()
    liste = []
    for s in set(cumle):
        if (str(s).isspace() == False) and (str(s).isalpha() == True):
            liste.append(s)
    liste.sort(key = locale.strxfrm)
 
    if (liste.__contains__("ı") == True) and (liste.__contains__("i") == True):
        liste.remove("i")
        liste.insert(liste.index("ı") + 1,"i")
 
    sonuc = ""
    for d in liste:
        if cumle.count(d) == 1:
            sonuc = sonuc + "{0}".format(d)
        else:
            sonuc = sonuc + "{0}{1}".format(cumle.count(d), d)
    return sonuc
 
#Birinci sorunun cevabı
print "TÜBİTAK Cevapları..\n(i) : {0}".format(anagram("Dünya güneşin etrafında döner"))
 
#Ikinci sorunun cevabı
tubitakCumleler = ["Su molekülünde üç atom vardır", "Yanma oksijen gerektirir", "Elmas karbondan oluşur"]
for s in tubitakCumleler:
    if anagram(s) == "2a3eg3ij2km2no3rsty":
        print "(ii): {0}".format(s)

Bulduğumuz cevabı da kanıtlayalım.

Görüntü 015


Detaylı Anlatım

Öncelikle anagram adında bir parametrik fonksiyon tanımladım:

def anagram(cumle):

Ardından “cumle” parametresine gelecek değeri, içerisinde bulunan harfleri tekrarlamayacak şekilde döngüye alıp bir listeye aktarıyorum. Fakat listeye aktarmadan önce, gelen değerin harf mi yoksa boşluk karakteri mi olduğuna dikkat ederek listeye aktarıyorum. Hemen bunun sonrasında bu listeyi alfabetik olarak sıralıyorum.

    cumle = cumle.lower()
    liste = []
    for s in set(cumle):
        if (str(s).isspace() == False) and (str(s).isalpha() == True):
            liste.append(s)
 
    #Aşağıdaki sort() fonksiyonun içerisindeki parametreyi birazdan açıklayacağım
    liste.sort(key = locale.strxfrm)

Ancak burada bir şey dikkatimi çekmişti, sizlerle paylaşmak isterim. Python ile Türkçe’de bulunan tüm harfleri içeren bir diziyi sıralamaya doğrudan aldığımda, Türkçe’de bulunan işaretli (ç, ö, ü, ş gibi) karakterlerin sıralamada en sonlarda belirdiğini gözlemledim. İnternette locale kullanarak türkçe karakterli işlemlerde setlocale yapmamız gerektiğini belirten bir yazıyla karşılaştım. Bu yüzden önce locale tanımlarımı yaptım ve ardından sort() fonksiyonun içerisinde böyle bir parametre yazdım.

locale ettikkten sonra herşeyin düzenli ancak “i” harfinin, “ı” harfinden önce geldiğini gördüm. İnternette bu sefer tam bir derinlemesine araştırma yaptım ve bunun çözümü ile alakalı pek çok şey okudum. Hiçbiri istediğim sonucu vermedi. UTF-8, Unicode yöntemleriyle çözmeye çalışıyorlardı fakat bana Windows – 1254 gerekiyordu. Düşünsenize bir kelime içerisindeki harfleri alfabetik sıraya soktunuz ve “cç”, “gğ”, “oö”, “sş”, “uü” harfleri düzenli & doğru gelirken, “iı” düzensiz geliyor(!) Tam bir saçmalık ve kabul edilemez bir durum!

Bende daha fazla vakit harcamamak ve bunun önüne geçmek için kısa bir çözüm buldum. Eğer bulduğum kelimelerin içerisinde “ı” ve “i” harfleri varsa, yerlerini değiştirmem benim için yeterliydi. Çünkü “ı” harfi yoksa, mantıklı olarak “i” harfi aslında olması gereken yerdedir alfabetik sıralamada. 🙂

if (liste.__contains__("ı") == True) and (liste.__contains__("i") == True):
        liste.remove("i")
        liste.insert(liste.index("ı") + 1,"i")

Ardından fonksiyonumuzun geri kalanını yazdım. Aşağıdaki kodlarda her harfin, kaç adet olduğunun bilgisini değişkene ekleyerek, fonksiyon içerisinde bulduğum sonucu “return” deyimi döndürdük.

sonuc = ""
    for d in liste:
        if cumle.count(d) == 1:
            sonuc = sonuc + "{0}".format(d)
        else:
            sonuc = sonuc + "{0}{1}".format(cumle.count(d), d)
    return sonuc

Geriye artık fonksiyonumuzu çağırmak kaldı. Tek yapmamız gereken fonksiyonu çağırırken içine parametre vermektir. Bende TÜBİTAK’ın verdiği soruları çözen kodları yazdım. Eğer siz sadece Anagram’daki değeri görmek istiyorsanız ‘print anagram(“cümle veya kelimenizi buraya yazın”)‘ demeniz yeterlidir.

#Birinci sorunun cevabı
print "TÜBİTAK Cevapları..\n(i) : {0}".format(anagram("Dünya güneşin etrafında döner"))
 
#Ikinci sorunun cevabı
tubitakCumleler = ["Su molekülünde üç atom vardır", "Yanma oksijen gerektirir", "Elmas karbondan oluşur"]
for s in tubitakCumleler:
    if anagram(s) == "2a3eg3ij2km2no3rsty":
        print "(ii): {0}".format(s)

Bir sonraki makalede görüşmek üzere.

Bu makalede geçen kodlar için : https://github.com/eniskurtayyilmaz/Python27/blob/master/anagram.py
Enis Kurtay YILMAZ

Python ile temel dosya işlemleri

Merhaba dostlar.
Bugünkü makalede Python programlama dili ile temel dosya işlemlerini, yeni öğrenenler açısından basit düzeyde gerçekleştireceğiz.

Programlama ile uğraşıyorsanız, er yada geç uğraşacağınız şeyden biri de dosyalardır. Dosyalar içerisinde yapmak isteyeceğiniz işlemlerdir. Bir dosya içerisine veri yazmak veya okumak olabilir bunlar. Bunun için “IO” (input and output) bileşenini kullanmanız gerekmektedir. Bir dosya ile bağlantı kurmak için önce open() fonksiyonunu kullanacağız. Python ile hadi kodlayalım!

dosya = open("yazi.txt", "w")

Yukarıdaki örnekte çalıştığınız dizin üzerinde “yazi.txt” dosyası ile bağlantıyı dosya değişkenine aktararak bağlantısını gerçekleştiriyoruz. Eğer çalıştığınız dizin üzerinde “yazi.txt” diye bir dosya yoksa yeni bir tane oluşturacaktır. Bunun sebebi ise IO bileşeni içerisindeki tanımlanmış mode’tur. Yukarıda “w” yazdığımız yer, aslında bizim tanımladığımız bir mode. Dosya içerisine yazı yazabileceğimizi belirtir.

Modlardan genel olarak bahsedelim biraz. Aslında mode, bir dosya ile yapacağımız işlemden önce erişim tanımlamaktır. Örneğin bir dosyayı sadece okuma işlemleri için modunu “r” yapmamız (read/okuma) yeterlidir. Bu sayede ilgili dosya ile sadece okuma işlemi yapacağımızı belirtmiş oluruz. Doğal olarak okuma modunda açtığımız için, üzerine yazma gibi bir durumumuz söz konusu değildir. Biraz onlardan ve özelliklerinden bahsedelim bahsedelim bu esnada.

Mode Tanım & Açıklama
“r” Read/Okumak anlamına gelir. Bu Mode ile sadece okuma işlemleri yapılır. Eğer böyle bir mode tanımlamış ve ileriki kodunuzda yazma işlemi yapmaya çalıştığınızda hata alırsınız.

Eğer belirttiğiniz dizinde dosya yok ise, hata alırsınız.

“w” Write/Yazmak anlamına gelir. Bu mode ile yazma işlemi yapılır. Eğer belirttiğiniz dizinde dosya yok ise, yeni dosya yaratır.

Eğer belirttiğiniz dizinde dosya var ise önce içindekini siler, ardından tekrardan yeni dosya yaratır.

Örneğin a.txt dosyası içerisinde “Merhaba” yazıyor olsun. Yeni bir “Naber” satırı yazma işlemi gerçekleştirdiğinizde, dosyanız aşağıdaki gibi gözükür.

Naber

“a” Append/Eklemek anlamına gelir. Bu Mode ile mevcut olanın üzerine eklemeler yapar. Eğer belirttiğiniz dizinde dosya yok ise, yeni dosya yaratır.

Eğer belirttiğiniz dizinde dosya var ise dosya içerisindeki yazanlara bir hamlede bulunmaz, yazacağınız yeni içeriği dosyaya ilave eder.

Örneğin a.txt isminde bir dosyanız olsun içerisinde “Merhaba” yazıyor olsun. Siz “a” modunda bağlanıyorsanız ve dosya içerisine yeni bir “Naber” satırı yazma işlemi gerçekleştirdiğinizde, dosyanız aşağıdaki gibi gözükür.

Merhaba
Naber

Bu modlara ek olarak, “w+”, “a+” gibi tanımlarda vardır. Temel anlamda gittiğimiz için başka bir makalede bunlardan bahsedeceğim.

Şimdi Python ile yazi.txt diye bir dosya oluşturalım ve ardından “merhaba\nnaber” yazdıralım. Bildiğiniz üzere “\n” kaçış dizisi ile “naber” yazısının bir alt satıra inmesini sağlayacağız.

dosya = open("yazi.txt","w")
dosya.write("merhaba\nnaber")
dosya.close()

Yukarıdaki kod ile yazi.txt adında bir dosya oluşturuyoruz, tanımladığımız “w” mode ile. Ardından write() fonksiyonunu alt alta gelecek şekilde yazımızı yazdırıyoruz. Dosyaya girip, baktığınızda aşağıdaki gibi gözükecektir.

merhaba
naber

En sondaki close() fonksiyonu ise bu dosya ile işimizin bittiğini, mevcut bağlantının ise sonlandırılmasını belirtiyoruz.

Peki mevcut olan bu dosyayı nasıl okutturabiliriz?

dosya = open("yazi.txt","r")
icerik = dosya.read()
dosya.close()
print satir

Yukarıda fark ettiyseniz, “r” yani okuma modunda dosyaya bağlandım. Ardından icerik adındaki değişkene, read() fonksiyonunu kullanarak dosya içerisindeki tüm verileri aktardım, dosya bağlantısını sonlandırdım. Son satırda da icerik adındaki değişkenin içerisindekini ekrana yazdırdım. Karşınıza aşağıdaki sonuç çıkacaktır.

merhaba
naber

Son bir örnek daha yapalım, bu sefer “a” modunda olsun yani mevcut olanın üzerine eklemeler yapalım “Append” ile.

dosya = open("yazi.txt","a")
dosya.write("iyi senden naber?")
dosya.close()

Bu sefer modu “a” yaptık ve dosya içerisine “iyi senden naber?” yazdık. Ardından mevcut bağlantıyı sonlandırdık.

Peki dosya içerisine girdiğimizde ne görmüş olacağız, ona da bakalım dilerseniz. Aşağıdaki gibi veriler gösterilecektir.

merhaba
naberiyi senden naber?

“naber” ve “iyi senden naber?” neden yanyana oldu? Çünkü kaçış dizisi veya boşluk kullanmadığımız için böyle bir şey gerçekleşti. Yukarıda kaçış dizisini hatırlamışsınızdır “\n” şeklindeydi.

Burası önemli! Çünkü buradan bir sonuç daha çıkarabiliriz. Demek ki write() fonksiyonu satır satır yazmıyor. İmlecin son durduğu yerden yazmaya başlıyor demektir. İpucu isterseniz, alt satıra geçmek için “\n” kaçış dizilerini kullanabiliriz.

Bir sonraki makalede görüşmek dileğiyle.

K. YILMAZ

Python ile girilen tek ve çift sayıların toplamı

Uzun bir süreden sonra tekrardan merhabalar..
Hayatımda son gelişmeleri kısaca özetlemek gerekirse, yaklaşık yedi gün önce(12/06/2015) üniversiteyi bitirdim ve bitirdiğimin ertesi haftasında İzmir’de yazılım geliştirme uzmanı olarak işe başladım..

Bu aralar yeni bir programlama dili öğreniyorum (Python) ve başlangıç seviyesindeki (beginner) arkadaşlar için örnek kod teşkil etmek adına bu yazıyı yazıyorum.

Şimdi dilerseniz şöyle bir senaryo düşünelim..
Bir kullanıcı, altı (6) tane sayıyı girerek, bu sayıların tek/çift durumlarına göre toplamlarını öğrenmek istiyor olsun. Başka bir kullanıcı da oniki (12) sayıyı girmek istiyor olsun.

Yazılımcı ve matematikçi gözden bakacak olursak, bir sayının tek veya çift durumu anlamak için “Sayı 2’ye tam bölündüğünde kalan veriyor mu, vermiyor mu?” durumuna bakmak yeterlidir.

Örneğin 4 sayısını ele alalım. 4 sayısını 2’e böldüğünüzde, kalan sıfırdır. Bildiğiniz üzere programlamada bir sayının modunu almak % işareti ile tanımlanmıştır.

Yukarıdaki senaryoyu dikkate alırsak aslında kullanıcının gireceği sayıların farklı ve değişken olma söz konusu vardır. Örneğin bir kullanıcı altı adet sayıyı hesaplamak istiyor, diğer kullanıcı ise oniki sayıyı..
Haliyle ilk olarak yapacağımız şey, kullanıcının kaç sayıyı hesaplamak istediğini bilmemizdir. Hem bu sayede döngüyü kullanarak girilen sayıların, tek mi çift mi olduğunu anlayabiliriz öyle değil mi?

Şimdi size bu senaryoya göre Python dilinde yazdığım kodları paylaşıyorum.
İyi kodlamalar.

# -*- coding: cp1254 -*-
__author__ = 'EnisKurtay'
 
kac_sayigirilecek = raw_input("Kaç sayı gireceksiniz? : ")
sayilar = []
toplam_teksayilar = 0
toplam_ciftsayilar = 0
 
for sayi in range(0,int(kac_sayigirilecek)):
        sayilar.append(int(raw_input("{0}. sayıyı giriniz : ".format(sayi + 1))))
        if sayilar[sayi] % 2 == 0:
            toplam_ciftsayilar = toplam_ciftsayilar + sayilar[sayi]
        else:
            toplam_teksayilar = toplam_teksayilar + sayilar[sayi]
 
print "Tek sayıların toplamı : {0}\n" \
      "Çift sayıların toplamı : {1}\n" \
      "Toplamda {2} sayı girildi.".format(toplam_teksayilar,toplam_ciftsayilar,kac_sayigirilecek)

K. YILMAZ

Dört senelik bir süreç, Mersin..

Dört senelik bir süreç olan üniversite hayatım dün bitti. Okulu bitirdikten sonraki hafta hemen işe başlamam ve İzmir gibi bir yerde kendi sevdiğim işi bulmam, sanırım tanrının bana verdiği en güzel hediyeydi Amerika’dan döndükten sonra. Bu konuda patronum, ev arkadaşım, iş ortağım ve 2008’de tanıştığım kişiye teşekkürlerim ayrıdır..

Her şeyin başında gelen, yaşattıklarını sıralasam bitmeyecek, hakkını ödemeyeceğim, diğer bir yarım olan “Annem”in emeği sonsuzdur. Her şeye rağmen benimle beraber üç şehir eskiten, en zor şartlarda bile bana yardımcı olan o müstahdem hanım olan anneme çok ama çok teşekkür ederim. O şimdi Mersin’de bir süre deniz, kum ve güneşin tadını çıkaracak ben İzmir’deyken. Annemin arkadaşları olan diğer müstahdem hanımlara ve eşlerine ayrı ayrı teşekkür ediyorum. Üniversite hayatımda onları tanıdığım ve yardımları için, annemle olan sıkı dostluklarına hayran kaldığım için ayrı ayrı teşekkür ediyorum.

Üniversite hayatım boyunca, 2011-2015 yıllarında bir şekilde tanıştığım ve bana değer katan o kadar çok insan var ki hangisine teşekkür yazacağımı bilemiyorum..

Başta hocalarımın bana öğrettiklerine, konular üzerindeki bana aktardıkları bakış açılarına ve deneyimlerine sonsuz teşekkür etmem gerektiğini düşünüyorum. Ne zaman odalarına gitsem veya ne zaman telefon ile kendileriyle iletişim kurduğumda, asla “Hayır” demeyen ve son üç gündür bil hassa vedalaşmaya gittiğim hocalarım için tekrardan sonsuz teşekkür ederim.

Ardından sıkı dostluklar kurduğum Oktay, Tuna, Koray ve Uğur arkadaşlarıma apayrı teşekkür ediyorum. “Vefalı dost” kavramını ne olursa olsun silmedikleri ve yaşattıkları için. Onlara hikâyemizin daha bitmediğini, ilerde görüşeceğimizi ve “dağıtmadan asla toparlayamazsın” sözünü bir kez daha hatırlatmak istiyorum. Hayatlarındaki her şeyin gönüllerince olmasını ve mutlu olmalarını diliyorum.

2011-2015 yıllarını kapsadığı için yazmam gerektiğini ve Amerika’da geç tanıştığımı düşündüğüm; sıkı dostluk kurduğum İbrahim, Murat, İbrahim’e de ayrı teşekkür ederim. Miami’de ve özellikle Myrtle Beach’te her şeyin dibini görmeye çalıştığımız günlerin anısına..

Adını sıralamaya başlasam çok uzun olabilecek, bana bir şekilde değer katan diğer arkadaşlarıma da; yaşadığım güzel maceralar ve entrikalar için ayrı ayrı teşekkür ediyorum kendilerine.

Son zamanlarda gördüğünüz veya gözlemlediğiniz bir diğer eski arkadaşım (arkadaş sıfatına bile layık görmeye utandığım kişi) içinse ona sadece güldüğümü ve “adamlık muhabbetlerinde” aklına geleceğime emin olduğumu belirterek, hayatında başarılar diliyorum. Dilerim bir gün uyanır, benim haricimdeki diğer insanlara özür dileme cesaretini toplar.

Son olarak, bunu demenin bir borç olduğunu düşündüğüm, üniversite hayatımda tek bir kişi için sadece özür dilemek ve hayatında mutluluklar dilemekle kalıyorum.

Gelelim son sözlere..
İyi ilişkiler kurduğum ve her seferinde gözümü bir şekilde açtığımı düşündüğüm üniversite hayatım, acısıyla-tatlısıyla bitti. Keşke dediğim hiçbir şeyin olmadığını sevinçle belirterek, mutlu ve huzurlu ayrılıyorum bu şehirden. Her ilçesini karış karış gezerek gördüğüm, yüzmediğim yerin kalmadığı, radyo yayını bile yaptığım.. Adana’ya sırf kebap yemek ve dostum Tuna’yı görmek için gittiğim, tantuninin ve limonun hiç bitmediği Mersin’i çok özleyeceğimi bilmenizi isterim. İstanbul – Bursa – Mersin derken şimdi sıra İzmir’e geldi.

Hey İzmir! Önümüzdeki yıllarda başka bir planın yoksa sana âşık olmaya geliyorum.

Bu arada..
Siz, çekirdeğe çiğdem diyormuşsunuz? 😉