Gerçek Hayat Problemleri ve Çözümleri
Oyuncu hareketleri, input buffer, event sistemi
HTTP istek kuyruğu, load balancing
Message queue, async işlemler
CPU process scheduling, cron jobs
Çocuk oyunu: Herkes daire şeklinde oturur, bir patates (veya top) elden ele geçirilir. Müzik durduğunda elinde patates kalan oyundan çıkar!
MS 67, Yahudi-Roma Savaşı: Tarihçi Josephus ve 40 asker Romalılar tarafından kuşatıldı. Teslim olmak yerine intihar etmeye karar verdiler. Daire şeklinde durup her 3. kişi öldürülecekti. Josephus matematik kullanarak kendini ve arkadaşını son iki kişi olarak konumlandırdı ve hayatta kaldılar!
from collections import deque
def sicak_patates(oyuncular, k):
"""
Sıcak Patates / Josephus Problemi
Args:
oyuncular: Oyuncu isimleri listesi
k: Kaç tur geçtikten sonra eleme olacak
Returns:
Kazanan oyuncu
"""
kuyruk = deque(oyuncular)
tur = 1
print("🎮 SICAK PATATES OYUNU BAŞLIYOR!")
print(f"📋 Oyuncular: {list(kuyruk)}")
print(f"🔢 Her {k}. kişi elenecek\n")
print("=" * 50)
while len(kuyruk) > 1:
print(f"\n🔄 Tur {tur}: Patates elden ele...")
# k-1 kez patatesi geçir (dequeue + enqueue)
for i in range(k - 1):
gecen = kuyruk.popleft()
kuyruk.append(gecen)
print(f" {i+1}. geçiş: {gecen} → sona gitti")
# k. kişi eleniyor
elenen = kuyruk.popleft()
print(f"\n ❌ {elenen} ELENDİ! (Patates onda kaldı)")
print(f" 📋 Kalanlar: {list(kuyruk)}")
tur += 1
kazanan = kuyruk[0]
print("\n" + "=" * 50)
print(f"🏆 KAZANAN: {kazanan}")
return kazanan
# Oyunu başlat!
oyuncular = ["Ali", "Ayşe", "Mehmet", "Fatma", "Ahmet"]
sicak_patates(oyuncular, k=3)
SPOOL = Simultaneous Peripheral Operations On-Line
Birden fazla kullanıcı aynı anda yazdırma isteği gönderdiğinde, yazıcı bunları sırayla işler. İlk gelen istek ilk işlenir (FIFO) - tam olarak Queue veri yapısının davranışı!
from collections import deque
import random
class YaziciKuyrugu:
"""Yazıcı Spooler Simülasyonu"""
def __init__(self, yazici_adi):
self.yazici_adi = yazici_adi
self.kuyruk = deque()
self.toplam_is = 0
def yazdir_ekle(self, kullanici, belge, sayfa_sayisi):
"""Yazdırma işi ekle"""
is_bilgisi = {
"id": self.toplam_is + 1,
"kullanici": kullanici,
"belge": belge,
"sayfa": sayfa_sayisi
}
self.kuyruk.append(is_bilgisi)
self.toplam_is += 1
print(f"📥 Eklendi: #{is_bilgisi['id']} - {kullanici}: {belge} ({sayfa_sayisi} sayfa)")
def yazdir(self):
"""Sıradaki işi yazdır"""
if not self.kuyruk:
print("❌ Kuyruk boş, yazdırılacak iş yok!")
return None
is_bilgisi = self.kuyruk.popleft()
print(f"\n🖨️ YAZDIRILIYOR...")
print(f" 📄 İş #{is_bilgisi['id']}: {is_bilgisi['belge']}")
print(f" 👤 Kullanıcı: {is_bilgisi['kullanici']}")
print(f" 📑 Sayfa: {is_bilgisi['sayfa']} sayfa")
print(f" ✅ Tamamlandı!")
return is_bilgisi
def kuyruk_durumu(self):
"""Kuyruktaki işleri göster"""
print(f"\n📊 {self.yazici_adi} - Kuyruk Durumu:")
if not self.kuyruk:
print(" (Boş)")
else:
for i, is_bilgisi in enumerate(self.kuyruk, 1):
print(f" {i}. #{is_bilgisi['id']} {is_bilgisi['kullanici']}: {is_bilgisi['belge']}")
# Simülasyon
print("=" * 50)
print("🖨️ OFİS YAZICI SİMÜLASYONU")
print("=" * 50)
yazici = YaziciKuyrugu("HP LaserJet")
# Çalışanlar yazdırma işi gönderiyor
yazici.yazdir_ekle("Ahmet", "Rapor.pdf", 15)
yazici.yazdir_ekle("Ayşe", "Sunum.pptx", 8)
yazici.yazdir_ekle("Mehmet", "Fatura.xlsx", 2)
yazici.yazdir_ekle("Fatma", "Sözleşme.docx", 25)
yazici.kuyruk_durumu()
print("\n" + "=" * 50)
print("📤 YAZDIRMA BAŞLIYOR (FIFO Sırası)")
print("=" * 50)
# Tüm işleri yazdır
while yazici.kuyruk:
yazici.yazdir()
yazici.kuyruk_durumu()
Bir dizi üzerinde k boyutlu bir pencere kaydır. Her konumda pencere içindeki en büyük sayıyı bul.
Baştaki indeks pencere dışına çıktıysa → popleft()
Yeni gelen > sondaki → pop() (döngüyle)
Yeni indeksi sona ekle. Baştaki = max!
| Pencere | [1, 3, -1] | [3, -1, -3] | [-1, -3, 5] | [-3, 5, 3] | [5, 3, 6] | [3, 6, 7] |
| Max | 3 | 3 | 5 | 5 | 6 | 7 |
Sonuç: [3, 3, 5, 5, 6, 7]
from collections import deque
def sliding_window_max(nums, k):
"""
Kayan Pencere Maksimum Problemi
Deque'de SADECE indeksleri tutuyoruz (değerleri değil!)
Deque her zaman azalan sırada kalır (monotonic decreasing)
Zaman: O(n) - her eleman en fazla 1 kez eklenir, 1 kez silinir
Alan: O(k) - deque en fazla k eleman tutar
"""
if not nums or k == 0:
return []
dq = deque() # İndeksleri tutar
sonuc = []
print(f"📊 Dizi: {nums}")
print(f"📏 Pencere boyutu: k = {k}")
print("=" * 60)
for i in range(len(nums)):
print(f"\n🔄 Adım {i+1}: nums[{i}] = {nums[i]}")
# KURAL 1: Pencere dışındakileri sil
if dq and dq[0] < i - k + 1:
eski = dq.popleft()
print(f" ❌ Kural 1: indeks {eski} pencere dışına çıktı, silindi")
# KURAL 2: Yeni gelen daha büyükse, küçükleri kov
while dq and nums[dq[-1]] < nums[i]:
kovulan = dq.pop()
print(f" 🚫 Kural 2: nums[{kovulan}]={nums[kovulan]} < {nums[i]}, kovuldu")
# KURAL 3: Yeni indeksi ekle
dq.append(i)
print(f" ➕ Kural 3: indeks {i} eklendi → deque: {list(dq)}")
# Pencere dolduğunda max'ı kaydet
if i >= k - 1:
max_val = nums[dq[0]]
sonuc.append(max_val)
pencere = nums[i-k+1:i+1]
print(f" ✅ Pencere {pencere} → Max: {max_val}")
print("\n" + "=" * 60)
print(f"🎯 SONUÇ: {sonuc}")
return sonuc
# Test
nums = [1, 3, -1, -3, 5, 3, 6, 7]
k = 3
sliding_window_max(nums, k)
İşletim sistemlerinin en temel CPU zamanlama algoritmasıdır. Her işleme (process) eşit bir zaman dilimi (time quantum) verilir.
İşlem zaman dilimi içinde bitmezse, kuyruğun sonuna gönderilir ve sıradaki işleme geçilir. Bu sayede tüm işlemler adil bir şekilde CPU zamanı alır.
from collections import deque
class RoundRobinScheduler:
"""
Round Robin CPU Scheduler Simülasyonu
Her işleme eşit zaman dilimi (time quantum) verilir.
İşlem bitmezse kuyruğun sonuna gönderilir.
"""
def __init__(self, time_quantum):
self.time_quantum = time_quantum
self.ready_queue = deque()
self.current_time = 0
def add_process(self, name, burst_time):
"""Yeni işlem ekle"""
process = {"name": name, "remaining": burst_time, "original": burst_time}
self.ready_queue.append(process)
print(f"📥 Eklendi: {name} (Toplam: {burst_time} birim)")
def run(self):
"""Tüm işlemleri çalıştır"""
print(f"\n{'=' * 60}")
print(f"⚙️ ROUND ROBIN SCHEDULER")
print(f"⏱️ Time Quantum: {self.time_quantum} birim")
print(f"{'=' * 60}")
completed = []
while self.ready_queue:
process = self.ready_queue.popleft()
name = process["name"]
remaining = process["remaining"]
# Ne kadar çalışacak?
run_time = min(self.time_quantum, remaining)
print(f"\n🔄 T={self.current_time}: {name} çalışıyor ({run_time} birim)")
self.current_time += run_time
process["remaining"] -= run_time
if process["remaining"] > 0:
# İşlem bitmedi, kuyruğun sonuna ekle
self.ready_queue.append(process)
print(f" ⏸️ {name} durdu, kalan: {process['remaining']} birim → Kuyruğa geri")
else:
# İşlem tamamlandı
turnaround = self.current_time
completed.append({"name": name, "turnaround": turnaround})
print(f" ✅ {name} TAMAMLANDI! (Turnaround: {turnaround} birim)")
# Kuyruk durumu
queue_names = [p["name"] for p in self.ready_queue]
print(f" 📋 Kuyruk: {queue_names if queue_names else '(Boş)'}")
# Özet
print(f"\n{'=' * 60}")
print("📊 ÖZET")
print(f"{'=' * 60}")
avg_turnaround = sum(p["turnaround"] for p in completed) / len(completed)
for p in completed:
print(f" {p['name']}: Turnaround = {p['turnaround']} birim")
print(f"\n 📈 Ortalama Turnaround: {avg_turnaround:.1f} birim")
# Simülasyon
scheduler = RoundRobinScheduler(time_quantum=4)
# İşlemler ekle
scheduler.add_process("P1", 10) # 10 birim CPU zamanı gerekiyor
scheduler.add_process("P2", 5) # 5 birim
scheduler.add_process("P3", 8) # 8 birim
# Çalıştır
scheduler.run()
API'lere gelen istekleri sınırlandırır. Örneğin: "Dakikada en fazla 100 istek" kuralı.
DDoS saldırılarını önler, sunucu kaynaklarını korur, adil kullanım sağlar.
Her istek geldiğinde:
from collections import deque
import time
class RateLimiter:
"""
Sliding Window Rate Limiter
Belirli bir zaman penceresinde maksimum istek sayısını sınırlar.
Queue'da zaman damgalarını tutarak eski istekleri temizler.
"""
def __init__(self, max_requests, window_seconds):
"""
Args:
max_requests: Pencere içinde izin verilen max istek
window_seconds: Pencere süresi (saniye)
"""
self.max_requests = max_requests
self.window_seconds = window_seconds
self.requests = deque() # Zaman damgalarını tutar
def allow_request(self, current_time):
"""
İsteğe izin verilip verilmeyeceğini kontrol et
Returns:
True: İzin verildi
False: Rate limit aşıldı
"""
# Pencere dışındaki eski istekleri temizle
window_start = current_time - self.window_seconds
while self.requests and self.requests[0] < window_start:
self.requests.popleft()
# Limit kontrolü
if len(self.requests) < self.max_requests:
self.requests.append(current_time)
return True
else:
return False
def get_status(self):
"""Mevcut durumu göster"""
return f"{len(self.requests)}/{self.max_requests}"
# Simülasyon
print("=" * 60)
print("🚦 RATE LIMITER SİMÜLASYONU")
print("📋 Kural: 10 saniyede en fazla 5 istek")
print("=" * 60)
limiter = RateLimiter(max_requests=5, window_seconds=10)
# Simülasyon senaryosu
test_times = [0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 15, 20, 21]
for t in test_times:
allowed = limiter.allow_request(t)
status = limiter.get_status()
if allowed:
print(f"T={t:2d}s → ✅ İZİN VERİLDİ [{status}]")
else:
print(f"T={t:2d}s → ❌ REDDEDİLDİ [{status}] (Rate limit aşıldı!)")
print("\n" + "=" * 60)
print("💡 Not: T=5, 6, 7, 8'de limit aşıldı çünkü son 10 saniyede")
print(" zaten 5 istek yapılmıştı. T=11'de pencere kaydı ve yer açıldı.")