Hafta 1 · Algoritma Düşüncesi ve İlk Java¶
YMT1101 Algoritma ve Programlama I · Fırat Üniversitesi Yazılım Mühendisliği · Doç. Dr. Ferhat Uçar
Bu defter, dersin ilk saatinde birlikte çalıştırıp okuduğumuz kodların kaydıdır. Bugün kod yazmıyoruz; her hücreyi çalıştırıyor, çıktısına bakıyor ve "ne oldu?" sorusunu cevaplıyoruz.
Kodlar JShell tarzındadır: sınıf ve main yazmadan doğrudan satır satır çalışır. Kendiniz denemek isterseniz
herhangi bir hücreyi kopyalayıp Java Playground sayfasına yapıştırmanız yeterli;
kurulum gerekmez.
Amaç bugün Java öğrenmek değil; bir bilgisayara adım adım tarif vermenin nasıl bir şey olduğunu görmek.
1 · Merhaba¶
Bilgisayara bir şey söyletmenin en kısa yolu System.out.println(...). Tırnak içindeki metni ekrana yazar
ve satırı bitirir. Satır sonundaki ; Java'da cümlenin noktasıdır.
System.out.println("Merhaba! Bu dersin ilk satırı.");
Merhaba! Bu dersin ilk satırı.
Metni bir kutuya koyup isim verebiliriz. Aşağıdaki ad bir değişken: bir değeri isimle saklar.
+ işareti iki metni uç uca ekler.
String ad = "Ferhat";
System.out.println("Merhaba " + ad + ", Algoritma ve Programlama dersine hoş geldin.");
Merhaba Ferhat, Algoritma ve Programlama dersine hoş geldin.
2 · Değişken ve hesap¶
Sayılar için iki temel tip var: int (tam sayı) ve double (ondalıklı sayı). Bilgisayar bunları farklı saklar
ve farklı hesaplar. Aşağıdaki iki bölmeden hangisi 3, hangisi 3.5 verir? Çalıştırmadan önce tahmin edin.
int a = 7;
int b = 2;
double c = 2.0;
System.out.println("7 / 2 = " + (a / b));
System.out.println("7 / 2.0 = " + (a / c));
7 / 2 = 3 7 / 2.0 = 3.5
İki tam sayının bölümü yine tam sayıdır; küsurat atılır, yuvarlanmaz. Bu, ileride en çok hata yapılan yerlerden biri.
Kalanı bulmak için % (mod) operatörü var. "17'yi 5'e bölünce kaç artar?" sorusunun cevabı:
System.out.println("17 % 5 = " + (17 % 5));
System.out.println("20 % 5 = " + (20 % 5));
System.out.println("9 % 2 = " + (9 % 2) + " (tek sayı: kalan 1)");
17 % 5 = 2 20 % 5 = 0 9 % 2 = 1 (tek sayı: kalan 1)
3 · Karar¶
Program her zaman düz bir yol izlemez; bazen bir soruya göre yön değiştirir. if ... else yapısı bunu sağlar.
sayi % 2 == 0 ifadesi "ikiye bölünce kalan sıfır mı?" diye sorar; == karşılaştırma, = atamadır.
int sayi = 17;
if (sayi % 2 == 0) {
System.out.println(sayi + " çift sayıdır.");
} else {
System.out.println(sayi + " tek sayıdır.");
}
17 tek sayıdır.
Deneyin:
sayideğerini 18, 0 ve -7 yapıp hücreyi yeniden çalıştırın. Sonuç beklediğiniz gibi mi?
4 · Tekrar¶
Bilgisayarın asıl gücü aynı işi bıkmadan tekrarlamak. for döngüsü üç parçadan oluşur:
başlangıç (int i = 1), devam koşulu (i <= 10) ve her turdaki adım (i++, yani "i'yi bir artır").
for (int i = 1; i <= 10; i++) {
System.out.println(i);
}
1 2 3 4 5 6 7 8 9 10
Şimdi aynı döngüyü bir şey biriktirmek için kullanalım: 1'den 100'e kadar sayıların toplamı.
toplam değişkeni sıfırdan başlar, her turda üstüne i eklenir.
int toplam = 0;
for (int i = 1; i <= 100; i++) {
toplam = toplam + i;
}
System.out.println("1'den 100'e toplam: " + toplam);
1'den 100'e toplam: 5050
Gauss bunu döngü kurmadan,
100 * 101 / 2formülüyle bulmuştu. İki yol da doğru; biri hesap, biri fikir. Hangisinin "daha iyi" olduğu sorusu bu dersin sonuna doğru (verimlilik) tekrar karşımıza çıkacak.
5 · Bilerek hata¶
Programcılığın ilk becerisi hata mesajından korkmamak. Aşağıdaki hücrede iki hata var: ilk satırda noktalı virgül eksik, ikinci satırda hiç tanımlanmamış bir değişken kullanılıyor. Çalıştırın ve mesajı sonuna kadar okuyun: bilgisayar size tam olarak neyi beğenmediğini söylüyor.
int yas = 20
System.out.println("Yaş: " + yaş);
| int yas = 20 ';' expected
';' expected demek "burada noktalı virgül bekliyordum". Java önce bunu görür ve durur; ikinci hata (yaş
tanımlı değil, çünkü değişkenin adı yas) ancak ilki düzeltilince ortaya çıkar. Hata mesajı bir ceza değil,
bir ipucu. Düzeltilmiş hali:
int yas = 20;
System.out.println("Yaş: " + yas);
Yaş: 20
6 · Bir algoritma: Babil karekök yöntemi¶
Algoritma, bir işi adım adım yapan tariftir. Yaklaşık 4000 yıl önce Babilliler karekökü şöyle buluyordu:
- Bir tahminle başla (mesela sayının kendisi).
- Tahmin ile "sayı bölü tahmin"in ortalamasını al; bu yeni tahmin olsun.
- Tahmin yeterince iyi olana kadar 2. adımı tekrarla.
Kaç kez tekrarlayacağımızı önceden bilmiyoruz, o yüzden for yerine while kullanıyoruz:
"koşul doğru olduğu sürece tekrar et".
double sayi = 25;
double tahmin = sayi; // 1. adım: ilk tahmin
int adim = 0;
while (Math.abs(tahmin * tahmin - sayi) > 0.000001) { // 3. adım: yeterince iyi değilse devam
tahmin = (tahmin + sayi / tahmin) / 2; // 2. adım: ortalama al
adim++;
System.out.println("Adım " + adim + ": tahmin = " + tahmin);
}
System.out.println("Sonuç: " + tahmin + " (" + adim + " adımda)");
Adım 1: tahmin = 13.0 Adım 2: tahmin = 7.461538461538462 Adım 3: tahmin = 5.406026962727994 Adım 4: tahmin = 5.015247601944898 Adım 5: tahmin = 5.000023178253949 Adım 6: tahmin = 5.000000000053722 Sonuç: 5.000000000053722 (6 adımda)
Beş altı adımda 5'e ulaştı. Tarifin her satırı koda birebir karşılık geliyor; kod, tarifin yazıya dökülmüş hali.
sayideğerini 2 yapın: hiç bitmeyecek gibi görünen bir sayıya bilgisayar nasıl yaklaşıyor?
7 · Bir bulmaca: nehri geçen çiftçi¶
Bir çiftçi, bir kurt, bir keçi ve bir lahana nehrin bir kıyısında. Kayığa çiftçiyle birlikte yalnızca bir şey sığıyor. Çiftçi yanlarında değilken kurt keçiyi, keçi de lahanayı yer. Hepsini sağ salim karşıya nasıl geçirir?
Bunu önce kağıt üzerinde çözün. Sonra şunu düşünün: bu çözümü bilgisayara nasıl tarif ederiz? Bilgisayarın deneme yanılma yapıp çözümü kendisinin bulması için ne söylememiz gerekir?
Aşağıda hazır bir çözüm var. Bugün sadece çalıştırıp çıktısını okuyoruz; 13. haftada bu programı siz yazacaksınız. O zamana kadar diziler, metotlar ve arama fikri elimizde olacak.
import java.util.*;
// Durum: 4 elemanlı boolean dizisi. false = sol kıyı, true = sağ kıyı.
// Sıra: [0] çiftçi, [1] kurt, [2] keçi, [3] lahana
String[] isim = {"çiftçi", "kurt", "keçi", "lahana"};
// Çiftçi yanlarında değilken kurt-keçi ya da keçi-lahana aynı kıyıda kalamaz
boolean guvenli(boolean[] d) {
if (d[1] == d[2] && d[0] != d[2]) return false;
if (d[2] == d[3] && d[0] != d[2]) return false;
return true;
}
// Deneme yanılma: her olası hamleyi dene, çıkmaza girersen geri al
boolean coz(boolean[] d, Set<String> gorulen, List<String> hamleler) {
if (d[0] && d[1] && d[2] && d[3]) return true; // herkes karşıda: bitti
if (!gorulen.add(Arrays.toString(d))) return false; // bu durumu daha önce gördük
for (int y = 0; y < 4; y++) { // y = 0: çiftçi tek başına gider
if (d[y] != d[0]) continue; // yolcu çiftçiyle aynı kıyıda olmalı
boolean[] yeni = d.clone();
yeni[0] = !yeni[0]; // çiftçi karşıya
if (y != 0) yeni[y] = !yeni[y]; // yanında yolcu varsa o da
if (!guvenli(yeni)) continue;
String yon = yeni[0] ? "karşıya" : "geri";
String kim = (y == 0) ? "tek başına" : isim[y] + " ile";
hamleler.add("Çiftçi " + kim + " " + yon);
if (coz(yeni, gorulen, hamleler)) return true;
hamleler.remove(hamleler.size() - 1); // olmadı, hamleyi geri al
}
return false;
}
List<String> hamleler = new ArrayList<>();
coz(new boolean[4], new HashSet<>(), hamleler);
for (int i = 0; i < hamleler.size(); i++) System.out.println((i + 1) + ". " + hamleler.get(i));
1. Çiftçi keçi ile karşıya 2. Çiftçi tek başına geri 3. Çiftçi kurt ile karşıya 4. Çiftçi keçi ile geri 5. Çiftçi lahana ile karşıya 6. Çiftçi tek başına geri 7. Çiftçi keçi ile karşıya
Yedi hamle. Bilgisayara "çözümü" söylemedik; sadece kuralları (neyin güvenli olduğu) ve deneme yöntemini (bir hamle yap, olmadıysa geri al) tarif ettik. Çözümü kendisi buldu. Algoritma düşüncesi tam olarak bu.
8 · Bugün ne gördük?¶
| Bölüm | Ne yaptık | Hangi haftada derinleşecek |
|---|---|---|
| 1 | İlk println, String değişken |
Hafta 2 |
| 2 | int / double, bölme ve % |
Hafta 2-3 |
| 3 | if / else ile karar |
Hafta 4 |
| 4 | for döngüsü, biriktirme |
Hafta 5-6 |
| 5 | Hata mesajı okuma | Her hafta |
| 6 | while ile bir algoritma (Babil) |
Hafta 6-7 |
| 7 | Dizi, metot, deneme yanılma ile arama | Hafta 8-13 |
Eve ödev (isteğe bağlı, 10 dk): Java Playground'ı açın, 3. bölümdeki karar
hücresini yapıştırıp sayi değerini değiştirerek çalıştırın. Sonra 4. bölümdeki toplamı 1'den 1000'e çıkarın.
Bir hata alırsanız mesajı okuyun; gelecek hafta ilk beş dakikada bu hataları konuşacağız.