<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Ahmet Kakıcı &#187; Programlama</title>
	<atom:link href="http://www.ahmetkakici.com/tag/programlama/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.ahmetkakici.com</link>
	<description>Blog</description>
	<lastBuildDate>Fri, 11 Jun 2010 11:56:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Java Soket Programlama &#8211; NetBeans Projesi</title>
		<link>http://www.ahmetkakici.com/programlama/java-soket-programlama-netbeans-projesi/</link>
		<comments>http://www.ahmetkakici.com/programlama/java-soket-programlama-netbeans-projesi/#comments</comments>
		<pubDate>Wed, 03 Jun 2009 11:01:32 +0000</pubDate>
		<dc:creator>Ahmet Kakıcı</dc:creator>
				<category><![CDATA[Programlama]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[socket]]></category>

		<guid isPermaLink="false">http://www.ahmetkakici.com/?p=193</guid>
		<description><![CDATA[Daha önceden detaylı açıklamasını yaptığım programın kaynak kodlarını vermiştim ancak o kodlarda ide tarafından oluşturulan bölümler mevcut değildi. Bugün netbeans kurduktan sonra eski projeleri de su yüzüne çıkardım ve paylaşıma sunuyorum. İndireceğiniz arşivin içinde serverGUI &#8211; odev &#8211; odevx klasörleri mevcut. odevx istemci tarafının kodlarının olduğu klasör, odev ise istemci tarafına ait proje klasörü. serverGUI [...]


Benzer yazılar:<ol><li><a href='http://www.ahmetkakici.com/programlama/programlama-ipuclari/' rel='bookmark' title='Permanent Link: Programlama İpuçları'>Programlama İpuçları</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>Daha önceden detaylı açıklamasını <a href="http://www.ahmetkakici.com/programlama/java-ile-sohbet-programi/" target="_self">yaptığım</a> programın kaynak kodlarını vermiştim ancak o kodlarda ide tarafından oluşturulan bölümler mevcut değildi. Bugün netbeans kurduktan sonra eski projeleri de su yüzüne çıkardım ve paylaşıma sunuyorum.</p>
<p>İndireceğiniz arşivin içinde <strong>serverGUI</strong> &#8211; <strong>odev</strong> &#8211; <strong>odevx</strong> klasörleri mevcut. <strong>odevx </strong>istemci tarafının kodlarının olduğu klasör, <strong>odev</strong> ise istemci tarafına ait proje klasörü. <strong>serverGUI</strong> ise adından da anlaşılabileceği gibi sunucuya ait proje klasörü. <strong>serverGUI </strong>klasörü altıntaki<strong> dist </strong>klasöründe ise projeye ait jar dosyası mevcut, dilerseniz sunucuyu direk olarak bu dosyadan başlatabilirsiniz.</p>
<p>Aşağıda kendi kendime yaptığım konuşmaya ait iki istemci  ve sunucuya ait pencere görüntüsü mevcuttur. Arayüz konusunda çok da yetenekli olmadığım için olabildiğince basit bir şekilde bıraktım.</p>
<p>İndirmek için <a title="İndir beni!" href="http://ahmetkakici.com/dosyalar/java-socket.rar" target="_self">tıklayın</a>, umarım işinize yarar.</p>


<p>Benzer yazılar:<ol><li><a href='http://www.ahmetkakici.com/programlama/programlama-ipuclari/' rel='bookmark' title='Permanent Link: Programlama İpuçları'>Programlama İpuçları</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.ahmetkakici.com/programlama/java-soket-programlama-netbeans-projesi/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Hangi Programlama Dilini Öğrenelim?</title>
		<link>http://www.ahmetkakici.com/programlama/hangi-programlama-dilini-ogrenelim/</link>
		<comments>http://www.ahmetkakici.com/programlama/hangi-programlama-dilini-ogrenelim/#comments</comments>
		<pubDate>Wed, 25 Mar 2009 11:17:55 +0000</pubDate>
		<dc:creator>Ahmet Kakıcı</dc:creator>
				<category><![CDATA[Programlama]]></category>

		<guid isPermaLink="false">http://www.ahmetkakici.com/?p=135</guid>
		<description><![CDATA[İnternette programlama üzerine yazılan çizilen forumların ve sitelerin en gözde muhabbetlerinden biridir bu; hangi dili öğrenmeliyim? Bu sitelerdeki yazıları takip ediyorum da bazen o kadar ilginç şeyler yazılıyor ki soran kişi de sorduğunu pişman olabiliyor. Dil seçimi yanında bazen de dilleri mukayese edip duruyorlar; asp &#8211; php, java &#8211; .net , vs gibi diller onlarca [...]


Benzer yazılar:<ol><li><a href='http://www.ahmetkakici.com/programlama/programlama-ipuclari/' rel='bookmark' title='Permanent Link: Programlama İpuçları'>Programlama İpuçları</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>İnternette programlama üzerine yazılan çizilen forumların ve sitelerin en gözde muhabbetlerinden biridir bu; hangi dili öğrenmeliyim? Bu sitelerdeki yazıları takip ediyorum da bazen o kadar ilginç şeyler yazılıyor ki soran kişi de sorduğunu pişman olabiliyor. Dil seçimi yanında bazen de dilleri mukayese edip duruyorlar; asp &#8211; php, java &#8211; .net , vs gibi diller onlarca kez kez karşılaştırılmış ve karşılaştırılmaya da devam edecektir.</p>
<p>Aslında hangi dili öğreneceğini veya hangi dilin iyi olduğunu bulması çok kolay. Bunun cevabı tam olarak dili öğrenmek isteyen kişilerde saklı ama malesef bu soruyu kendilerine sormak yerine başkalarına soruyorlar.</p>
<p><span id="more-135"></span>Bir bebek düşünün Türkiye toprakları üzerinde dünyaya gelmiş. Gelmiş ama ne konuşması var ne okuması ne de yazması. Sonra çevresinden görüyor bakıyor ki türkçe oldukça popüler bir dil, öğrenmeye başlıyor. Sorgulama var mı? Yok. Tereddüt var mı ? Yok. Peki bu çocuğun çevresinde onlarca dil bilen kişi olsaydı ne olacaktı? İşte o zaman sorgulamaya başlayacak; hangi dili öğrenmeliyim? Ama asıl soracağı a veya b bu dili neden öğrenmeliyim olmalıdır..</p>
<p>Bu bebeğimiz ömrü boyunca Türkiye sınırları içinde yaşayacak ise başlangıç için ne ingilizce ne fransızca öğrenmesinin bir anlamı yoktur. Türkiye&#8217;de yaşayacağı sonucunu çıkarttıktan sonra dil öğrenmeye karar verirse hiçbir sorun yaşamadan dilini öğrenir ve kullanır. Ancak eğer bu sonucu çıkarmadan acaba ne öğreneyim diye sağına soluna sorular sormaya başlarsa işler karışıyor.</p>
<p>Kimileri gelip ingilizce öğrenmelisin diyor. Sebep? Evrensel bir dildir, herkes onu bilir ve bilmeyen iş/ekmek bulamaz. O sırada başka biri geliyor ve diyor ki; fransızca öğren. Sebep? Kibar bir dilmiş, kulağa hoş geliyormuş hatta kadınlar bayılıyormuş! Kimisi hemen itiraz ediyor; çince öğren, diyor. Neden ? Efendim Çin gelecek yüzyıl içinde çok büyüyecekmiş, dünya devi olacakmış ve şimdi çok popüler olmasa da ileride ortalığı kasıp kavuracakmış.</p>
<p>Bizim bebeğin epey kafası karışacak sanırım. Zira Türkiye sınırları dışına çıkmayacak olmasına rağmen ve hatta hayatı boyunca herhangi bir yabancı ile konuşma fırsatı bile olmayacakken kafasına onlarca şey yığılıyor. Sonra her birinden azar azar öğrenip abidik kubidik konuşuyor.</p>
<p>Olması gereken ise hayat boyunca yaşayabileceğiniz şeyleri göz önüne alarak bir dil öğrenmek. Benzetmeleri bırakıp biraz programlama tarafına dönecek olursak örneğin web programlama ile uğraşmayı isteyen bir kişiye C++ öğren demenin bir anlamı yoktur. Kafasına koyduğu iş web programlama ise öncelikle oturup bu işi yapabileceği dilleri çıkartıp artılarını ve eksilerini çıkarması gerekir, daha sonra karşısında oluşan artı ve eksilere göre seçimini yapması daha kolay olur. Bu noktada yine forumlara yazıp sorabilir tabii ki. Benim bu sebeplerden dolayı şu dillerden birini öğrenemem gerekli, elimdekiler bunlar ve yapacaklarım da şunlar. İşte bu aşamadan sonra çok daha mantıklı cevaplar gelecektir.</p>
<p>Kimin söylediğini bilmediğim bir söz ile bu yazıya da son vereyim. Nereye gideceğini bilmiyorsan hangi yoldan gittiğinin hiçbir önemi yoktur.</p>


<p>Benzer yazılar:<ol><li><a href='http://www.ahmetkakici.com/programlama/programlama-ipuclari/' rel='bookmark' title='Permanent Link: Programlama İpuçları'>Programlama İpuçları</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.ahmetkakici.com/programlama/hangi-programlama-dilini-ogrenelim/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Java ile Sohbet Programı</title>
		<link>http://www.ahmetkakici.com/programlama/java-ile-sohbet-programi/</link>
		<comments>http://www.ahmetkakici.com/programlama/java-ile-sohbet-programi/#comments</comments>
		<pubDate>Tue, 17 Mar 2009 20:49:17 +0000</pubDate>
		<dc:creator>Ahmet Kakıcı</dc:creator>
				<category><![CDATA[Programlama]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[socket]]></category>
		<category><![CDATA[tcp]]></category>
		<category><![CDATA[udp]]></category>

		<guid isPermaLink="false">http://www.ahmetkakici.com/?p=132</guid>
		<description><![CDATA[Sonunda uzun zamandır ertelediğim bu yazıyı da yayınladım ve kafamdan sildim. Aşağıda göreceğiniz kodlar basit bir sohbet programının kodlarıdır. Ayırca java&#8217;da soket programlama için de bir örnek teşkil etmektedir. Programı NetBeans ile yazdım ve NetBeans tarafından otomatik olarak eklenen kodlar aşağıda yer almamaktadır. Kodları ve programın işleyişini daha iyi anlayabilmeniz için bir takım terimleri ve [...]]]></description>
			<content:encoded><![CDATA[<p>Sonunda uzun zamandır ertelediğim bu yazıyı da yayınladım ve kafamdan sildim. Aşağıda göreceğiniz kodlar basit bir sohbet programının kodlarıdır. Ayırca java&#8217;da soket programlama için de bir örnek teşkil etmektedir. Programı NetBeans ile yazdım ve NetBeans tarafından otomatik olarak eklenen kodlar aşağıda yer almamaktadır.</p>
<p>Kodları ve programın işleyişini daha iyi anlayabilmeniz için bir takım terimleri ve yapıları bilmeniz gerektiğini düşünerekten öncelikle bu bilgileri verelim.</p>
<p><strong>Protokol Nedir?</strong></p>
<p>Herhangi bir ağ içerisinde bulunan cihazların birbirleriyle haberleşmeleri için bellirli protokoller tanımlanmıştır. Bu protokoller sayesinde kullanıcılar alt yapıdaki detaylarla uğraşmadan veri alışverişini gerçekletirebilir.<span id="more-132"></span></p>
<p>Farklı amaçlar için farklı protokoller geliştirilmiştir. Bu farklı protokollerin birbirlerine göre üstünlük ve zayıflıkları vardır. Kullanım alanına göre doğru protokol seçilmelidir.</p>
<p>Yaztığım programda User Datagram Protokol  &#8211; UDP protokolünü kullandım.  UDP protokolü veri iletişimini bağlantı kurmaksızın paketler gönderir. Bağlantı kurulmadığından dolayı protokolden mesajın iletildiğine dair herhangi bir bilgi edinilemez. Bu tip bir onay sistemi kullanıcı tarafından isteğe bağlı olarak ayrıca yazılmalıdır. UDP’de gönderilen paketlerin herhangi bir sıra numarası ve sırayla ulaşma garantisi de yoktur. Bu tip özellikler için ekstra başlık bigileri gerekmektedir, UDP bu başlık bilgilerini içermediğinden başlık bilgisi de diğer protokllere göre (ör:TCP) daha küçüktür. Başlık bilgilerinin küçük olması sayesinde UDP daha az bant genişliğine ihtiyaç duyar. Bu avantajından dolayı gerçek zamanlı ses veya görüntü iletişiminde tercih edilir.</p>
<p><strong>Port Nedir ?</strong></p>
<p>Portlar bir bilgisayarın ağda sahip olduğu IP adresinden dışarıya açılan birbirinden bağımsız kapılar olarak tanımlanabilir. Port numaraları 16bit ile ifade edildiğinden 65536 adet port mevcuttur. Herhangi bir uygulamanın kullanacağı port numarası seçilirken daha önceden başka bir programın bu portu kullanıp kullanmadığına dikkat edilmelidir. Aksi halde iki uygulama da düzgün çalışmayabilir.</p>
<p>UDP protokolünde veri iletişimi yapmak için IP ve PORT ikilisini kullanarak adresleme yapmak gerekir. Bu ikili kullanar bir soket yaratılır ve iletişim soket üzerinden yapılır.</p>
<p><strong>Soket Nedir ?</strong></p>
<p>Soket IP adresi ve Port birleşiminden oluşan uygulamalarda ağ içerisinde bulunan alt düzey ayrıntılarla uğraşmadan veri alışverişi yapmayı sağlayan ve unix sistemlerde bulunan dosya yapısına benzer bir yapıdır.  TCP/IP protokolünde mevcut olan soketler uygulama seviyesinde bağlantıları simgelemeye yarar.</p>
<p>Yaygın olarak kullanılan iki türlü soket yapısı mevcuttur. Bunlardan biri SOCK_STREAM ile tanımlanan ve streaming yapmaya yarıyan soket tipidir. Bu soket yapısında bağlantılı (connection oriented) haberleşme kullanılır. Yani haberleşme sırasında aktif olan bağlantı ve soket yapısı mevcuttur. TCP protokolü SOCK_STREAM tipinde soketler üzerinden haberleşme yapar. Bu soketlerden yapılan iletişim tamamen güvenlidir. Yani yanlış veri iletimi olması durumunda protokolden dolayı sistem kararlı ve doğru veriyi iletene kadar tekrar gönderme/isteme işlemini yapar. Ayrıca bu soketler üzerinden gönderilern verilerin alıcı tarafa da aynı sırayla ulaşacağı garanti edilmiştir. “A” ve “B” datasını içeren iki mesajı gönderdiğimizde alıcı tarafta yine “A” ve “B” sırasıyla alınacağı garanti edilmiştir.</p>
<p>Diğer bir soket türü ise SOCK_DGRAM ile tanımlanan datagram tipi soketlerdir. TCP’ye göre güvensiz veri iletişimi yapar. Bunun nedeni gönderilerecek datayı UDP protokolü üzerinden yollaması ve paketi bir kez ağa bıraktıktan sınra herhangi bir takip işlemi yapmamasıdır. Yani kullanıcıya verinin ulaşıp ulaşmadığına dair herhangi bir bilgi sağlamaz. Buna karşılık alıcıdan onay mesajı yollatarak iletimi biraz daha olsun kararlı hale getirebilinir. Bu soketin tercih edilme sebebi ise stream türünde yayınlardır. Her ne kadar streaming soket “streaming” için daha uygun gibi görünsede datagram tipi soketler bu iş için daha uygundur. Bunun sebebi kayıp paketlerin tekrar yollanması, aşırı başlık bilgisi, çok bant genişliği harcaması, bağlantının sürekli olarak aktif kalması gibi dezavantajlarından dolayı datagram soketler streaming işlemi için tercih edilmektedir.</p>
<p><strong>Paket Nedir ?</strong></p>
<p>UDP ile bağlantısız haberleşme yapıldığından veriler birbirinden bağımsız paketler ile gönderilir. TCP protokolünde bağlantılı haberleşme yapıldığından veri iletişimi başlarken bir bağlantı kurulur ve sürekli olarak bu bağlantı üzerinden haberleşme sağlanır. Veri iletişimi olmasa dahi bağlantı açık kalır. UDP  protokolü için Java dilinde belirlenen paket değişken tipi  Datagram Packet’dir.  Her bir paket içerisinde gönderilecek veri ve paketteki veri miktarını belirten değişkenler vardır. Bunun yanı sıra paketi gönderdiğimiz bilgisayarın IP adresi ve port numarası da pakete dahil edilmelidir.</p>
<p>Gönderici ve alıcı adresleri de UDP paketinin içinde olmasına rağmen bu paketler tek başına iletişim için yeterli değildir. UDP paketleri de ağda iletim için IP protokolünü kullanır. Bundan dolayı her paketin başına IP başlık bilgileri de eklenir. Aşağıdaki şekilde bir IP başlığı ve altında ise UDP paketinin temel yapısı gösterilmiştir:</p>
<p><a class="thickbox" href="http://www.ahmetkakici.com/wp-content/gallery/java-sohbet/paket.jpg"><img class="ngg-singlepic ngg-center" src="http://www.ahmetkakici.com/wp-content/gallery/java-sohbet/paket.jpg" alt="paket.jpg" /></a></p>
<p><a class="thickbox" href="http://www.ahmetkakici.com/wp-content/gallery/java-sohbet/udp.jpg"><img class="ngg-singlepic ngg-center" src="http://www.ahmetkakici.com/wp-content/gallery/java-sohbet/udp.jpg" alt="udp.jpg" /></a></p>
<p><strong>Programın Genel Yapısı</strong></p>
<p>Program sunucu/istemci mimarisine dayanarak çalışmaktadır. İstemci kısmı Applet olarak yazıldı ve web üzerinden sohbet edebilme imkanı sağlamaktadır. Sunucu kısmı ise masaüstü uygulaması olarak yazılmıştır. Sunucu çalışmaya başlar başlamaz ilgili portu dinleyerek gelen paketleri değerlendirerek mesajları istemciler arasında iletmektedir. İstemciler birbirleri arasında direk mesajlaşmak yerine sunucu üzerinden mesajlaşmaktadır. Bundan dolayı istemcilerde diğer istemcilerin adresleri yerine sadece isimleri tutulmaktadır.</p>
<p><strong>İstemci Tarafı</strong></p>
<p>İstemci kodu iki temel sınıftan oluşmaktadır. ClientMsgHandler ve ClientGUI. ClientMsgHandler veri iletim fonksiyonlarını içermektedir. ClientGUI ise arayüzü ve ClientMsgHandler’dan gelen verileri kullanıcıya göstermektedir. ClientMsgHandler thread sınıfını implement ederek oluşturulmuştur. Bu sayede arayüzde herhangi bir takılma olmadan veri iletişim işlemleri eş zamanlı olarak yapılmaktadır.</p>
<p>Programda iki türde istemci vardır. Birincisi sunucu üzerinde çalışan ve web üzerinden hizmet veren istemcidir. Web üzerinden sunucuya bağlanan istemciler için yazılmıştır ve sunucu adresini bilmeksizin her istemci bu sunucuya bağlanabilir. Diğer istemci türünde ise istemci kodu bilgisayara indirilip web tarayıcısı üzerinden local olarak çalıştırılabilir. Bu istemcide ise sunucunun ip adresini de ayrıca bilmek gerekmektedir.</p>
<p><strong>İstemci Tarafındaki Sınıflar ve Fonksiyonları</strong></p>
<p><strong>ClientMsgHandler</strong> sınıfına ait fonksiyonlar:<br />
<strong>Send:</strong>String tipinde tutulan gönderilecek mesajı byte dizisine çevirir. Daha sonra DatagramSocket üzerinden yollamak üzere yeni bir PatagramPacket hazırlayak oluşturulan byte dizsini, alıc adresini ve iletişimde kullanılacak port numarasını da pakete ekler. Son olarak paketi DatagramSocket üzerinden gönderir.</p>
<p><strong>Recieve</strong>: DatagramSocket üzerinden gelen paketi alabilmek için yeni bir DatagramSocket yaratır. Okunan veriyi bu pakete yazdıktan sonra mesaj kısmını byte dizisinden string tipine çevirir. Daha sonra mesajı işlemek üzere ParseMsg ve HandleMsg fonkisyonlarını çağırır.</p>
<p><strong>SetHost</strong>: Parametre olarak host adresini alıp bu adresi InetAddress türüne çevirir.<br />
<strong></strong></p>
<p><strong>BuildMsg</strong>: Parametre olarak aldığı mesaj türüne göre gönderilecek mesajı string olarak oluşturur. String türündeki mesajın formatı aşağıdaki gibidir:<br />
gönderici_adı  &gt; alıcı_adı &gt; mesaj_türü &gt; mesaj_içeriği<br />
Bu yapıda “&gt;” sembolü ayraç olarak kullanılmıştır.<br />
Mesaj türleri ise aşağıdaki şekildedir:</p>
<p><strong>ADD_ME</strong> – Kullanıcı ekleme<br />
<strong>REMOVE_ME</strong> – Kullanıcı silme<br />
<strong>SEND_MSG</strong> – Normal mesaj<br />
<strong>GET_USERS</strong> – Kullanıcı listesi isteği<br />
<strong>ACK_MSG</strong> – Onay mesajı</p>
<p><strong>ParseMsg</strong>: Alınan mesajı “&gt;” ayracına göre bölümleyerek mesajın içeriğini gerekli değişkenlere atar.</p>
<p><strong>HandleMsg</strong>: Parse edilen mesajın türüne bağlı olarak işlemleri gerçekleştirir.  Mesaj türlerine göre yaptığı işlemler aşağıdaki gibidir:<br />
<strong></strong></p>
<p><strong>SEND_MSG</strong>: Gelen mesajı arayüzde göstermek üzere ClientGUI sınıfına gönderir.<strong></strong></p>
<p><strong>REMOVE_ME</strong>: Gelen kullanıcı adını ClientGUI’de gösterilen listeden silmek üzere ClientGUI sınıfına iletir. Aynı zamanda istemcilerin tutulduğu vector yapısından ilgili istemciyi silmesi için RemoveClient fonksiyonuna kullanıcı adını iletir.<strong></strong></p>
<p><strong>ACK_MSG</strong>: Bağlantının kurulduğunu onaylayan bu mesaj alındığı zaman arayüzde gerekli değişiklikler yapılarak mesaj iletimine uygun yapı oluşturulur.<strong></strong></p>
<p><strong>ADD_ME</strong>: Gelen kullanıcı adını istemcilerin tutulduğu vector yapısına ekler ve arayüz sınıfının da bu kullanıcı adını göstermesini sağlar.<strong></strong></p>
<p><strong>GET_USERS</strong>: Kullanıcı isteğinin karşılığı niteliğindedir. İlk  kez bağlantı kuruluduğunda liste alınarak arayüzde gösterilir. Aynı zamanda istemcilerin her birini vector yapısına ekler. Bu mesaj alındıktan sonra bağlantı tamamlanmış ve kullanıcı listesi alınmış olduğundan dolayı mesaj dinleme işlemini başlatacak thread çalıştırılr. Sonsuz bir döngü içinde ilgili port sürekli olarak dinlenir.</p>
<p><strong>Connect</strong>: ClientGUI’den alınan kullanıcı adını içeren bir mesaj ile sunucuya bağlantı isteğini gönderir. Send methodunu çağırarak mesajın iletimini sağlar, daha sonra Recieve methoduyla bağlantı isteğine gelcek cevabı bekler. Cevap gelmeme ihtimaline karşı soket’in bloklanma süresi 2sn olarak ayarlanmıştır. Sunucundan cevap alınırsa veya soket süresi dolarsa bağlantı kurulamadığı ClientGUI’de gösterilir ve soket’in bloklanma süresi tekrar sıfıra setlenir (sonsuz).</p>
<p><strong>Disconnect</strong>: Sunucuylya yapılan bağlantının bitirilmesi isteğini gönderir. Bu sayede bağlantıyı kapatan istemciler diğer istemcilerin listesinden silinecektir. UDP gibi bağlantısız bir iletişim protokolü kullanıldığından dolayı bu işlem gereklidir. Aksi halde sunucu  &#8211; istemci arasında sürekli ping gönderek her iki tarafında hala hatta olduğu kontrol edilmelidir.</p>
<p><strong>GetClientList</strong>: Sunucu ile ilk defa bağlantı kurulduğu zaman varolan istemcilerin listesini almak için gerekli mesajı oluşturup gönderir ve cevabı alır. Kullanıcı listesi alınmadan önce ilgili port ayrı bir thread ile dinlenmediği için bu fonksiyon içinden Recieve fonkisyonu çağrılmıştır.</p>
<p><strong>BuildClientList</strong>:  Sunucu istemciye diğer istemcilerin isim listesini gönderirken isimleri “|” ayracı ile ayırır. HandleMsg fonksiyonu bu ayraça göre gelen veriyi bölerek BuildClientList fonksiyonuna string dizisi olarak iletir. BuildClientList fonksiyonu ise gelen bu diziyi vector yapısına çevirerek kaydeder. Vector yapısı kullanılmasının amacı istemci sayısının dinamik olarak değişmesi ve ClientGUI’de ki listede istemcilerin kolaylıkla gösterilmesidir.</p>
<p><strong>RemoveClient</strong>: Herhangi bir istemci sunucuya ayrıdığını bildirdiğinde sunucu geride kalan bütün istemcilere bu mesajı iletir ve istemciler bu fonksiyon ile ayrılan istemcinin adını vector yapısından ve ClientGUI’de kullanılan listeden siler.</p>
<p><strong>ClientGUI </strong>sınıfına ait fonkisyonlar:</p>
<p><strong>SendMessage</strong>: TextField2’ye girilen mesajı ve JList1’den seçilen kullanıcı adını ClientMsgHandler sınıfına göndererek mesajın sunucuya iletilmesini sağlar.</p>
<p><strong>AddMessage</strong>: ClientMsgHandler tarafından alınan mesajları jTextArea’ya kimden geldiğini göstererek ekler.</p>
<p><strong>UpdateUserList</strong>: Sunucuya herhangi bir istemci bağlandığında veya ayrıldığında arayüzde gösterilen istemci isimlerini yeniler.</p>
<p><strong>SetStatus</strong>: Sunucuya bağlanıp bağlanılmadığını ve mesaj gönderirken hangi kullanıcının seçildiğini jTextFeild3’e yazdırır.</p>
<p><strong>Connect</strong>: Bağlan butonuna basıldığı zaman kullanıcıdan alınan ip adresi (veya host adı) ve kullanıcı adıyla sunucuya bağlanmak için ClientMsgHandler’da bulunan Connect fonksiyonun çağırır.</p>
<p><strong>Destroy</strong>: Kullanıcı tarayıcıyı kapattığı zaman sunucuya bağlantıyı sonlandırma mesajını gönderir.</p>
<p><strong>Sunucu Tarafı </strong></p>
<p>Sunucu işlemleri genel olarak istemcilerin listesini tutmak ve gelen mesajları iletmek üzerine kuruludur.  ClientHandler sınıfı sürekli olarak ilgili portu dinleyerek mesaj iletim işini üstlenmektedir. Onun haricinde serverGUI mesajlaşmaların ve sisteme gelip giden istemcilerin özetini gösteren bir arayüz oluşturmaktadır.</p>
<p><strong>ClientHandler </strong>sınıfına ait fonksiyonlar:<br />
<strong></strong></p>
<p><strong>BuildMsg</strong>: Parametre olarak aldığı mesaj türüne göre gönderilecek mesajı string olarak oluşturur. String türündeki mesajın formatı aşağıdaki gibidir:<br />
gönderici_adı  &gt; alıcı_adı &gt; mesaj_türü &gt; mesaj_içeriği<br />
Bu yapıda “&gt;” sembolü ayraç olarak kullanılmıştır.<br />
Mesaj türleri ise aşağıdaki şekildedir:<br />
<strong></strong></p>
<p><strong>ADD_ME</strong> – Kullanıcı ekleme<br />
<strong>REMOVE_ME</strong> – Kullanıcı silme<br />
<strong>SEND_MSG</strong> – Normal mesaj<br />
<strong>GET_USERS</strong> – Kullanıcı listesi isteği<br />
<strong>ACK_MSG</strong> – Onay mesajı</p>
<p><strong>ParseMsg</strong>:  Alınan mesajı “&gt;” ayracına göre bölümleyerek mesajın içeriğini gerekli değişkenlere atar.</p>
<p><strong>HandleMsg</strong>: Parse edilen mesajın türüne bağlı olarak işlemleri gerçekleştirir.  Mesaj türlerine göre yaptığı işlemler aşağıdaki gibidir:<br />
<strong></strong></p>
<p><strong>SEND_MSG</strong>: Mesaj gönderilecek istemcinin adını clients vector yapısı içinde arar. Bulduğu elemandan adresi alarak mesajı  ilgili istemciye gönderir.  Ayrıca sunucu arayüzünde de mesajı ve kimden kime gönderildiğini yazar.<br />
<strong></strong></p>
<p><strong>REMOVE_ME</strong>:  İstemci sunucudan ayrıldığı zaman client vector yapısı içinden bu istemciyi siler ve diğer tüm istemcilere ilgili istemci adını yollayarak listelerinden silmesini bildirir. Buna ek olarak sunucu arayüzünde de çıkan istemcinin adını yazar.</p>
<p><strong>ADD_ME</strong>: Yeni istemcinin adını ve adresini arayüzde gösterir. Daha sonra istemcilerin tutulduğu vektöre yeni bir istemci sınıfı nesnesi yaratıp ekler. Bundan sonra ise istemciye bağlantının kabul edildiğine dair bir onay mesajı yollar. Yeni gelen kullanıcıya onay mesajı gönderip bağlantıyı kabul ettikten sonra önceden bağlanan istemcilere yeni gelen istemcinin adını gönderir.</p>
<p><strong>GET_USERS</strong>:  Bu mesajdan sonra sunucu mesajı gönderen istemciye o anda bağlı olan istemcilerin isimlerini gönderir. İsimler birbirinden “|” ayracı ile ayrılmıştır.</p>
<p><strong>ServerSend</strong>: Gönderilecek mesajı byte dizisine çevirerek datagram paketi içine koyar ve datagram soketi üzerinden gönderir.</p>
<p><strong>ServerRecieve</strong>: İlgili portu dinleyerek gelen mesajları string tipine çevirir. Ayrıca gönderenin adresini de datagram paketinden çıkararak kaydeder.</p>
<p><strong>NotifyAllClients</strong>:  Belirlenen mesajı o anda bağlı olan istemcilerin hepsine gönderir.</p>
<p><strong>BuildClientList</strong>: Bağlı olan istemcilerin isimlerini bir string’de birleştirerek mesajı gönderilmeye hazır hale getirir.</p>
<p><strong>GetReceiverAddressByName</strong>: Sunucuya gelen mesajlarda sadece gönderilecek istemcinin adı bulunmaktadır. Adresler ise sunucuda tutulan clients vector yapısındadır. Bu fonksiyon mesaj gönderilecek istemcinin adını vector elemanlarıyla karşılaştırıp ilgili adresi bulur.</p>
<p><strong>RemoveClient</strong>: Parametre olarak aldığı kullanıcı adını clients vector yapısında arar ve ilgili istemciyi  vector’den siler. Daha sonra geride kalan istemcilere bu silme işlemini bildirir.</p>
<pre class="brush: java;">

/**
*
* @author Ahmet
*/
import java.io.*;
import java.net.*;
import java.util.*;

public class clientMsgHandler extends Thread{

private DatagramSocket socket;
private DatagramPacket giden;
private DatagramPacket gelen;
private InetAddress address;

private int msgType;
private String received;
private String[] parsedMsg;
public String myName;
public String message;
public String receiverName;
public String senderName;

private static final int PORT = 4444;
private static final String MSG_SEPERATOR = &quot;&gt;&quot;;
private static final int ADD_ME=0;
private static final int REMOVE_ME=1;
private static final int SEND_MSG=2;
private static final int GET_USERS=3;
private static final int ACK_MSG = 4;
public clientGUI parent;

public boolean connected = false;
public String hostname;
public String msg2send;
public Vector clients = new Vector();

public clientMsgHandler(String argHostname) throws IOException{
hostname = argHostname;
address = InetAddress.getByName(hostname);
socket = new DatagramSocket();
socket.setSoTimeout(0);
}

@Override
public void run(){
while(true){
try{
Recieve();
socket.setSoTimeout(0);
}catch(Exception e){}
}

}
public void SetHost(String argHostname) throws UnknownHostException{
hostname = argHostname;
address = InetAddress.getByName(hostname);
}
private void Send(){
byte[] buf = new byte[msg2send.length()];
buf = msg2send.getBytes();
giden = new DatagramPacket(buf, buf.length, address, PORT);
try{
socket.send(giden);
}catch(Exception e){}
System.out.println(&quot;Giden mesaj: &quot; + msg2send);
}

public void Recieve(){
byte[] buf = new byte[256];
gelen = new DatagramPacket(buf, buf.length);
try{
socket.receive(gelen);
}catch(Exception e){}
received = new String(gelen.getData(), 0, gelen.getLength());
System.out.println(&quot;Gelen mesaj: &quot; + received);
ParseMsg();
HandleMsg();
}

private void BuildMsg(int argFlag){
msg2send = myName+MSG_SEPERATOR+receiverName+MSG_SEPERATOR+argFlag+MSG_SEPERATOR+message;
}

public void SendMsg(){
BuildMsg(SEND_MSG);
Send();
}

public void ParseMsg(){

try {
parsedMsg = received.split(MSG_SEPERATOR);
senderName = parsedMsg[0];
msgType = Integer.parseInt(parsedMsg[1]);
message = parsedMsg[2];
} catch (Exception exception) {
parent.SetStatus(&quot;Bağlantı kurulamadı.&quot;);
msgType = -1;
message = &quot;&quot;;
}
}

public void Connect(){
try {
message = myName;
receiverName = &quot;Server&quot;;
BuildMsg(ADD_ME);
Send();
socket.setSoTimeout(2000);
Recieve();
socket.setSoTimeout(0);

} catch (SocketException ex) {}
}

public void Disconnect(){
receiverName= &quot;Server&quot;;
BuildMsg(REMOVE_ME);
Send();
connected=false;
}

public void HandleMsg(){
if(msgType==SEND_MSG){
parent.AddMessage(message,senderName);
}
else if(msgType==REMOVE_ME){
RemoveClient(message);
parent.UpdateUserList();
}
else if(msgType==ACK_MSG){
connected=true;
}
else if(msgType==ADD_ME){
clients.add(message);
parent.UpdateUserList();
}
else if(msgType==GET_USERS){
String[] clientList = parsedMsg[2].split(&quot;\\|&quot;);
BuildClientList(clientList);
start();
}
}

public void GetClientList(){
message = myName;
BuildMsg(GET_USERS);
Send();
Recieve();
}

private void BuildClientList(String[] clientList){
clients.removeAllElements();
for (int i = 0; i &lt; clientList.length; i++) {
if(!myName.equalsIgnoreCase(clientList[i].toString()))
clients.add(clientList[i]);
}
}

private void RemoveClient(String argName){
for (int i = 0; i &lt; clients.size(); i++) {
String tmp = (String) clients.elementAt(i);
if (tmp.equals(argName)) {
clients.remove(i);
break;
}

}

}

}
</pre>
<pre class="brush: java;">

import java.io.IOException;

/*
* clientGUI.java
*
* Created on 16 Nisan 2008 Çarşamba, 21:26
*/
import java.net.UnknownHostException;
import javax.swing.JOptionPane;

/**
*
* @author  Ahmet
*/
public class clientGUI extends javax.swing.JApplet {

private clientMsgHandler tr;

private void jTextField1ActionPerformed(java.awt.event.ActionEvent evt) {
// Kullanıcı adı girişi
Connect();
}

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// Bağlan butonu
Connect();
}

private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
// Gönderme işlemi
int selected = jList1.getSelectedIndex();
if(selected&gt;-1)
SendMessage();
jTextField2.requestFocusInWindow();
}

private void jTextField2ActionPerformed(java.awt.event.ActionEvent evt) {
// Gönderme işlemi
int selected = jList1.getSelectedIndex();
if(selected&gt;-1)
SendMessage();
}

private void jList1ValueChanged(javax.swing.event.ListSelectionEvent evt) {
// Listeden kişi seçildiğinde:
jTextField3.setText(jList1.getSelectedValue().toString());
jButton2.setEnabled(true);
}

private void jTextField1FocusGained(java.awt.event.FocusEvent evt) {
// Kullanıcı adı girişi
if(jTextField1.getText().equalsIgnoreCase(&quot;Kullanıcı Adı&quot;))
jTextField1.setText(&quot;&quot;);
}

private void jTextField4FocusGained(java.awt.event.FocusEvent evt) {
// Server IP
if(jTextField4.getText().equalsIgnoreCase(&quot;Server IP&quot;))
jTextField4.setText(&quot;&quot;);
}

public void SendMessage(){
tr.message = jTextField2.getText();
tr.receiverName = jList1.getSelectedValue().toString();
tr.SendMsg();
AddMessage(tr.message,tr.myName);
jTextField2.setText(&quot;&quot;);
}

public void AddMessage(String argMsg, String argSender){
jTextArea1.append(&quot;\n&quot; + argSender + &quot;:&quot; + argMsg);

}

public void UpdateUserList(){
jList1.removeAll();
jList1.setListData(tr.clients);
}

public void Connect(){
try {
tr.myName = jTextField1.getText();
tr.SetHost(jTextField4.getText());
tr.Connect();
if (tr.connected) {
jList1.setVisible(true);
jTextField2.setVisible(true);
jButton2.setVisible(true);
jTextField1.setEnabled(false);
jTextField4.setEnabled(false);
tr.GetClientList();
jList1.setListData(tr.clients);
jButton1.setEnabled(false);
SetStatus(&quot;Bağlantı Kuruldu&quot;);
}
} catch (UnknownHostException ex) {

}
}

public void SetStatus(String argMsg){
jTextField3.setText(argMsg);
}

}
</pre>
<pre class="brush: java;">

class ClientHandler extends Thread{

private static final int PORT = 4444;
private static final int BUFFER_LENGTH = 256;
private static final String MSG_SEPERATOR = &quot;&gt;&quot;;

private static final int ADD_ME=0;
private static final int REMOVE_ME=1;
private static final int SEND_MSG=2;
private static final int GET_USERS=3;
private static final int ACK_MSG = 4;

public Vector clients = new Vector();
protected DatagramSocket socket = null;

String receivedMsg;					// Parse edilmemis mesaj
private String message;					// Mesajin icerigi - yazi
private int msgType;					// Mesaj turu
private String msg2send;				// Gonderilecek mesaj
private SocketAddress receiverAdress;                   // Mesajin gidecegi adres
private SocketAddress senderAddress;                    // Mesajin geldigi adres
private String receiverName;                            // Mesajin gidecegi kisi
private String senderName;                              // Mesaj gonderen kisi
public ServerGUIView parent;

@Override
public void run(){
while(true){
try{
ServerReceive();
ParseMsg();
HandleMsg();
}catch(Exception e){}

}
}

public ClientHandler() throws IOException {
super(&quot;ClientHandler&quot;);
socket = new DatagramSocket(PORT);
}

public void RemoveClient(String argName){
for(int i=0;i&lt;clients.size();i++){
Client tmp = (Client)clients.get(i);
if (tmp.clientName.equals(argName)){
clients.remove(i);
break;
}
}
}

public void GetReceiverAddressByName(){
for(int i=0;i&lt;clients.size();i++){
Client tmp = (Client)clients.get(i);
if (tmp.clientName.equalsIgnoreCase(receiverName)){
receiverAdress = tmp.clientAddress;
break;
}
}
}
private void BuildClientList(){
message = &quot;&quot;;
for(int i=0;i&lt;clients.size();i++){
Client tmp = (Client)clients.get(i);
message += tmp.clientName+&quot;|&quot;;
}

}

private void NotifyAllClients(){
message = senderName;
senderName = &quot;Server&quot;;
for(int i=0;i&lt;clients.size();i++){
Client tmp = (Client)clients.get(i);
if (!tmp.clientName.equalsIgnoreCase(message)){
receiverAdress = tmp.clientAddress;

ServerSend();
}

}
}

private void BuildMsg(int argFlag){
msg2send = senderName+MSG_SEPERATOR+argFlag+MSG_SEPERATOR+message;
}

public void ServerReceive()throws IOException{
byte[] buffer = new byte[BUFFER_LENGTH];
DatagramPacket gelenPaket = new DatagramPacket(buffer, BUFFER_LENGTH);
try{
socket.receive(gelenPaket);
}catch(Exception e){}
receivedMsg = new String(gelenPaket.getData(), 0, gelenPaket.getLength());
senderAddress = gelenPaket.getSocketAddress();
}

public void ServerSend(){
try{
byte[] buffer = new byte[msg2send.length()];
buffer = msg2send.getBytes();
DatagramPacket gidenPaket = new DatagramPacket(buffer, buffer.length, receiverAdress);
socket.send(gidenPaket);
}
catch(Exception e){

}
}

private void ParseMsg(){
String[] parsedMsg = receivedMsg.split(MSG_SEPERATOR);
senderName = parsedMsg[0];
receiverName = parsedMsg[1];
msgType = Integer.parseInt(parsedMsg[2]);
message = parsedMsg[3];
}

public void HandleMsg()throws IOException{
if(msgType==ADD_ME){
parent.AddTextarea(&quot;Yeni kullanici: &quot; + message + &quot;, adresi:&quot; + senderAddress+&quot;\n&quot;);
clients.add(new Client(message,senderAddress));
receiverAdress = senderAddress;
BuildMsg(ACK_MSG);
ServerSend();
BuildMsg(ADD_ME);
NotifyAllClients();
}
else if(msgType==SEND_MSG){
GetReceiverAddressByName();
parent.AddTextarea(senderName + &quot; -&gt; &quot; + receiverName + &quot; mesaj gonderiyor :'&quot; + message + &quot;'\n&quot;);
BuildMsg(SEND_MSG);
ServerSend();
}
else if(msgType==REMOVE_ME){
parent.AddTextarea(senderName + &quot;, bağlantıyı sonlandırdı.\n&quot;);
RemoveClient(senderName);
message = senderName;
BuildMsg(REMOVE_ME);
NotifyAllClients();
}
else if(msgType==GET_USERS){
parent.AddTextarea(senderName+&quot; kullanicisina liste yollaniliyor.\n&quot;);
BuildClientList();
senderName = &quot;Sunucu&quot;;
receiverAdress = senderAddress;
BuildMsg(GET_USERS);
ServerSend();
}
}
}

class Client{
String clientName;
SocketAddress clientAddress;

public Client(String argName,SocketAddress argAddress){
clientName = argName;
clientAddress = argAddress;
}
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ahmetkakici.com/programlama/java-ile-sohbet-programi/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>Yapay Sinir Ağlarının Katmanları</title>
		<link>http://www.ahmetkakici.com/yapay-sinir-aglari/yapay-sinir-aglarinin-katmanlari/</link>
		<comments>http://www.ahmetkakici.com/yapay-sinir-aglari/yapay-sinir-aglarinin-katmanlari/#comments</comments>
		<pubDate>Thu, 19 Feb 2009 13:17:09 +0000</pubDate>
		<dc:creator>Ahmet Kakıcı</dc:creator>
				<category><![CDATA[Yapay Sinir Aglari]]></category>
		<category><![CDATA[Programlama]]></category>

		<guid isPermaLink="false">http://www.ahmetkakici.com/?p=127</guid>
		<description><![CDATA[Serinin üçüncü ve diğerlerine göre nispeten kısa bir bölümüyle yapay sinir ağlarına devam ediyoruz (1 &#8211; 2) . Bu yazıyı kısa kesmemin sebebi bundan sonraki bölümde yapay sinir ağlarının sınıflandırılması konusuna değinecek olmam ve onun da biraz uzun olmasıdır. Uzun uzadıya yazıp kimseyi bunaltmak istemem :) Yapay Sinir Ağlarının Yapısı Yapay sinir ağları yapay sinir [...]]]></description>
			<content:encoded><![CDATA[<p>Serinin üçüncü ve diğerlerine göre nispeten kısa bir bölümüyle yapay sinir ağlarına devam ediyoruz (<a href="http://www.ahmetkakici.com/yazilim/yapay-sinir-aglarina-giris/" target="_blank">1</a> &#8211; <a href="http://www.ahmetkakici.com/yapay-sinir-aglari/yapay-sinir-aglarinin-mimarisi-ve-yapi-elemanlari/" target="_blank">2</a>) . Bu yazıyı kısa kesmemin sebebi bundan sonraki bölümde yapay sinir ağlarının sınıflandırılması konusuna değinecek olmam ve onun da biraz uzun olmasıdır. Uzun uzadıya yazıp kimseyi bunaltmak istemem :)</p>
<p><strong>Yapay Sinir Ağlarının Yapısı<br />
</strong></p>
<p>Yapay sinir ağları yapay sinir hücrelerinin birbirine bağlanmasıyla oluşan yapılardır. Yapay sinir ağları üç ana bölümde incelenir; giriş, ara ve çıkış katmanları. <span id="more-127"></span></p>

<a href="http://www.ahmetkakici.com/wp-content/uploads/2009/02/ysa/ysa-yapi.jpg" title="" class="thickbox" rel="singlepic74" >
	<img class="ngg-singlepic ngg-center" src="http://www.ahmetkakici.com/index.php?callback=image&amp;pid=74&amp;width=320&amp;height=240&amp;mode=" alt="ysa-yapi.jpg" title="ysa-yapi.jpg" />
</a>

<p><strong>Giriş Katmanı</strong></p>
<p>Yapay sinir ağına dış dünyadan girdilerin geldiği katmandır. Bu katmanda dış dünyadan gelecek giriş sayısı kadar nöron bulunmasına rağmen genelde girdiler herhangi bir işleme uğramadan alt katmanlara iletilmektedir.</p>
<p><strong>Ara Katmanı</strong></p>
<p>Giriş katmanından çıkan bilgiler bu katmana gelir. Ara katman sayısı ağdan ağa değişebilir. Bazı yapay sinir ağlarında ara katman bulunmadığı gibi bazı yapay sinir ağlarında ise birden fazla ara katman bulunmaktadır.  Ara katmanlardaki nöron sayıları giriş ve çıkış sayısından bağımsızdır. Birden fazla ara katman olan ağlarda ara katmanların kendi aralarındaki nöron sayıları da farklı olabilir. Ara katmanların ve bu katmanlardaki nöronların sayısının artması hesaplama karmaşıklığını ve süresini arttırmasına rağmen yapay sinir ağının daha karmaşık problemlerin çözümünde de kullanılabilmesini sağlar.<strong></strong></p>
<p><strong>Çıkış Katmanı</strong></p>
<p>Ara katmanlardan gelen bilgileri işleyerek ağın girdi katmanından gelen verilere karşılık olan çıktıları üreten katmandır. Bu katmanda üretilen çıktılar dış dünyaya gönderilir. Geri beslemeli ağlarda bu katmanda üretilen çıktı kullanılarak ağın yeni ağırlık değerleri hesaplanır.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ahmetkakici.com/yapay-sinir-aglari/yapay-sinir-aglarinin-katmanlari/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Yapay Sinir Ağlarının Mimarisi ve Yapı Elemanları</title>
		<link>http://www.ahmetkakici.com/yapay-sinir-aglari/yapay-sinir-aglarinin-mimarisi-ve-yapi-elemanlari/</link>
		<comments>http://www.ahmetkakici.com/yapay-sinir-aglari/yapay-sinir-aglarinin-mimarisi-ve-yapi-elemanlari/#comments</comments>
		<pubDate>Wed, 18 Feb 2009 10:28:30 +0000</pubDate>
		<dc:creator>Ahmet Kakıcı</dc:creator>
				<category><![CDATA[Yapay Sinir Aglari]]></category>
		<category><![CDATA[Programlama]]></category>

		<guid isPermaLink="false">http://www.ahmetkakici.com/?p=125</guid>
		<description><![CDATA[Yapay sinir ağlarına giriş yazısının ardından seriye devam ediyoruz. Yapay Sinir Ağlarının Mimarisi ve Yapı Elemanları Yapay sinir ağları biyolojik sinir ağlarının modellemesi olduğu için yapay sinir ağlarının çalışmasını anlayabilmek için öncelikle biyolojik sinir sisteminin yapısına bakmak gerekir. Biyolojik sinir sisteminin yapı taşı olan sinir hücreleri nöronlar, yapay sinir ağlarının da yapı taşıdır. Biyolojik Sinir [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.ahmetkakici.com/yazilim/yapay-sinir-aglarina-giris/" target="_blank">Yapay sinir ağlarına giriş</a> yazısının ardından seriye devam ediyoruz.</p>
<p><strong>Yapay Sinir Ağlarının Mimarisi ve Yapı Elemanları</strong><br />
Yapay sinir ağları biyolojik sinir ağlarının modellemesi olduğu için yapay sinir ağlarının çalışmasını anlayabilmek için öncelikle biyolojik sinir sisteminin yapısına bakmak gerekir. Biyolojik sinir sisteminin yapı taşı olan sinir hücreleri nöronlar, yapay sinir ağlarının da yapı taşıdır.</p>
<p><span id="more-125"></span></p>
<p><strong>Biyolojik Sinir Hücresinin Yapısı</strong><br />
Biyolojik sinir sisteminin temel yapı taşı olan nöronların yapısı dört ana bölümden oluşmaktadır; dendrit, akson, çekirdek ve bağlantılar. Dendritlerin sinir hücresinin ucunda bulunan ve ağaç kökü görünümüne sahip bir yapıya sahiptir. Dendritlerin görevi bağlı olduğu diğer nöronlardan veya duyu organlarından gelen sinyalleri çekirdeğe iletmektir. Çekirdek dendrit tarafından gelen sinyalleri bir araya toplayarak ve aksona iletir. Toplanan bu sinyaller akson tarafından işlenerek nöronun diğer ucunda bulunan bağlantılara gönderilir. Bağlantılar ise yeni üretilen sinyalleri diğer nöronlara iletir.<br />

<a href="http://www.ahmetkakici.com/wp-content/uploads/2009/02/ysa/noron.gif" title="" class="thickbox" rel="singlepic67" >
	<img class="ngg-singlepic ngg-center" src="http://www.ahmetkakici.com/index.php?callback=image&amp;pid=67&amp;width=320&amp;height=240&amp;mode=" alt="Sinir Hücresi - Nöron" title="Sinir Hücresi - Nöron" />
</a>
</p>
<p><strong>Biyolojik Sinir Ağlarının Yapısı</strong><br />
Bir insanın beyninde yaklaşık olarak 10 milyar sinir hücresi ve bu nöronların birbirleriyle yaptığı bağlantı sayısının ise 60 trilyon olduğu tahmin edilmektedir. Bu sinirler girdi bilgilerini duyu organlarından alırlar. Daha sonra alıcı (taşıyıcı) sinirler bu sinyalleri işleyip bir sonraki sinire aktararak sinyalin merkezi sinir sistemine kadar ulaşmasını sağlar. Merkezi sinir sistemi bu sinyalleri alıp yorumladıktan sonra tepki sinyallerini üretir. Bu sinyaller de tepkilerin oluşacağı organlara tepki sinirleri vasıtasıyla iletilir. Bu sayede duyu organlarından gelen bilgilere karşı tepki organlarına uygun işaretler sinir sistemi vasıtasıyla yollanır.</p>

<a href="http://www.ahmetkakici.com/wp-content/uploads/2009/02/ysa/sinir sistemi.jpg" title="" class="thickbox" rel="singlepic69" >
	<img class="ngg-singlepic ngg-center" src="http://www.ahmetkakici.com/index.php?callback=image&amp;pid=69&amp;width=320&amp;height=240&amp;mode=" alt="Biyolojik Sinir Ağları" title="Biyolojik Sinir Ağları" />
</a>

<p><strong>Yapay Sinir Hücresinin Yapısı</strong><br />
Yapay sinir hücreleri de biyolojik sinir hücrelerine benzer yapıdadır. Yapay nöronlar da aralarında bağ kurarak yapay sinir ağlarını oluştururlar. Aynı biyolojik nöronlarda olduğu gibi yapay nöronların da giriş sinyallerini aldıkları, bu sinyalleri toplayıp işledikleri ve çıktıları ilettikleri bölümleri bulunmaktadır.<br />
Bir yapay sinir hücresi beş bölümden oluşmaktadır;</p>
<ul>
<li>Girdiler</li>
<li>Ağırlıklar</li>
<li>Birleştirme fonksiyonu</li>
<li>Aktivasyon fonksiyonu</li>
<li>Çıktılar</li>
</ul>

<a href="http://www.ahmetkakici.com/wp-content/uploads/2009/02/ysa/yapay-sinir-hucresi.jpg" title="" class="thickbox" rel="singlepic70" >
	<img class="ngg-singlepic ngg-center" src="http://www.ahmetkakici.com/index.php?callback=image&amp;pid=70&amp;width=320&amp;height=240&amp;mode=" alt="Yapay sinir hücresi" title="Yapay sinir hücresi" />
</a>

<ul>
<li><strong>Girdiler</strong></li>
</ul>
<p>Girdiler nöronlara gelen verilerdir. Girdiler yapay sinir hücresine bir diğer hücreden gelebileceği gibi direk olarak dış dünyadan da gelebilir. Bu girdilerden gelen veriler biyolojik sinir hücrelerinde olduğu gibi toplanmak üzere nöron çekirdeğine gönderilir.</p>
<ul>
<li><strong>Ağırlıklar</strong></li>
</ul>
<p>Yapay sinir hücresine gelen bilgiler girdiler üzerinden çekirdeğe ulaşmadan önce geldikleri bağlantıların ağırlığıyla çarpılarak çekirdeğe iletilir. Bu sayede girdilerin üretilecek çıktı üzerindeki etkisi ayarlanabilinmektedir. Bu ağırlıkların değerleri pozitif, negatif veya sıfır olabilir. Ağırlığı sıfır olan girdilerin çıkıl üzerinde herhangi bir etkisi olmamaktadır.</p>
<ul>
<li> <strong>Birleştirme Fonksiyonu</strong></li>
</ul>
<p>Birleştirme fonksiyonu bir yapay sinir hücresine ağırlıklarla çarpılarak gelen girdileri toplayarak o hücrenin net girdisini hesaplayan bir fonksiyondur.</p>

<a href="http://www.ahmetkakici.com/wp-content/uploads/2009/02/ysa/birlestirme.jpg" title="" class="thickbox" rel="singlepic71" >
	<img class="ngg-singlepic ngg-center" src="http://www.ahmetkakici.com/index.php?callback=image&amp;pid=71&amp;width=148&amp;height=67&amp;mode=" alt="Birleştirme Fonksiyonu" title="Birleştirme Fonksiyonu" />
</a>

<ul>
<li><strong> Aktivasyon Fonksiyonu</strong></li>
</ul>
<p>Birleştirme (toplama ) fonksiyonundan çıkan NET toplam hücrenin çıktısını oluşturmak üzere aktivasyon fonksiyonuna iletilir. Aktivasyon fonksiyonu genellikle doğrusal olmayan bir fonksiyon seçilir. Yapay sinir ağlarının bir özelliği olan “doğrusal olmama” aktivasyon fonksiyonlarının doğrusal olmama özelliğinden gelmektedir.<br />
Aktivasyon fonksiyonu seçilirken dikkat edilmesi gereken bir diğer nokta ise fonksiyonun türevinin kolay hesaplanabilir olmasıdır. Geri beslemeli ağlarda aktivasyon fonksiyonunun türevi de kullanıldığı için hesaplamanın yavaşlamaması için türevi kolay hesaplanır bir fonksiyon seçilir.</p>
<p><strong>- Doğrusal Aktivasyon Fonksiyonu</strong><br />
Doğrusal problemler çözmek amacıyla aktivasyon fonksiyonu doğrusal bir fonksiyon da seçilebilir. Doğrusal aktivasyon fonksiyonları matematiksel olarak F(x) = A * x olarak genellenebilir. Bu formülde A sabit bir katsayıdır.  A değerinin değişimi şekilde gösterilen doğrunun çıkış ekseniyle yaptığı açıyı değiştirmektedir.<br />

<a href="http://www.ahmetkakici.com/wp-content/uploads/2009/02/ysa/Lineer.jpg" title="" class="thickbox" rel="singlepic43" >
	<img class="ngg-singlepic ngg-center" src="http://www.ahmetkakici.com/index.php?callback=image&amp;pid=43&amp;width=320&amp;height=240&amp;mode=" alt="Doğrusal/Lineer Aktivasyon Fonksiyonu" title="Doğrusal/Lineer Aktivasyon Fonksiyonu" />
</a>
</p>
<p><strong>- Adım Aktivasyon Fonksiyonu</strong><br />
Girdilerin sıfırdan büyük olup olmamasına göre -1 veya 1 çıktısı veren fonksiyondur. Sadece iki çeşit çıktı vermektedir.</p>

<a href="http://www.ahmetkakici.com/wp-content/uploads/2009/02/ysa/adim.jpg" title="" class="thickbox" rel="singlepic45" >
	<img class="ngg-singlepic ngg-center" src="http://www.ahmetkakici.com/index.php?callback=image&amp;pid=45&amp;width=320&amp;height=240&amp;mode=" alt="Adım/Step Aktivasyon Fonksiyonu" title="Adım/Step Aktivasyon Fonksiyonu" />
</a>

<p><strong>- Sigmoid Aktivasyon Fonksiyonu</strong><br />
Sigmoid aktivasyon fonksiyonu sürekli ve türevi alınabilir bir fonksiyondur. Doğrusal olmayışı dolayısıyla yapay sinir ağı uygulamalarında en sık kullanılan fonksiyondur. Bu fonksiyon girdi değerlerinin her biri için sıfır ile bir arasında bir değer üretir. Sigmoid fonksiyonunun matematiksel ifadesi F(x)= 1/[(1+e)^(-x)]</p>

<a href="http://www.ahmetkakici.com/wp-content/uploads/2009/02/ysa/Sigmod.jpg" title="" class="thickbox" rel="singlepic44" >
	<img class="ngg-singlepic ngg-center" src="http://www.ahmetkakici.com/index.php?callback=image&amp;pid=44&amp;width=320&amp;height=240&amp;mode=" alt="Sigmod Aktivasyon Fonksiyonu" title="Sigmod Aktivasyon Fonksiyonu" />
</a>

<p><strong>- Tanjant Hiperbolik Aktivasyon Fonksiyonu</strong><br />
Tanjant hiperbolik fonksiyonu, sigmoid fonksiyonuna benzer bir fonksiyondur. Sigmoid fonksiyonunda çıkış değerleri 0 ile 1 arasında değişirken hiperbolik tanjant fonksiyonunun çıkış değerleri -1 ile 1 arasında değişmektedir. Matematiksel ifadesi:  F(X)  =  (1- e^(-2x))/(1+ e^2x )</p>

<a href="http://www.ahmetkakici.com/wp-content/uploads/2009/02/ysa/tanh.jpg" title="" class="thickbox" rel="singlepic68" >
	<img class="ngg-singlepic ngg-center" src="http://www.ahmetkakici.com/index.php?callback=image&amp;pid=68&amp;width=320&amp;height=240&amp;mode=" alt="Tanjant Hiperbolik Aktivasyon Fonksiyonu" title="Tanjant Hiperbolik Aktivasyon Fonksiyonu" />
</a>

<ul>
<li><strong>Çıktılar</strong></li>
</ul>
<p>Aktivasyon fonksiyonundan çıkan değer nöronun çıktı değeri olmaktadır. Bu değer ister yapay sinir ağının çıktısı olarak dış dünyaya verilir ister tekrardan ağın içinde kullanılabilir. Nöronun bir çıktısı olmasına rağmen bu çıktı istenilen sayıda nörona bağlı olabilir.</p>
<p>Yapay sinir hücresi hakkında bu kadar bilgiden sonra bir sonraki yazının konusu yapay sinir ağının yapısı olacak. Sonraki yazıda görüşmek üzere ;)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ahmetkakici.com/yapay-sinir-aglari/yapay-sinir-aglarinin-mimarisi-ve-yapi-elemanlari/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Yapay Sinir Ağlarına Giriş</title>
		<link>http://www.ahmetkakici.com/yazilim/yapay-sinir-aglarina-giris/</link>
		<comments>http://www.ahmetkakici.com/yazilim/yapay-sinir-aglarina-giris/#comments</comments>
		<pubDate>Sun, 15 Feb 2009 13:37:28 +0000</pubDate>
		<dc:creator>Ahmet Kakıcı</dc:creator>
				<category><![CDATA[Programlama]]></category>
		<category><![CDATA[Yapay Sinir Aglari]]></category>
		<category><![CDATA[Yazılım]]></category>

		<guid isPermaLink="false">http://www.ahmetkakici.com/?p=123</guid>
		<description><![CDATA[Bitirme ödevim için uğraşmaya başladığım ve tezimde de genişçe yer ayırdığım yapay sinir ağları hakkında tezimden ufak tefek alıntılar yaparak burada paylaşmaya başlıyorum. Tezin tamamını yayınlamak yerine can alıcı noktalarını bir yazı dizisi halinde burada yayınlayacağım. Öncelikle yapay sinir ağlarının ne olduğu ve özellikleri hakkındaki bölüm ile başlamak iyi olur diyerekten yazıma geçiyorum; Yapay Sinir [...]]]></description>
			<content:encoded><![CDATA[<p>Bitirme ödevim için uğraşmaya başladığım ve tezimde de genişçe yer ayırdığım yapay sinir ağları hakkında tezimden ufak tefek alıntılar yaparak burada paylaşmaya başlıyorum. Tezin tamamını yayınlamak yerine can alıcı noktalarını bir yazı dizisi halinde burada yayınlayacağım.</p>
<p>Öncelikle yapay sinir ağlarının ne olduğu ve özellikleri hakkındaki bölüm ile başlamak iyi olur diyerekten yazıma geçiyorum;</p>
<p><span id="more-123"></span></p>
<p><strong>Yapay Sinir Ağlarının Tanımı</strong></p>
<p>Yapay sinir ağları canlılarda bulunan sinir sisteminin çalışmasını elektronik ortama taşımayı hedefleyen bir programlama yaklaşımıdır. Yapay sinir ağlarının da canlılarda olduğu gibi öğrenme, hatırlama ve öğrendiklerini güncelleme gibi yeteneklerinin olması hedeflenmektedir.</p>
<p>Sinir sisteminin davranışlarını kopyalayabilmek için yapısının da kopyalanması gerektiğini düşünen bilim adamları yapay sinir ağlarını modellerken de sinir sisteminin yapısını örnek almışlardır.</p>
<p>Yapay sinir hücrelerinin birbirine bağlanmasıyla oluşan bir yapay sinir ağı öğrenme algoritmalarından herhangi birini kullanarak öğrenme sürecini tamamladığında kullanıma hazır hale gelir. Yapay sinir ağı çalıştığı sürece öğrenme ve bilgilerini güncelleme yeteneğine de sahiptir.</p>
<p><strong>Yapay Sinir Ağlarının Genel Özellikleri</strong></p>
<p>Yapay sinir ağları genel olarak canlı beyninin yapısını gerçekleştirmeyi hedefler. Aşağıdaki işlemleri gerçekleştirebilir:</p>
<ul>
<li>Öğrenme</li>
<li>İlişkilendirme</li>
<li>Sınıflandırma</li>
<li>Genelleme</li>
<li>Tahmin</li>
<li>Özellik belirleme</li>
<li>Optimizasyon</li>
</ul>
<p>Bu işlemleri yapan sinir ağlarının ortak noktası ise bir müdahale yapılmaksızın, elinde bulunan bilgilere göre sonuç üretebilmesidir.<br />
Yapay sinir ağları öğrenme işlemi sırasında verilen bilgiler ile kendini düzenleyerek daha sonraki girdiler için doğru kararlar verebilme yeteneğine sahiptir.</p>
<p><strong>Yapay Sinir Ağlarının Üstünlükleri</strong><br />
Yapay sinir ağ modelleri biyolojik sinir ağlarının çalışmasından esinlenerek ortaya çıkarılmıştır. Canlılarda bulunan sinir sisteminin modellenmesi sayesinde yapay sinir ağları biyolojik sinir sisteminin üstünlüklerine sahip olmuştur.</p>
<ul>
<li><strong>Doğrusal Olmama </strong></li>
<p>Yapay sinir ağları özellikle doğrusal olmayan sistemlerde tahmin yapma açısından istatistik hesaplamalarına göre daha kolay ve doğru sonuç vermesinden dolayı sık kullanılan bir yöntem haline gelmiştir. Özellikle işletmecilik ve finans alanlarında olmak üzere tahmin gerektiren birçok alanda kullanılmaktadır.<br />
Yapay sinir ağlarının temel elemanlarından olan yapay sinir hücrelerinin (nöron) doğrusal sonuçlar vermeyişinden dolayı bu özellik ağa da yansımıştır. Doğrusal olmama özelliğinden dolayı yapay sinir ağları karmaşık problemlerin çözümünde de sıkça kullanılmaktadır</p>
<li><strong>Paralellik</strong></li>
<p>Klasik problem çözme algoritmalarının aksine yapay sinir ağları paralel çalışmaya uygun bir yapıya sahiptir. Bu özelliği sayesinde çok daha hızlı problem çözebilme yeteneğine sahip olmuştur.</p>
<li><strong>Hata Toleransı</strong></li>
<p>Yapay sinir ağları özellikle doğrusal olmayan sistemlerde tahmin yapma açısından istatistik hesaplamalarına göre daha kolay ve doğru sonuç vermesinden dolayı sık kullanılan bir yöntem haline gelmiştir. Özellikle işletmecilik ve finans alanlarında olmak üzere tahmin gerektiren birçok alanda kullanılmaktadır.<br />
Yapay sinir ağlarının temel elemanlarından olan yapay sinir hücrelerinin (nöron) doğrusal sonuçlar vermeyişinden dolayı bu özellik ağa da yansımıştır. Doğrusal olmama özelliğinden dolayı yapay sinir ağları karmaşık problemlerin çözümünde de sıkça kullanılmaktadır</p>
<p>Bilgisayar üzerinde çalışan bir elemanın zarar görüp devre dışı kalması o elmanın içinde bulunduğu sistemin çalışmamasına neden olur. Ancak paralel çalışabilme özelliği ve yapay sinir hücrelerinin bağımsız çalışabilme yapısından dolayı yapay sinir ağında herhangi bir eleman zarar gördüğünde ağın geri kalanı sorunsuz bir şekilde çalışmaya devam eder. İlk olarak yanlış sonuçlar verebilse de daha sonra yeni yapısını öğrenerek eski performansında çalışmaya devam edebilir.</p>
<li><strong>Öğrenebilirlik</strong></li>
<p>Klasik algoritmaların çoğu verilen formüllerin hesaplanması ile aynı girdiler için daima aynı çıktıları üretirler. Lineer olan bu algoritmaların aksine yapay sinir ağları sayesinde programlar öğrenme yeteneği de kazanmışlardır. Klasik algoritmalarda tam olarak tanımlı bir çözüm yolu olmayan problemler çözülemezken yapay sinir ağları sayesinde problemler çözüm yöntemi hakkında herhangi bir bilgi verilmeksizin çözülebilir. Yapay sinir ağlarının bu tip problemleri çözebilmesi için gereken tek şey örnek girdiler için sonuçların verilmesidir.</p>
<li><strong>Genelleme </strong></li>
<p>Yapay sinir ağları üzerinde çalıştığı probleme göre eğitildikten sonra eğitim sırasında karşılaşmadığı durumlar için de yanıt verebilir. Örneğin bir satranç taşının görüntüsünün tanıtılmasından sonra bu taşın görüntüsünü içeren ancak gürültülü bir görüntü verildiğinde bile yapay sinir ağı bu taşı tanıyabilir.</p>
<li><strong>Uyarlanabilirlik </strong></li>
<p>Yapay sinir ağı üzerinde çalıştığı probleme gör kendini düzenleyerek ağırlıklarını belirler. Bir problemi çözmek için eğitilen yapay sinir ağı herhangi bir başka problemde de kolaylıkla kullanılabilir. Bunun için gereken tek şey yeni problemin girdi ve çıktılarıyla ağın tekrar eğitilmesidir.</p>
<li><strong>Hız </strong></li>
<p>Yapay sinir ağları paralel yapısı nedeniyle hızlı bir şekilde çalışıp problem çözme yeteneğine sahiptir. Aynı özelliğinden dolayı donanım üzerinde de kolaylıkla gerçeklenebilir.</p>
<li><strong>Analiz ve Tasarım Kolaylığı </strong></li>
<p>Yapay sinir ağlarının temel yapı taşı olan yapay sinir yapısı bütün yapay sinir ağlarında aynıdır. Bundan dolayı yapay sinir hücresinin tasarımından sonra bu temel eleman ile yapay sinir ağları kolaylıkla oluşturulabilir. Yapay sinir ağlarının temel yapısının da aynı olmasından dolayı bu ağlar her türlü problemin çözümünde kullanılabilinir.</ul>
<p><strong>Yapay Sinir Ağlarının Dezavantajları</strong></p>
<ul>
<li><strong>Eğitim Süreci</strong></li>
<p>Yapay sinir ağları oluşturulduklarında hiçbir bilgi içermediğinden dolayı direk olarak kullanılamazlar. Herhangi bir problem çözümünde kullanılacak olan yapay sinir ağının problemde kullanılmadan önce eğitilmesi şarttır. Bu eğitim süresi problemin çözümünden çok daha uzun zaman alabilir.</p>
<li><strong>Başlangıç Koşullarına Bağlı Olması</strong></li>
<p>Yapay sinir ağları başlangıç koşullarından bağımsız olarak çok kolay dahi olsa herhangi bir problemi çözemezler. Karar verme anında sadece daha önce öğrendiği koşullara göre sonuç üretebilir. Eğitim sırasında verilen örnekler ağın sonraki problemleri çözmesinde de etkilidir.</ul>
<p><a href="http://www.ahmetkakici.com/yapay-sinir-aglari/yapay-sinir-aglarinin-mimarisi-ve-yapi-elemanlari/" target="_blank">Bir sonraki yazıda</a> biyolojik sinir sisteminin yapısına kısaca değinerek yapay sinir ağlarının yapısını anlatan bir yazı ile beraber olacağız. Daha sonrasında ise yapay sinir ağlarının işleyişini ele alabiliriz :)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ahmetkakici.com/yazilim/yapay-sinir-aglarina-giris/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>C# ile Görüntü İşleme &#8211; 2</title>
		<link>http://www.ahmetkakici.com/programlama/c-ile-goruntu-isleme-2/</link>
		<comments>http://www.ahmetkakici.com/programlama/c-ile-goruntu-isleme-2/#comments</comments>
		<pubDate>Fri, 02 Jan 2009 14:31:41 +0000</pubDate>
		<dc:creator>Ahmet Kakıcı</dc:creator>
				<category><![CDATA[Programlama]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[görüntü işleme]]></category>
		<category><![CDATA[image processing]]></category>
		<category><![CDATA[kod]]></category>

		<guid isPermaLink="false">http://www.ahmetkakici.com/?p=105</guid>
		<description><![CDATA[Daha önce görüntü okuma, gösterme ve kaydetme gibi başlıca fonksiyonları vermiştim. Aşağıda ise asıl görüntüyü işeyecek fonksiyonlar bulunmaktadır. Tabii buradaki fonksiyonları kullanbilmek için daha önceden verdiğim şekilde görüntünün dizilere aktarılmış olması gerekiyor. Önceki yazıda gri seviyeye çevirilmiş görüntümüz vardı eğer bu görüntüyü siyah beyaza çevirmek istiyorsanız bunun için bir eşik değeri seçerek 0-255 arasındaki gri [...]]]></description>
			<content:encoded><![CDATA[<p>Daha önce görüntü okuma, gösterme ve kaydetme gibi başlıca fonksiyonları <a href="http://www.ahmetkakici.com/yazilim/goruntu-isleme-c/" target="_blank">vermiştim</a>. Aşağıda ise asıl görüntüyü işeyecek fonksiyonlar bulunmaktadır. Tabii buradaki fonksiyonları kullanbilmek için daha önceden verdiğim şekilde görüntünün dizilere aktarılmış olması gerekiyor.</p>
<p>Önceki yazıda gri seviyeye çevirilmiş görüntümüz vardı eğer bu görüntüyü siyah beyaza çevirmek istiyorsanız bunun için bir eşik değeri seçerek 0-255 arasındaki gri seviye görüntüyü bu seviyeye göre siyah veya beyaz olarak ayırmak gerekiyor. Eşik değerini sabit bir değer olarak belirleyebileceğiniz gibi her görüntüye göre dinamik olarak bir eşik değeri belirleyebilen bir yöntem de mevcuttur: otsu. Otsu algoritması sayesinde üzerinde çalıştığınız görüntüye özel bir eşik değerini otomatik olarak belirleyebilirsiniz. Bunun için görüntünün histogram dizisine ihtiyacınız olacak. İlk yazıda verdiğim kodda histogram çıkartma özelliği yoktu. Bunun için aşağıdaki kodu kullanabilirsiniz:</p>
<p><span id="more-105"></span></p>
<pre class="brush: csharp;">

int[,] pixelArray = new int[pictureBox1.Image.Height, pictureBox1.Image.Width];
int[,] greyPixelArray = new int[pictureBox1.Image.Height, pictureBox1.Image.Width];
int[] histogram = new int[256];

void BuildPixelArray(ref Image myImage)
{
pixelArray = new int[imageWidth, imageHeight];
greyPixelArray = new int[imageWidth, imageHeight];
Rectangle rect = new Rectangle(0, 0, myImage.Width, myImage.Height);
Bitmap temp = new Bitmap(myImage);
BitmapData bmpData = temp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int remain = bmpData.Stride - bmpData.Width * 3;
unsafe
{
byte* ptr = (byte*)bmpData.Scan0;
for (int j = 0; j &lt; bmpData.Height; j++)
{
for (int i = 0; i &lt; bmpData.Width; i++)
{
pixelArray[i, j] = ptr[0] + ptr[1] * 256 + ptr[2] * 256 * 256;
greyPixelArray[i, j] = (int)((double)ptr[0] * 0.11 + (double)ptr[1] * 0.59 + (double)ptr[2] * 0.3);
histogram[greyPixelArray[i, j]]++;
ptr += 3;
}
ptr += remain;
}
}
temp.UnlockBits(bmpData);
}
</pre>
<p>Burada histogram dizisini de oluşturduktan sonra artık otsu algoritması sayesinde dinamik olarak eşik değerini belirleyebiliriz:</p>
<pre class="brush: csharp;">

int otsuValue;

void Otsu()
{
double fmax = -1.0;
double m1, m2, S, toplam1 = 0.0, toplam2 = 0.0;
int nTop = 0, n1 = 0, n2;

for (int i = 0; i &lt; 256; i++)
{
toplam1 += (double)i * (double)histogram[i];
nTop += histogram[i];
}

for (int i = 0; i &lt; 256; i++)
{
n1 += histogram[i];
if (n1 == 0)
continue;
n2 = nTop - n1;
if (n2 == 0)
break;
toplam2 += (double)i * (double)histogram[i];
m1 = toplam2 / n1;
m2 = (toplam1 - toplam2) / n2;
S = (double)n1 * (double)n2 * (m1 - m2) * (m1 - m2);
if (S &gt; fmax)
{
fmax = S;
otsuValue = i;
}
}
}
</pre>
<p>Otsu veya sabit bir değere göre görüntüyü siyah beyaza çevirecek kod ise aşağıdadır. Bu fonksiyonun aldığı argThreshold parametresi eşik değerini belirtern 0-255 arasında bir değerdir.</p>
<pre class="brush: csharp;">

void Binary(int argThreshold)
{
binaryPixelArray = new int[imageWidth, imageHeight];
for (int i = 0; i &lt; imageWidth; i++)
{
for (int j = 0; j &lt; imageHeight; j++)
{
if (greyPixelArray[i, j] &lt; threshold)
binaryPixelArray[i, j] = 0;
else
binaryPixelArray[i, j] = 255;
}
}
}
</pre>
<p>Görüntüyü siyah beyaza çevirdikten sonra eğer kenar bulma algoritmalarını kullanmak isterseniz bir kaç seçeneğiniz mevcut. Bunlardan en popüleri sobel kenar bulma filtresidir. Aşağıdaki fonksiyonda type parametresi hangi tür kenarların bulunacağını belirtmek içindir. Dikey, yatay, köşegen şeklindeki kenarları veya tamamını ayrı ayrı bulabilirsiniz.</p>
<pre class="brush: csharp;">

void Sobel(int type)
{
int normalizeMax = 0;
int normalizeMin = maxIntVal;

sobelPixelArray = new int[imageWidth, imageHeight];
int[,] sobelArray1 =
new int[3, 3] {
{ 1, 0, -1 },
{ 2, 0, -2 },
{ 1, 0, -1 }
};

int[,] sobelArray2 =
new int[3, 3] {
{ 1, 2, 1 },
{ 0, 0, 0 },
{-1,-2,-1 }
};
int[,] sobelArray3 =
new int[3, 3] {
{ 2, 1, 0 },
{ 1, 0,-1 },
{ 0,-1,-2 }
};

int G1, G2, G3;
for (int i = 1; i &lt; imageWidth - 1; i++)
{
for (int j = 1; j &lt; imageHeight - 1; j++)
{
G1 = 0;
G2 = 0;
G3 = 0;
for (int k = -1; k &lt; 2; k++)
{
for (int l = -1; l &lt; 2; l++)
{
G1 += greyPixelArray[i + k, j + l] * sobelArray1[k + 1, l + 1];
G2 += greyPixelArray[i + k, j + l] * sobelArray2[k + 1, l + 1];
G3 += greyPixelArray[i + k, j + l] * sobelArray3[k + 1, l + 1];
}
}
if(type == 0)
{
sobelPixelArray[i, j] = Math.Abs(G1) + Math.Abs(G2) + Math.Abs(G3);
}
else if (type == 1)
{
sobelPixelArray[i, j] = Math.Abs(G2);
}
else if (type == 2)
{
sobelPixelArray[i, j] = Math.Abs(G1);
}
else if (type == 3)
{
sobelPixelArray[i, j] = Math.Abs(G3);
}

if (normalizeMax &lt; sobelPixelArray[i, j])
normalizeMax = sobelPixelArray[i, j];
if (normalizeMin &gt; sobelPixelArray[i, j])
normalizeMin = sobelPixelArray[i, j];
}
}

NormalizeArray(ref sobelPixelArray, normalizeMax, normalizeMin);
}
</pre>
<p>Yukarıda bulunan kodun en altında çağırılan normalize fonksiyonu ise sonuç dizisini 0-255 değerleri arasına düşürmek içindir:</p>
<pre class="brush: csharp;">

void NormalizeArray(ref int[,] sourceArray,int normalizeMax,int normalizeMin)
{

int factor = normalizeMax - normalizeMin;
for (int i = 0; i &lt; sourceArray.GetLength(0); i++)
{
for (int j = 0; j &lt; sourceArray.GetLength(1); j++)
{
sourceArray[i, j] = (sourceArray[i, j] - normalizeMin) * 255 / factor;
}
}
}
</pre>
<p>Bir diğer kenar bulma yöntemi ise Prewitt&#8217;tir:</p>
<pre class="brush: csharp;">

int[,] prewittPixelArray;

void Prewitt()
{
int normalizeMax = 0;
int normalizeMin = maxIntVal;
prewittPixelArray = new int[imageWidth, imageHeight];
int[,] PrewittArray1 =
new int[3, 3] {
{-1,-1,-1 },
{ 0, 0, 0 },
{ 1, 1, 1 }
};

int[,] PrewittArray2 =
new int[3, 3] {
{ -1, 0, 1 },
{ -1, 0, 1 },
{ -1, 0, 1 }
};
int[,] PrewittArray3 =
new int[3, 3] {
{-1,-1, 0 },
{-1, 0, 1 },
{ 0, 1, 1 }
};

int[,] PrewittArray4 =
new int[3, 3] {
{ 1, 1, 0 },
{ 1, 0,-1 },
{ 0,-1,-1 }
};

int G1, G2, G3, G4;
for (int i = 1; i &lt; imageWidth - 1; i++)
{
for (int j = 1; j &lt; imageHeight - 1; j++)
{
G1 = 0;
G2 = 0;
G3 = 0;
G4 = 0;
for (int k = -1; k &lt; 2; k++)
{
for (int l = -1; l &lt; 2; l++)
{
G1 += greyPixelArray[i + k, j + l] * PrewittArray1[k + 1, l + 1];
G2 += greyPixelArray[i + k, j + l] * PrewittArray2[k + 1, l + 1];
G3 += greyPixelArray[i + k, j + l] * PrewittArray3[k + 1, l + 1];
G4 += greyPixelArray[i + k, j + l] * PrewittArray4[k + 1, l + 1];
}
}

prewittPixelArray[i, j] = Math.Abs(G1) + Math.Abs(G2) + Math.Abs(G3) + Math.Abs(G4);
if (normalizeMax &lt; prewittPixelArray[i, j])
normalizeMax = prewittPixelArray[i, j];
if (normalizeMin &gt; prewittPixelArray[i, j])
normalizeMin = prewittPixelArray[i, j];
}
}

int factor = normalizeMax - normalizeMin;
for (int j = 1; j &lt; imageHeight - 1; j++)
{
for (int i = 1; i &lt; imageWidth - 1; i++)
{
prewittPixelArray[i, j] = (prewittPixelArray[i, j] - normalizeMin) * 255 / factor;
}
}
}
</pre>
<p>Prewitt ve sobel&#8217;e alternatif olarak Robert kenar bulma filtresi de mevcuttur :</p>
<pre class="brush: csharp;">

int[,] robertPixelArray;

void Robert()
{

robertPixelArray = new int[imageWidth, imageHeight];
for (int i = 1; i &lt; imageHeight - 1; i++)
{
for (int j = 1; j &lt; imageWidth - 1; j++)
{
robertPixelArray[j, i] = Math.Abs(greyPixelArray[j, i] - greyPixelArray[j - 1, i - 1]) + Math.Abs(greyPixelArray[j, i - 1] - greyPixelArray[j - 1, i]);
}
}
}
</pre>
<p>Eğer kenar bulma algoritmalarını kullanmadan önce görüntüdeki gürültüleri temizlemek istiyorsanız mean, median ve gaussian filtereleri ile bu işlemi yapabilirsiniz.</p>
<p>Mean filtresi :</p>
<pre class="brush: csharp;">

int[,] meanPixelArray;

void Mean()
{
meanPixelArray = new int[imageWidth, imageHeight];
for (int i = 1; i &lt; imageHeight - 1; i++)
{
for (int j = 1; j &lt; imageWidth - 1; j++)
{
meanPixelArray[j, i] =
(
greyPixelArray[j, i - 1]
+ greyPixelArray[j, i + 1]
+ greyPixelArray[j, i]
+ greyPixelArray[j - 1, i - 1]
+ greyPixelArray[j - 1, i + 1]
+ greyPixelArray[j - 1, i]
+ greyPixelArray[j + 1, i - 1]
+ greyPixelArray[j + 1, i + 1]
+ greyPixelArray[j + 1, i]
) / 9;
}
}
}
</pre>
<p>Median filtresi:</p>
<pre class="brush: csharp;">

int[,] medianPixelArray;

void Median()
{

medianPixelArray = new int[imageWidth, imageHeight];
int[] tempArray = new int[9];
for (int i = 1; i &lt; imageHeight - 1; i++)
{
for (int j = 1; j &lt; imageWidth - 1; j++)
{
int counter = 0;
for (int k = -1; k &lt; 2; k++)
{
for (int l = -1; l &lt; 2; l++)
{
tempArray[counter++] = greyPixelArray[j + l, i + k];
}
}
System.Array.Sort(tempArray);
medianPixelArray[j, i] = tempArray[4];
}
}
}
</pre>
<p>Gaussian filtresi</p>
<pre class="brush: csharp;">

int[,] gaussianPixelArray;

void Gaussian()
{
gaussianPixelArray = new int[imageWidth, imageHeight];

int[,] gaussianArray =
new int[5, 5] {
{1,4,7,4,1},
{4,16,26,16,4},
{7,26,41,26,7},
{4,16,26,16,4},
{1,4,7,4,1}
};
int tempSum;
for (int i = 2; i &lt; imageHeight - 2; i++)
{
for (int j = 2; j &lt; imageWidth - 2; j++)
{
tempSum = 0;
for (int k = -2; k &lt; 3; k++)
{
for (int l = -2; l &lt; 3; l++)
{
tempSum += greyPixelArray[j + l, i + k] * gaussianArray[k + 2, l + 2];
}
}
gaussianPixelArray[j, i] = tempSum / 273;
}
}
}
</pre>
<p>Daha sonraki yazıda yapısal (morfolojik) işlemleri yapan filtreleri de açıklamalarıyla birlikte vermeyi düşünüyorum. O zamana kadar hepinize kolay gelsin.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ahmetkakici.com/programlama/c-ile-goruntu-isleme-2/feed/</wfw:commentRss>
		<slash:comments>30</slash:comments>
		</item>
		<item>
		<title>Prolog ile Determinant Hesabı</title>
		<link>http://www.ahmetkakici.com/programlama/prolog-ile-determinant-hesabi/</link>
		<comments>http://www.ahmetkakici.com/programlama/prolog-ile-determinant-hesabi/#comments</comments>
		<pubDate>Wed, 24 Dec 2008 11:37:42 +0000</pubDate>
		<dc:creator>Ahmet Kakıcı</dc:creator>
				<category><![CDATA[Programlama]]></category>
		<category><![CDATA[kod]]></category>
		<category><![CDATA[prolog]]></category>

		<guid isPermaLink="false">http://www.ahmetkakici.com/?p=104</guid>
		<description><![CDATA[Determinant; bir kare matrisi, reel bir sayıyla eşleştiren özel bir fonksiyondur. Sadece kare matrislere uygulanabilir. Determinant hesabının temel yolu minör ve kofaktörlerinin hesaplanması yöntemidir. Buna ek olarak kolay hesaplama için Sarrus Yöntemi adında başka bir yöntem daha geliştirilmiştir. Minör ve kofaktör hesabı ile daha büyük matrisleri daha sistemli bir şekilde çarpabiliriz. Minör tanım olarak: A [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://en.wikipedia.org/wiki/Determinant" target="_blank">Determinant</a>; bir kare matrisi, reel bir sayıyla eşleştiren özel bir fonksiyondur. Sadece kare matrislere uygulanabilir. Determinant hesabının temel yolu minör ve kofaktörlerinin hesaplanması yöntemidir. Buna ek olarak kolay hesaplama için <a href="http://en.wikipedia.org/wiki/Rule_of_Sarrus" target="_blank">Sarrus Yöntemi</a> adında başka bir yöntem daha geliştirilmiştir.<br />
<span id="more-104"></span><br />
Minör ve kofaktör hesabı ile daha büyük matrisleri daha sistemli bir şekilde çarpabiliriz.<br />
Minör tanım olarak: A = (aij) nxn kare matrisinde bir aij ( 1≤i,j≤n)  öğesinin bulunduğu i. satır ve j. sütunun çıkarılmasıyla elde edilen n-1. dereceden kare matrisinin determinantıdır. Mij ile ifade edilir.<br />
A = (aij) nxn matrisinde aij öğesinin minörü olan Mij ‘nin (-1)^(i+j) ile çarpılmasıyla elde edilen sayıya aij öğesinin kofakötür denir ve Aij ile gösterilir.<br />
Bir kare matrisin minör ve kofaktörlerinin çarpımlarının toplamı o matrisin determinantını verir.<br />
Prolog dilinde yazılan programda da kofaktör ve minör hesabı ile determinant hesabı yapılmıştır. Goal kısmında örnek bir matris verilerek determinantı hesaplanıştır.</p>
<pre class="brush: jscript;">

DOMAINS
liste=integer*
matris = liste*
int=integer

PREDICATES
ilkEleman(liste,int)
uzunluk(liste,int)
detBul(liste,liste,int)
ilkleriSil(matris,matris)
negatif(int,int)
sonaAt(matris,matris)
tersCevirListe(matris,matris)
tersCeviriciListe(matris,matris,matris)
det(matris,int,int,int)

CLAUSES
ilkEleman([X|_],X).

uzunluk([],0).
uzunluk([_|K],U):-uzunluk(K,X),U=X+1.

ilkleriSil([],[]).
ilkleriSil([[_|BasKuyruk]|Kuyruk1],[ BasKuyruk |SonucKuyruk]):-
ilkleriSil(Kuyruk1,SonucKuyruk).

negatif(-1,1).
negatif(1,-1).

sonaAt([Bas|Kuyruk],Sonuc):-
tersCevirListe(Kuyruk,TersKuyruk),
tersCevirListe([Bas|TersKuyruk],Sonuc).

tersCevirListe(X,Y):-tersCeviriciListe(X,[],Y).
tersCeviriciListe([],X,X).
tersCeviriciListe([B|K],TMP,SONUC) :-
tersCeviriciListe(K,[B|TMP],SONUC).

detBul([Bas1,Kuyruk1|_],[Bas2,Kuyruk2|_],Sonuc):-
Sonuc = Bas1*Kuyruk2-Bas2*Kuyruk1.

det([Bas1,Bas2|_],_,Sonuc,_):-
uzunluk(Bas1,En),
En&lt;=2,
detBul(Bas1,Bas2,Sonuc),!.

det([Bas|_],Sayac,0,_):-uzunluk(Bas,En),En&lt;=Sayac,!.

det([Bas|Kuyruk],Sayac,Sonuc,_):-
YeniSayac=Sayac+1,
uzunluk(Bas,En),
En&gt;Sayac,
En&lt;=3,
sonaAt([Bas|Kuyruk],Sonda),
ilkEleman(Bas,KatSayi),
ilkleriSil(Kuyruk,KuyrukOrta),
det(KuyrukOrta,0,OrtaSonuc,_),
det(Sonda,YeniSayac,YanSonuc,_),
Sonuc=(KatSayi*OrtaSonuc)+YanSonuc,!.

det([Bas|Kuyruk],Sayac,Sonuc,X):-
YeniSayac=Sayac+1,
uzunluk(Bas,En),
En&gt;Sayac,
sonaAt([Bas|Kuyruk],Sonda),
ilkEleman(Bas,KatSayi),
ilkleriSil(Kuyruk,KuyrukOrta),
negatif(X,Y),
det(KuyrukOrta,0,OrtaSonuc,Y),
det(Sonda,YeniSayac,YanSonuc,Y),
Sonuc=(X*KatSayi*OrtaSonuc)+YanSonuc.

GOAL
write(&quot;_____&quot;),nl,det([[1,2,4,8],[2,2,7,11],[3,6,3,12],[4,13,0,5]],0,Sonuc,1),write(Sonuc).
</pre>
<p>Programda kullanılan yüklemlere tek tek bakacak olursak yüklemlerin yaptığı görevler aşağıda açıklanmıştır:</p>
<ul>
<li>ilkEleman(liste,int):  aldığı tamsayı listesinin ilk elemanını vermektedir.</li>
<li>uzunluk(liste,int) :  aldığı tamsayı listesinin eleman sayısını vermektedir.</li>
<li>detBul(liste,liste,int) :  2&#215;2 matrisin çarpımını yapar. Aldığı iki listenin uzunluğu da birbirine eşit ve iki olmalıdır.</li>
<li>ilkleriSil(matris,matris) :  Minörleri ilk satıra göre açtığım için verilen matrisin ilk satırını silmek için bu yüklem kullanılmıştır.</li>
<li>negatif(-1,1) :  Kofaktörlerin katsayılarını hesaplamak için kullanılmıştır. Her kofaktörde bir önceki kofaktörün katsayısının negatifi hesaplanmıştır.</li>
<li>sonaAt(matris,matris) :  Minörlerin hesabında bir sonraki sütuna göre açılım yapıldığında bu yüklem sayesinde ilk sütun sona atılarak ikinci sütun ilk sütun haline getirilir. Ayrıca 3&#215;3 matrislerde determinant hesaplanırken katsayılarının sırasıyla +1 ve -1 ile çarpılmasına bu yüklem sayesinde gerek kalmamıştır.</li>
<li>tersCevirListe(matris,matris) :  Sona at yükleminde ilk sütunu sona atmak için varolan matrisin ilk sütunu alınarak kalan matris ters çevirilerek ilk sütun başa koyulduktan sonra matris tekrar ters çevrilmiştir. Bu yüklem ters çevirme işlemini yapmaktadır.</li>
<li>tersCeviriciListe(matris,matris,matris) :  tersCevirListe yükleminde kullanılan geçici matrisi bu yüklem ile tanımlayarak asıl yüklemin iki parametre ile gerekli çevirmeyi yapması sağlanmıştır.<br />
det(matris,int,int,int) ) : det yüklemi bütün determinant çarpım işlemlerini gerçekleştirmektedir.</li>
</ul>
<p>Yukarıdan aşağıya doğru yazılmış dört yüklemi sırasıyla incelersek;</p>
<ol>
<li>İlk yüklem 2&#215;2 matris kaldığı zaman bunu detBul yüklemi sayesinde hesaplar ver geri döndürür.</li>
<li>İkinci yüklem ise ilk sütunu sona atarak hesaplanan determinantların durma koşulunu belirler. Eğer sayac değişkeni sıfır olmuşsa yani n sütun varsa ve her biri için açılım yapılmışsa sonuç değeri sıfır olarak döndürür.</li>
<li>Üçüncü yüklem ise 3. dereceden matrislerin determinant hesabında kullanılmıştır. 3. Dereceden matrislerde daha fazla alt matris olmadığından dolayı katsayı değişimine gerek kalmamıştır.</li>
<li>Dördüncü yüklem ise 4. derece ve üstü matrislerin determinantını hesaplarken kofaktörü değiştirmek için kullanılmıştır.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.ahmetkakici.com/programlama/prolog-ile-determinant-hesabi/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Prolog ile Liste İşlemleri</title>
		<link>http://www.ahmetkakici.com/programlama/prolog-ile-liste-islemleri/</link>
		<comments>http://www.ahmetkakici.com/programlama/prolog-ile-liste-islemleri/#comments</comments>
		<pubDate>Tue, 23 Dec 2008 13:43:46 +0000</pubDate>
		<dc:creator>Ahmet Kakıcı</dc:creator>
				<category><![CDATA[Programlama]]></category>
		<category><![CDATA[kod]]></category>
		<category><![CDATA[prolog]]></category>

		<guid isPermaLink="false">http://www.ahmetkakici.com/?p=102</guid>
		<description><![CDATA[Prolog&#8217;un bel kemiği olan liste veri yapısı için daha önceden kullandığım liste fonksiyonlarını aşağıda listeledim. Fonksiyonların isimlerinden ne iş yaptıkları belli oluyor yine de anlamadığınız yer olursa bir yorum bırakabilirsiniz. PREDICATES listeGoster(liste) uzunluk(liste,int) uye(int,liste) ekle(int,liste,liste) yoksaEkle(int,liste,liste) sil(int,liste,liste) hepsiniSil(int,liste,liste) elemanTopla(liste,int) arttir(int,liste,liste) birles(liste,liste,liste) birlesim(liste,liste,liste) kesisim(liste,liste,liste) buda(liste,liste) tersCevir(liste,liste) tersCevirici(liste,liste,liste) prefix(liste,liste) suffix(liste,liste) CLAUSES listeGoster([]). listeGoster([B&#124;K]):-write(B),nl,listeGoster(K). uzunluk([],0). uzunluk([_&#124;K],U):-uzunluk(K,X),U=X+1. uye(X,[X&#124;_]). uye(X,[_&#124;K]):-uye(X,K). [...]]]></description>
			<content:encoded><![CDATA[<p>Prolog&#8217;un bel kemiği olan liste veri yapısı için daha önceden kullandığım liste fonksiyonlarını aşağıda listeledim. Fonksiyonların isimlerinden ne iş yaptıkları belli oluyor yine de anlamadığınız yer olursa bir yorum bırakabilirsiniz.</p>
<p><span id="more-102"></span></p>
<pre class="brush: jscript;">

PREDICATES
listeGoster(liste)
uzunluk(liste,int)
uye(int,liste)
ekle(int,liste,liste)
yoksaEkle(int,liste,liste)
sil(int,liste,liste)
hepsiniSil(int,liste,liste)
elemanTopla(liste,int)
arttir(int,liste,liste)
birles(liste,liste,liste)
birlesim(liste,liste,liste)
kesisim(liste,liste,liste)
buda(liste,liste)
tersCevir(liste,liste)
tersCevirici(liste,liste,liste)
prefix(liste,liste)
suffix(liste,liste)

CLAUSES
listeGoster([]).
listeGoster([B|K]):-write(B),nl,listeGoster(K).

uzunluk([],0).
uzunluk([_|K],U):-uzunluk(K,X),U=X+1.

uye(X,[X|_]).
uye(X,[_|K]):-uye(X,K).

ekle(X,L,[X|L]).

yoksaEkle(X,L,L):-uye(X,L),!.
yoksaEkle(X,L,[X|L]).

sil(X,[X|L],L).
sil(X,[B|K1],[B|K2]):-sil(X,K1,K2).

hepsiniSil(_,[],[]).
hepsiniSil(X,[X|L],M):-sil(X,L,M),!.
hepsiniSil(X,[Y|K1],[Y|K2]):-sil(X,K1,K2).

elemanTopla([],0).
elemanTopla([X|K],T):-elemanTopla(K,Y),T=Y+X.

arttir(_,[],[]).
arttir(X,[B1|K1],[B2|K2]):-B2=B1+X,arttir(X,K1,K2).

birles([],L,L).
birles([B|K1],L2,[B|K2]):-birles(K1,L2,K2).

birlesim([],L,L).
birlesim([B|K1],L2,K2):- uye(B,L2),birlesim(K1,L2,K2),!.
birlesim([B|K1],L2,[B|K2]):- birlesim(K1,L2,K2).

kesisim([],_,[]).
kesisim(_,[],[]).
kesisim([B|K1],L2,[B|K2]):-uye(B,L2),kesisim(K1,L2,K2),!.
kesisim([_|K1],L2,K2):-kesisim(K1,L2,K2).

buda([],[]).
buda([B|K],L):- uye(B,K),buda(K,L),!.
buda([B|K1],[B|K2]):- buda(K1,K2).

tersCevir(X,Y):-tersCevirici(X,[],Y).
tersCevirici([],X,X).
tersCevirici([B|K],TMP,SONUC) :- tersCevirici(K,[B|TMP],SONUC).

prefix([],_).
prefix([B|K1],[B|K2]):-prefix(K1,K2).

suffix(X,Y):-tersCevir(X,TX),tersCevir(Y,TY),prefix(TX,TY).
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ahmetkakici.com/programlama/prolog-ile-liste-islemleri/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
