Einstein'ın Mantık Sorusu

Geçen yıldan beri Einstein'ın mantık sorusu olarak bilinen problemin Prolog'da çözümünü paylaşmak istiyordum. Zamanın ve bilgisayarımdaki verilerin derinliğinde kaybolmuş küçük çalışmamı nihayet gün yüzüne çıkarabildim.

Einstein'ın mantık sorusu:

Kurallar :
1) Beş farklı renkte beş ev var,
2) Her evde beş farklı ülkeden birer kişi oturuyor,
3) Bu evlerde yasayan kişiler;
- Farklı tür içecek içiyor
- Farklı marka sigara içiyor
- Farklı cins hayvan besliyor,
4) Sigara, içecek ve hayvanların hiçbiri aynı cins değil.

Verilen Bilgiler :
1) İngiliz kırmızı evde yaşıyor.
2) İsveçli köpek besliyor.
3) Danimarkalı çay içiyor.
4) Beyaz evin solunda yeşil ev var.
5) Yeşil evin sahibi kahve içiyor.
6) Kuş bakan kişi Pall Mall marka sigara içiyor.
7) Sarı evin sahibi Dunhill marka sigara içiyor.
8) Tam merkezdeki evde yasayan kişi süt içiyor.
9) Norveçli ilk evde oturuyor.
10) Kedi besleyen kişinin evinin yanındaki evde oturan kişi Blend marka sigara içiyor.
11) Dunhill marka sigara içen kişinin evinin yanındaki evde oturan kişi at besliyor.
12) Blue Master marka sigara içen kişi aynı zamanda meyve suyu içiyor.
13) Alman Prince marka sigara içiyor.
14) Mavi evin yanında oturan kişi norveçli.

İstenilen Bilgi :

Su içen kişinin evi hangi renk?

Balığı besleyen kimdir?

Visual Prolog'taki kod

domains

ID= symbol

EV = ev(ID,SIRA) % Her bir ev bir sirayla tanimlaniyor

EVLISTE = reference EV* % Ev listesi

SIRA = integer % Ev sirasi

SIRALISTE = SIRA* % Sira listesi

predicates

nondeterm cozum

nondeterm aday(EVLISTE,EVLISTE,EVLISTE,EVLISTE,EVLISTE)

nondeterm perm(EVLISTE)

nondeterm kisitlar(EVLISTE,EVLISTE,EVLISTE,EVLISTE,EVLISTE)

nondeterm permutasyon(SIRALISTE,SIRALISTE)

nondeterm sil(SIRA,SIRALISTE,SIRALISTE)

uye(EV,EVLISTE)

nondeterm yaninda(SIRA,SIRA)

nondeterm solunda(SIRA,SIRA)

clauses

cozum():-

kisitlar(Renkler,Icecekler,Uyruklar,Sigaralar,Hayvanlar),

aday(Renkler,Icecekler,Uyruklar,Sigaralar,Hayvanlar),

uye(ev(balik,BalikEvi),Hayvanlar),

uye(ev(BalikBesleyen,BalikEvi),Uyruklar),

write("Balik ",BalikBesleyen," tarafindan besleniyor\n").

aday(L1,L2,L3,L4,L5):-

perm(L1),

perm(L2),

perm(L3),

perm(L4),

perm(L5).

perm([ev(_,A),ev(_,B),ev(_,C),ev(_,D),ev(_,E)]):-

permutasyon([A,B,C,D,E],[1,2,3,4,5]).

kisitlar(Renkler,Icecekler,Uyruklar,Sigaralar,Hayvanlar):-

% Ingiliz kirmizi evde oturuyor

uye(ev(ingiliz EV),Uyruklar),

uye(ev(kirmizi, EV1),Renkler),

% isvecli kopek besliyor

uye(ev(isvecli, EV2),Uyruklar),

uye(ev(kopek, EV2),Hayvanlar),

% danimarkali cay iciyor

uye(ev(danimarkali, EV3),Uyruklar),

uye(ev(cay, EV3),Icecekler),

% Beyaz evin solunda yesil ev var.

uye(ev(yesil, EV4),Renkler),

solunda(EV5, EV4),

uye(ev(beyaz, EV5),Renkler),

% yesil evin sahibi kahve iciyor

uye(ev(kahve, EV6),Icecekler),

uye(ev(yesil, EV6),Renkler),

% Kus bakan kisi PallMall marka sigara iciyor

uye(ev(pallMall, EV7),Sigaralar),

uye(ev(kus, EV7),Hayvanlar),

% Sari evin sahibi Dunhill marka sigara iciyor

uye(ev(dunhill, EV8),Sigaralar),

uye(ev(sari, EV8),Renkler),

% Tam merkezde oturan kisi sut iciyor

uye(ev(sut,3),Icecekler),

% Ilk siradaki evde Norvecli oturuyor

uye(ev(norvecli,1),Uyruklar),

% Kedi besleyen kisinin evinin yanındaki evde

%oturan kisi Blend marka sigara içiyor.

uye(ev(blend, EV9),Sigaralar),

yaninda(EV9, EV10),

uye(ev(kedi, EV10),Hayvanlar),

% Dunhill marka sigara içen kisinin evinin yanindaki evde oturan kisi at besliyor.

uye(ev(dunhill, EV11),Sigaralar),

yaninda(EV11, EV12),

uye(ev(at, EV12),Hayvanlar),

% Bluemaster marka sigara icen ayni zamanda meyve suyu iciyor

uye(ev(bluemaster, EV13),Sigaralar),

uye(ev(orange_juice, EV13),Icecekler),

% Alman Prince marka sigara iciyor

uye(ev(alman, EV14),Uyruklar),

uye(ev(prince, EV14),Sigaralar),

% mavi evin yanındaki evde oturan norvecli

uye(ev(norvecli, EV15),Uyruklar),

yaninda(EV15, EV16),

uye(ev(mavi, EV16),Renkler).

permutasyon([],[]).

permutasyon([A|X],Y):-

sil(A,Y,Y1),

permutasyon(X,Y1).

sil(A,[A|X],X).

sil(A,[B|X],[B|Y]):-

sil(A,X,Y).

uye(A,[A|_]):-!.

uye(A,[_|X]):-

uye(A,X).

yaninda(X,Y):-

solunda(X,Y).

yaninda(X,Y):-

solunda(Y,X).

solunda(1,2).

solunda(2,3).

solunda(3,4).

solunda(4,5).

goal

cozum.


Üstteki kod için bazı açıklamalar:
  • uye(EV,EVLISTE): Renk,İçecek gibi alanlarla belirlenmiş bir ev listesinde(EVLİSTE) ilk parametre olarak verilen evin(EV) bulunup bulunmadığına bakıyor.
  • permutasyon(SIRALISTE,SIRALISTE):Dizilebilecek her türlü kombinasyonu yapar.
  • sil(SIRA,SIRALISTE,SIRALISTE):ilk parametreyle verilen değişkenin 2. parametredeki listeden silinip 3. parametre olarak verilmesini sağlar.

Hiçbir şey ifade etmiyor mu? Tamam, prolog'ta temel bir kaç şeye daha değineğim o zaman.

Prolog bildirimsel(declarative) bir dildir. Yani bir olguyu bildirmemiz gerek. Örnek olarak hava güneşli diyeceksek gunesli. dememiz yeterli.
Eğer olgumuz, gerçeğimiz(fact) bir parametre içeriyorsa örneğin "Dünya yuvarlaktır", diyeceksek, yuvarlak yüklemini dünya öznesini-parametresini- kullanarak şu şekilde belirtiriz: yuvarlak(dünya).
Peki iki parametreli bir olguyu nasıl anlatabiliriz? Diyelim ki "Emre İlker'in abisidir" olgusunu bildireceğiz. Şöyle yapmamız gerekirdi. abi(emre,ilker).

Tüm bunları insanın düşünce tarzına benzer şekilde tanımlıyoruz. Hatta cümlenin sonuna nokta da koyuyoruz.

Dikkat ettiyseniz parametreleri küçük harfle yazdık. Çünkü büyük harfle yazdığımızda onu değişken(variable) olarak algılıyor. Kim Emre'nin kardeşidir sorusu için, abi(emre,Kim). dememiz gerekir.

Olguları bildirmenin dışında kurallar dediğimiz cümlecikler de vardır. Burada önemli olan :- işaretinin eğer anlamına geldiğini bilmektir. Bunu kullanarak kurallar yazarız. Örneğin Emre'den büyük olan İlker'den de büyüktür.
buyuk(Buyuk,ilker):-buyuk(Buyuk,emre).


Prolog'da ,(virgül) "ve" anlamına gelirken ;(noktalı virgül) "veya" anlamına gelir. % (yüzde işareti) kod dışı yazılar için kullanılır.

Son olarak Liste denilen kavramdan bahsetmemek olmaz. Tanımlanırken, nelerden oluştuğunu gösteren türden sonra * koyularak belirtilir. Liste dizilere benzer. Bu dizinin ilk elemanı başı(header) kalan elemanlar da kuyruğudur(tail). [bas|kuyruk] olarak gösterilebilir.



Kaynaklar:
Kısa bir Prolog Öğretici
Visual Prolog'a Giriş

Hiç yorum yok: