Ders 05 / 11
Tarih İşlevleri
Aynı 54 destek talebinin ortalama çözüm süresi üç gün sayma kararıyla 6,33, 7,33 ve 5,20 gün çıkıyor; uçlar hariç sayımda 6 talep sıfır gün sürmüş görünüyor, iş günü sayımında iki talep takvimde iki gün sürdüğü hâlde sıfır iş günü gösteriyor. Bir ay sonrasının ay sonunda ne demek olduğu 60 abonenin 6'sında ayrışıyor: kırpma kuralı üç aboneyi aynı güne toplayıp 28, 29 ve 30 günlük üç dönem üretiyor, taşma kuralı hepsine 31 gün veriyor ama Şubat okumasını Mart'a kaydırıyor. 54 açılış tarihinin 19'u metin olarak yazıldığında iki ayrı güne okunabiliyor ve en büyük sapma 323 gün.
İçindekiler
Bir arıza kaydının açılışıyla kapanışı arasında kaç gün geçtiği basit bir çıkarma gibi görünür. Değildir: çıkarma iki uç arasındaki aralığı verir, sorulan şey ise çoğu zaman kapsanan gün sayısıdır ve ikisi bir gün farklıdır. Bu ders tarihin hücrede ne olduğunu kurar, aynı talep kümesinin ortalama çözüm süresini üç kararla hesaplar ve “bir ay sonra” ifadesinin ay sonunda iki ayrı tarih verdiğini gösterir.
- TT16. Tarih hücrede bir sayıdır: bir başlangıç gününden itibaren gün sayısı; bu modelde seri 1, 1 Ocak 2026’dır. Biçim yalnızca bir görünüştür.
- TT17. Destek talepleri ve okuma günleri kurgudur. Okuma günü ayın 1’i ile 31’i arasında dağıtılmıştır; ay sonu sorusunu yaratan budur.
- TT18. Hafta sonu iki gündür, tatil günü tanımlanmamıştır.
isgunuiki ucu da dahil ederek hafta içi günleri sayar; tatil listesi eklenirse sayı yine değişir.
Hücrede Duran Şey Bir Sayıdır
Aşağıdaki blok takvim çevrimini, okuma günlerini ve destek taleplerini kurar.
// takvim.mjs — elektronik tablo MODELI: tarih hucrede bir SAYIDIR, bicim yalnizca gorunustur. // Seri numarasi 1 = 1 Ocak 2026. Destek talepleri ve okuma gunleri kurgudur. export const TOHUM = 20260602, TALEP = 54, SATIR = 60; const uretec = (t) => { let s = t >>> 0; return () => (s = (s * 1664525 + 1013904223) >>> 0) / 4294967296; }; // Takvim cevrimi 2026-2027 icindir; iki yil da artik yil degildir, ikisi de 365 gundur. const AY = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; const ONCE = AY.map((_, i) => AY.slice(0, i).reduce((a, b) => a + b, 0)); export const seri = (y, a, g) => (y - 2026) * 365 + ONCE[a - 1] + g; // seri 1 = 1 Ocak 2026 export const tarihi = (s) => { let k = s - 1, y = 2026, a = 0; while (k >= 365) { k -= 365; y++; } // ay sinirini asan gun sonraki aya tasar while (k >= AY[a]) k -= AY[a++]; return [y, a + 1, k + 1]; }; const REF = /(\$?)([A-Z])(\$?)(\d+)/g; export const kaydir = (f, dS, dR) => f.replace(REF, (_, a, s, b, r) => (a ? "$" + s : String.fromCharCode(s.charCodeAt(0) + dS)) + (b ? "$" + r : String(+r + dR))); const iki = (n) => String(n).padStart(2, "0"); const ISLEV = { tarih: (y, a, g) => seri(y, a, g), ay: (s) => tarihi(s)[1], gun: (s) => tarihi(s)[2], bicim: (s) => { const [y, a, g] = tarihi(s); return `${iki(g)}.${iki(a)}.${y}`; }, aysonu: (s) => { const [y, a] = tarihi(s); return seri(a === 12 ? y + 1 : y, a === 12 ? 1 : a + 1, 1) - 1; }, // sonraki ayin ilk gununden bir onceki haftagunu: (s) => ((seri(2026, 1, 1) + s - 1 + 3) % 7) + 1, // 1 Ocak 2026 persembe enk: (a, b) => Math.min(a, b), isgunu: (b, k) => { let n = 0; for (let s = b; s <= k; s++) if (ISLEV.haftagunu(s) <= 5) n++; return n; }, }; export function deger(H, ad) { const v = H[ad]; if (v === undefined) return 0; if (typeof v !== "string" || v[0] !== "=") return v; const ifade = v.slice(1).replace(REF, (m) => JSON.stringify(deger(H, m.replace(/\$/g, "")))); return Function(...Object.keys(ISLEV), `return (${ifade});`)(...Object.values(ISLEV)); } export function sayfa() { const H = {}, r = uretec(TOHUM); H.A1 = "abone"; H.C1 = "tuketim"; H.T1 = "acilis"; H.U1 = "kapanis"; H.V1 = "okuma gunu"; for (let i = 0; i < SATIR; i++) { const s = i + 2; H["A" + s] = "AB-" + String(1041 + i * 7).padStart(4, "0"); r(); // 01'deki bolge sutunu: uretec ayni sirada calisir H["C" + s] = Math.round((2 + r() * r() * 78) * 10) / 10; H["V" + s] = 1 + (i * 7) % 31; // okuma gunu ayin 1'i ile 31'i arasinda } // Destek talepleri: acilis 2026'nin ilk yarisinda, sure 0-20 gun. const z = uretec(TOHUM + 3); for (let i = 0; i < TALEP; i++) { const s = i + 2, b = seri(2026, 1, 1) + Math.floor(z() * 180); H["T" + s] = b; H["U" + s] = b + Math.floor(z() * z() * 21); } return H; } if (import.meta.url === `file://${process.argv[1]}`) { const H = sayfa(); const g = (B) => (h) => h.map((v, j) => (j ? String(v).padStart(B[j]) : String(v).padEnd(B[0]))).join(""); const y = g([8, 10, 14, 10]); const o = (f) => deger({ ...H, X1: f }, "X1"); console.log(y(["hucre", "acilis", "bicim(acilis)", "kapanis"])); for (const s of [2, 4, 5, 55]) console.log(y(["T" + s, H["T" + s], o(`=bicim(T${s})`), H["U" + s]])); const F = Array.from({ length: TALEP }, (_, i) => H["U" + (i + 2)] - H["T" + (i + 2)]); console.log(`\n${TALEP} destek talebi. Ayni gun kapanan (fark 0): ` + `${F.filter((v) => v === 0).length}. Ham fark toplami ${F.reduce((a, b) => a + b, 0)} gun.`); console.log(`1 Ocak 2026 seri ${seri(2026, 1, 1)}, 31 Ocak 2026 seri ${seri(2026, 1, 31)}, ` + `28 Subat 2026 seri ${seri(2026, 2, 28)}; Subat 2026 ayinin son gunu ` + `${o("=bicim(aysonu(tarih(2026,2,1)))")}.`); }
hucre acilis bicim(acilis) kapanis T2 51 20.02.2026 57 T4 72 13.03.2026 89 T5 148 28.05.2026 159 T55 69 10.03.2026 69 54 destek talebi. Ayni gun kapanan (fark 0): 6. Ham fark toplami 342 gun. 1 Ocak 2026 seri 1, 31 Ocak 2026 seri 31, 28 Subat 2026 seri 59; Subat 2026 ayinin son gunu 28.02.2026.
T2 hücresinde duran şey 20.02.2026 değil, 51’dir; ikinci sütun ile üçüncü sütun aynı
hücrenin iki okunuşudur. Bir hücrenin gösterdiği tarih, içindeki sayının bir yorumudur.
Son satır ay sonu sorusunu kuruyor: Şubat 2026’nın son günü 28’dir, ayın 29, 30 ya da 31’inde okunan sayaçların Şubat karşılığı yoktur.
Üç Gün Sayma Kararı
Aynı 54 talep üç formülle ölçülür: birincisi uçları hariç tutar, ikincisi ikisini de sayar, üçüncüsü yalnız hafta içi günleri sayar.
// sure.mjs — ayni talep kumesi uc gun sayma karariyla: uclar haric, uclar dahil, is gunu. import { sayfa, deger, kaydir, TALEP } from "./takvim.mjs"; const KARAR = [ ["uclar haric", "=U2-T2"], ["uclar dahil", "=U2-T2+1"], ["is gunu (uclar dahil)", "=isgunu(T2,U2)"], ]; const H = sayfa(); const sutun = (f) => { const K = { ...H }; for (let i = 0; i < TALEP; i++) K["W" + (i + 2)] = kaydir(f, 0, i); return Array.from({ length: TALEP }, (_, i) => deger(K, "W" + (i + 2))); }; const g = (B) => (h) => h.map((v, j) => (j ? String(v).padStart(B[j]) : String(v).padEnd(B[0]))).join(""); const D = KARAR.map(([, f]) => sutun(f)); const y = g([24, 12, 12, 10]); console.log(y(["W sutunu formulu", "toplam gun", "ortalama", "sifir"])); KARAR.forEach(([ad], i) => { const d = D[i], t = d.reduce((a, b) => a + b, 0); console.log(y([ad, t, (t / TALEP).toFixed(2), d.filter((v) => v === 0).length])); }); console.log(`\n${TALEP} talep. Ortalama cozum suresi ` + KARAR.map(([ad], i) => `${(D[i].reduce((a, b) => a + b, 0) / TALEP).toFixed(2)} (${ad})`) .join(", ") + " gun."); // Herhangi bir kararda sifir cikan talepler: sifir bir sure degil, bir sayma sonucudur. const z = g([8, 14, 14, 12, 12, 10]); console.log("\n" + z(["hucre", "acilis", "kapanis", "uclar haric", "uclar dahil", "is gunu"])); const o = (f) => deger({ ...H, X1: f }, "X1"); for (let i = 0; i < TALEP; i++) if (D[0][i] === 0 || D[2][i] === 0) console.log(z(["W" + (i + 2), o(`=bicim(T${i + 2})`), o(`=bicim(U${i + 2})`), D[0][i], D[1][i], D[2][i]]));
W sutunu formulu toplam gun ortalama sifir uclar haric 342 6.33 6 uclar dahil 396 7.33 0 is gunu (uclar dahil) 281 5.20 2 54 talep. Ortalama cozum suresi 6.33 (uclar haric), 7.33 (uclar dahil), 5.20 (is gunu (uclar dahil)) gun. hucre acilis kapanis uclar haric uclar dahil is gunu W14 10.06.2026 10.06.2026 0 1 1 W17 14.05.2026 14.05.2026 0 1 1 W26 19.01.2026 19.01.2026 0 1 1 W28 19.05.2026 19.05.2026 0 1 1 W49 06.03.2026 07.03.2026 1 2 0 W50 13.02.2026 14.02.2026 1 2 0 W51 06.05.2026 06.05.2026 0 1 1 W55 10.03.2026 10.03.2026 0 1 1
Rapor edilecek sayı ortalama çözüm süresidir ve üç değeri var: 6,33, 7,33 ve 5,20 gün. En büyüğü ile en küçüğü arasındaki fark en küçük değerin yüzde 41’i kadar. Üçü de savunulabilir; hangisinin kastedildiğini “ortalama çözüm süresi” ifadesi söylemiyor.
Sıfır sütunu kararın nerede kanadığını gösteriyor. Uçlar hariç sayımda 6 talep sıfır gün sürmüş görünüyor; oysa o talepler açıldıkları gün kapandılar, yani bir gün sürdüler. Sıfırları “anında çözüldü” diye okuyan bir rapor verinin değil, sayma kararının sonucunu yazar.
Alt tablonun son iki satırı ters yönde bir uç veriyor: W49 ve W50 takvimde iki gün sürdü,
tamamen hafta sonuna denk geldiği için sıfır iş günü gösteriyor. Aynı kayıt üç sayma
kuralında üç ayrı süre taşır.
Bir Ay Sonra Ne Zamandır
“Bir ay” sabit bir gün sayısı değildir. Aşağıdaki blok Şubat okumasını iki kuralla hesaplar, metne çevrilmiş tarihlerin belirsizliğini sayar ve gün sayma kararını dört yazımda tarar.
// ay.mjs — "bir ay sonra" iki kuralla; ve gun sayma kararinin sayfada nerede durdugu. import { sayfa, deger, kaydir, seri, TALEP, SATIR } from "./takvim.mjs"; const H = sayfa(); const o = (K, f) => deger({ ...K, X9: f }, "X9"); const g = (B) => (h) => h.map((v, j) => (j ? String(v).padStart(B[j]) : String(v).padEnd(B[0]))).join(""); // Ocak okumasi ayin V. gunu; Subat okumasi "bir ay sonra". Iki kural iki tarih verir. const KURAL = { kirpma: "=tarih(2026,2,enk(V2,gun(aysonu(tarih(2026,2,1)))))", tasma: "=tarih(2026,2,V2)", }; const sutun = (K, c, n, f) => { const M = { ...K }; for (let i = 0; i < n; i++) M[c + (i + 2)] = kaydir(f, 0, i); return Array.from({ length: n }, (_, i) => deger(M, c + (i + 2))); }; const OCAK = Array.from({ length: SATIR }, (_, i) => seri(2026, 1, H["V" + (i + 2)])); const S = Object.fromEntries(Object.entries(KURAL).map(([a, f]) => [a, sutun(H, "Y", SATIR, f)])); const y = g([10, 8, 14, 10, 14, 10]); console.log(y(["hucre", "okuma", "kirpma", "donem", "tasma", "donem"])); for (const s of [2, 6, 15, 24]) { const i = s - 2; console.log(y(["V" + s, H["V" + s], o(H, `=bicim(${S.kirpma[i]})`), S.kirpma[i] - OCAK[i], o(H, `=bicim(${S.tasma[i]})`), S.tasma[i] - OCAK[i]])); } const farkli = S.kirpma.filter((s, i) => s !== S.tasma[i]).length; const kacan = S.tasma.filter((s) => o(H, `=ay(${s})`) !== 2).length; console.log(`\n${SATIR} abonenin ${farkli} tanesinde iki kural farkli tarih veriyor ` + `(okuma gunu 29, 30 ya da 31 olanlar). Tasma kuralinda ${kacan} abonenin ` + `"Subat okumasi" Subat ayina dusmuyor.`); // Metin olarak girilmis tarih: gun ile ay yer degistirebiliyorsa hucre iki gune okunur. const ikili = Array.from({ length: TALEP }, (_, i) => [H["T" + (i + 2)], o(H, `=ay(T${i + 2})`), o(H, `=gun(T${i + 2})`)]) .filter(([, a, gn]) => gn <= 12 && gn !== a) // gun 12'den buyukse yer degistiremez .map(([s, a, gn]) => Math.abs(seri(2026, gn, a) - s)); console.log(`${TALEP} acilis tarihinin ${ikili.length} tanesi "GG.AA.YYYY" metni olarak ` + `girildiginde iki ayri gune okunabiliyor; en buyuk sapma ${Math.max(...ikili)} gun.`); // Geri okuma taramasi: gun sayma karari formul metninde nerede duruyor. const P = { ...H, X1: "uc dahil (1/0)", X2: 1 }; // etiket solda, deger sagda const YAZIM = [["=U2-T2", "yok"], ["=U2-T2+1", "gomulu sabit"], ["=U2-T2+$X$2", "parametre hucresi"], ["=isgunu(T2,U2)", "islev adi"]]; const z = g([16, 20, 10, 10, 10]), top = (d) => d.reduce((x, v) => x + v, 0); console.log("\n" + z(["formul", "karar nerede", "toplam", "X2=0", "pesinden"])); for (const [f, yer] of YAZIM) { const a = sutun(P, "W", TALEP, f), b = sutun({ ...P, X2: 0 }, "W", TALEP, f); console.log(z([f, yer, top(a), top(b), a.filter((v, i) => v !== b[i]).length])); }
hucre okuma kirpma donem tasma donem V2 1 01.02.2026 31 01.02.2026 31 V6 29 28.02.2026 30 01.03.2026 31 V15 30 28.02.2026 29 02.03.2026 31 V24 31 28.02.2026 28 03.03.2026 31 60 abonenin 6 tanesinde iki kural farkli tarih veriyor (okuma gunu 29, 30 ya da 31 olanlar). Tasma kuralinda 6 abonenin "Subat okumasi" Subat ayina dusmuyor. 54 acilis tarihinin 19 tanesi "GG.AA.YYYY" metni olarak girildiginde iki ayri gune okunabiliyor; en buyuk sapma 323 gun. formul karar nerede toplam X2=0 pesinden =U2-T2 yok 342 342 0 =U2-T2+1 gomulu sabit 396 396 0 =U2-T2+$X$2 parametre hucresi 396 342 54 =isgunu(T2,U2) islev adi 281 281 0
Birinci tablo iki kuralın bedelini yan yana koyuyor. Kırpma kuralında ayın 29, 30 ve 31’inde okunan üç abone 28 Şubat’a toplanıyor ve dönemleri 30, 29 ve 28 gün oluyor: aynı tarihte okunan üç sayacın dönemi üç ayrı uzunlukta ve sayfada bunu söyleyen bir sütun yok. Taşma kuralında dönem 31 gün, ama Şubat okuması 1, 2 ve 3 Mart’a kayıyor: 6 abonenin Şubat okuması Şubat ayında değil.
Metin tarih satırı üçüncü bir belirsizlik ölçüyor. 54 açılışın 19’unda gün numarası 12’den
küçüktür; böyle bir tarih GG.AA.YYYY metni olarak yazıldığında ay ile gün yer değiştirebilir
ve hücre iki ayrı güne okunur — en büyük sapma 323 gün. Metne çevrilmiş bir tarih geri
okunamaz bir karardır.
Son tablo dersin ikinci sayısıdır. İlk iki yazım kararı sayfada tutmuyor: =U2-T2 uçların
hariç tutulduğunu söylemez, =U2-T2+1 bir 1 gösterir ama o 1’in ne olduğunu söylemez.
Üçüncüde karar X2 hücresindedir, etiketiyle iki adımda okunur ve değiştirildiğinde 54 hücre
peşinden gelir; dördüncüde karar işlevin adındadır. İlk ikisinin sonucu 342 ile 396; ikisi de
doğru, ikisi de kaynaksız.
Özet
- Tarih hücrede bir sayıdır; biçim o sayının bir yorumudur ve içeriğini değiştirmez.
- Aynı 54 talebin ortalama çözüm süresi üç sayma kararıyla 6,33, 7,33 ve 5,20 gün çıktı; fark en küçük değerin yüzde 41’i kadar.
- Sıfır bir süre değil, bir sayma sonucudur: uçlar hariç sayımda 6 talep, iş günü sayımında hafta sonuna denk gelen 2 talep sıfır gösterdi.
- “Bir ay sonra” ay sonunda iki ayrı tarih verir: kırpma kuralı 28, 29 ve 30 günlük üç dönem üretti, taşma kuralı 31 gün verdi ama 6 abonenin Şubat okumasını Mart’a kaydırdı.
- Gün sayma kararı yalnız parametre hücresine ya da işlev adına yazıldığında geri okunur;
gömülü
+1sayıyı gösterir, kararı göstermez. Metne çevrilmiş 19 tarih hiç geri okunamaz.
Sonraki Adım
Buraya kadar her formül aynı satıra bakıyordu. Oysa önceki ders bir şeyi varsaymıştı: ziyaret kaydındaki kodun abone tablosunda bulunması ve karşılığındaki tüketimin getirilmesi. O işi yapan şey bir arama işlevidir ve arama, kendisine verilen sütun numarasına ya da başlık adına göre iki ayrı biçimde yazılabilir. İki biçim aynı sonucu verir; ta ki tablonun ortasına bir sütun eklenene kadar. Sonraki ders bir sütun eklendiğinde kaç aramanın kırıldığını, kaçının hata verdiğini ve kaçının hata vermeden yanlış değer döndürdüğünü sayar.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.