KabaLang örnekleri: konsol, masaüstü ve web için dokuz proje
Konsol: fraktal (paralel şeritli 24-bit Mandelbrot/Julia + yakınlaşma), sudoku (geri izlemeli, canlı animasyon), fatura (JSON → terminal tablosu, PDF ve Excel). Masaüstü: hesap makinesi (işlem önceliği, canlı bağlama), odak (Pomodoro), parola atölyesi (entropi ölçer, SHA-256). Web: pano (Kanban REST API + SQLite), kisalt (302 yönlendirme, SVG istatistik), anket (adres başına tek oy, sunucuda çizilen grafik). Hepsi `kabalang calistir` ile derlenip çalışır; web uygulamaları yalnız 127.0.0.1'i dinler, SQL parametre bağlamalı, HTML çıktısı kaçırılır.
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
# Fatura — JSON siparişten terminal tablosu, PDF ve Excel
|
||||
|
||||

|
||||
|
||||
`siparis.json`'u okur; her kalem için indirim ve KDV hesaplar, KDV'yi
|
||||
oranlara göre döker ve sonucu üç biçimde verir:
|
||||
|
||||
1. Terminalde kutu çizgili, renkli bir fatura tablosu
|
||||
2. `fatura.pdf` — Türkçe karakterleri ve `₺` işaretini taşıyan, sayfa
|
||||
numaralı PDF
|
||||
3. `fatura.xlsx` — tablolar ayrı çalışma sayfalarında
|
||||
|
||||
```bash
|
||||
kabalang calistir fatura.kbl # siparis.json → ./fatura.pdf + ./fatura.xlsx
|
||||
kabalang calistir fatura.kbl -- baska.json --cikti ~/Belgeler
|
||||
```
|
||||
|
||||
## KabaLang'ın gösterdikleri
|
||||
|
||||
| Özellik | Nerede |
|
||||
|---|---|
|
||||
| `yapi` + metotlar | `Kalem.brut()`, `matrah()`, `kdv_tutari()` — hesap verinin yanında |
|
||||
| `sonuc<T, Hata>` | `siparis_oku` dosya yokken ya da JSON bozukken **değerle** hata döner; yok sayılamaz |
|
||||
| `dene / yakala` | JSON dizisini sonuna kadar gezmek |
|
||||
| `json` | İç içe erişim: `v["satici"]["ad"]`, `v["kalemler"][i]["adet"]` |
|
||||
| `kaba.belge` | Aynı belge nesnesinden `pdf_yaz` ve `xlsx_yaz` |
|
||||
| f-string biçimi | `{ad:<32}`, `{tutar:>15}`, `{k % 100:02d}` — hizalı tablo ve kuruş |
|
||||
|
||||
## Para nasıl tutuluyor
|
||||
|
||||
Her ara sonuç **kuruşa yuvarlanır** (`kurus()`); `0.1 + 0.2` gibi ikili kesir
|
||||
artıkları faturaya taşınmaz. `para()` sayıyı Türkçe biçime çevirir:
|
||||
`1249.9 → 1.249,90 ₺`.
|
||||
|
||||
Örnek siparişin toplamları elle de hesaplanıp karşılaştırıldı:
|
||||
ara toplam 65.439,80 ₺ · indirim 1.879,99 ₺ · KDV 11.748,96 ₺ ·
|
||||
**genel toplam 75.308,77 ₺**.
|
||||
|
||||
> Satıcı ve alıcı bilgileri örnek amaçlı, hayalidir.
|
||||
@@ -0,0 +1,179 @@
|
||||
# ╔══════════════════════════════════════════════════════════════════╗
|
||||
# ║ FATURA — JSON siparişten KDV'li fatura: terminal + PDF + Excel ║
|
||||
# ║ ║
|
||||
# ║ siparis.json'u okur, satır satır indirim ve KDV hesaplar, ║
|
||||
# ║ oranlara göre KDV dökümü çıkarır; sonucu terminalde kutu ║
|
||||
# ║ çizgili bir tablo olarak basar ve aynı veriden fatura.pdf ile ║
|
||||
# ║ fatura.xlsx üretir. Para kuruşa yuvarlanarak tutulur. ║
|
||||
# ║ ║
|
||||
# ║ kabalang calistir fatura.kbl ║
|
||||
# ║ kabalang calistir fatura.kbl -- baska.json --cikti ~/Belgeler ║
|
||||
# ╚══════════════════════════════════════════════════════════════════╝
|
||||
kullan kaba.sistem
|
||||
kullan kaba.belge
|
||||
|
||||
yapi Kalem:
|
||||
ad = ""
|
||||
adet = 0
|
||||
birim_fiyat = 0.0
|
||||
indirim = 0 # yüzde
|
||||
kdv = 0 # yüzde
|
||||
|
||||
fonksiyon brut() -> ondalik:
|
||||
don kurus(birim_fiyat * ondalik(adet))
|
||||
fonksiyon matrah() -> ondalik:
|
||||
don kurus(brut() * (1.0 - ondalik(indirim) / 100.0))
|
||||
fonksiyon kdv_tutari() -> ondalik:
|
||||
don kurus(matrah() * ondalik(kdv) / 100.0)
|
||||
|
||||
# Kuruşa yuvarla: 0.1 + 0.2 gibi ikili kesir artıklarını faturaya taşıma.
|
||||
fonksiyon kurus(x: ondalik) -> ondalik:
|
||||
don matematik.yuvarla(x * 100.0) / 100.0
|
||||
|
||||
# 1249.9 → "1.249,90 ₺" — Türkçe binlik ve ondalık ayıracı.
|
||||
fonksiyon para(x: ondalik) -> metin:
|
||||
k = sayi(matematik.yuvarla(x * 100.0))
|
||||
tam = metin(k // 100)
|
||||
gruplu = ""
|
||||
i = tam.uzunluk()
|
||||
iken i > 3:
|
||||
gruplu = "." + tam.dilim(i - 3, 3) + gruplu
|
||||
i = i - 3
|
||||
gruplu = tam.dilim(0, i) + gruplu
|
||||
don f"{gruplu},{k % 100:02d} ₺"
|
||||
|
||||
# ── Siparişi oku ─────────────────────────────────────────────────────
|
||||
# Beklenen hata (dosya yok, bozuk JSON) dönüş değeriyle bildirilir.
|
||||
fonksiyon siparis_oku(yol: metin) -> sonuc<metin, Hata>:
|
||||
eger degil dosya.var_mi(yol):
|
||||
don hata(f"sipariş dosyası bulunamadı: {yol}")
|
||||
ham = dosya.oku(yol)
|
||||
eger degil json.gecerli_mi(ham):
|
||||
don hata(f"{yol} geçerli bir JSON değil")
|
||||
don tamam(ham)
|
||||
|
||||
# ── Terminal tablosu ─────────────────────────────────────────────────
|
||||
fonksiyon boya(yazi: metin, rgb: metin) -> metin:
|
||||
don "\033[38;2;" + rgb + "m" + yazi + "\033[0m"
|
||||
|
||||
fonksiyon cizgi(sol: metin, orta: metin, sag: metin) -> metin:
|
||||
don boya(" " + sol + "━".tekrarla(4) + orta + "━".tekrarla(34) + orta + "━".tekrarla(6) + orta + "━".tekrarla(15) + orta + "━".tekrarla(6) + orta + "━".tekrarla(5) + orta + "━".tekrarla(16) + sag, "70;80;110")
|
||||
|
||||
fonksiyon satir(no: metin, ad: metin, adet: metin, birim: metin, ind: metin, kdv: metin, tutar: metin) -> metin:
|
||||
c = boya("┃", "70;80;110")
|
||||
don f" {c}{no:>3} {c} {ad:<32} {c}{adet:>5} {c}{birim:>14} {c}{ind:>5} {c}{kdv:>4} {c}{tutar:>15} {c}"
|
||||
|
||||
# ── Program ──────────────────────────────────────────────────────────
|
||||
ks = KomutSatiri("fatura", "JSON siparişten KDV'li fatura üretir")
|
||||
ks.konumsal("siparis", "Sipariş dosyası (varsayılan: siparis.json)")
|
||||
ks.secenek("cikti", "c", "PDF ve XLSX'in yazılacağı klasör")
|
||||
c = ks.coz()
|
||||
eger c.yardim_mi():
|
||||
c.yardim_yaz()
|
||||
cikis(0)
|
||||
eger c.hatali_mi():
|
||||
c.hata_yaz_ve_cik()
|
||||
|
||||
okunan = siparis_oku(c.konumsal("siparis").deger_veya("siparis.json"))
|
||||
eger okunan.hatali_mi():
|
||||
konsol.hata_yaz("✗ " + okunan.hata().mesaj() + "\n")
|
||||
cikis(1)
|
||||
v = json.coz(okunan.deger())
|
||||
|
||||
# JSON dizisinin uzunluğu sorulamıyor; sınırın dışına çıkınca biter.
|
||||
kalemler = [Kalem()] # boş yapı listesi: bir öğeyle kurup sil
|
||||
kalemler.sil(0)
|
||||
i = 0
|
||||
bitti = yanlis
|
||||
iken degil bitti:
|
||||
dene:
|
||||
j = v["kalemler"][i]
|
||||
kalemler.ekle(Kalem(metin(j["ad"]), sayi(j["adet"]), ondalik(j["birim_fiyat"]), sayi(j["indirim"]), sayi(j["kdv"])))
|
||||
i = i + 1
|
||||
yakala:
|
||||
bitti = dogru
|
||||
|
||||
# ── Hesap ────────────────────────────────────────────────────────────
|
||||
ara_toplam = 0.0
|
||||
indirim_toplam = 0.0
|
||||
kdv_toplam = 0.0
|
||||
dongu k icinde kalemler:
|
||||
ara_toplam = ara_toplam + k.brut()
|
||||
indirim_toplam = indirim_toplam + k.brut() - k.matrah()
|
||||
kdv_toplam = kdv_toplam + k.kdv_tutari()
|
||||
matrah_toplam = ara_toplam - indirim_toplam
|
||||
genel_toplam = kurus(matrah_toplam + kdv_toplam)
|
||||
|
||||
# ── Terminal ─────────────────────────────────────────────────────────
|
||||
no = metin(v["fatura_no"])
|
||||
tarih = metin(v["tarih"])
|
||||
satici = metin(v["satici"]["ad"])
|
||||
alici = metin(v["alici"]["ad"])
|
||||
yazdir("")
|
||||
yazdir(boya(f" ◆ FATURA {no}", "125;170;255") + boya(f" {tarih}", "110;120;150"))
|
||||
yazdir(boya(f" {satici} → {alici}", "200;208;224"))
|
||||
yazdir(cizgi("┏", "┳", "┓"))
|
||||
yazdir(satir("#", "Ürün / hizmet", "Adet", "Birim fiyat", "İnd.", "KDV", "Tutar"))
|
||||
yazdir(cizgi("┣", "╋", "┫"))
|
||||
s = 1
|
||||
dongu k icinde kalemler:
|
||||
ind = "—"
|
||||
eger k.indirim > 0:
|
||||
ind = f"%{k.indirim}"
|
||||
yazdir(satir(metin(s), k.ad, metin(k.adet), para(k.birim_fiyat), ind, f"%{k.kdv}", para(k.matrah())))
|
||||
s = s + 1
|
||||
yazdir(cizgi("┗", "┻", "┛"))
|
||||
|
||||
fonksiyon toplam_satiri(ad: metin, deger: metin, rgb: metin) -> metin:
|
||||
don boya(f"{ad:>78}", "150;160;185") + boya(f"{deger:>17}", rgb)
|
||||
|
||||
yazdir(toplam_satiri("Ara toplam", para(ara_toplam), "200;208;224"))
|
||||
yazdir(toplam_satiri("İndirim", "−" + para(indirim_toplam), "248;113;113"))
|
||||
yazdir(toplam_satiri("KDV matrahı", para(matrah_toplam), "200;208;224"))
|
||||
dongu oran icinde [20, 10, 1]:
|
||||
o_matrah = 0.0
|
||||
o_kdv = 0.0
|
||||
dongu k icinde kalemler:
|
||||
eger k.kdv == oran:
|
||||
o_matrah = o_matrah + k.matrah()
|
||||
o_kdv = o_kdv + k.kdv_tutari()
|
||||
eger o_kdv > 0.0:
|
||||
yazdir(toplam_satiri(f"KDV %{oran} ({para(o_matrah)} üzerinden)", para(o_kdv), "200;208;224"))
|
||||
yazdir(toplam_satiri("GENEL TOPLAM", para(genel_toplam), "74;222;128"))
|
||||
|
||||
# ── Belge: aynı veriden PDF + Excel ──────────────────────────────────
|
||||
klasor = c.secenek("cikti").deger_veya(".")
|
||||
b = belge.yeni(f"Fatura {no}")
|
||||
belge.altbilgi(b, f"{satici} · {no}")
|
||||
belge.baslik(b, "FATURA", 1)
|
||||
belge.paragraf(b, f"Fatura no: {no} Tarih: {tarih}")
|
||||
belge.baslik(b, "Satıcı", 3)
|
||||
belge.paragraf(b, satici + " — " + metin(v["satici"]["adres"]) + " — " + metin(v["satici"]["vergi"]))
|
||||
belge.baslik(b, "Alıcı", 3)
|
||||
belge.paragraf(b, alici + " — " + metin(v["alici"]["adres"]) + " — " + metin(v["alici"]["vergi"]))
|
||||
belge.baslik(b, "Kalemler", 2)
|
||||
belge.tablo_basligi(b, ["#", "Ürün / hizmet", "Miktar × fiyat", "İnd. / KDV", "Tutar"])
|
||||
s = 1
|
||||
dongu k icinde kalemler:
|
||||
ind = "—"
|
||||
eger k.indirim > 0:
|
||||
ind = f"%{k.indirim}"
|
||||
belge.tablo_satiri(b, [metin(s), metin(k.ad), f"{k.adet} × {para(k.birim_fiyat)}", f"{ind} / %{k.kdv}", para(k.matrah())])
|
||||
s = s + 1
|
||||
belge.baslik(b, "Özet", 2)
|
||||
belge.tablo_basligi(b, ["Kalem", "Tutar"])
|
||||
belge.tablo_satiri(b, ["Ara toplam", para(ara_toplam)])
|
||||
belge.tablo_satiri(b, ["İndirim", "-" + para(indirim_toplam)])
|
||||
belge.tablo_satiri(b, ["KDV matrahı", para(matrah_toplam)])
|
||||
belge.tablo_satiri(b, ["KDV toplamı", para(kdv_toplam)])
|
||||
belge.tablo_satiri(b, ["GENEL TOPLAM", para(genel_toplam)])
|
||||
belge.vurgu(b, f"Ödenecek tutar: {para(genel_toplam)}")
|
||||
|
||||
yazdir("")
|
||||
eger belge.pdf_yaz(b, klasor + "/fatura.pdf"):
|
||||
yazdir(boya(f" ✓ {klasor}/fatura.pdf yazıldı", "74;222;128"))
|
||||
degilse:
|
||||
yazdir(boya(" ✗ PDF yazılamadı", "248;113;113"))
|
||||
eger belge.xlsx_yaz(b, klasor + "/fatura.xlsx"):
|
||||
yazdir(boya(f" ✓ {klasor}/fatura.xlsx yazıldı", "74;222;128"))
|
||||
belge.kapat(b)
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"fatura_no": "A37-2026-000142",
|
||||
"tarih": "2026-10-02",
|
||||
"satici": {
|
||||
"ad": "Atölye 37 Bilişim Ltd. Şti.",
|
||||
"adres": "Yıldız Teknopark, B Blok No:7, İstanbul",
|
||||
"vergi": "Boğaziçi VD · 1234567890"
|
||||
},
|
||||
"alici": {
|
||||
"ad": "Mavi Deniz Kafe ve Ortak Çalışma Alanı",
|
||||
"adres": "Kordon Boyu Cad. No:12, Konak / İzmir",
|
||||
"vergi": "Konak VD · 9876543210"
|
||||
},
|
||||
"kalemler": [
|
||||
{ "ad": "Mekanik klavye (Türkçe Q)", "adet": 4, "birim_fiyat": 2450.00, "indirim": 10, "kdv": 20 },
|
||||
{ "ad": "27\" IPS monitör", "adet": 2, "birim_fiyat": 8999.90, "indirim": 5, "kdv": 20 },
|
||||
{ "ad": "Ergonomik çalışma sandalyesi", "adet": 3, "birim_fiyat": 6340.00, "indirim": 0, "kdv": 20 },
|
||||
{ "ad": "Yazılım bakım hizmeti (aylık)", "adet": 1, "birim_fiyat": 12500.00, "indirim": 0, "kdv": 20 },
|
||||
{ "ad": "Toplantı ikramı (kişi başı)", "adet": 12, "birim_fiyat": 185.00, "indirim": 0, "kdv": 10 },
|
||||
{ "ad": "Kahve çekirdeği 1 kg", "adet": 5, "birim_fiyat": 780.00, "indirim": 0, "kdv": 1 }
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
# Fraktal — terminalde 24 bit renkli Mandelbrot ve Julia
|
||||
|
||||

|
||||
|
||||
Terminali bir tuvale çevirir. Her karakter hücresi **iki piksel** taşır:
|
||||
üst yarım blok `▀` ön plan rengiyle üst pikseli, arka plan rengiyle alt
|
||||
pikseli çizer. 100 sütunluk bir terminal böylece 100 × 72 piksellik bir
|
||||
görüntü olur.
|
||||
|
||||
```bash
|
||||
kabalang calistir fraktal.kbl # Mandelbrot kümesi
|
||||
kabalang calistir fraktal.kbl -- --tur julia # Julia kümesi (c = -0.8 + 0.156i)
|
||||
kabalang calistir fraktal.kbl -- --yakinlas # denizatı vadisine 120 karelik dalış
|
||||
kabalang calistir fraktal.kbl -- -s 160 -r 44 # geniş terminal: 160 sütun × 44 satır
|
||||
```
|
||||
|
||||
## KabaLang'ın gösterdikleri
|
||||
|
||||
| Özellik | Nerede |
|
||||
|---|---|
|
||||
| `birlikte:` + `baslat` | Görüntü dört şeride bölünür, şeritler **aynı anda** hesaplanır ve sırası korunarak birleştirilir (`kare_ciz`) |
|
||||
| `sayilabilir` | `Kume.MANDELBROT` / `Kume.JULIA` — kapalı değer kümesi |
|
||||
| `yapi` | `Kamera` (merkez, görüş genişliği, yineleme sınırı) ve palet `Durak`ları |
|
||||
| f-string biçimi | `{kam.merkez_x:.5f}{kam.merkez_y:+.5f}i` — işaretli ve hassasiyetli sayı |
|
||||
| `KomutSatiri` | `--tur`, `--yakinlas`, `--sutun`/`--satir` ve kendiliğinden üretilen `--yardim` |
|
||||
| Tipli imzalar | `fonksiyon kacis(zx: ondalik, ...) -> ondalik` |
|
||||
|
||||
## Nasıl çalışır
|
||||
|
||||
* **Kaçış süresi:** `z ← z² + c` yinelenir; `|z|` 2'yi aşarsa nokta kümeden
|
||||
kaçmıştır. Ne kadar çabuk kaçtığı rengini belirler, hiç kaçmayan nokta
|
||||
kümenin içidir (lacivert).
|
||||
* **Palet:** altı renk durağından (derin uzay → gece mavisi → mavi →
|
||||
camgöbeği → lavanta → beyaz) bir kez 256 tonluk bir liste üretilir.
|
||||
* **Derin yakınlaşma:** renk, yineleme sayısının üçgen dalgasıdır; böylece
|
||||
20 yinelemede de 700 yinelemede de paletin tamamı kullanılır.
|
||||
|
||||
Bir kare (7.200 piksel, 120 yineleme sınırı) birkaç milisaniyede hesaplanır;
|
||||
süre başlık satırında yazar.
|
||||
@@ -0,0 +1,171 @@
|
||||
# ╔══════════════════════════════════════════════════════════════════╗
|
||||
# ║ FRAKTAL — terminalde 24 bit renkli Mandelbrot ve Julia kümesi ║
|
||||
# ║ ║
|
||||
# ║ Her karakter hücresi İKİ piksel taşır: üst yarım blok `▀`'nin ║
|
||||
# ║ ön plan rengi üst pikseli, arka plan rengi alt pikseli çizer. ║
|
||||
# ║ Görüntü dört şeride bölünür ve şeritler AYNI ANDA hesaplanır. ║
|
||||
# ║ ║
|
||||
# ║ kabalang calistir fraktal.kbl → Mandelbrot ║
|
||||
# ║ kabalang calistir fraktal.kbl --tur julia → Julia kümesi ║
|
||||
# ║ kabalang calistir fraktal.kbl --yakinlas → derinlere dalış║
|
||||
# ╚══════════════════════════════════════════════════════════════════╝
|
||||
kullan kaba.sistem
|
||||
|
||||
sayilabilir Kume:
|
||||
MANDELBROT
|
||||
JULIA
|
||||
|
||||
# Kameranın baktığı yer: karmaşık düzlemde merkez ve görüş genişliği.
|
||||
yapi Kamera:
|
||||
merkez_x = -0.65
|
||||
merkez_y = 0.0
|
||||
genislik = 3.2
|
||||
sinir = 120 # en fazla kaç yineleme
|
||||
|
||||
# ── Renk ─────────────────────────────────────────────────────────────
|
||||
# Palet, renk duraklarından bir kez üretilir: derin uzay → gece mavisi →
|
||||
# KabaForce mavisi → camgöbeği → lavanta → beyaz. Aradaki 256 ton doğrusal
|
||||
# karışımdır; her piksel yalnız listeden bir ton seçer.
|
||||
yapi Durak:
|
||||
konum = 0.0
|
||||
r = 0
|
||||
g = 0
|
||||
b = 0
|
||||
|
||||
fonksiyon karistir(a: sayi, b: sayi, t: ondalik) -> sayi:
|
||||
don a + sayi(ondalik(b - a) * t)
|
||||
|
||||
fonksiyon palet_uret() -> liste<metin>:
|
||||
duraklar = [Durak(0.00, 10, 13, 21), Durak(0.18, 26, 42, 108),
|
||||
Durak(0.40, 55, 126, 244), Durak(0.62, 34, 211, 238),
|
||||
Durak(0.82, 167, 139, 250), Durak(1.00, 250, 245, 255)]
|
||||
palet = [] # boş liste sabiti metin listesidir
|
||||
i = 0
|
||||
iken i < 256:
|
||||
t = ondalik(i) / 255.0
|
||||
k = 0
|
||||
iken t > duraklar[k + 1].konum:
|
||||
k = k + 1
|
||||
a = duraklar[k]
|
||||
b = duraklar[k + 1]
|
||||
oran = (t - a.konum) / (b.konum - a.konum)
|
||||
palet.ekle(f"{karistir(a.r, b.r, oran)};{karistir(a.g, b.g, oran)};{karistir(a.b, b.b, oran)}")
|
||||
i = i + 1
|
||||
don palet
|
||||
|
||||
PALET = palet_uret()
|
||||
|
||||
fonksiyon renk(t: ondalik) -> metin:
|
||||
eger t < 0.0: # kümenin içi: derin uzay laciverti
|
||||
don "6;8;14"
|
||||
don PALET[sayi(t * 255.0)]
|
||||
|
||||
# ── Kaçış süresi ─────────────────────────────────────────────────────
|
||||
# z ← z² + c. |z| 2'yi aşarsa nokta kümeden kaçmıştır; ne kadar
|
||||
# çabuk kaçtığı rengini belirler. Hiç kaçmazsa -1 döner (kümenin içi).
|
||||
# Renk yineleme sayısının üçgen dalgasıdır (0 → 1 → 0, her 80 adımda):
|
||||
# böylece 20 yinelemede de 500 yinelemede de palet baştan sona kullanılır.
|
||||
fonksiyon kacis(zx: ondalik, zy: ondalik, cx: ondalik, cy: ondalik, sinir: sayi) -> ondalik:
|
||||
i = 0
|
||||
iken i < sinir:
|
||||
x2 = zx * zx
|
||||
y2 = zy * zy
|
||||
eger x2 + y2 > 4.0:
|
||||
dalga = ondalik(i % 80) / 40.0
|
||||
eger dalga > 1.0:
|
||||
dalga = 2.0 - dalga
|
||||
don matematik.karekok(dalga)
|
||||
zy = 2.0 * zx * zy + cy
|
||||
zx = x2 - y2 + cx
|
||||
i = i + 1
|
||||
don -1.0
|
||||
|
||||
fonksiyon piksel(kume: Kume, kam: Kamera, px: sayi, py: sayi, sutun: sayi, satir: sayi) -> ondalik:
|
||||
# Terminal hücresi kare değil; iki piksel ≈ bir sütun genişliği.
|
||||
olcek = kam.genislik / ondalik(sutun)
|
||||
x = kam.merkez_x + (ondalik(px) - ondalik(sutun) / 2.0) * olcek
|
||||
y = kam.merkez_y + (ondalik(py) - ondalik(satir)) * olcek
|
||||
eger kume == Kume.JULIA:
|
||||
don kacis(x, y, -0.8, 0.156, kam.sinir)
|
||||
don kacis(0.0, 0.0, x, y, kam.sinir)
|
||||
|
||||
# Bir şerit: [bas, son) arasındaki karakter satırlarını tek metin olarak üretir.
|
||||
fonksiyon serit(kume: Kume, kam: Kamera, bas: sayi, son: sayi, sutun: sayi, satir: sayi) -> metin:
|
||||
cikti = ""
|
||||
j = bas
|
||||
iken j < son:
|
||||
px = 0
|
||||
iken px < sutun:
|
||||
ust = renk(piksel(kume, kam, px, 2 * j, sutun, satir))
|
||||
alt = renk(piksel(kume, kam, px, 2 * j + 1, sutun, satir))
|
||||
cikti = cikti + "\033[38;2;" + ust + "m\033[48;2;" + alt + "m▀"
|
||||
px = px + 1
|
||||
cikti = cikti + "\033[0m\n"
|
||||
j = j + 1
|
||||
don cikti
|
||||
|
||||
# Dört şeridi dört görevde birlikte hesapla; sıra korunarak birleştir.
|
||||
fonksiyon kare_ciz(kume: Kume, kam: Kamera, sutun: sayi, satir: sayi) -> metin:
|
||||
d = satir // 4
|
||||
resim = "" # birlikte: kendi kapsamıdır, sonucu dışarıda tut
|
||||
birlikte:
|
||||
a = baslat serit(kume, kam, 0, d, sutun, satir)
|
||||
b = baslat serit(kume, kam, d, 2 * d, sutun, satir)
|
||||
c = baslat serit(kume, kam, 2 * d, 3 * d, sutun, satir)
|
||||
e = baslat serit(kume, kam, 3 * d, satir, sutun, satir)
|
||||
resim = a.bekle() + b.bekle() + c.bekle() + e.bekle()
|
||||
don resim
|
||||
|
||||
fonksiyon baslik(kume: Kume, kam: Kamera, sure: sayi) -> metin:
|
||||
ad = "MANDELBROT"
|
||||
eger kume == Kume.JULIA:
|
||||
ad = "JULIA c = -0.8 + 0.156i"
|
||||
yakinlik = 3.2 / kam.genislik
|
||||
don f"\033[1;38;2;125;170;255m ◆ {ad}\033[0m\033[38;2;110;120;150m · merkez {kam.merkez_x:.5f}{kam.merkez_y:+.5f}i · ×{yakinlik:.1f} · {kam.sinir} yineleme · {sure} ms\033[0m"
|
||||
|
||||
# ── Komut satırı ─────────────────────────────────────────────────────
|
||||
ks = KomutSatiri("fraktal", "Terminalde 24 bit renkli fraktal çizer")
|
||||
ks.secenek("tur", "t", "mandelbrot ya da julia")
|
||||
ks.bayrak("yakinlas", "y", "Mandelbrot'un derinliklerine kare kare dal")
|
||||
ks.secenek("sutun", "s", "çizim genişliği (karakter, varsayılan 100)")
|
||||
ks.secenek("satir", "r", "çizim yüksekliği (karakter satırı, varsayılan 36)")
|
||||
c = ks.coz()
|
||||
eger c.yardim_mi():
|
||||
c.yardim_yaz()
|
||||
cikis(0)
|
||||
eger c.hatali_mi():
|
||||
c.hata_yaz_ve_cik()
|
||||
|
||||
SUTUN = sayi(c.secenek("sutun").deger_veya("100"))
|
||||
SATIR = sayi(c.secenek("satir").deger_veya("36")) # 36 karakter satırı = 72 piksel satırı
|
||||
eger SUTUN < 8 veya SATIR < 4:
|
||||
konsol.hata_yaz("fraktal: --sutun en az 8, --satir en az 4 olmalı\n")
|
||||
cikis(2)
|
||||
|
||||
kume = Kume.MANDELBROT
|
||||
kam = Kamera()
|
||||
eger c.secenek("tur").deger_veya("mandelbrot") == "julia":
|
||||
kume = Kume.JULIA
|
||||
kam.merkez_x = 0.0
|
||||
kam.genislik = 3.0
|
||||
|
||||
eger c.bayrak("yakinlas"):
|
||||
# Denizatı vadisine dalış: her karede görüş %8 daralır.
|
||||
kam.merkez_x = -0.743643887
|
||||
kam.merkez_y = 0.131825904
|
||||
konsol.yaz("\033[?25l\033[2J") # imleci gizle, ekranı temizle
|
||||
kare = 0
|
||||
iken kare < 120:
|
||||
t0 = zaman.milisaniye()
|
||||
resim = kare_ciz(kume, kam, SUTUN, SATIR)
|
||||
konsol.yaz("\033[H" + baslik(kume, kam, zaman.milisaniye() - t0) + "\033[K\n" + resim)
|
||||
kam.genislik = kam.genislik * 0.92
|
||||
kam.sinir = kam.sinir + 5
|
||||
uyu(40) # hesap ~3 ms sürüyor; göz için yavaşlat
|
||||
kare = kare + 1
|
||||
konsol.yaz("\033[?25h")
|
||||
degilse:
|
||||
t0 = zaman.milisaniye()
|
||||
resim = kare_ciz(kume, kam, SUTUN, SATIR)
|
||||
yazdir(baslik(kume, kam, zaman.milisaniye() - t0))
|
||||
konsol.yaz(resim)
|
||||
@@ -0,0 +1,39 @@
|
||||
# Sudoku — geri izlemeli çözücü, canlı animasyonla
|
||||
|
||||

|
||||
|
||||
Boş hücreye 1–9 arasındaki ilk uygun rakamı koyar ve ilerler. Çıkmaza
|
||||
girerse bir önceki hücreye döner (**geri izleme**) ve oradaki bir sonraki
|
||||
rakamı dener. Her adım ekranda görünür:
|
||||
|
||||
* **beyaz** — bulmacada verilen rakam
|
||||
* **camgöbeği** — çözücünün koyduğu, henüz kesinleşmemiş rakam
|
||||
* **sarı** — şu an denenen hücre · **kırmızı ✗** — geri alınan hücre
|
||||
* **yeşil** — çözüm bulunduktan sonra kesinleşen rakamlar
|
||||
|
||||
```bash
|
||||
kabalang calistir sudoku.kbl # animasyonlu (~10 sn)
|
||||
kabalang calistir sudoku.kbl -- --hizli # yalnız sonuç
|
||||
kabalang calistir sudoku.kbl -- 3000000000050090002005040000200007001600000587043106000008901000000670800000054 37 --hizli
|
||||
```
|
||||
|
||||
Kendi bulmacanızı 81 haneli bir dizi olarak verebilirsiniz (`0` = boş hücre).
|
||||
|
||||
## KabaLang'ın gösterdikleri
|
||||
|
||||
| Özellik | Nerede |
|
||||
|---|---|
|
||||
| `sinif` + kurucu `kur` | `Cozucu` ızgarayı **kendi üzerinde** değiştirir (metotlar nesnenin kendisinde çalışır) |
|
||||
| `sayilabilir` | Hücre durumu: `VERILEN · YERLESMIS · DENENIYOR · GERI_ALINDI · KESIN` |
|
||||
| Tipli liste alanı | `izgara: liste<sayi> = []`, `durum: liste<Hucre> = []` |
|
||||
| `**` üs işleci | Doğrulamada her grubun `2¹ + … + 2⁹ = 1022` toplamı |
|
||||
| f-string genişlik | `{self.deneme:5d}` sabit genişlikli sayaç |
|
||||
|
||||
## Doğruluk
|
||||
|
||||
Program çözümü yazmadan önce `gecerli_mi` ile denetler: her satır, sütun ve
|
||||
3×3 kutu 1..9'u tam bir kez içermeli. Bu, çözücüden **bağımsız** bir
|
||||
denetimdir — çözücü hatalı olsaydı ekranda `✓` görünmezdi.
|
||||
|
||||
Ölçülen: varsayılan bulmaca 1.682 deneme / 1.631 geri alma; "dünyanın en zor
|
||||
sudokusu" diye bilinen bulmacalardan biri 243.098 deneme, animasyonsuz ~55 ms.
|
||||
@@ -0,0 +1,197 @@
|
||||
# ╔══════════════════════════════════════════════════════════════════╗
|
||||
# ║ SUDOKU — geri izlemeli çözücü, canlı animasyonla ║
|
||||
# ║ ║
|
||||
# ║ Boş hücreye 1..9 arası ilk uygun rakamı koyar ve ilerler. ║
|
||||
# ║ Çıkmaza girerse bir önceki hücreye döner (geri izleme) ve ║
|
||||
# ║ oradaki bir sonraki rakamı dener. Her adım ekranda görünür: ║
|
||||
# ║ sarı = şu an denenen · kırmızı = geri alınan · yeşil = çözüm ║
|
||||
# ║ ║
|
||||
# ║ kabalang calistir sudoku.kbl → animasyonlu ║
|
||||
# ║ kabalang calistir sudoku.kbl --hizli → yalnız sonuç ║
|
||||
# ╚══════════════════════════════════════════════════════════════════╝
|
||||
kullan kaba.sistem
|
||||
|
||||
BULMACA = "030050040008010500460000012070502080000603000040109030250000098001020600080060020"
|
||||
|
||||
sayilabilir Hucre:
|
||||
VERILEN # bulmacada yazılı gelen rakam
|
||||
YERLESMIS # çözücünün koyduğu, henüz kesin değil
|
||||
DENENIYOR
|
||||
GERI_ALINDI
|
||||
KESIN
|
||||
|
||||
# ── Renkler ──────────────────────────────────────────────────────────
|
||||
fonksiyon boya(yazi: metin, rgb: metin) -> metin:
|
||||
don "\033[38;2;" + rgb + "m" + yazi + "\033[0m"
|
||||
|
||||
fonksiyon hucre_rengi(h: Hucre) -> metin:
|
||||
eger h == Hucre.VERILEN:
|
||||
don "235;240;255"
|
||||
eger h == Hucre.DENENIYOR:
|
||||
don "250;204;21"
|
||||
eger h == Hucre.GERI_ALINDI:
|
||||
don "248;113;113"
|
||||
eger h == Hucre.KESIN:
|
||||
don "74;222;128"
|
||||
don "34;211;238"
|
||||
|
||||
# ── Çözücü ───────────────────────────────────────────────────────────
|
||||
# Sınıf, ızgarayı kendi üzerinde değiştirir: metotlar nesnenin KENDİSİ
|
||||
# üzerinde çalışır (işleve geçen liste ise kopyadır).
|
||||
sinif Cozucu:
|
||||
izgara: liste<sayi> = []
|
||||
durum: liste<Hucre> = []
|
||||
deneme = 0
|
||||
geri_alma = 0
|
||||
canli = dogru
|
||||
|
||||
fonksiyon kur(self, bulmaca: metin, canli: mantik):
|
||||
i = 0
|
||||
iken i < 81:
|
||||
rakam = sayi(bulmaca.dilim(i, 1))
|
||||
self.izgara.ekle(rakam)
|
||||
eger rakam == 0:
|
||||
self.durum.ekle(Hucre.YERLESMIS)
|
||||
degilse:
|
||||
self.durum.ekle(Hucre.VERILEN)
|
||||
i = i + 1
|
||||
self.canli = canli
|
||||
|
||||
# Aynı satırda, sütunda ya da 3×3 kutuda r rakamı var mı?
|
||||
fonksiyon uygun_mu(self, konum: sayi, r: sayi) -> mantik:
|
||||
satir = konum // 9
|
||||
sutun = konum % 9
|
||||
kutu = (satir // 3) * 27 + (sutun // 3) * 3
|
||||
i = 0
|
||||
iken i < 9:
|
||||
eger self.izgara[satir * 9 + i] == r veya self.izgara[i * 9 + sutun] == r:
|
||||
don yanlis
|
||||
eger self.izgara[kutu + (i // 3) * 9 + i % 3] == r:
|
||||
don yanlis
|
||||
i = i + 1
|
||||
don dogru
|
||||
|
||||
# Geri izleme, açık bir yığınla: `bos` boş hücrelerin listesi, `i`
|
||||
# sıradaki boş hücre. İleri gidemeyince i bir geri çekilir.
|
||||
fonksiyon coz(self) -> mantik:
|
||||
bos = [0] # boş SAYI listesi: [] metin listesi olurdu
|
||||
bos.sil(0)
|
||||
k = 0
|
||||
iken k < 81:
|
||||
eger self.izgara[k] == 0:
|
||||
bos.ekle(k)
|
||||
k = k + 1
|
||||
i = 0
|
||||
iken i >= 0 ve i < bos.uzunluk():
|
||||
konum = bos[i]
|
||||
r = self.izgara[konum] + 1
|
||||
self.izgara[konum] = 0
|
||||
iken r <= 9 ve degil self.uygun_mu(konum, r):
|
||||
r = r + 1
|
||||
eger r <= 9:
|
||||
self.deneme = self.deneme + 1
|
||||
self.izgara[konum] = r
|
||||
self.durum[konum] = Hucre.DENENIYOR
|
||||
self.ciz(konum)
|
||||
self.durum[konum] = Hucre.YERLESMIS
|
||||
i = i + 1
|
||||
degilse:
|
||||
self.geri_alma = self.geri_alma + 1
|
||||
self.durum[konum] = Hucre.GERI_ALINDI
|
||||
self.ciz(konum)
|
||||
self.durum[konum] = Hucre.YERLESMIS
|
||||
i = i - 1
|
||||
don i == bos.uzunluk()
|
||||
|
||||
fonksiyon tamamla(self):
|
||||
i = 0
|
||||
iken i < 81:
|
||||
eger self.durum[i] != Hucre.VERILEN:
|
||||
self.durum[i] = Hucre.KESIN
|
||||
i = i + 1
|
||||
|
||||
# ── Çizim ───────────────────────────────────────────────────────
|
||||
fonksiyon ekran(self) -> metin:
|
||||
cizgi = boya(" ┣━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━┫", "70;80;110")
|
||||
cikti = boya(" ┏━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┓", "70;80;110") + "\n"
|
||||
s = 0
|
||||
iken s < 9:
|
||||
eger s == 3 veya s == 6:
|
||||
cikti = cikti + cizgi + "\n"
|
||||
satir = boya(" ┃", "70;80;110")
|
||||
k = 0
|
||||
iken k < 9:
|
||||
d = self.izgara[s * 9 + k]
|
||||
h = self.durum[s * 9 + k]
|
||||
yazi = " · "
|
||||
eger d != 0:
|
||||
yazi = f" {d} "
|
||||
eger h == Hucre.GERI_ALINDI:
|
||||
yazi = " ✗ "
|
||||
satir = satir + boya(yazi, hucre_rengi(h))
|
||||
eger k % 3 == 2:
|
||||
satir = satir + boya("┃", "70;80;110")
|
||||
k = k + 1
|
||||
cikti = cikti + satir + "\n"
|
||||
s = s + 1
|
||||
cikti = cikti + boya(" ┗━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━┛", "70;80;110") + "\n"
|
||||
don cikti
|
||||
|
||||
fonksiyon ciz(self, konum: sayi):
|
||||
eger degil self.canli:
|
||||
don
|
||||
konsol.yaz("\033[H\n" + boya(" ◆ SUDOKU · geri izleme", "125;170;255") + "\n\n" + self.ekran())
|
||||
konsol.yaz(f"\n deneme {self.deneme:5d} geri alma {self.geri_alma:5d} hücre {konum // 9 + 1},{konum % 9 + 1} \n")
|
||||
uyu(3)
|
||||
|
||||
# Çözüm gerçekten geçerli mi? Her satır, sütun ve kutu 1..9'u tam bir kez içermeli.
|
||||
fonksiyon gecerli_mi(izgara) -> mantik:
|
||||
grup = 0
|
||||
iken grup < 9:
|
||||
satir_toplam = 0
|
||||
sutun_toplam = 0
|
||||
kutu_toplam = 0
|
||||
i = 0
|
||||
iken i < 9:
|
||||
satir_toplam = satir_toplam + 2 ** izgara[grup * 9 + i]
|
||||
sutun_toplam = sutun_toplam + 2 ** izgara[i * 9 + grup]
|
||||
kutu_toplam = kutu_toplam + 2 ** izgara[(grup // 3) * 27 + (grup % 3) * 3 + (i // 3) * 9 + i % 3]
|
||||
i = i + 1
|
||||
# 2¹ + 2² + … + 2⁹ = 1022: yalnız 1..9'un her biri bir kez varsa tutar.
|
||||
eger satir_toplam != 1022 veya sutun_toplam != 1022 veya kutu_toplam != 1022:
|
||||
don yanlis
|
||||
grup = grup + 1
|
||||
don dogru
|
||||
|
||||
# ── Program ──────────────────────────────────────────────────────────
|
||||
ks = KomutSatiri("sudoku", "Geri izlemeli sudoku çözücü")
|
||||
ks.bayrak("hizli", "h", "Animasyonsuz, yalnız sonucu göster")
|
||||
ks.konumsal("bulmaca", "81 haneli bulmaca (0 = boş hücre)")
|
||||
c = ks.coz()
|
||||
eger c.yardim_mi():
|
||||
c.yardim_yaz()
|
||||
cikis(0)
|
||||
eger c.hatali_mi():
|
||||
c.hata_yaz_ve_cik()
|
||||
|
||||
bulmaca = c.konumsal("bulmaca").deger_veya(BULMACA)
|
||||
eger bulmaca.uzunluk() != 81:
|
||||
konsol.hata_yaz("bulmaca 81 haneli olmalı\n")
|
||||
cikis(2)
|
||||
|
||||
cozucu = Cozucu(bulmaca, degil c.bayrak("hizli"))
|
||||
konsol.yaz("\033[2J\033[?25l")
|
||||
t0 = zaman.milisaniye()
|
||||
basardi = cozucu.coz()
|
||||
sure = zaman.milisaniye() - t0
|
||||
cozucu.tamamla()
|
||||
|
||||
konsol.yaz("\033[H\n" + boya(" ◆ SUDOKU · geri izleme", "125;170;255") + "\n\n" + cozucu.ekran())
|
||||
eger basardi ve gecerli_mi(cozucu.izgara):
|
||||
ek = ""
|
||||
eger cozucu.canli:
|
||||
ek = " (animasyon dahil)"
|
||||
yazdir(boya(f"\n ✓ çözüldü — {cozucu.deneme} deneme, {cozucu.geri_alma} geri alma, {sure} ms{ek}", "74;222;128") + "\033[K")
|
||||
degilse:
|
||||
yazdir(boya("\n ✗ bu bulmacanın çözümü yok", "248;113;113") + "\033[K")
|
||||
konsol.yaz("\033[?25h")
|
||||
Reference in New Issue
Block a user