İçeriğe geç
academia.sh

Ders 11 / 27

Yineleme Yapıları

Aynı on kaynak üç kayıt biçiminde yazılır: elle on blok, sayı temelli yineleme, küme temelli yineleme. Satır sayısı, istisnanın maliyeti ve adres kararlılığı sayılır; ortadan bir bölge çıkarıldığında sayı temelli biçimin altı kalemlik plan ürettiği, kayan beş adresin ölçüm ağında otuz beş kaçan sayaç partisine karşılık geldiği ölçülür.

İçindekiler

Bir önceki dersin kaydında iki toplayıcı makine vardı ve ikisi ayrı ayrı, dört satırı harfi harfine aynı olan iki blok olarak yazılmıştı. Bölge büyüdü: ölçüm ağı artık on ayrı alt bölgede sayaç okuyor. Aynı bloğu on kez kopyalamak bir seçenek, kaydın kendisine “bunu on kez yap” demek başka bir seçenek. Bu ders üçüncü bir seçeneği de ekler ve üçünü aynı kalemlerde karşılaştırır.

Karşılaştırmanın çıkış noktası şudur: üç biçim de aynı gerçeği üretir. On makine, aynı alt ağlar, aynı boyutlar, aynı etiketler. Aralarındaki fark gerçekte değil, kayıtta ve kaydın kaynağa verdiği adrestedir. O adres, kaydın bir sonraki uygulamada hangi gerçek kaynağı kastettiğini belirleyen tek şeydir — ve bu dersin bütün sayıları oradan çıkar.

Ölçüm bölgesel ölçüm ağı üzerindedir ve kurgudur; koşan şey node ile kurulmuş bir modeldir.

BS31. Ölçüm ağı on alt bölgede sayaç okur; bölge adları listede yazılı sıradadır. BS32. Üç kayıt biçimi de aynı on makineyi tanımlar; nitelikleri birebir aynıdır. BS33. Adres, kaynağın durumda bulunduğu anahtardır: elle biçimde blok adı, sayı temelli biçimde sıra numarası, küme temelli biçimde harita anahtarı. BS34. Bir bölge iki kat sayaç taşır ve makinesi büyük olmalıdır; bu, biçimlerin istisnayı nasıl taşıdığını ölçmek için konmuş tek sapmadır. BS35. altag ve etiket alanları yerinde güncellenemez; değişirlerse kaynak yeniden oluşturulur. boyut yerinde güncellenir. BS36. Her toplayıcı 15 saniyede bir sayaç partisi çeker. Yeniden oluşturulan bir makine, önceki dersin süreleriyle 105 saniye hizmet dışıdır.

Aynı On Kaynak, Üç Kayıt

// yineleme.mjs — on kaynak uc bicimde yazilir; satir, adres kararliligi ve plan sayilir. Model.
export const BOLGE = ["kuzey_1", "kuzey_2", "kuzey_3", "dogu_1", "dogu_2",
  "dogu_3", "bati_1", "bati_2", "bati_3", "bati_4"];
const ISTISNA = { dogu_2: "buyuk" };            // BS34: bir bolge iki kat sayac tasiyor
const nitelik = (b, ist) => ({ altag: `altag.${b}`, boyut: ist[b] ?? "orta",
  etiket: `toplayici-${b}` });

export function elle(bolgeler, ist = ISTISNA) {
  const metin = bolgeler.map((b) => `kaynak makine "toplayici_${b}" {\n` +
    `  altag  = altag.${b}.kimlik\n  boyut  = "${ist[b] ?? "orta"}"\n` +
    `  etiket = "toplayici-${b}"\n}`).join("\n");
  const cozum = new Map(bolgeler.map((b) => [`makine.toplayici_${b}`, nitelik(b, ist)]));
  return { metin, cozum, dal: 0 };               // deger kendi blogunda, kosul yok
}

export function sayiTemelli(bolgeler, ist = ISTISNA) {
  const dal = Object.entries(ist).map(([k, v]) =>
    `bolgeler[sayi.indeks] == "${k}" ? "${v}" : `).join("");
  const metin = `yerel bolgeler = [${bolgeler.map((b) => `"${b}"`).join(", ")}]\n` +
    `kaynak makine "toplayici" {\n  sayi   = ${bolgeler.length}\n` +
    `  altag  = altag[bolgeler[sayi.indeks]].kimlik\n  boyut  = ${dal}"orta"\n` +
    `  etiket = "toplayici-" + bolgeler[sayi.indeks]\n}`;
  const cozum = new Map(bolgeler.map((b, i) => [`makine.toplayici[${i}]`, nitelik(b, ist)]));
  return { metin, cozum, dal: Object.keys(ist).length };
}

export function kumeTemelli(bolgeler, ist = ISTISNA) {
  const metin = "yerel bolgeler = {\n" +
    bolgeler.map((b) => `  ${b} = "${ist[b] ?? "orta"}"`).join("\n") + "\n}\n" +
    `kaynak makine "toplayici" {\n  kume   = bolgeler\n` +
    "  altag  = altag[kume.anahtar].kimlik\n  boyut  = kume.deger\n" +
    '  etiket = "toplayici-" + kume.anahtar\n}';
  const cozum = new Map(bolgeler.map((b) => [`makine.toplayici["${b}"]`, nitelik(b, ist)]));
  return { metin, cozum, dal: 0 };               // istisna haritanin degerinde
}

const YENIDEN = ["altag", "etiket"];            // BS35: bu alanlar yerinde guncellenemez

export function planla(once, sonra) {
  const p = { ekle: 0, degistir: 0, yeniden: 0, sil: 0 };
  for (const [adres, y] of sonra.cozum) {
    const e = once.cozum.get(adres);
    if (!e) { p.ekle++; continue; }
    const fark = Object.keys(y).filter((k) => e[k] !== y[k]);
    if (fark.length) fark.some((k) => YENIDEN.includes(k)) ? p.yeniden++ : p.degistir++;
  }
  for (const adres of once.cozum.keys()) if (!sonra.cozum.has(adres)) p.sil++;
  return p;
}

export const BICIM = [["elle on blok", elle], ["sayi temelli", sayiTemelli],
  ["kume temelli", kumeTemelli]];
const satir = (m) => m.split("\n").length;
const UC = { dogu_2: "buyuk", bati_1: "buyuk", kuzey_3: "kucuk" };

if (import.meta.url === `file://${process.argv[1]}`) {
  // Uc bicim ayni on gercek kaynagi mi uretiyor: adresi degil, nitelikleri karsilastir.
  const imza = (c) => [...c.values()].map((v) => JSON.stringify(v)).sort().join("|");
  const imzalar = BICIM.map(([, f]) => imza(f(BOLGE).cozum));
  console.log("uc bicim de ayni gercegi uretiyor mu: " +
    `${imzalar.every((x) => x === imzalar[0]) ? "evet" : "hayir"} ` +
    `(${elle(BOLGE).cozum.size} kaynak, ayni nitelikler)`);

  console.log("\nkaydin bedeli (10 kaynak)");
  console.log("bicim          satir  kosul dali  3 istisnada satir/dal  adreste bolge adi");
  for (const [ad, f] of BICIM) {
    const r = f(BOLGE), u = f(BOLGE, UC);
    const adresli = [...r.cozum.keys()].some((a) => a.includes("dogu_2"));
    console.log(`${ad.padEnd(15)}${String(satir(r.metin)).padStart(5)}${String(r.dal).padStart(12)}` +
      `${`${satir(u.metin)}/${u.dal}`.padStart(23)}${(adresli ? "var" : "yok").padStart(19)}`);
  }

  const SENARYO = [
    ["ortadan bir bolge cikti (dogu_2 kapandi)", BOLGE.filter((b) => b !== "dogu_2")],
    ["ortaya bir bolge girdi (dogu_1b acildi)", [...BOLGE.slice(0, 4), "dogu_1b", ...BOLGE.slice(4)]],
    ["sona bir bolge eklendi (bati_5 acildi)", [...BOLGE, "bati_5"]],
  ];

  for (const [ad, yeni] of SENARYO) {
    console.log(`\n${ad}`);
    console.log("bicim          ekle  degistir  yeniden olustur  sil  toplam kalem  kayan adres");
    for (const [bAd, f] of BICIM) {
      const once = f(BOLGE), sonra = f(yeni), p = planla(once, sonra);
      const kayan = [...sonra.cozum].filter(([a, v]) =>
        once.cozum.has(a) && JSON.stringify(once.cozum.get(a)) !== JSON.stringify(v)).length;
      console.log(`${bAd.padEnd(15)}${String(p.ekle).padStart(4)}${String(p.degistir).padStart(10)}` +
        `${String(p.yeniden).padStart(17)}${String(p.sil).padStart(5)}` +
        `${String(p.ekle + p.degistir + p.yeniden + p.sil).padStart(14)}${String(kayan).padStart(13)}`);
    }
  }
}
uc bicim de ayni gercegi uretiyor mu: evet (10 kaynak, ayni nitelikler)

kaydin bedeli (10 kaynak)
bicim          satir  kosul dali  3 istisnada satir/dal  adreste bolge adi
elle on blok      50           0                   50/0                var
sayi temelli       7           1                    7/3                yok
kume temelli      18           0                   18/0                var

ortadan bir bolge cikti (dogu_2 kapandi)
bicim          ekle  degistir  yeniden olustur  sil  toplam kalem  kayan adres
elle on blok      0         0                0    1             1            0
sayi temelli      0         0                5    1             6            5
kume temelli      0         0                0    1             1            0

ortaya bir bolge girdi (dogu_1b acildi)
bicim          ekle  degistir  yeniden olustur  sil  toplam kalem  kayan adres
elle on blok      1         0                0    0             1            0
sayi temelli      1         0                6    0             7            6
kume temelli      1         0                0    0             1            0

sona bir bolge eklendi (bati_5 acildi)
bicim          ekle  degistir  yeniden olustur  sil  toplam kalem  kayan adres
elle on blok      1         0                0    0             1            0
sayi temelli      1         0                0    0             1            0
kume temelli      1         0                0    0             1            0

İlk satır karşılaştırmanın zeminidir: üç biçim de on kaynağı aynı niteliklerle üretiyor. Kayıt biçimi gerçeği değiştirmiyor.

Satır sütunu ilk bedeli verir. Elle yazım 50 satır, küme temelli 18, sayı temelli 7. Elle yazımın 50 satırının 40’ı tekrardır: aynı üç alan on kez, yalnız bölge adı değişerek. Sayı temelli biçim en kısasıdır çünkü listeyi tek satıra sıkıştırır. Küme temelli biçim aradadır ve fazlalığı rastlantı değildir — haritanın her satırı bir bölgeyi adıyla ve değeriyle yazar.

Koşul dalı sütunu istisnanın fiyatını verir. Bir bölgenin büyük makine istemesi, elle yazımda o bloğun kendi satırına yazılan bir değerdir; küme temelli biçimde haritanın o anahtarındaki değerdir; ikisinde de sıfır koşul. Sayı temelli biçimde ise ifadeye bir dal girer. Son sütundan bir öncekine bakıldığında bunun nasıl büyüdüğü görülür: istisna sayısı üçe çıkınca elle ve küme temelli biçimlerde satır ve dal sayısı değişmez, sayı temelli biçimde tek satırda üç iç içe koşul birikir. İstisnayı taşıyan yer, sayı temelli biçimde kaydın veri kısmı değil ifade kısmıdır.

Son sütun ise bu dersin asıl kalemidir. Elle ve küme temelli biçimlerde adres bölge adını taşır: makine.toplayici_dogu_2 ya da makine.toplayici["dogu_2"]. Sayı temelli biçimde adres makine.toplayici[4]tür ve dördüncü sıranın hangi bölge olduğu adreste yazmaz — o bilgi listenin uygulama anındaki hâlindedir. Durumda bir kaynağa bakıp hangi bölgeye ait olduğunu söylemek için kaydın o günkü sürümünü bulmak gerekir.

Adresin ne olduğu bir ayrıntı gibi görünür, ama bu kursun ölçüsünde merkezî bir kalemdir. Kayıt uygulandığında her kaynağın gerçek kimliği bir adresin altına yazılır; bir sonraki uygulamada kayıt ile gerçeği eşleştiren tek şey o adrestir. Adres kaynağın kimliğini taşıyorsa eşleşme kaydın kendisinden okunur; sıra numarası taşıyorsa eşleşme kaydın o günkü sırasına bağlıdır. İkinci durumda kayıt ile gerçek arasındaki bağ, kayıtta yazılı olmayan bir şeye — listenin geçmişteki hâline — dayanır.

Ortadan Bir Eleman Çıkınca

Üç senaryo aynı çıktının alt bölümlerindedir ve birlikte okunduğunda kural nettir.

dogu_2 bölgesi kapandığında elle ve küme temelli biçimler tek kalemlik plan üretir: bir kaynak silinir, diğer dokuzu hiç dokunulmadan yerinde kalır. Sayı temelli biçim aynı gerçek değişiklik için altı kalem üretir: beş yeniden oluşturma ve bir silme. Sebep aritmetiktir. Liste dördüncü elemanını kaybedince beşinci eleman dördüncü sıraya, altıncı beşinciye kayar; makine.toplayici[4] adresi dün dogu_2yi gösteriyordu, bugün dogu_3ü gösteriyor. Kayıt “dördüncü makinenin alt ağı ve etiketi değişti” der; bu iki alan yerinde güncellenemediği için karar yeniden oluşturmadır. Kayan adres sütunu bunu doğrudan sayar: beş adres artık başka bir gerçek kaynağa işaret ediyor.

Ortaya bir bölge girmesi daha da pahalıdır: yedi kalem, altı kayan adres. Ekleme noktasından sonraki her adres bir kayar.

Üçüncü senaryo sınırı çizer. Bölge listenin sonuna eklendiğinde üç biçim de tek kalem üretir; sayı temelli biçim de temizdir, çünkü hiçbir adres kaymaz. Yani sayı temelli yineleme yanlış değil, sırası anlam taşımayan ve yalnız sondan büyüyen kümeler için doğru biçimdir. Bölge listesi öyle bir küme değildir: bölgeler kapanır, araya yenisi girer.

Planın öngörme oranı burada tersine bir soru sorar. Plan yanılmıyor — sayı temelli biçimde “beş kaynak yeniden oluşturulacak” diyor ve uygulamada tam beşi yeniden oluşturuluyor, oran 5/5. Yanılan plan değil, planı okuyan kişinin beklentisidir: bir bölge kapandı, bir makine gitmeli. Beklenti bir kalem, plan altı kalem. Aradaki beş kalem gerçeklikten değil, kayıt biçiminden doğuyor.

Kaydın bunu kendi başına fark edememesi de ölçülebilir bir sınırdır. Kayıt “beşinci makinenin alt ağı değişti” ile “beşinci sıra artık başka bir bölge” arasındaki farkı göremez, çünkü elinde yalnız adres ve nitelikler vardır. İkisi de aynı şeye benzer: bir adres, değişmiş nitelikler. Ayrımı ancak kaydı yazan kişi bilir, ve o kişi de planı okurken beş kalemi gerçek bir değişiklik sanabilir. Sayı temelli biçimin riski gizli değildir — planda açıkça yazar — ama planın altı kalemi ile gerçeğin bir kalemi arasındaki farkı ayırt etmek okuyucuya bırakılmıştır.

Kayan Adresin Ölçüm Ağındaki Karşılığı

// bedel.mjs — plan kalemini olcum agi biriminde sayar: kacan sayac partisi. Model.
import { BOLGE, BICIM, planla } from "./yineleme.mjs";
const DISI = 105, PERIYOT = 15, YENIDEN_SN = 110, SIL_SN = 10;   // BS36, onceki dersin sureleri
const yeni = BOLGE.filter((b) => b !== "dogu_2");

console.log("dogu_2 kapandi — ayni gercek degisiklik, uc kayit bicimi");
console.log("bicim          yeniden  hizmet disi makine-sn  kacan parti  uygulama sn");
for (const [ad, f] of BICIM) {
  const p = planla(f(BOLGE), f(yeni));
  const sn = p.yeniden * DISI;
  console.log(`${ad.padEnd(15)}${String(p.yeniden).padStart(7)}${String(sn).padStart(22)}` +
    `${String(p.yeniden * Math.floor(DISI / PERIYOT)).padStart(13)}` +
    `${String(p.yeniden * YENIDEN_SN + p.sil * SIL_SN).padStart(13)}`);
}
console.log("\nkapanan bolgenin kendi partileri zaten toplanmiyor;");
console.log("yukaridaki kayip dokuz saglam bolgenin kaybidir.");
dogu_2 kapandi — ayni gercek degisiklik, uc kayit bicimi
bicim          yeniden  hizmet disi makine-sn  kacan parti  uygulama sn
elle on blok         0                     0            0           10
sayi temelli         5                   525           35          560
kume temelli         0                     0            0           10

kapanan bolgenin kendi partileri zaten toplanmiyor;
yukaridaki kayip dokuz saglam bolgenin kaybidir.

Sayılar ölçüm ağı biriminde okunduğunda karar netleşir. Kapanan bölgenin makinesi zaten gidecekti; üstteki kayıp sağlam duran dokuz bölgenin kaybıdır. Sayı temelli biçimde beş sağlam makine 105’er saniye hizmet dışı kalır: 525 makine-saniye ve 35 kaçan sayaç partisi. Elle ve küme temelli biçimlerde bu kalemler sıfırdır. Uygulama süresi de 560 saniyeye karşı 10 saniyedir.

Kaçan parti geri gelmez. Sayaçlar okumayı sürdürür ama o pencerede kimse çekmediği için ölçüm ağının o beş bölgesinde 105 saniyelik bir boşluk oluşur — ve bu boşluğun kaydında hiçbir iz yoktur. Kayıt doğru, plan doğru, uygulama doğru; kaybolan yalnız veridir.

Bu bölümün kapanışında kaydın kapsamadığı bir kalem adıyla anılmalıdır: bölge listesinin kendisi. Kayıtta on bölge adı yazılıdır, ama hangi bölgede sayaç olduğu kaydın bildiği bir şey değildir — saha ekibinin tuttuğu bir listeden elle kopyalanmıştır. Bir bölge kapandığında kayıt bunu kendiliğinden öğrenmez; biri gidip listeden siler. Kaydın en pahalı kalemi olan bu değişikliğin tetikleyicisi, kaydın tamamen dışındadır.

Kayıt Biçimi Kararı

Biçim Satır (10 kaynak) Ortadan çıkarmada kalem Kayan adres İstisna dalı Ne zaman
Elle on blok 50 1 0 0 Kaynaklar birbirinden gerçekten farklıysa
Sayı temelli 7 6 5 istisna başına 1 Sırası anlamsız, yalnız sondan büyüyen küme
Küme temelli 18 1 0 0 Elemanların kimliği olan küme

Tablo tek bir ölçüyle özetlenir: satırdan tasarruf etmenin fiyatı adres kararlılığıdır. Sayı temelli biçim elle yazımın 50 satırını 7’ye indirir — yedi kat — ve karşılığında ortadaki her değişiklikte beş ile altı arasında gereksiz yeniden oluşturma üretir. Küme temelli biçim 18 satırla elle yazımın üçte birine iner ve adres kararlılığını hiç kaybetmez; ödediği bedel, bölge adlarının kayıtta ikinci kez, harita anahtarı olarak yazılmasıdır.

Karar üç biçim arasında değil, iki soru arasındadır. Birincisi: bu on kaynak birbirinin kopyası mı, yoksa her birinin kendi kimliği mi var? Ölçüm ağında ikincisi doğrudur — dogu_2 bir sıra numarası değil, sahada duran bir bölgedir. İkincisi: bu küme ortasından değişir mi? Bölge listesi kapanmalar ve açılmalarla değişir, yani değişir. İki cevap birlikte küme temelli biçimi işaret eder; sayı temelli biçim buradaki 7 satırı 18 satıra tercih ettirecek kadar ucuz değildir.

Özet

  • Üç kayıt biçimi de aynı 10 gerçek kaynağı aynı niteliklerle üretiyor; fark gerçekte değil, kaydın kaynağa verdiği adrestedir.
  • Satır: elle 50, küme temelli 18, sayı temelli 7. İstisna sayısı 3’e çıkınca sayı temelli biçimde tek ifadede 3 iç içe koşul birikir, diğer ikisinde dal sayısı 0 kalır.
  • dogu_2 kapandığında elle ve küme temelli biçim 1 kalem, sayı temelli biçim 6 kalem üretti; 5 adres başka bir gerçek kaynağa kaydı. Ortaya bölge girmesinde sayılar 1’e karşı 7 ve 6 oldu.
  • Sona ekleme üç biçimde de 1 kalem: sayı temelli yineleme, sırası anlam taşımayan ve yalnız sondan büyüyen kümeler için doğru biçimdir.
  • Plan yanılmadı — “5 yeniden oluşturulacak” dedi ve 5’i yeniden oluşturuldu, oran 5/5. Beklenti ile plan arasındaki 5 kalemlik fark kayıt biçiminden doğdu.
  • Ölçüm ağı biriminde: 5 sağlam makine 105’er saniye hizmet dışı, 525 makine-saniye, 35 kaçan sayaç partisi, 560 saniyelik uygulama — küme temelli biçimde hepsi 0 ve 10 saniye.

Sonraki Adım

Bu ders plan kalemlerini saydı ama planı hep hazır kabul etti: kalemler bir yerden geliyordu. Sonraki ders o yeri kurar — kayıt ile durumu karşılaştırıp kalem kalem ekle, değiştir, yeniden oluştur ve sil kararını üreten planlayıcının kendisini yazar. Ölçülecek şey planın kendi doğruluğudur: kaç kalem planda yok ama uygulamada oluyor, kaç kalem planda olup gerçekleşmiyor, ve “yeniden oluşturulacak” denilen kalemlerin kaçı gerçekten yeniden oluşturuluyor.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat