İlginç Bir Programlama Tekniği: Recursion
Ayhan KALAYLIOĞLU bilgisayar programlama dilinde kısaca kendi kendini çağırabilen altprogramları ifade eder.
Şimdi şöyle bir soru akla gelebilir. Bir altprogram nasıl oluyor da kendi altprogramı oluyor; çelişki yok mu; sınırı nerede, kim ve nasıl belirliyor? Aslında olaya paniğe kapılmadan sakince yaklaşınca konu daha iyi anlaşılıyor. Bu programlama tekniği bilhassa dallanıp budaklanan işlemlerin çözümünde kullanılıyor. RECURSION olayını açıklamadan önce bilinmeyen ya da unutmuş olanlar için altprogram olayının detaylarını açıklayalım. Bilindiği gibi altprogram bir program parçasıdır. Başka bir program tarafından çağırılabilir ve altprogramın bittiğini belirten bir emirle (RETURN emri) asıl programa geri döner. Altprogramların başka bir özelliği de birçok altprogramın birbirlerini çağırabilmesi ve sırayı karıştırmadan doğru olarak geri dönebilmesidir. Bu özellik sayesinde birçok program daha derli toplu, anlaşılır bir biçimde yazılabilmektedir. Modüler programlama denilen olayın temel taşlarından biri de budur. Bütün yapılan işlerin sınırları belirlenir ve hepsi ayrı altprogramlara bölünür. Böylece ufacık bir programla birçok işin halledilmesi mümkün olur. Makine dilinde programlama bilenleriniz veya başka diller kullanmış olanlarınızın duymuş olabileceği bir olay bu sorunun başlıca çözüm anahtarıdır. Çözüm 'STACK' (yığın, bilgi yığını) denilen bir veri yapısı sayesinde sağlanmıştır. Stack'ı bilgilerin yazılıp üst üste konduğu sayfalara benzetebiliriz. En son yazılmış bilgi en üstte olacağı için ilk olarak ele o gelecektir. Yığının (stack) temel çalışma prensibi de budur; “LAST IN FIRST OUT”. (Yığına en son atılan bilginin ilk önce çıkması prensibi.) Altprogram olayına dönersek; BASIC dili GOSUB emrine rastladığında altprogramın geri döneceği adresi yığına atar ve işlemin geri kalan kısmı GOTO emrinin aynısıdır. Altprogram içinde ise RETURN emrine rastladığınızda adres yığından alınır ve program oradan devam eder. Böylece geri dönüş işlemi doğru bir biçimde gerçekleşmiş olur.
zılır.Sırasını ve yerini karıştırmamak için bir göstergeç kullanılır (stack pointer). Bu göstergeç bir sonraki bilginin nereye yazılacağını gösterir. Yeni bir bilgi yazılırken bu bilgi yığının ucuna göstergeç vasıtasıyla eklenir ve hemen ardından göstergeç bir artırılır. Yığından bilgi alındığında tam ters işlem gerçekleşir. Onca yığın göstergeci bir eksiltilir. Hemen ardından bilgi yığından göstergeç vasıtasıyla okunur. Dönelim RECURSION olayına: ayııı altprogramlar-
PROBLEMİN Çözümü
GEÇEN ZAMAN <SAAT,DAKİKA,SANIYE): 200008 BAŞLANGIÇ ŞEKLİ
KK OK kO *S * * 4 * * * HO * * ** * * * Ek kl kk
ÇüZüLMÜŞ ŞEKLİ
ek
*SCCCC *
*
*
* *t*k
** — CCCCCCx
* *
* *CCCE *
OOO Akk
İki olayı birleştirip incelersek; geri dönüş adresleri peşpeşe birbirleri üzerine yığılacak, fakat sıraları geri dönüş açısından yorumlandığında doğ- Tu olacaktır. Böylece istenilen seviy de derinliklere inen altprogramlar yazılıp yürütülebilir. Yığının fiziksel yapısına gelince: Yığın bildiğimiz hafızanın belli bir bölgesidir. Bilgiler hafızaya peşpeşe yada olduğu gibi yığın tipi veri yapılarına ihtiyaç vardır. Bu yığın yalnızca geri dönüş adreslerini içermez; aynı zamanda programın her kendini çağırışında içinde bulunduğu durumu gösteren bilgileri de içermelidir. Böylece altprogram kendi kendine (bir üst seviyeye) geri döndüğü zaman kaçıncı seviyede ve ne durumda bulunduğunu hatırlayacaktır. Programımız bir altprogramı çağırıp (altprogramın kendi kendisi olduğunu bir an unutahm), işini yaptırdıktan sonra kaldığı yerden devam edebilmesi sağlanmıştır. Zaten programımız nerede olduğunun farkına varamazsa sonsuz döngülere girecek ve ana işlem ünitesinin yığınını tümüyle doldurup “OUT OF MEMORY ERROR' mesajı ile başarısız bir biçimde sonuçlanacaktır. RECURSION tipi programlar bir veri yapısı üzerinde çalışırlar ve bu veri yapısını değiştirirler (zaten sonuç olarak yapılan net iş budur). Bu çalışma alanı altprogram hangi seviyede olursa olsun, erişilebilir ve diğer seviyelerinde görebileceği biçimde değiştirilebilir olmalıdır. Bu uzun ve karmaşık cümlenin ne anlama geldiğini birazdan vereceğim örneklerle açıklayacağım. Burada vereceğim örnekler birçok bilgisayar programcısının aklına takılan veya merak ettiği ve büyük ihtimalle kafasını karıştırıp vazgeçtiği konuları içermektedir. Mesela: * Satranç nasıl oynanır? ÖNERİ: Bir altprogramımız olsa; diyelim ki yaptığı iş “belli bir pozisyonda olabilecek tüm hedefleri değerlendirmek” olduğu zaman içinde diğer karşı ihtimalleri ve karşı ihtimallerin karşı ihtimallerini vs. değerlendirmek için kendi kendini çağırması gerekecektir ve bu program “RE-CURSIVE” çalışarak sorunu çözecektir. Ne güzel değil mi? * Bir BASIC satırının içindeki karmakarışık bir matematiksel işlemin değeri nasıl hesaplanır? ÇÖZÜM: COMMODORE 64'ümüzün BASIC ROM'unda FRMEVL adında bir altprogram vardır. Bu altprogram çağırıldığında yukarıda söylenen işi yapar. İşlemler soldan sağa okunur; fakat matematiksel olarak bu sırada yürümesi şart değildir. Bu da önemli bir sorun teşkil eder. İşlem sırası çoğu zaman “soldan sağa” ölçüsüne uymaz. Mesela işlemsel önceliklere göre (Örneğin: çarpma veya bölme işlemi, toplama veya çıkarma işlemlerinden önce yapılır) veya parantezlerle işlenme yönü belirtilmişse. Buna göre işlem önceliği sağ taraftaki argümanı bilmeyi gerektiriyorsa
FRMEVL o ana kadarki bulduğu değeri yığına atar ve sağ taraftaki argümanı hesaplaması için kendi kendini çağırır. Gelen sonuçla yığından geri aldığı ilk sonuç arasında daha düşük öncelikli işlemi yapar. Böylece şunlar sağlanır: Satır soldan sağa işlenir. (Zaten başka türlü bir çözüm saçma ve karışık olurdu.) Ayrıca dilendiği kadar işlem belirli öncelik sırasıyla oluşturulur ve gerçekten hatasız olarak bu sırada işlenmesi gerçekleşir. * Grafik ekranında bir resmimiz olsun. Boş olan bir bölümünü boya döker gibi doldurmak istiyoruz. Ne yapmalıyız? ÇÖZÜM: Burada gene RECURSI-ON imdadımıza yetişiyor. Bir altprogram yazarız. Yaptığı iş belli bir koordinatta çevresine bakar ve uygun yerleri doldurarak yoluna devam eder, şayet herhangi bir yerde yolu birkaç ihtimale çıkarsa o koordinatı yığına atar, ihtimallerden birini seçer, kendi kendini çağırarak o yönde doldurma işleminin devamını sağlar. Böyle bir grafik programının çalışmasını gördüyseniz bu özelliği de görmüşsünüzdür. İhtimaller birçok yerde dallanır budaklanır, program ise ihtimalfasında bir ışık yakmış ve ufkunu genişletmiş olmasıdır. Başta da dediğim gibi, konuya sakin bir şekilde paniğe kapılmadan yaklaşılırsa gerçekten de çözüm bulunabiliyor. Ben şimdi bu örneklere bir dördüncüsünü ekleyeceğim. Fakat bu örnek, diğer örnekler gibi kalmayacak. Bu örneği aynı zamanda hayata kavuşturacağız. Heyecanlanan genç programcı arkadaşlar isterlerse burada kısa bir ara verip, zihinlerini toplayıp tekrar yazının başına oturabilirler. Örneğimiz fare ve labirentle yapılan denemeler üzerine. Yalnız bizim faremiz koku alamıyor. Yollara girip çıkıp deneme-yanılma yöntemiyle yolu bulacak. Fakat daha evvel girdiği yollara bir daha girmeyecek. Yoksa bir bölgenin etrafında dönüp durmasını kimse engelleyemez. İsterseniz fareyi bir kenara bırakıp, olaya daha sade bakalım. Olay bazı gazetelerin bulmaca köşelerinde ver-
PROBLEMİN ÇöZüMü
GEÇEN ZAMAN <SAAT,DAK BAŞLANGIÇ ŞEKLİ
Ok *S * * * * 4 * * * * * * * OKKA O kak
İKA,SANIYE):
ÇÖZÜLMÜŞ ŞEKLİ
*SCCCCCCCCC 4 *CCCCECCECC* * lerden birini seçerek yoluna devam eder. O anlık öteki ihtimali (veya ihtimalleri) bırakır. Fakat eninde sonunda o noktaya geri döner ve işini kusursuz olarak bitirir. Programın bunca fazla ihtimale karşı yapacağı işi unutmamasını kullanılmasıdır. Umudumuz yukarıdaki üç örneğin birçok bilgisayar programcısının kadikleri problemler gibi bir labirent içinde bir noktadan başka bir noktaya gitme olayından başka bir şey değil. Çalışmamızı öncelikle programın yalnızca rekursif altprogram bölümü üzerinde yoğunlaştıralım. Geri kalan iş süsleme, ekran hazırlama tipinde olacağı için onları ayrı tutalım. Onları nasıl olsa yaparız. Bizi esas uğraştıracak olan rekursif altprogramın dizaynıdır. Şimdi programımızı kaba hatlarından başlayıp ince detaylara doğru adım adım gerçekleştirelim. Programımız rekursif olacak. Peki ne zaman kendi kendini çağıracak? Tabii ki yol birkaç ihtimalli olduğunda koordinatları yığında saklayıp ihtimallerden birini seçip o yönde işi min devam etmesi için kendi kendir çağıracak. Bundan başka altprogramımızın düz yolları kendi başına halletmesi ayrıca tercih edilen bir unsur. Peki... Yol tıkanınca ne olacak? Bu sorunun cevabı da oldukça basit: Yolun tıkanması kaçınılmaz bir olay. Yol tıkanınca yeni ihtimaller denenmeli. Yani yolun tıkandığı bir üst seviyedeki programa bildirilmeli ve yeni bir ihtimali seçmesi sağlanmalı. Zaten altprogramın işlemesi birkaç derinlikten sonra ele alındığında bir altprogramın bildirebileceği olaylar iki ihtimallidir. Bunlar “yol ve
“çözüm bulundu”'dan başkası değil-
PROBLEMİN ÇöZül
GEÇEN ZAMAN
BAŞLANGIÇ ŞEKLİ
O kkk Ek * * tk 4 * * 4 4k ** *k 4 *
* * * * * * * * kak
KALA #CCCCCCC
4k * ** * * ** * 4 * * ** 4 *
* * * * * * * KK akk ler. Bunları “sıfır” ve “bir” durumları olarak sembolize edelim. Bir altprogram “bir” durumuyla geri döndüğü zaman o seviyede veya daha alt seviyelerde çözüm bulunmuş demektir. Daha fazla uğraşmasına gerek kalmadan aynı mesajla o da geri döner. Ta ki tümüyle geri çıkılana kadar.
Peki altprogram tümüyle geri döndüğünde (dışarıdan rekursif altprogramı çağıran diğer programa geri dönüldüğünde) bildirilen değer sıfır durumuysa ne olacak? Basitçe görülmektedir ki, böyle bir durumda yapılacak bir şey yoktur. Programımız tüm ihtimalleri denemiş, çözüm bulamamıştır. Bu, programı-
PROBLEMİN ÇöZÜüMÜü
GEÇEN ZAMAN
BAŞLANGIÇ ŞEKLİ
*5 Ek * * ** * bt * * ** * ** &* kt 4 4 4k Ok ak
SANİYE) 1
KKK Ok kk CCCCCCCE* * * * * *ttk * * * *k .* * * tk kkk
* ss. ee RR mızın yetersizliğinden çok labirentin gerçekten de çözümsüz bir iabirent olduğunu gösterir. Kullanıcıya hatası bildirilir ve program bitirilir. Görüldüğü gibi arapsaçına dönecek, çorba gibi karışacak gibi görünen ihtimaller bile dikkatle değerlendirildiğinde çözümleri bulunabiliyor. Artık bu noktada programımızın kesinlikle kusursuz çalışacağına eminiz. Bir adım daha atarak programımızın ilk satırlarını oluşturalım. i) Program X ve Y parametreleriyle çağırılması gerekiyor. ii) Geri dönerken O veya 1 durumu bildiriyor. Programımız ilk satırlarında X, Y noktasında çevresine bakıyor. Gidebileceği nokta tek bir tane ise oraya gidiyor ve çevresine bakma işleminden yeniden başlıyor. Böylece yol tek yönlüyse o yolun sonuna kadar gitmesi sağlanmış oluyor. Burada bazılarımızın dikkatini çekmiş olabilir; programın bir evvelki noktaya geri dönmemesi nasıl sağlanacak? Tek bir çözüm var: Programın geçtiği noktalara iz bırakması ve böylece aynı noktalara bir daha girmemesi. Bu konuyu daha detaylı olarak birazdan bir kere daha döneceğiz. İlk satırlara geri dönelim. Programımızın düz yolda ilerlemesi sağlanmıştı. Diyelim ki bu yol üzerinde hedefe ya da çözüme rastladı; ne yapacak? Gayet basit: Bir durumuna geçerek RETURN emriyle geri dönecek ve müjdeyi üst seviyedeki programlara verecek. Diyelim ki düz yolda giderken yolu tıkandı bu sefer ne yapacak? Bu sefer de sıfır durumuna geçerek üzüntülerini üst seviyedeki programlara bildirecek. Şimdi dördüncü ve en karışık ihtimale geliyoruz; yol çatallaşırsa ne olacak? Zaten RECURSION'i gerektiren durum da bu. Programımız N, Y koordinatlarını yığına atacak ve ihtimallerden birini seçip o yönde bir nokta ilerleyecek ve o ihtimali değerlendirmesi için kendi kendini çağıracak. Geri dönüşte X, Y koordinatlarını yığından geri alacak ve çağırdığı programın gönderdiği durum kodunu kontrol edecek. Şayet durum kodu *bir'se altprogram işi çözmüş demektir. Programımız aynı durum koduyla geri dönecektir. Durum kodu “sıfır” ise alt seviyedeki programın yolu tıkanmış demektir. Bu durumda yapılacak iş girilmiş olan çıkmaz yolun belirlenmesine gelir. Arkasından diğer ihtimallerin değerlendirilmesi programın başındaki “çevresine bakma' işlemine gider. Şimdi geçtiği yola iz bırakma olayına geri dönelim. Başta basit görürakılan iz şu işlere yarayacak. Öncelikle üzerinden geçilen noktaların hazırlanması için gerekli. Hedefi bulma işi bittiğinde ise bırakılmış olan izler çözüm yolunu içerir. Fakat çözüm için gerekli olandan fazlası yani çıkmaz yolları da içerir. Bu çıkmaz yolların esas çözüm yolundan ayırdedilebilir özellikte olması gerekir. O yüzdendir ki sıfır koduyla geri dönen altprogramın bıraktığı izler değiştirilmekte (bir bakıma silinmekte). Bu safha da dikkati çeken bir nokta da her seviyede yürüyen programın bıraktığı iz farklı olursa bir kolaylık sağlanacağı. Böylece değişik seviyelerin izleri daha kolay bulunup drüzeltilebilir. Basit bir mantıksal çıkarım gösterecektir ki çözüm bulunduğu zaman her seviyeye ait bir tek iz olacaktır; bu da çözüme giden izdir. Bunca tartışmadan sonra akla gelen en basit çözüm iz bırakma kodunun seviye (veya yığın göstergeci) ile doğru orantılı veya aynı değerde olmasıdır. Herkesin olayı rahatça takip edebil-
PROGRAM ADI :
68130
gazan
Bazda
Ba25a
Bıasa
01138
B11408
RECURSTON
REM öle Ae KOİ OKKA OAK
REM * *
REM &* MAZE SOLYING *
REM * RECURSİYE VERSİON *
REM * (C) 2.10.1986 THURSDAY *
REM * BY AYHAN KALAYLIOGLU *
REM * *
REM ak olak ak
GOSUB 800
4SPACE >-
PRINT RINT
FOR TO " #NEXT
INT
PRINT TO *
"4"
FOR Yz2 TO YU-L1:PRINT
FOR TO
3PRİNT
PRINT TO "4
"33NEXT "Ex"
FOR TO "
INT
PRİNT :PRİNT
PRINT "RUN 1880“
END
END
KUS 10: YUZ 10:RETURN
GOSUB Sad
DIM
FOR Isi TO 4:READ
DATA -1,0,0,1,1,0,0,-1
FOR TO YUY*L:FOR X-00 TO
XT :NEKT
FOR TO TO
IF CDzi9 THEN
IF THEN
IF THEN
IF ACX,YIs254 THEN
Y;2)-43
NEXT
IF Ss0 OR E-zâ THEN PRİNT
D
YEYS
GOSUB
:PR
"HATAL":EN
<154)
<159>
<asa>
<a245>
<a58>
<1s2>
<a26>
<148>
<088>
<aa2a>
<a51>
<246>
<1sa>
<1a7>
<isa>
<168>
<113>
<aa2a5>
<a57>
<129>
01150
01160 IF THEN PRİNT "HATA2" SEND
O1170 FOR TO YUZFOR X-1 TO <a3a>
IF AND THEN
<a213>
01190 NEXT <177>
PRİNT "<CLR><2DOWN><SSPACE
N COZUMU" <193>
PRINT "<4SPACE
PRINT "GECEN ZAMAN <SAAT,DAKIKA,SAN
©1230 SEK
LI" <160>
B1240 "<4SPACE> <1aa>
O1250 :PRİNT <186>
I-1:GOSUB 2000
©1270 PRİNT :PRİNT <aa6>
01280 PRINT "<SSPACE>COZULMUS SEKLİ"
01290 PRINT "<4SPACE > <163>
01300 PRİNT :PRİNT <238>
01310 2000 <a24>
01320 END
FOR TO © STEP TO
KUHL <254>
82010 PRİNT 3PRIİNT
NEXT #:RETURN <181)>
10000 GOSUB 15000 <154>
100186 IF DA THEN RC-1:RETURN <aa5>
10020 IF DAzA THEN <162>
10030 IF DA THEN YEDYLDI *YEAC
X,YI-SP:GOTO
10040 <150>
10050 SP-SP*1:MS-sP
10060 <083>
GOSUB <144>
10080 SP-SP-i
10090 IF THEN RETURN <175>
18100 FOR TO YUZFOR TO XU <a7a>
10110 IF THEN <064>
10120 NEXT :NEXT
10130 <179>
10140 GOTO 10008 <198>
15000 <113>
15010 FOR Dsi TO 4
15020 IF THEN DA-5
15040 <a49>
15030 IF THEN DA-D
15040 NEXT <2182)
15050 D-DD <176>
15060 RETURN <130>
mesi açısından programı BASIC'te yazacağız. Fakat makine dili bilenleriniz bu programın makine dilinde yazılmaya daha uygun olduğunu anlayacaklardır. Mesela makine dilinde ana işlem ünitesinin yığınını kullanmak oldukça uygun olurdu. Fakat BASIC'te böyle bir olanağımız olmadığı için, suni bir yığın oluşturmak z0rundayız. Fakat bu göründüğü kadar kötü değil. Geri dönüş adresleriyle BASIC dilinin kendisi uğraşacağı için bizim yığınımız sadece bilgileri içerecek ve programımız daha kolay anlaşılır olacaktır. Programın dileyen kimse tarafından makine diline çevrilebileceğini düşünerek veri yapımızda kullanacağımız kodlamayı | Byte'a sığacak biçimde seçtim. Aslında bu şart mı?
Hayır hiç de değil. Kodlama yapılması eninde sonunda gerekli bir olaydır; fakat esnek ve değiştirilebilir bir detaydan başka bir şey değildir. Programın birçok bölümünün uygun ve rahat bir biçimde çalışmasını sağlar (aynı veri yapısını aynı şekilde değerlendirme zorunluluğu). Bir bakıma programın kendi içinde oluşturulmuş bir standarttır.
Kadlamamız şöyledir:
© Kullanılmıyor. 1 Birinci seviye B İkinci seviye 32 Üçün seviye
250 Çıkmaz yal 2851 Çözüm yolu
252 Hedef (E:End) 2853 Başlangıç
254 Dolu nokta (4) 255 Boş nokta
Görüldüğü gibi kodlamamız seviyelerin 1'den başlayıp 249'a kadar gitmesine izin veriyor. (249 yetecek mi diyenlerin merakını giderelim: Yaptığımız denemelerde 17'nci seviyeyi geçen pek olmadı.) Yaptıklarımızı derleyip toparlamak için rekursif altprogramımızın akış diyagramını çizelim. Böylece programın yapacağı iş daha rahat görünür.
PROGRAMIN SATIR SATIR AÇIKLAMASI
SATIR 100- 170: Programla ilgili açıklamaları içeren REM satırları. SATIR 200: X ve Y yönündeki genişlikleri alma. SATIR 210- 300: Dolu bir labirent hazırlama (XW ve YW genişliklerinde). Sol üst köşeye S (Başlangıç, Start) sağ alt köşeye E (Bitiş, End) yazmak.
Fakat gene de bunların yerleri değiştirilebilir.
SATIR 310- 330: İki satır alta "RUN 1000" yazma (programın çözüm kısmı böyle çağırılıyor) ve programın ilk bölümünü bitirme.
SATIR 500: XW ve YW değerlerinin belirlenmesi. Bu satır değiştirilerek labirentin ebatları değiştirilebilir. (örneğin:
SATIR 1000: İkinci ve asıl kısmın başlangıcı. XW ve YW değerlerinin alınması. SATIR 1010: Boyutlu hafızaların belirlenmesi.
SATIR 1030: DX ve DY değerlerini okuyan ve bu verilerin bulunduğu kısım.
SATIR 1040: Ekrandan okumadan önce A ve hafızalarını sanki bütün labirent doluymuş gibi belirlemek.
SATIR 1050- 1100: A ve C'yi ekrandan okumak! *'lar labirent sınırı, *'lar dolu alan, S başlangıç, E bitiş ve boşluk boş alanı simgeliyor.
SATIR 1110: SP ve MS hafızalarını başlangıç değerlerine (1) oturtmak. SATIR 1120: Başlangıç veya bitiş yoksa "HATA!" mesajını verip
Programı bitirmek.
SATIR 1130: Komputer'in sistem saatini sıfırlamak ve asıl koordinatlar olarak başlangıç noktasının koordinatlarını belirlemek.
SATIR 1140: Rekursif altprogramı çağırıp labirenti çözdürmek. SATIR 1150: U$'e çözüm için gerekli olan zamanı almak. SATIR 1160: Labirentin çözümü yoksa "HATA!" mesajını verip programı bitirmek.
SATIR 1170- 1190: Bulunan çözümü C hafızasına "C" karakterleriyle işlemek. SATIR 1200- 1220: Problemin çözüldüğünü bildirip geçen zamanı yazmak. SATIR 1230- 1270: Hatırlatma amacıyla başlangıç şeklini ekrana vermek. SATIR 1310: Labirentin çözülmüş şeklini ekrana vermek. SATIR 1320: Programı bitirme.
SATIR 2000: C hafızasını ekrana çıkartmak için (1-2, Çözüm)
SATIR 1800: Rekursif altprogramın başlangıcı. "Çevreye bakma" altprogramını çağırma.
SATIR 1810: Çözüm bulunmuşsa "bir" durumuyla geri dönme.
SATIR 18820: 1 Yol tıkanmışsa "sıfır" geri dönme.
SATIR 18030
SATIR atılıyor, yığın arkasından da atılıyor.
"çevreye
SATIR
kendini çağırıyor.
SATIR 18080
SATIR 10090
SATIR 10100-10120: demektir.
SATIR 10130
SATIR 10140 1: ©
Burada yol çok göstergeci bakma"
1! Seçilmiş
1 Yığın göstergeci bir
Burada bir alt O yüzden O'na ait koordinatta
Tek seçenek varsa o yolda bir adım yürümek.
ihtimalli demek. X,Y yığına bir arttırılıyor ve — MS'ye — alınıyor. altprogramının önerdiği yönde bir adım ihtimali değerlendirmek için altprogram kendi eksiltiliyor.
1 Çözüm bulunmuşsa aynı durum koduyla geri dönülüyor.
seviyedeki izler siliniyor altprogramın yolu tıkanmış (Çözümsüz olduğu belirleniyor.)
1 Yığından koordinat okunuyor.
yeni ihtimalleri değerlendirmek için
“çevreye bakma" işleminden itibaren yeni baştan başlanıyor. SATIR 15000-1506! “Çevreye bakma" altprogramı. DA hafızasında kaç yönün boş olduğu bildiriliyor. DA sıfır ise yol tıkanmış demektir. Şayet hedefi bulursa olarak geri dönüyor. Bundan başka çağıran programa seçme derdinden kurtulması için boş yönlerden birini öneriyor. ALTPROGRAM! Kullanılan Değişkenlerin Listesi BAK XW: (X-WIDTH) X-Yönündeki genişlik —>—— | HEDEF DURUM KODU |>-| GERİ DÖN | — YW: (Y-WIDTH) Y-Yönündeki genişlik H MU? BİR nişlik A A: Rekursif altprogram çalışma | alanı H İ C : İlk ekran ve onun çözülmüş halini içeren hafıza mem İHTİMALLİ YÜRÜ SX : X-Koordinatları yığını H YOL SY : Y-Koordinatları yığını KOORDİNATLARI SP : (STACKPOINTER) Yığın Gös- YAZ, tergeci T RC : (RETURNCODE) Geri dönüş YIĞIN GÖSTERGECİNİ kodu (0 veya 21) BİR yar D : (DIRECTION) Yön DA : (DIRECTIONS AVAILABLE) BİRİNİ SEÇ VE O Seçilebilir yön sayısı YOLDA BİR ADIM AT DD: D'nin ara değerlerini saklar DX : D'yi X yönünde yorumlar ÇAĞIR DY: D'yi Y yönünde yorumlar X : X-Koordinatı CN Y : Y-Koordinatı MS : SP'nin en büyük değerini saklar KOORDİNATLARI U$ : Geçen zamanı saat, dakika, sa- AL niye cinsinden saklar XS : Başlangıç noktasının X-Koordi- em —>| natı BİR Mİ? YS : Başlangıç noktasının Y-Koordinatı ÇIKMAZ YOLU | > İŞARETLE
S : Başlangıç var mı, yok mu? Bitiş var mı, yok mu?
tam terazi burcunu yazmaya hazırlanıyordum ki, bir arkadaşım bana hesap sordu, nasıl bu kadar az örnekten hareketle burçlar hakkında böyle genellemelere gidebildiğim hakkında. Arkadaşım, tabii, terazi burcundandı. Hatta bir de örnek verdi. Onun babası da aslan burcundanmış ve gerçekten düzen tutkunuymuş, ama tutkunu olduğu düzen, hiç de öyle benim anlattığım gibi muhteşem bir şey değilmiş; aksine tam da isyan ettiğimiz türden kuru, baskıcı bir şeymiş. İşte bu karşı çıkışın yarattığı tedirginlik dilimi bağladı, oturup ne yaptığımı, Teleteknik'teki herkese rağmen yazmaya devam etmekle neyin mücadelesini verdiğimi düşünmeye zorladı. Bir kere arkadaşımın babasının düzen tutkunu olması, zaten genelleme bakımından yeterli. Ama beni ilgilendiren işin genelleme yanı değil; bildik olguların, kelimelerin unutulmuş anlamlarını ele geçirmeye çalışmak. Tanıdığımız dünyanın başka türlü de görülebileceğini hissettirmek. Burçlar arasındaki farklarla ilgilenmem bu yüzden, habire tarihsel örnekler peşinde koşmam da.
Venüs'ün
Egemenliğinde Akıl
Elbette ben de rastladım tam bir şirketin genel müdürü olacak türden aslanlara. Ama benim için önemli olan insanın içine sıkıntılar veren bu düzen tutkusunun berisinde farklı bir saik yatabileceği, bu tutku aracılığıyla dile gelmeye çalışan başka türlü bir düzen imgesi olabileceği ihtimali. Ama böyle bir yaklaşım, üstelik de düzen konusunda, terazi insanının hassas mantığının tahammül edemeyeceği bir gevşeklik anlamına geliyor. Çünkü o da kendince bir düzen tutkunudur. Her şeyin, ama özellikle fikirlerin, kavramların yerli yerinde durması, açık seçik tanımlanmış sınırlarının olması, aralarındaki ilişkilerin ince uçlu bir kalemle çizilmesi, onun için öncelikle bir estetik meselesidir. Bu yüzden terazinin hassas tartısı, yitirilmiş anlamları, yalnızca bir imkân ya da bir anı olarak var olanları tartamaz.
Bencilliğin Türleri
Bu söylediklerime bir başka örnek vereyim... Akrep insanı için de, yay insanı için de bencilliğe eğilimli oldukları söylenir. Ama bunu söylemek için astrolojiye ihtiyacımız yok ki! Bu türden yargıları zaten gündelik hayatımız içerisinde habire verip duruyoruz. Böylesi yargılar, hakkında konuştuğu-