Plakalar (Çözüm)

Soru

Elimizdeki tamkare plakalar 1 ve 4, tamkare olmayanlar da 2, 3 ve 5’tir. Döner kavşaktaki sürücülerden biri önünde ve arkasında tamkare bir plaka görseydi kendi plakasının tamkare olmayacağını hemen anlayacaktı. İlk turda herkesin bilmiyorum demesi bu ihtimali ortadan kaldırdı, yani tamkare plakalar aralarında bir araç olacak şekilde dizili değil. Bu durumda kalan tek olasılık tamkare plakaların arka arkaya olmaları.

Tamkare plakalı araçların bir araç arayla dizili olduğu temsili durum

Yukarıdaki şekilde de görüldüğü gibi 1 ve 4 plakalı araçlar arasında sadece bir araç varsa bu durumda o araç (şekildeki 3 plakalı araç) ilk soruya rahatlıkla hayır cevabını verebilir. Ayrıca şekilde yine görüldüğü üzere iki araç arasında bir tarafta sadece bir araç varken diğer tarafta da iki araç vardır. Bu nedenle yukarıdaki paragrafta iki tamkare plakalı araç arka arkaya olmalıdır dedim.

Eğer iki tamkare plakalı araç arka arkaya ise o zaman bu iki araç ve bunların önündeki ve arkasındaki birer araç da ya önde ya da arkada sadece bir tane tamkare plakalı araç görecektir.

Tamkare plakalı iki aracın arka arkaya olduğu temsili durum

Bu şekilde de görüldüğü gibi 1 plakalı araç sadece 4 plakalıyı, 4 plakalı 1 plakalıyı, 3 plakalı 4 plakalıyı ve son olarak da 2 plakalı 1 plakalı aracı görebilir. Bu bilgi ise hiçbiri için yeterli olmayacak ve ikinci turda da kendi plakalarının tamkare olup olmadığını bilemeyecekler. Kendi plakasının tamkare olmadığını sadece iki tamkare olmayan plakayı gören sürücü bilecektir. Bu da soruda verildiği üzere Ebru’dur. Demek ki Ebru’nun önünde ve arkasında tamkare olmayan plakalı araçlar vardır.

Dönel kavşaktaki araçları artık trafiğin sağdan ilerlediği yerler için göstereceğim. Bu durumda araçlar kavşakta saat yönünün tersi istikametinde ilerlemektedirler. Son konuşmaya gelindiğinde araç sürücüleri ile bilinen durum aşağıdaki şekildeki gibidir:

Son cevaplar öncesi durum

Son soruya cevaplar verilmeden önce bütün sürücüler bu şekildeki bilgilerden haberdardır. Biz araçta olmadan bu sonuçlara ulaşabildiysek onlar da bu sonuçlara ulaşabilmiştir.

Didem burada arkasındaki araç olarak Ebru’nun aracını görüyor ve kendi aracının plakasının da tamkare olmadığını biliyor. Eğer Ebru’nun aracının plakası 2 olsaydı rahatlıkla evet cevabını verecekti. Ebru’nun aracının plakası 5 olsaydı da hayır cevabını verecekti. Bu iki cevabı da veremediğine göre Ebru’nun aracının plakası 3 olmalı. Şimdi bu bilgi ışığında şeklimize yeniden bakalım.

Didem’in son cevabından sonraki durum

Şimdi Betül ve Ebru hayır diyor. Ebru, Ayşe’nin aracının plakasını görüyor ve hayır diyor. Demek ki Ayşe’nin aracının plakası 3’ten büyük, yani 5 olmalı. Ayşe’nin aracının plakası 5 olursa Didem’in aracının plakası da 2 olmalı. Betül de kendi aracının plakasının 1 ya da 4 olması gerektiğini biliyordu. Arkasındaki araç Canan’ın aracı olduğuna ve bunun plakası da kendininkinden küçük olmadığına göre Betül’ün aracının plakası 1 ve Canan’ın aracının plakası da 4 olmalı. Şimdi şeklimize yeniden bakalım.

Betül ve Ebru’nun son cevaplarından sonraki durum

Bu son tablo Ayşe’nin ve Canan’ın son cevaplarına da uygun durumdadır. Ayşe’nin aracının arkasında Betül’ün aracı var ve Canan’ın aracının arkasında da Didem’in aracı var.

 

Kodu gözden geçirme

Çalıştığım yerde tabii ki doğru düzgün yapılmayan bir yazılım geliştirme tekniğidir. En basit şekliyle yazılmış olan programın belli kurallara göre kontrol edilmesidir. Bu kurallar ciddi ortamlarda yazılı olarak bulundurulur. Bu kuralların bulunmadığı durumlarda gözden geçirmeyi yapan kişiler kendileri karar verirler. Bu sonuçlar sonca programcıya bir şekilde iletilir. Bu birebir bilgisayar başında bir görüşme olabilir ya da başka bir şekilde ilgili programcıya yapılacak iş olarak bildirilebilir. Bu şekilde bazı karışık hatalar çok geç olmadan bulunabilir.

Bazı yerlerde bu iş statik kod analizi araçlarına paslanır. Bu ikisi birbirinin yerini tutmaz ama istatistik tutulmayan yerlerde tek başlarına yeterli oldukları sanısına kapılmak çok kolay olmakta. Kodu gözden geçirme işleminden sonra ilgili programcıyla bulunan noktaların tartışılması ilginç bir olaydır. Tecrübesiz programcılar genelde kendilerine saldırıldığı sanısına kapılırlar ve gereksiz, duygusal tartışmalara girişebilirler. İki taraf için de öğretici olabilecek bu aşama böyle şeylerle boşa harcanmamalı bence.

Teoriye dalıp asıl anlatacağım şeyi unutuyordum az daha. İlaç endüstrisinde çalışan müşteriler genelde bizden programla beraber bu gözden geçirme sonuçlarını da rapor halinde isterler. Bir seferinde bir ekipten böyle bir kod gözden geçirme isteği geldi. O gün öğlende program müşteriye teslim edilecekmiş ve bu işi yapacak boşta elemanları yokmuş. Kabul ettim. Hangi özelliklere bakmam gerektiğini sordum. Genel bir kontrol istediler, zaten tek bir dosyada değişiklik yapmışlar. Kontrol bitince programı onayladığımı belirten bir kağıdı da imzalamam gerekiyormuş. Programı açıp okumaya başladım. Bir süre sonra bir hafıza bölümünün serbest bırakılmadığını gördüm. Bu tür hatalar normalde her işletildiğinde hafızanın bir kısmını programdan çalarak daha az kullanılabilir hafıza bırakır. Bir süre sonra da programa hafıza kalmaz ve program da çalışamaz. Bunun üzerine şefe gittim ve durumu anlattım. “Bu hatayı buldum ve dolayısıyla programı onaylayamayacağım” dedim. O da baktı ve hatayı gördü. Bunun üzerine o da kendi şefine gitti ve çözüm aramaya başladılar. Programı düzeltip, test edecek zamanları kalmamıştı. Bunun üzerine raporumun altına bir ek yazıldı (hata, sistemin genel özellikleri nedeniyle ortaya çıkamaz gibi bir şeyler) ve şefim de bu raporu imzaladı. Bir sorun daha kolayca çözülmüş oldu.

Akraba kayırıcılığı

Akraba kayırıcılığı tabii ki sadece şarka mahsus bir durum değil. Yani öyle düşünüp moraliniz bozulmasın. En fazla “Almanlar bizi kıskanıyor, onlar da yapıyor” deyip geçin.

Görüntü işleme projesi başladığında çok sıkışık bir zaman planımız vardı. Önce fuara yetişmesi gereken bir proje yaptık ve ardından da büyük bir müşteri için anlaşılan diğer üreticilerin yanaşmadığı bir proje. Fazladan mesailerle geçen aylar sonunda müşteri projenin ne durumda olduğunu görmek için şirkete uğramaya karar verdi. Sistemin yeterince hızlı çalışıp çalışmayacağını görmek istiyordu. Ulaşmamız gereken zaman da ciddi bir şey değildi. Bütün bir paketi inceleyip sonuçları bir sonraki makineye bildirmek için 2 saniye zamanımız vardı.

O sırada proje yöneticisinden ne tür yardıma ihtiyacımız olabilir gibi bir soru geldi. Biz de önümüzde bu tür sorunlarla sık sık karşılaşacağımız için zaman ölçme konusunda ufak bir desteğe ihtiyacımız var dedik. Aslında bunu yapabilecek elemanlarımız vardı ama herkes meşgul olduğundan böyle bir şey istedik. Hem işimize yarayacak bir şey olacaktı, hem de bu iş sırasında bizi soru yağmuruyla işimizden de pek alıkoymayacaktı. Yöneticimiz tamam deyip bu işle ilgileneceğini söyledi. Şaşırmıştık ama yine de daha önceki performanslarına göre iyi bir hareketti diyerek sevinçle karşıladık.

Birkaç gün sonra proje yöneticimiz müjdeyi verdi. Destek bulunmuştu. Destek verecek ekiple toplantı da o cuma yapılacaktı. Müşteri bir sonraki cuma gelecekti ve o hafta perşembe günü resmi tatildi. Kısaca pek bir zaman kalmamıştı. Bizim ekip şefi tatilde olduğundan toplantıya benim girmemi istedi. Kabul ettim.

Toplantı günü geldiğinde hazırlıklarım tamamlanmıştı. Olumsuz bir durum için de B planımız vardı. Program müşteri geldiğinde bitmiş olmayacaktı tabii ama iyi yolda olduğumuzu gösterebilirdik. Toplantı odasına girdiğimde (nedense toplantılara hep geç gidiyormuşum izlenimi bırakıyorum ama yok öyle bir şey) bizim yönetici ve diğer şirketin sahibi masada yerlerini almış havadan sudan konuşuyorlardı. Kısa bir tanışmadan sonra problemi anlattım. “Bu projede ve ileridekilerde sık sık duyarlı bir şekilde zaman ölçmemiz gerekecek ve bu altyapıyı kurmak için şu an ayıracak kaynağımız olmadığından profesyönel yardım almayı düşündük. Bu iş için kullanmayı düşündüğümüz programlar şunlar ve sistemimizin özellikleri de şöyle. Bu iş haftaya müşteri gelmeden biterse iyi olur.”

Desteği verecek eleman bunun yapılabileceğini, kolay olduğunu filan anlattı. İyi o zaman, toplantı hemen biter, gider diğer işlere bakarım diye düşünüyordum ki birden daha iyi bir planı olduğundan bahsetmeye başladı. İki saniye önceki rahatlama yerini birden korkuya bıraktı. Yöneticimiz de merak etti ve neler yapılabileceğini sordu. Eleman da anlatmaya başladı: Bizim görüntü işleme alanında oldukça fazla tecrübemiz var. Anladığım kadarıyla sizin sorun şuralarda (Bizim sorunları ne zaman konuştunuz siz ya?). Sizin kullandığınız model (Oh, oh, detaylar bile konuşulmuş) yerine monolitik bir yapı kullanarak program daha hızlandırılabilir ve böylece zaman ölçmeye gerek kalmaz (Bu nasıl bir kabus böyle?).

“İyi de bizim sadece zaman ölçmeye ihtiyacımız var” diye araya gireyim dedim ama masal devam ediyordu. “Şimdi biz müşterinin ürününü inceleyecek rutinleri yazalım. Sonra onu sizin programa entegre ederiz. Kesinlikle daha hızlı bir program olacaktır.”

“Müşteri haftaya geliyor. Önümüzdeki hafta kısa bir hafta. Böyle bir program yapsanız bile bu süre içinde entegre edilmesi imkansız.”

“Bizim hazır kütüphanelerimiz var. O kadar sürmez. Entegrasyonda sizi de destekleriz.”

Bu sırada kara kara dereyi geçerken at değiştirilmez Almanca nasıl denir acaba diye düşünüyordum. Adamın önerdiği şey bugüne kadar pratikte hiçbir zaman başarılı olamamış bir yöntemdi. Hatta Brooks kanunu diye de geçer: “adding human resources to a late software project makes it later”. Bu yeni elemanların bizim sisteme alışana kadar bir süre geçmesi lazım, ayrıca bu sıradaki iletişimler de bizim elemanları işlerinden alıkoyacak. Haftaya yetişmesine imkan yok yani.

Bunları da anlattım ve bizim proje yöneticisi dahiyane bir çözümle olaya girdi. “Aynı anda iki yolu da izleyemez miyiz acaba?”. Destek veren şirketin sahibi buna hemen olumlu yaklaştı. Ben de nasıl bir oyuna kurban gittiğimi ancak o zaman anladım.

“Çarşamba sabaha kadar rutinler hazır olursa belki entegrasyon şansımız olur. Ondan sonra imkansız. Zaman ölçümlerini de en geç o zamana hazırlarsanız iyi olur.”

Toplantıdan sonra proje yöneticisine ayrıca bu yapılan planın yetişmeyeceğini zaman ölçme kısmını en kısa sürede yaptırmasını söyledim. En azından ileride kullanabileceğimiz bir şey yapmış olurlardı o zaman. Tabii ki “hee, tamam” cevabını aldım.

Sonraki hafta her gün planın ne durumda olduğunu sordum. Çarşamba günü de geldi ve ne zaman ölçümü ne de söz verilen rutinler geldi. Çarşamba öğlende proje yöneticisine “Rutinler artık gelmese de olur, umarım müşterinin tatmin olacağı kadar hızlıyızdır.” dedim. Tabii ki cuma günü rutinler geldi. Bizim sisteme eklememi istediler. Ben de “Ben kendimle dalga geçebilirim, bunun için size ihtiyacım yok” dedim ve müşteriye sunum için B planını deneyeceğimizi anlattım. Hemen programa birkaç kıytırık zaman ölçme rutini ekledik, programı yeniden derledik ve müşteriyi karşıladık. İstenen zamana henüz ulaşamamıştık ama projecilerimiz bunu müşteriye iyiye gidiş olarak satabilmişti. Müşteri de memnun kalmıştı (memnun kalmaya ihtiyacı olan müşteriyi memnun etmek kadar kolay bir şey yoktur).

Destek hizmeti aldığımız firmanın sahibi bizim proje yöneticisinin sınıf arkadaşıymış. Yaptığımız toplantının sonucu baştan belliymiş yani. Böylece kendi rutinlerini bizim sisteme entegre etmeye çalışarak güzel bir proje kapmayı başardılar. Bu süre içinde zaman ölçme sistemi asla kurulmadı. Hala, B planında ne yaptıysak o kullanılıyor. Bir yılda eklediğimiz destek rutinlerini işe yaramadıkları için sistemden çıkarabilmemiz üç dört yıl daha sürdü.

Birkaç illüzyon

David Richeson’ın Blog (Division by zero) sayfasında bulduğum aşağıdaki yazıdaki kağıttan yapılmış bazı şekilleri denemeyi başardım. Sayfada her şeklin nasıl yapıldığı anlatılıyor. Oradaki açıklamaların çıktısını yazıcıdan aldım ve makasla kesip işaretli yerlerden katllayıp bant ile yapıştırdım. Aşağıdaki videolarda da denemelerimi görebilirsiniz. Tahtadan yapılmışları ile daha kolay olacağını sanıyorumçünkü ilüzyon tamamen tutuş ve bakış açısına bağlı çalışıyor.

Yazı

Mecburi saçmalıklar

Şirketteki ilk projelerimden biri, bir ürünü DBMS destekli bir hale getirmekti. Önceki versiyon Codebase denen bir sistemle yazılmıştı ve sık sık veri kaybına ya da bozukluklarına yol açmaktaydı. Transaksiyon kontrolü de zordu o sistemde. DBMS olarak MySQL’i seçtik ve projeye başladık. Programlama dili olarak C++ ve geliştirme ortamı olarak da Visual Studio 2003 ve MFC (Microsoft Foundation Classes) kullandık. MFC, ODBC (Open Database Connectivity) üzerinden veri tabanıyla iletişim imkanı sunuyordu. CDatabase nesneleri filan vardı. Değişik dilleri desteklemek zorunda olduğumuzdan da Unicode desteğini aktifleştirmiştik. Başka veri tabanlarını destekleme durumu ortaya çıkabilir diye hem şema hem de veritabanı tabloları için ayrı kütüphaneler de yazdık. Bu tür sistemler o sıralarda Java için çok yaygındı ama C++ için hoşumuza giden bir çözüm bulamamıştık. Projeyi beraber yaptığım arkadaş da o sıralarda C++’tan başka bir dile geçmeye yanaşmıyordu.

İlk basit denemelerden sonra ümit vadeden planımız garip bir sorunla karşılaşmıştı. Nerede olduğunu bilmediğimiz bir Access Violation hatasına çarpıp duruyorduk. Tabii ki hata anındaki stack trace (o anda programda işletilen komutların hiyerarşik listesi) hiçbir şey ifade etmiyordu. Anlaşılan bayağı şiddetli bir buffer overrun (program yanlış yerlere veri yazarak başka nesneleri ve dolayısıyla programın çalışmasını bozuyor) sorunuyla karşı karşıyaydık. Tabii hatanın tam olarak hangi komutta ortaya çıktığını bilmediğimizden internette de aratamıyorduk. Sonuçta buffer overrun ya da access violation nedeni bulmak için oldukça genel terimlerdi. Stack trace, hatanın fark edildiği anda okunamaz  durumda (daha doğrusu bizim durumumuzda anlamsız) olduğundan gözümüz kapalı yavaş yavaş uçuruma doğru yürüme yolunu seçtik. Problemin tek iyi tarafı tekrarlanabilir olmasıydı. Bu sayede defalarca uçuruma gelip hangi anda düşmeye başladığımızı anlamaya çalışacaktık.

Standard yöntem programı hata ayıklayıcı ile çalıştırıp adım adım işletmek olabilirdi. Hata mesajının geldiği yere bakarak programın maksimum nereye kadar ilerlediğini tahmin edebiliyorduk ve baştan oraya gitmek epey zaman alacaktı. Bunun üzerine programın çeşitli yerlerine breakpointler (Program o satıra kadar işletilir ve o noktada otomatik olarak durdurulur) koyarak nereye kadar gidebildiğine baktık. Bu yerleri de genelde hep ikiye bölerek bu aramayı hızlandırdık, yani bir nevi binary search algoritması kullandık. Bir süre sonra hata mesajının nerede ortaya çıktığını bulduk ama bu çok işe yaramıyordu çünkü buffer overrun daha önce olmuş olmalıydı. Biz sadece en geç ne zaman olmuş olabileceğini bulmuş oldu.

Program unit test gibi yöntemler kullanılmadan yazılmış olduğundan parçaları tek tek hızla test etme şansımız da yoktu. Elimizdeki tek araç visual studio içindeki hata ayıklayıcısıydı. Nesnelerin değerleri filan normal gözüküyordu. Bununla oynarken sadece nesnelerin değerlerini değil aynı zamanda bu nesnelerin bulunduğu adreslerdeki (ve bu adreslerin çevrelerinde) değişiklikleri de görebildiğimizi fark ettik. Visual studio her işletilen satır için seçilen adres bölgelerindeki değişiklikleri kırmızı gösterebiliyordu. Çaresizlikten buralara bakayım dedim. Sonuçta hatanın yaklaşık hangi satırlarda olduğunu bulabilmiştim. O satırlardaki nesnelerin hangi adreslerde olduğunu da buldum. Ondan sonra dürbünümü o alana tutup programı satır satır işletmeye başladım. Her satırda ufak tefek kırmızı değişiklikler görünüyordu ama bunlar aradığım şey değildi. O nesnelerin büyüklüklerini bildiğimden bu kırmızı bölgelerin nesnenin içinde mi dışında mı olduğunu hesaplayabiliyordum. Böyle motivasyonumu kaybetmiş bir şekilde satırları tek tek işletirken birden adres ekranı havayi fişek patlaması gibi kıpkırmızı oldu. En son hangi satırda olduğuma baktım hemen ve veri tabanıyla bağlantı kurma komutunu gördüm. İnternette arattım. CDatabase, buffer overrun filan dedim ve binlerce sonuç aldım. Meğer MFC’nin o versiyonu unicode ile bir hesap hatası yapıyormuş ve bu sayede epeyce bir adres alanına yanlış değerler yazıyormuş. Böyle olunca da program bir sonraki adımda nereye gideceği bilgilerini de bozmuş oluyor. Evet, sorunu bulmuştum ama çözüm neydi? Forumlara bakılırsa Microsoft yakında bir yama yayımlamayı düşünmüyordu ama biz programı müşteriye söz vermiştik.

Sonuçta çaresizliğimizin doruğunda visual studio’nun küçük boyutlarda yaptığı bir şeyi yapmaya karar verdim. Veri tabanı nesnesinin sağına ve soluna dev gibi yasak bölgeler inşa ettim. Yanlış hatırlamıyorsam 10 kB büyüklüğünde boş alan koydum. Bir nevi hendek yöntemi. Bu şekilde diğer nesneleri veri tabanı nesnesindeki hatalardan korumayı başardım. Şansımıza veri tabanı nesnesi sınırları içinde bir sorun çıkmamıştı. Aylar sonra gelen Microsoft yaması ile bu utanç verici çözümü de kaldırdık ama bence bu utancın büyük kısmı Microsoft’a aittir. Bütün bu hatayı arama ve düzeltme süreci neredeyse iki hafta sürdü. Aslında bu iki haftada hatanın adını aramış olduk, adı konulunca kendimizi sanki herkesin aynı sorundan muzdarip olduğu bir ortamda bulduk.

Bir iş görüşmesi

Yaklaşık bir yıl süren işşizliğimin sonlarına doğru iş arama yöntemimi değiştirmem gerektiğine karar vermiştim. İş ve işçi bulma kurumu her ay en son net maaşımın yüzde seksenini otomatikman veriyordu ama bir yılın ardından bunda daha fazla kesintilere gideceklerdi. Ayrıca bana gönderdikleri iş teklifleri de artık iyice saçmalaşmaya başlamıştı. Bunun üzerine internetten çevredeki şirketlere bakmaya başladım. Ehliyetim olmadığından tren ve yürüyerek makul bir zaman içinde ulaşabileceğim bir iki tanesini seçip özgeçmişimi yolladım. Ondan sonra son bir yıldır yaptığım işlere geri döndüm. Uyumak ve reality show seyretmek.

Noel öncesi bir gün televizyonda talk show seyrederken telefon geldi. Öğleden sonra müsaitsem benimle görüşmek istiyorlardı. Randevu defterime baktım ve reality showları başka bir güne kaydırabileceğimi gördüm. Olumlu cevap verdim ve yola çıktım. Yirmi dakika ötedeki Kaiserslautern şehrine ilk gidişimdi. Trene bindim  ve istasyonda indim. Haritalardan baktığım otobüs durağına gittim ve 102 nolu otobüsü beklemeye başladım. Lanet otobüsten iki tane vardı. Hangisine binmem gerektiğini bilmiyordum. Sormaktan çekinip taksiyle gideyim dedim. Zaten az zamanım kalmıştı. Taksiye bindim adresi verdim. Bir gözüm saatte diğeri de taksimetrede gitmeye başladık. Görüşme saatine çok az kalmıştı ki şöför birden yanlış geldiğini, gitmemiz gereken sanayi merkezinin şehrin diğer tarafında olduğunu söyledi. Yapacak bir şey yoktu. Peki o zaman şehrin öbür tarafına gidelim dedim. Neyse ki şehir küçükmüş. Beş dakika kadar gecikmeyle şirkete vardım. Parayı uzattım ve adam yok dedi. “Benim hatam. Alamam.” dedi. Ben de Almanca’m çok iyi olmadığından ısrar etmedim.

İçeri girdim ve kısa süre sonra beni görüşme odasına aldılar. AR-GE şefi ve iki yazılım bölümü yöneticisi masada yerlerini aldılar. Sonra başladık. Şirketin neler yaptığından haberim olup olmadığını sordular. Internetten baktığımı, endüstriyel teraziler filan yaptıklarını söyledim. Sonra bana bir tane terazi birimi verdiler. Küçük bir metal parça, çok az hareket ediyor ve bununla paketleri çok hassas tartıyorlardı. Bu parça ile ilgili sorular sormaya başladılar. Tabii ki internet sayfasından bu aletin şemalarına çalışmıştım ama şemalar tersti. Bu yüzden bazı sorulara yanlış cevap verdim.

Ardından zeka testine geçtik. İşin uzmanları için belk işe yarar bir test olabilir ama bu ekibin bunu bilerek yaptığını sanmıyorum. Neyse işte. Klasik terazi bilmeceleriydi. On adet toptan ağır olanını üç tartıda bulmak gibi oldukça basit şeyler sordular. Ortaokuldan beri bu tür bilmecelerle ilgilendiğimden ölçecek bir durum yoktu.

Bilmeceleri bitince programlama bilgimi ölçmeye karar verdiler ve terazi birimi yazılım şefi aşağıdaki soruyu sordu:

int x = 42;
int y = 15;
x ^= y;
y ^= x;
x ^= y;

Bu kod ne yapar

Kısa bir C kodu bu. Öğrenmek istedikleri şey sanırım bit işlemlerini yapabilip yapamadığımdı. Yukarıdaki işlemler XOR diye bildiğimiz bit işlemleri. Yani aynı değerdeki bitler 0, farklı değerlerdeki bitler de 1 sonucunu verecek. Soruyu görünce istemsizce gülümsedim. Bir iki saniye ne desem acaba diye düşündüm ve bu değiş tokuş fonksiyonudur dedim. Yani işlem sonunda y değişkeninde 42, x değişkeninde de 15 değeri olur. Sorgu ekibi şaşırmıştı. İlk kez doğru cevap almışlardı ve daha da kötüsü bu cevabı hiçbir şey ölçemeyecekleri bir şekilde almışlardı. Nasıl bilebildiğimi sordular. Ben de bilmeceleri sevdiğimi ve bu “bilmeceyi” de daha önceden bildiğimi söyledim. Güldüler ama ben de tedirgin oldum, şimdi bir şey ölçemediklerinden daha basit ve yapamayacağım bir şey sorabilirlerdi. Bunu engellemek için konuşmaya devam ettim. “Ama değiş tokuş için bunu kullanmamak lazım, çünkü bu haliyle her zaman çalışmaz. Bunu fonksiyon şeklinde yazarsak referans ya da göstericiler kullanmak lazım ve o zaman da iki göstericinin de aynı adresi gösterdiği duruma dikkat etmek lazım. Yoksa iki değişken de sıfırlanır (a xor a = 0).”

 void xorSwap (int *x, int *y) {
     if (x != y) { //bu kontrol adresteki değerin sıfırlanmasını engeller
         *x ^= *y;
         *y ^= *x;
         *x ^= *y;
     }
 }

Bunun üzerine soruyu soran şef eline kağıt kalem alıp dediklerimi denemeye başladı. AR-GE şefi de kendisine başka bir sorusu olup olmadığını sordu. Başka soru yoktu. Demek bu sorunun cevaplanmayacağından çok emindiler. Biraz rahatlamıştım ki güçlü ve zayıf olan üçer yönümü sordular. Buna verecek cevabım yoktu. Daha daha doğrusu üçe indirmek imkansızdı. Neyse ki sorguculardan biri “anlaşılan hazırcevaplık güçlü olduğunuz bir alan değil” dedi de hep beraber güldük.

Görüşmenin gerisi olaysız geçti. Bir sonraki aşamaya kalmıştım. Çıkarken, umarım sordukları gibi program yazmıyorlardır diye düşünüyordum ki işe girdikten sonra bir programda şöyle bir satır gördüm.

*x ^= *y ^= ( *y ^= *x );

Bana sorulan sorudaki işlemin tek satırda yapılmasıydı bu. Bu görüşmedeki durumdan daha feci bir durumdu çünkü yukarıdaki  satır dilin kurallarına göre tanımlanmamış bir davranıştır, yani derleyici burada istediği her şeyi yapabilir ve bu andan itibaren program da artık özgürdür. Neyse ki arkadaşı ikna etmek şefi ikna etmekten daha kolay oldu.

Bence bir iş görüşmesinde bundan çok daha iyi bilgi ölçme, değerlendirme imkanları vardır. Örneğin işe başvuran kişi bir hata ayıklama, kod inceleme ya da “pair programming” seansına davet edilebilir. Bu sırada kendisiyle çok daha zengin bir iletişim kurulabilir.

Yazılımda direniş

Projede uzun zamandır giderilmeyen çeşitli hatalar var. Bunlar sistemin çalışmasını çok kısıtlayan hatalar değil ama en azından rahatsız edici şeyler.

Birbiriyler haberleşme yapan uygulamaların daha bu haberleşmeye hazır olmadan iletişime geçmeleri en basit örneklerden biri. Sistemde, haberleşme başladığı an belli aşamaların bitirildiği varsayılır. Bunun dışında haberleşme başlayınca yine karşılıklı olarak beklenen davranışlar da vardır ve bunlar protokollerle tanımlanmıştır. Kontrol birimi makinenin durumunu bildirirken haberleşme başlatılırken açılmış olan oturumun kod numarasını kullanmalıdır gibi. Eğer bu oturum kod numarası kullanılmazsa diğer uygulamalar bu mesajları göz ardı eder ve sistem beklendiği gibi çalışmaz (ama çalışır).

Başka bir hata ise çok farklı makinelerin üretilmesine rağmen ortak arabirimlerin ihmal edilmesi. Örneğin, görüntü işleme birimi belli durumlarda otomatik olarak tekrar ayarlanmalı. Bunu yapmak için belli bir modüldeki bir parametreye bir değer yazmak yeterli. Projeye 10 yıl önce başladığımızda da böyle yaptık. Zamanla daha farklı kameralar kullanmaya başladık, dolayısıyla da yeni modüller ve parametreler tanımlandı. Bazı modüllerde birden fazla parametrenin kullanılması gerekti. Böylece bu parametreyi kullanan uygulamanın kodu iyice karışık haller almaya başladı. Bu sorunu halletmenin yolllarından biri tabii ki bu işlem için bir arabirim tanımlamak. Anlaşılan bu parametre diğer parametrelere göre daha özel bir duruma sahip ve nerede olduğu da makineye göre değişebiliyor. Eğer otomatik ayarlama diye bir komut tanımlansaydı bu her makinede kolayca uygulanabilirdi ama görüntü işleme grubu bunu programlayamayacağını bildirdi. Anlaşılan kullandıkları kütüphanede bu değişikliği yapabilecek birine sahip değillerdi. Bir başka çözüm olarak yazdığım program bir konfigürasyon dosyasında bu bilgileri tutabilir ve her makine için bu dosya değiştirilebilir. Bunun avantajı tabii ki tek bir kodun her makine için çalışması. Tabii ki dezavantajları da var. Makineyi kuran elemanın bu dosyanın dilini anlaması lazım ve görüntü işleme birimiyle beraber bu değişiklikleri yapması lazım. Bu çözüme de yanaşılmadı. Ben de bütün bildiğim parametrelere ayarlama anında değerler yazmaya başladım. Tabii ki bazı makinelerde bu modüller mevcut olmadığından ekranda uyarı mesajları görünüyordu.

Test grubu bu hata mesajlarını her gördüğünde bunlar üzerine kısa toplantılar yapılıyordu ve her seferinde bunların nasıl çözüleceğini anlatıyordum. Cevap hep aynıydı: Bu değişiklikleri yapacak zamanımız yok. Doğru bir çözüm ile sorunlara yaklaşılmadığından daha kışkırtıcı çözümler aramaya başladım. Diğer uygulamaların protokolleri çiğnediği her durum için hata mesajları tanımlamaya başladım. Her seferinde bu hataları kullanıcı arabiriminde gösteriyorum.

Bu sabah görüntü işlemecilerden biri geldi ve bir makinede ufak tefek sorunlar olduğunu söyledi. Sorunların neler olduğunu sordum. Yazdığım uygulama mevcut olmayan modüllerdeki parametreleri sorguluyormuş. “Tabii ki yapıyor” dedim. “Bana verilmiş tanımlı bir arabirim olmadığı sürece bütün parametreleri sorgulayacağım” dedim. Görüntü işlemeci de “Veri tabanında o parametrenin olmadığını biliyorsun, onu sormana gerek yok ki” diye cevap verdi. Durumu daha açık bir şekilde anlatmam gerektiğini anladım ve kısa tiradıma başladım. “Eğer veri tabanında olmayan parametreyi sorgulamazsam hata mesajı gelmez. O zaman da herkes makine doğru çalışıyor diye düşünür. Makine doğru çalışıyor izlenimi yaratırsam kimse daha temeldeki bu tasarım problemleriyle ilgilenmez. Yani bütün bu hata mesajlarını sizi rahatsız etmek için yapıyorum. Bu program ve tasarım hataları giderilene kadar da mesajları göreceksiniz. Bunların ne olduğunu soranlara da durumu anlatmak zorunda kalacaksınız. Bunu durdurmanın yolu çok kolay. Protokollere uyun. Bana arabirim verin.” diye karşılık verdim.

Sonra ne mi oldu? Tabii ki hiçbir şey. Eleman, birkaç hafta sonra aynı konuşmayı tekrar yapmak üzere gülerek uzaklaştı. Ben de bir sonraki hata mesajım ne olsun acaba diye düşünmeye başladım.

Plakalar

Bu soruyu da Alex Bellos’un the guardian’daki köşesinden aldım.

Bir dönel kavşağa 5 araç giriyor. Sürücüler sırayla Ayşe, Betül, Canan, Didem ve Ebru. Araçların plaka numaraları da 1, 2, 3, 4 ve 5 ama bu sırayla olmak zorunda değil. Her sürücü önündeki ve arkasındaki araçların plakalarını görüyor ama kendi aracınınkini göremiyor. Her sürücü diğer sürücülerle kulaklık ve mikrofon aracılığıyla konuşabiliyor.

Birden kulaklıklarda bir ses duyuyorlar:

– Aracınızın plakası tamkare mi?

Hep birden bilmediklerini söylüyorlar.

Aynı ses tekrar soruyor.

– Aracınızın plakası tamkare mi?

Ebru hariç herkes bilmediklerini söylüyor. Ebru ise hayır cevabını veriyor. (Ebru da dahil herkes aynı anda cevap veriyor)

Aynı ses yine duyuluyor.

– Aracınızın plaka numarası arkanızdaki aracın plaka numarasından büyük mü?

Didem bilmediğini söylüyor.

Ardından Betül ve Ebru hayır diyorlar.

Sonra da Ayşe ve Canan’ın evet cevapları geliyor.

Herkesin aracının plaka numaralarını bulun.

 

Fisher’in kaçış evrim modeli üzerine denemeler

Evrim teorisi temelde basit olmasına rağmen birçok durumda akılda canlandırmakta zor oluyor. Bu nedenle bu konuyu daha iyi anlayabilmek için elimden geldiğince simülasyonlar yazmaya karar verdim. Bu ilk sümülasyonda cinsel seçilim konusunda Fisher kaçış modelini denedim. Önce anladığım kadarıyla bu noktalara kısaca değineceğim ve sonra da simülasyonu sunacağım.

Evrimde doğal seçilimin yanında cinsiyetler arası seçilim de oldukça önemlidir. Hayatta kalabilen bir birey eğer çiftleşemezse genleri bir sonraki nesle aktarılamaz.

Bazı kuş türlerinde erkeklerde hayatta kalma şansını artırmaya yaramayacak büyüklükte kuyruklar vardır. Bu kuyruklar yardım etmediği gibi aynı zamanda yük de olmaktadır. Peki, o zaman nasıl bu kadar büyümüşler?

Ronald Fisher, 1930’da bu durumu açıklayabilecek bir model öne sürdü. Erkekteki süs özelliğini güçlü bir şekilde seçen dişi bu şekilde doğal seçilimin etkisini zayıflatabilirdi. Bu şekilde bu süs, süsün masrafı cinsel seçilimin getirisinden büyük olana kadar artabilir ya da büyüyebilir. Burada masraftan kasıt örneğin kuşun artık hiç uçamayacağı bir kuyruğa sahip olması olabilir. Bu durumda bu erkekler dişiler tarafından seçilecek olsa bile hayatta kalamadıklarından çiftleşme şansı bulamayacaklardır.

Fisher’in açıklaması için erkeklerdeki abartılı süs ve dişilerdeki bu süsü tercih etme genetik özellikler olmalı, yani genlerle nesilden nesile aktarılabilmeli. Gruptaki diğer bireylere göre ortaya çıkan bu iki ayrılık da (erkekteki süs gelişimi ve dişideki bu süsü seçme eğilimi) Fisher’e göre birbirlerini pozitif bir şekilde ilerleteceklerdir.

Süslü erkeği tercih eden bir dişinin dişi yavrusu olursa kendi tercih geni de yüzde elli ihtimalle bu yavruya geçecektir ve bu yavru da yüzde elli ihtimalle annesinin tercih özelliğini gösterecektir. Bu dişi yavru aynı şekilde babadan da büyük süs genini yüzde elli ihtimalle alacak. Her ne kadar kendisi büyük süs özelliğini göstermese de yine kendisi bu geni bir sonraki nesle aktarma şansını sürdürecektir. Aynı mantığı erkek yavru için de yürütebiliriz. Erkek yavru babadan aldığı büyük süs geninin etkisini gösterirken anneden aldığı büyük süs seçim genini de bir sonraki nesle aktaracaktır.

Aşağıdaki linkten bu modelin simülasyonuna erişebilirsiniz. Simülasyon animasyonsuz çalıştırıldığında sadece her nesilde kaç tane normal erkek (normal süse sahip), normal dişi (eş seçimini süs büyüklüğünden bağımsız yapan), farklı erkek (büyük süse sahip) ve farklı dişi (eş seçiminde büyük süsü tercih eden) birey olduğu hesaplanıyor. Bir sonraki nesli üretmek için o nesildeki bireyler seçim yöntemlerine göre birer eş seçiyor ve sonraki nesilde toplam popülasyon büyüklüğünde çocuk oluşana kadar ürüyorlar. Çocukların erkek veya dişi olması ya da babadan ve anneden hangi genlerin geleceği rastgele seçiliyor. Eş seçiminde monogami ya da poligami olması seçeneği de mevcut. Poligamide bir erkek birden fazla dişi ile çiftleşebiliyor. Burada çiftleşmeden kastım başarılı döllemedir, beraber olma sıklığı ya da çeşitliliği simülasyonda ele alınmamıştır. Eğer animasyon seçeneği kullanılırsa popülasyon büyüklüğünü küçük tutmak iyi olacaktır yoksa hem simülasyon çok uzun sürecek hem de popülasyon ekrana sığmayacaktır. Animasyon modunda bireyler dikdörtgen şeklinde gösterilmektedir. Erkek bireyler E, dişi bireyler de D harfi ile işaretlenir. Dikdörtgenlerin alt tarafında anne ve babadan geçen genler gösteriliyor. S geni, büyük süsü gösterirken s geni de normal süsü göstermektedir. Aynı şekilde T geni büyük süsü tercihi simgelerken t geni de rastgele tercih anlamına geliyor. Üremeye katılan çiftler animasyon sırasında yeşil gösteriliyor. Sonra bir alt satırda bu birleşmeden ortaya çıkan çocuklar yeni nesilde genlerle beraber gösteriliyor. Ardından dişi birey bu nesilde bir daha çiftleşemeyeceğinden kırmızıya dönüyor. Eğer ilişki durumu monogamiyse erkek birey de kırmızı oluyor. Poligami seçilmişse aynı erkek başka çiftleşmelerde de bulunabiliyor.

Üreme aşamasında şöyle bir algoritma kullandım. Seçilen çiftleşmelerden önce sırayla birer çocuk ürüyor. Ardından toplam nüfus istenen değere ulaşana kadar aynı çiftleşmelerden rastgele seçimler yapılıyor ve basla çocuklar da ürüyor. Animasyon sırasında ise bu iki kademe aynı anda oluyor gibi gösterilmekte.

Simülasyonlarda da görüldüğü gibi poligaminin yaygın olduğu popülasyonlarda aşırı süs ve bu süslerin tercih genleri daha hızlı yayılıyor.

Simülasyon

Bu simülasyonda daha başka özellikler de görmek isterseniz bunu yorum kısmında belirtebilirsiniz.