HackerRank — Java Loops II
Döngüler, Math kütüphanesi, Java Loops II sorusunun çözümü
HackerRank üzerindeki Java problemlerini çözüyoruz. Bu yedinci problem. Eğer diğer problem çözümlerini okumadıysanız önce onlara bakmanızı tavsiye ederim, hepsinin toplu hali:
Önce problemi anlayalım sonra da çözümüne geçelim. Problemi anlama kısmını okuduktan sonra problemi çözmeyi denemenizi sonra da buradaki çözümle karşılaştırmanızı şiddetle tavsiye ederim :)
Problemin linki 👇
Problemi anlayalım
Problemi çözerken önceki “Loop I” probleminde olduğu gibi döngüleri kullanacağız. For loop bu tarz problemler için tercihim. Bu problemden öğrenebileceğimiz konu: Math kütüphanesi.
Math kütüphanesi, çoğu matematiksel işlemi gerçekleştirebileceğimiz methodlar sunar. Eğer Math kütüphanesini kullanmazsak genelde yapmamız gereken işlemler bitwise shift işlemleri olur, ki bunları da her seferinde hesaplamak biraz can sıkıcı. Onun yerine hazır method kullanmak çoğu zaman kullanışlı ve okunaklı oluyor. Bitwise operatörler ileriki problemlerde daha çok haşır neşir olacağımız bir konu, o yüzden Math kütüphanesi ile devam edelim.
Math kütüphanesi içinde tanımlı bir çok metod var, bunlardan en sık kullanılanları:
- Math.max(x,y): Hangi sayının daha büyük olduğunu döner
- Math.min(x,y): Hangi sayının daha küçük olduğunu döner
- Math.sqrt(x): Sayının karekökünü döner
- Math.abs(x): Sayının mutlak değerini döner
- Math.random(): Rastgele bir sayı döner
- Math.floor(x): Sayıya en yakın bir aşağısındaki tam sayıyı döner
- Math.ceil(x): Sayıya en yakın bir yukarısındaki tam sayıyı döner
- Math.pow(x, y): x^y sonucunu döner
Bunlar ilk aklıma gelenler, sin-cos-tan gibi işlemler için de Math kütüphanesini kullanıyorum. Bu problemde “Math.pow(x, y)” kullanacağız.
Problem Beklentisi
Input olarak 3 integer değer aınacak: a, b ve n. Bu üç integer ile aşağıdaki seri oluşturulacak:
Bu seriyi kaç defa oluşturacağını sormak için ilk başta alınan input query sayısını verecek. Yani ilk başta 2 girildiyse 2 defa 3 tane integer girilecek, 2 defa bu seri oluşturulacak. Girilen integer değerleri için şartlar:
Çıktı olarak her bir seri farklı bir satırda olacak, seri elemanlarının arasında bir boşluk olacak.
Örnek Input:
2
0 2 10
5 3 5
Örnek Output:
2 6 14 30 62 126 254 510 1022 2046
8 14 26 50 98
Inputta ilk girilen 2 değeri 2 defa seri oluşturacağımızı belirledi. Sonrasında iki farklı seri oluşturmak için 3'er integer aldık.
Birinci seri oluşurken:
a=0, b=2, n=10
- s0: 0+2^0*2 = 2
- s1: 0+2⁰*2+2¹*2 = 6
- s2: 0+2⁰*2+2¹*2+2²*2 =14
- …
- s9: 0+2⁰*2+2¹*2+2²*2+2³*2+…+2⁹*2=2046
şeklinde çözümleyebiliriz.
Problem Çözümü
Problem çözümünde HackerRank tarafından Scanner yapısı sağlanmış bizim yapmamız gereken döngü içerisine kodlarımızı eklemek:
İlk çözümümüz aşağıdaki şekilde:
public static void solutionOne() {
Scanner in = new Scanner(System.in);
int t = in.nextInt();
for (int i = 0; i < t; i++) {
int a = in.nextInt();
int b = in.nextInt();
int n = in.nextInt();
int result = a;
for (int j = 0; j < n; j++) {
result += (int) (Math.pow(2, j) * b);
System.out.print(result + " ");
}
System.out.println();
}
in.close();
}
Query sayısı kadar (t) dönen döngü içine bir döngü daha ekliyoruz. Bu döngü de n kadar dönüyor. Sonuçları yazdığımız değişkenin (result) default değeri a (serimiz a’ya toplayarak başladığı için). Döngü içerisinde result değişkeninin üzerine toplama yapılırp print ediliyor. Üzerine toplama yaparken Math kütüphanesinin pow() metodu kullanılıyor. Döngüden çıkıldığında yeni satıra geçmesi amacıyla boş println ekliyoruz.
Bu problem çözümü aslında basit ve kısa oldu ama complexity baktığımızda O(n^2) olmasının önüne geçemedik. Sabit tanımda query sayısından dolayı O(n) complexity vardı, ikinci yazdığımız for döngüsü daha da süreyi uzattı. Bu problemde çok fazla girdi olmadığı için sürenin yavaşlamasını hissetmeyeceğiz ama ProjectEuler gibi platformlardan zor problem çözerseniz O(n^2) size kafa yaktırabilir :D
İkinci çözümümüzde, tüm işlemleri for döngüsünün tanımına taşıyoruz. Bu işlem iyi bir pratik değil, sadece olasılığının olduğunu göstermek amaçlı:
public static void solutionTwo() {
Scanner in = new Scanner(System.in);
int t = in.nextInt();
for (int i = 0; i < t; i++) {
int a = in.nextInt();
int b = in.nextInt();
int n = in.nextInt();
for (int j = 0, k = 1, e = a + k * b; j < n; ++j, k *= 2, e += k * b) {
System.out.print(e + " ");
}
System.out.println();
}
in.close();
}
Her şeyin for tanımında olması bana çok karmaşık görünüyor. Uzun vadede koda tekrar baksam “Burada ne yapmışım?” diye düşüneceğime eminim. Bu problem çok karmaşık olmadığı için anlamak uzun sürmeyecektir. Ama gerçek hayatta yazdığımız kodlarda bu şekilde bir çok harfin yan yana geldiği uzun uzadıya giden for döngüsü tanımların rica ederim kaçının :) Vallahi hem size hem de sizden sonra okuyana zor :D
“ Java Loops II” problemini de çözmüş olduk! Bol kodlu ama bug’sız günler dilerim :)
Tüm problemlerin çözümleri 👇