sayfa başı

10 Mart 2019 Pazar

C Çalışma Soruları – 24 (tam kare)

Necati Ergin Hocamın kendi sayfasında bulunan çalışma sorularını ve cevaplarını burada yanıtlamaya çalıştım. Sorulara buradan ulaşabilirsiniz.
Bir tamsayının tam kare olup olmadığını sınayan is_perfect_square isimli işlevi tanımlayınız:
int is_perfect_square(int val);
İşlevimiz kendisine gönderilen tamsayı tam kare ise sıfır dışı bir değere aksi halde 0 değerine geri dönmeli. Bu soruda yazdığınız işlevin doğru olmasının yanı sıra verimliliği de önem taşıyor.
Yanıt:

İlk çözüm olarak aklımıza döngü içinde her adımda yapmak gelebilir. Aslında bu bir çözüm ama verimli bir kod olmuyor, o yüzden geçersiz bir çözüm. Merak edenler için kod aşağıda.

#include <stdio.h>

int main()
{
    int i;
    int num;
    
    printf("Enter a number: ");
    scanf("%d", &num);
    
    for(i = 0; i <= num; i++)
    {
        if (num == (i * i))
        {
            printf("%d Perfect Square", num);
            return 0;
        }
    }
    
    printf("NO !!");
    return 0;
}

math.h başlık dosyasında olan sqrt() fonk kullanmak çözüm için doğru yol. Bir tam kare sayının karekökü bir tam sayıdır. O zaman bir sayının karekökü tam sayı mı değil mi bilgisine ulaşır isek sorunun çözümüne de ulaşmış olacağı. Bunun için tür dönüşümü özelliğinden faydalanacağı. Sayının karekökünü bir float sayıyı yükleyeceğiz ve ardından bu değeri bir int sayıya atayacağız. Eğer sayının karekökü tam sayı ise float sayıdan int sayıya değer atamada değer kaybı olamayacaktır. Bu sayede sonuca da ulaşmış olacağız. Örnek geçerli çözüm kodu aşağıdadır.
#include <stdio.h>
#include <math.h>

int main()
{
    float fSqr;
    int iSqr;
    int num;
    
    printf("Enter a number: ");
    scanf("%d", &num);
    
    fSqr = sqrt(num);
    
    iSqr = fSqr;
    
    if ((iSqr*iSqr) == num)
    {
        printf("%d Perfect Square", num);
        return 0;        
    }

    printf("NO !!");
    return 0;
}



4 Mart 2019 Pazartesi

C Çalışma Soruları – 23 (basamaksal kök)

Necati Ergin Hocamın kendi sayfasında bulunan çalışma sorularını ve cevaplarını burada yanıtlamaya çalıştım. Sorulara buradan ulaşabilirsiniz.
Bir tamsayının basamaksal kökünü (digital root) bulan get_digital_root  isimli işlevi tanımlayınız:

   int get_digital_root(int val);
Bir tamsayının basamaksal kökü tüm basamaklarının toplanması ile elde edilen tamsayıdır. Basamakları toplama, tek basamaklı bir sayı elde edilene kadar sürdürülür.  Örneğin 34879 sayısının basamaksal kökü 4‘dür:
34879 -> 3 + 4 + 8 + 7 + 9 = 31
31 -> 3 + 1 = 4

Yanıt:
34879 örnek sayısının basamaklarını toplamının ilk adımda 31 olduğu ve aynı işlemin tekrar yapılması gerektiğini gördük. Sorunun çözümünü düşünürken bu durum bir döngü yapısını çağrıştırıyor.

#include <stdio.h>
#include <stdlib.h>


int sumDigitalRoot(int num)
{
    int sum = 0;
    
    while (num > 0)
    {
        sum += num % 10;
        
        num = num/10;        
    }
        
    return sum; 
}

int get_digital_root(int val)
{
    int result = val;
    
    while((result = sumDigitalRoot(result)) > 9);
    
  /*  
    while (1)
    {
        result = sumDigitalRoot(result);
        
        if(result < 9)
        {
            break;
        }
    } 
   */ 
    return result;       
}

int main()
{
    printf("Result: %d", get_digital_root(34879));
    return 0;
}

C Çalışma Soruları – 22 (factorion sayıları)

Necati Ergin Hocamın kendi sayfasında bulunan çalışma sorularını ve cevaplarını burada yanıtlamaya çalıştım. Sorulara buradan ulaşabilirsiniz.


Sayma sayılarında 10’luk sayı sisteminde yalnızca 4 tane factorion sayı var. İyi ama factorion sayı ne demek? Basamaklarının faktöriyelleri toplamı kendisine eşit olan sayıya “factorion” deniyor. Örneğin abc tamsayısı eğer bir factorion ise

   abc = a! + b! + c!
eşitliğinin doğru olması gerekiyor. İlk iki factorion sayının 1 ve 2 olduğu açık. Diğer iki factorion sayıyı da bir C programı yazarak siz bulun. Bir ipucu olarak her iki sayının da 100.000‘den küçük olduğunu söyleyelim.
Yanıt:
Necati Hoca bu sorunun cevabını vermiş.  Blog da tüm çözümler bulunması için bende burada Necati Hoca’nın çözümünü kullandım.


#include <stdio.h>
 
int is_factorion(int val) 
{
    static const int a_facts[] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 };
    int sum = 0;
    int temp = val;

    while (temp)
    {
        sum += a_facts[temp % 10];
        temp /= 10;
        if (sum > val)
           return 0;
    }
    return sum == val;
}
 
int main()
{
    int k;
    
    for (k = 3; k < 100000; ++k)
        if (is_factorion(k))
           printf("%d ", k);
 
    return 0;
}

26 Şubat 2019 Salı

C Çalışma Soruları – 21 (göstericiler)

Necati Ergin Hocamın kendi sayfasında bulunan çalışma sorularını ve cevaplarını burada yanıtlamaya çalıştım. Sorulara buradan ulaşabilirsiniz.


Aşağıdaki C programı çalıştırıldığında bu programın çıktısı ne olur?

#include <stdio.h>
 
int main()
{
    int a[4] = { 2, 0, 3, 1};
    int i;
    
    ++2[a][a][a][a];
    
    for (i = 0; i < 4; ++i)
        printf("%d ", a[i]);
 
    return 0;
}

Yanıt:
++2[a][a][a][a]; satırı her ne kadar göze karışık ve zor görünsede aslında göstericilerde içeriğe ulaşma kurallarını göz önüne alınca oldukça basitleşiyor. Çözümü anlamak için aşağıdaki kod parçasına bakalım.
int a[4] = { 2, 0, 3, 1};
printf(" %d  %d %d \n\n", 1[a], *(a+1), a[1]);  //çıktısı 0 0 0
printf(" %d  %d %d \n\n", 2[a], *(a+2), a[2]);  //çıktısı 3 3 3

Gördüğünüz gibi 1[a] ile a[1] aynı sonuçları gösteriyor. Kısaca a dizisinin 1. Indeksli elemanına ulaşltık.
++2[a][a][a][a]; satırını yukarıdaki bilgiler ile soldan sağa doğru çözümleyelim. ++a[2][a][a][a]; şeklinde gösterebiliriz. a[2] değeri 3 olur ve ++3[a][a][a]; şekline dönüşür. ++a[3][a][a]; şeklinde tekrar dönüştürebiliriz ve a[3] değeri 1 olur. ++1[a][a]; bir sonraki dönüşümü ++0[a]; olur son adımda ++a[0]; ulaşmış oluruz ve bu da a nın 0. Indeksteki elemanının değerini bir arttırır. Sonuç olarak a dizisinin son hali { 3, 0, 3, 1} olur ve bu da programın çıktısıdır.

C Çalışma Soruları – 20 (göstericiler)

Necati Ergin Hocamın kendi sayfasında bulunan çalışma sorularını ve cevaplarını burada yanıtlamaya çalıştım. Sorulara buradan ulaşabilirsiniz.

Aşağıdaki C programı çalıştırıldığında bu programın çıktısı ne olur?

#include <stdio.h>
 
int main()
{
    int a[5] = { -1, 3, 2, -2, 0};
    int *p = a + 3;
    int i;
    
    a[p[*p]]++;
    a[p[*p]]++;

    for (i = 0; i < 5; ++i)
        printf("%d ", a[i]);
        
    return 0;
}

Yanıt:
Sorunun yanıtına geçmeden önce *p ile p[0] aynı sonuçlar ürettiğini bilmek gerekir. Yani bu iki yöntemle pointer içeriğine ulaşabiliriz. Aşağıdaki iki satır koşulur ise aynı çıktıyı ürettiğini göreceksiniz.
   printf(" %d \n", p[0]);
   printf(" %d \n", *p);
Yukarıdaki temel bilgiler ile p[2] nin ne anlama geldiğini görebiliriz. p taşıdığı adresten, taşıdığı tür adresi biçiminde 2 adres ilerle ve içeriğini al manasına gelir.(p nin adresi değişmez.) Sorunun çözümüne geçelim.
a[p[*p]]++; ilk satırda *p, -2 değerini üretir. a[p[-2]]++; şekline döner. p[-2] demek p nin taşıdığı adresten 2 adres geri gel ve içeriğini al demektir. p nin taşıdığı adres a+3 olduğu için 2 gerisi a+1 olur ve içeriği de 3 olur. Bu durumda a[3]++;  şekline döner. Bu işlem sonucunda a nın 3. endeksli elemanı olan -2 ulaşıp değerini bir arttırmış oluruz ve -1 olur. Dizinin yeni hali aşağıdaki gibi olur.
{ -1, 3, 2, -1, 0}
Kodun geri kalanındaki a[p[*p]]++; kısmını da yukarıdaki açıklamalar doğrultusunda işlersek dizinin son hali { -1, 3, 3, -1, 0} olur ve çıktı olarak bu dizi elemanlarını alırız.

C Çalışma Soruları – 18 (işleçler)

Necati Ergin Hocamın kendi sayfasında bulunan çalışma sorularını ve cevaplarını burada yanıtlamaya çalıştım. Sorulara buradan ulaşabilirsiniz.

Aşağıdaki C programı çalıştırıldığında bu programın çıktısı ne olur?
#include <stdio.h>
 
int main()
{
    int a = 11;

    if (10 < --a < 20)
       printf("%d", --a);
    else
        printf("%d", ++a);

    return 0;
}

Yanıt:
< operatöründe işlem soldan sağa doğrudur. Bu bilgi ile if koşulunu daha anlaşılır hale getirebiliriz.
if ((10 < --a) < 20) dönüşümünden sonra çözüme geçebiliriz.  (10 < --a) sonucu 0 olur.(a’nın değeri 10 oldu.) Bu adımdan sonra  if (0 < 20) koşuluna dönüşür ve sonuç 1 olacağından if bloğu çalışır. If bloğunda bulunan printf içinde de --a işlemi ile a’nın değeri 1 azaltılır ve çıktı olarak 9 değerini görürüz.

25 Şubat 2019 Pazartesi

C Çalışma Soruları – 17 (döngü deyimleri)

Necati Ergin Hocamın kendi sayfasında bulunan çalışma sorularını ve cevaplarını burada yanıtlamaya çalıştım. Sorulara buradan ulaşabilirsiniz.

Aşağıdaki C programı çalıştırıldığında bu programın çıktısı ne olur?
#include <stdio.h>
 
int main()
{
    int x = 1;
    
    while (x-- >= 1)
        while (x-- >= 0);
            printf("%d", x);
            
    return 0;
}

Yanıt:
Soruda ikinci while satırı sonunda noktalı virgül olduğunu görmek gerekir. Bu durumda printf fonksiyonu while döngülerinin dışındadır. While döngüleri bittikten sonra printf fonksiyonu çağrılır.
sağ taraf -- operatörü kullanıldığı için koşul içinde o anki x’in deri kullanılır ve daha sonra bir azaltılır. Ayrıca döngü koşulu sınanması için ilk olarak -- işleminin gerçekleşmesi gerekir. Koşul bu işlemden sonra sınanır. Her while döngüsünde -- işlemi iki defa gerçekleşir ve sonuç -3 olur.
Daha iyi anlamak için aşağıdaki kod parçası koşulabilir. While koşulu x in ilk değeri için bile sa
ğlamazken koşul şartına gelmeden önce -- işlemi gerçekleşir ve sonuç 0 olur.

   int x = 1;    
   while (x-- >= 100);
        printf("%d", x) ;