Forum: Ders Arası RSS
Problem çözümleri eksik olan dersler
Sayfa:  1  2  sonraki 
acehreli (Moderatör) #1
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: Problem çözümleri eksik olan dersler
Problem çözümlerini vermediğim 6 ders kalmış:

  http://ddili.org/ders/d/siniflar.html
  http://ddili.org/ders/d/tureme.html
  http://ddili.org/ders/d/object.html
  http://ddili.org/ders/d/gostergeler.html
  http://ddili.org/ders/d/bit_islemleri.html
  http://ddili.org/ders/d/foreach_opapply.html

Çok mu kolay? Çok mu zor? Ne oluyor? Deneyen var mı? :)

Ali
canalpay (Moderatör) #2
Kullanıcı başlığı: Can Alpay Çiftçi
Üye Tem 2009 tarihinden beri · 1133 mesaj · Konum: İzmir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Bana zor gibi geldi :-)

Sırasıyla yanıtlamaya başlayayım:
Sınıflarla ilgili soruların bana göre yanıtları :

1. Soru : sayılar ve çiftler dizinide aynı nesneye erişim sağlıyor. Burada çiftler sayıların dilimi.
(Ayrıca sınıflar referans olduğu için foreach ile değerleri değiştirilebiliyor.)

2. Artık aynı nesneye değil farklı nesneye erişim sağlıyor. Burada çiftler sayıların dilimi değil.

3. Yapılar sınıflar gibi referans değil. Bu yüzden kopyaya erişiyor ve kopyayı değiştiriyor.


Yanıtlardan emin değilim :-)  Hocam sorular zordu B kitapçığı daha kolay idi :-p

Şimdi Türemeye bakayım :
1.sorunun istediği kodu yazdım çok eğlenceli idi :-) :
import std.cstream;
 
class DemirYoluAracı
{
    void ilerle(in int kilometre)
    {
        dout.writef(kilometre, " kilometre: ");
 
        foreach (i; 0 .. kilometre) {
            dout.writef(ses(), ' ');
        }
 
        dout.writefln();
    }
    abstract string ses();
}
 
class Drezin : DemirYoluAracı
{
    override string ses()
    {
        return "of puf";
    }
}
class Vagon: DemirYoluAracı
{
    override string ses()
    {
        return "takıtak tukutak";
    }
}
class Lokomotif: DemirYoluAracı
{
    override string ses()
    {
        return "çuf çuf";
    }
}
 
void main()
{
    auto drezin = new Drezin;
    drezin.ilerle(2);
 
    auto vagon = new Vagon;
    vagon.ilerle(3);
 
    auto lokomotif = new Lokomotif;
    lokomotif.ilerle(4);
}

2.Soru void main() şu hale gelirse iş çözülür :
 
 
void main()
{
    auto lokomotif = new Lokomotif;
    auto tren = new YolcuTreni;
    tren.lokomotif=lokomotif;
    tren.ilerle(1);
 
}

Yada sizin problemde verdiğiniz fikri uygulamazsak yine çözülür. İlk sizin verdiğiniz fikri uygulamadım baktım parçalama arızası vermiyor :-D Ondan sonra anladım ki sizin verdiğiniz fikirden gitmek gerekiyorki hatayı alalım ve hatayı düzeltelim:

Bu arada sizin bütün kodları vermemişsiniz. Derslerden topladım kodları çok oldu :-)

Diğer mesajda diğerlerine bakarım.
acehreli (Moderatör) #3
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Teşekküüür! :)

canalpay:
1. Soru : sayılar ve çiftler dizinide aynı nesneye erişim sağlıyor. Burada çiftler sayıların dilimi.

Doğru.

(Ayrıca sınıflar referans olduğu için foreach ile değerleri değiştirilebiliyor.)

Doğru!

2. Artık aynı nesneye değil farklı nesneye erişim sağlıyor.

Evet.

(Kolaylık olsun diye, şuradaki 2 numaralı problemle ilgili konuşuyoruz: http://ddili.org/ders/d/siniflar.html)

İkinci foreach içinde

eleman = new Sayı(uniform(0, 20));

yazınca, eleman o noktada yeni bir Sayı nesnesine erişim sağlamaya başlıyor. Bu eleman'ın yaşamı çok kısa: yaşamı, döngünün kapama parantezinde son buluyor.

Burada çiftler sayıların dilimi değil.

Aslında çiftler yine de aynı; onda bir değişiklik olmuyor. eleman, foreach içinde önce o dilimin bir elemanı ile aynı nesneyi gösterirken, biz eleman'ı yepyeni bir nesneyi göstermesini sağlayarak onun çiftler'le ilişkisini kesiyoruz.

3. Yapılar sınıflar gibi referans değil. Bu yüzden kopyaya erişiyor ve kopyayı değiştiriyor.

Doğru.

Yanıtlardan emin değilim :-)  Hocam sorular zordu B kitapçığı daha kolay idi :-p

D kitapçığı bile gelse yine de doğru yanıtlardın! ;)

Şimdi Türemeye bakayım :
1.sorunun istediği kodu yazdım çok eğlenceli idi :-) :

Sevindim! :) Benim en eğlendiğim problem mors kodu ile ilgili olandı. İşlevler dersinin

  http://ddili.org/ders/d/islevler.html

2 numaralı sorusunun yanıtında şöyle bir tablo var: :D

string morsKarşılığı(char harf)
{
    string[char] morsAlfabesi =
    [
        ' ' : boşluk() ~ boşluk(),
        'a' : dıt()   ~ dıııt(),
        'b' : dıııt() ~ dıt()   ~ dıt()   ~ dıt(),
        'c' : dıııt() ~ dıt()   ~ dıııt() ~ dıt(),
        // ... 

Benim hoşuma gitmişti... :)

2.Soru void main() şu hale gelirse iş çözülür :

Yine kolaylık olsun diye, şimdi de şu dersin

  http://ddili.org/ders/d/tureme.html

2 numaralı problemiyle ilgili konuşuyoruz.

 
 
void main()
{
    auto lokomotif = new Lokomotif;
    auto tren = new YolcuTreni;
    tren.lokomotif=lokomotif;
    tren.ilerle(1);
 
}

Doğru.

Sorun, Tren'in lokomotif üyesini ilklenmemiş, yani null olarak bırakmaktı. Aslında Tren'e bir kurucu işlev eklemek daha iyi olur:

class Tren : DemirYoluAracı
{
// ...
    this()
    {
        lokomotif = new Lokomotif;
    }
// ...
}

Böylece hem başka zamanlarda da unutulması önlenmiş olur, hem de kullanımı daha kolay olur.

Diğer mesajda diğerlerine bakarım.

Teşekkür! :)

Ali
canalpay (Moderatör) #4
Kullanıcı başlığı: Can Alpay Çiftçi
Üye Tem 2009 tarihinden beri · 1133 mesaj · Konum: İzmir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
En baştan problemleri çözmeye başlayacağım.

Zaten geriye kalan çözümsüz problemleri çok çözmek istemiyorum. Bit işlemleri matematiktede çok az mantık adıyla görmüştük sanırım. Hiç sevmem :-) Düşük almıştım :-p  (Programlama dilinden olayları bildiğim halde :-p )

Göstergeler. Çözebilirim ama göstergeleride sevemedim :-)  Özellikle işlev göstergeleri ve kapamalar.  Dersi okudum ama pek anlayamadım. Ve ikinci kez dersi bile okuyamıyorum. Yarısında sıkılıyorum. Onlar için örnek kodlara bakarak anlamam gerekir herhalde.

Diğerleri zaten işleç yükleme ile ilgili ve gidiciler :-)

İlk çözüme sizin sevdiğiniz sorudan başlayacağım.
canalpay (Moderatör) #5
Kullanıcı başlığı: Can Alpay Çiftçi
Üye Tem 2009 tarihinden beri · 1133 mesaj · Konum: İzmir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Object dersinin sorularını çözüyorum :

1. Soru :
 
void main()
{
enum Renk { mavi, yeşil, kırmızı };
 
class Nokta
{
    int x;
    int y;
    Renk renk;
 
    this(int x, int y, Renk renk)
    {
        this.x = x;
        this.y = y;
        this.renk = renk;
    }
    
    override bool opEquals(Object o)const
    {
        auto sağdaki = cast(const Nokta)o;
        return((x == sağdaki.x)&&(y == sağdaki.y));
    }
}
 
    // Renkleri farklı
    auto maviNokta = new Nokta(1, 2, Renk.mavi);
    auto yeşilNokta = new Nokta(1, 2, Renk.yeşil);
 
    // Yine de eşitler
    assert(maviNokta == yeşilNokta);
 
}


2.Soru :

void main()
{
enum Renk { mavi, yeşil, kırmızı };
 
class Nokta
{
    int x;
    int y;
    Renk renk;
 
    this(int x, int y, Renk renk)
    {
        this.x = x;
        this.y = y;
        this.renk = renk;
    }
    override int opCmp(Object o)const
    {
        auto sağdaki = cast(const Nokta)o;
        if(x != sağdaki.x ) {
            return x - sağdaki.x;
        } else {
            if ( y != sağdaki.y ) {
                return y - sağdaki.y;
            } else {
                return 0;
            }
        }
    }
 
 
 
}
 
    auto maviNokta = new Nokta(1, 2, Renk.mavi);
    auto yeşilNokta = new Nokta(1, 2, Renk.yeşil); //Gereksiz.
 
 
    auto kırmızıNokta1 = new Nokta(-1, 10, Renk.kırmızı);
    auto kırmızıNokta2 = new Nokta(-2, 10, Renk.kırmızı);
    auto kırmızıNokta3 = new Nokta(-27, Renk.kırmızı);
 
    assert(kırmızıNokta2 < maviNokta);
    assert(kırmızıNokta3 < kırmızıNokta2);
}

3.Soruyu daha çözemedim. Geldiğim yer :

void main()
{
        enum Renk { mavi, yeşil, kırmızı };
 
    class Nokta
    {
        int x;
        int y;
        Renk renk;
 
        this(int x, int y, Renk renk)
        {
            this.x = x;
            this.y = y;
            this.renk = renk;
        }
        override int opCmp(Object o)const
        {
            auto sağdaki = cast(const Nokta)o;
            if(x != sağdaki.x ) {
                return x - sağdaki.x;
            } else {
                if ( y != sağdaki.y ) {
                    return y - sağdaki.y;
                } else {
                    return 0;
                }
            }
        }
        
        override bool opEquals(Object o) const
        {
            auto sağdaki = cast(const Nokta)o;
 
            return ((x == sağdaki.x)
                    &&
                    (y == sağdaki.y));
        }
 
 
 
    }
    auto maviNokta = new Nokta(1, 2, Renk.mavi);
    auto yeşilNokta = new Nokta(1, 2, Renk.yeşil); 
    auto kırmızıNokta = new Nokta(1,2, Renk.kırmızı);
 
 
    
    class ÜçgenBölge
    {
        Nokta[3] noktalar;
 
        this(Nokta bir, Nokta iki, Nokta üç)
        {
            noktalar = [ bir, iki, üç ];
        }
        
        override bool opEquals(Object o) const
        {
            auto sağdaki = cast(const ÜçgenBölge)o;
 
            return ((noktalar[0] == sağdaki.noktalar[0])
                    &&
                    (noktalar[1] == sağdaki.noktalar[1])
                    &&
                    (noktalar[2] == sağdaki.noktalar[2] ));
        }
        
        override int opCmp(Object o) const
        
        {
            auto sağdaki = cast(const ÜçgenBölge)o;
            if ( noktalar[0] != sağdaki.noktalar[0]) {
                
                if (noktalar[0] > sağdaki.noktalar[0]) {
                    
                    return 5;
                    
                } else {
                    
                    return -5;
                    
                }
                
            } else {
                if( noktalar[1] != noktalar[1] ) {
                    
                    if (noktalar[1] > sağdaki.noktalar[1]) {
                    
                        return 5;
                    
                    } else {
                    
                        return -5;
                    
                    }
                    
                } else {
                    if( noktalar[2] != sağdaki.noktalar[2] ) {
                        
                        if (noktalar[2] > sağdaki.noktalar[2]) {
                            
                            return 5;
                            
                        } else {
                            
                            return -5;
                            
                        }
                        
                    } else {
                        return 0;
                    }
                }
            }
 
        }
 
        override hash_t toHash() const
        {
            // Yanlış buraya ne gelecek ki ? return noktalar[0] + noktalar[1] + noktalar[2];
        }
        
    }
 
}


Bu arada başka bir sorum daha var : opCmp işleç yüklemesini tanımlarken opEquals işleç yüklemesinide tanımlamak gerekiyor diyor derste. Ama ben tanımlamadan derleyebiliyorum.
acehreli (Moderatör) #6
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
canalpay:
1. Soru

Doğru. (Ama fazla kolaydı tabii... :p)

2.Soru :

    override int opCmp(Object o)const
    {
        auto sağdaki = cast(const Nokta)o;
        if(x != sağdaki.x ) {
            return x - sağdaki.x;
        } else {
            if ( y != sağdaki.y ) {
                return y - sağdaki.y;
            } else {
                return 0;
            }
        }
    }

Ben de aynısını ?: işleciyle daha kısa yazmışım:

    override const int opCmp(Object o)
    {
        auto sağdaki = cast(const Nokta)o;
 
        return (x != sağdaki.x
                ? x - sağdaki.x
                : y - sağdaki.y);
    }

Anlaşılan, o sıralarda const'ı işlev parametrelerinden sonra yazmaya karar vermemişim daha. Artık seninki gibi yazıyorum ama ondan önce kesin bir boşluk bırakırım. ;)

3.Soruyu daha çözemedim. Geldiğim yer :

void main()
{
        enum Renk { mavi, yeşil, kırmızı };
 
    class Nokta
    {

Bir şeye dikkat ettim: sen türleri main'in içinde tanımlamışsın. Zararı yok ve D buna izin veriyor ama normalde işlevlerin dışında tanımlanır. Eğer bir tür yalnızca tek işlev içinde kullanılacaksa, yani o kadar yerelse, o zaman tek işlevin içinde tanımlandığı da olur.

    class ÜçgenBölge
    {
        Nokta[3] noktalar;
 
        this(Nokta bir, Nokta iki, Nokta üç)
        {
            noktalar = [ bir, iki, üç ];
        }
        
        override bool opEquals(Object o) const
        {
            auto sağdaki = cast(const ÜçgenBölge)o;
 
            return ((noktalar[0] == sağdaki.noktalar[0])
                    &&
                    (noktalar[1] == sağdaki.noktalar[1])
                    &&
                    (noktalar[2] == sağdaki.noktalar[2] ));
        }

Ben, sabit uzunluklu dizilerin bir özelliğinden yararlanmışım:

    override const bool opEquals(Object o)
    {
        auto sağdaki = cast(const ÜçgenBölge)o;
        return noktalar == sağdaki.noktalar;
    }

Sabit uzunluklu diziler değer türü oldukları için, yukarıdaki basit karşılaştırma çalışıyor.

        override int opCmp(Object o) const
        
        {
            auto sağdaki = cast(const ÜçgenBölge)o;
            if ( noktalar[0] != sağdaki.noktalar[0]) {
                
                if (noktalar[0] > sağdaki.noktalar[0]) {
                    
                    return 5;
                    
                } else {
                    
                    return -5;
                    
                }
                
            } else {
                if( noktalar[1] != noktalar[1] ) {
                    
                    if (noktalar[1] > sağdaki.noktalar[1]) {
                    
                        return 5;
                    
                    } else {
                    
                        return -5;
                    
                    }
                    
                } else {
                    if( noktalar[2] != sağdaki.noktalar[2] ) {
                        
                        if (noktalar[2] > sağdaki.noktalar[2]) {
                            
                            return 5;
                            
                        } else {
                            
                            return -5;
                            
                        }
                        
                    } else {
                        return 0;
                    }
                }
            }
 
        }

Benimki şöyleymiş:

    override const int opCmp(Object o)
    {
        auto sağdaki = cast(const ÜçgenBölge)o;
 
        foreach (i, nokta; noktalar) {
            const int karşılaştırma =
                nokta.opCmp(sağdaki.noktalar[i]);
 
            if (karşılaştırma != 0) {
                return karşılaştırma;
            }
        }
 
        return 0;
    }

 
        override hash_t toHash() const
        {
            // Yanlış buraya ne gelecek ki ? return noktalar[0] + noktalar[1] + noktalar[2];
        }
        
    }
 
}

Ben şöyle yapmışım:

    override const hash_t toHash()
    {
        return typeid(noktalar).getHash(&noktalar);
    }

Ama şimdi bir şüphem var! Çünkü derleyicinin değer türleri için kullandığı getHash, nesnelerin bütün bitlerini göze alır. Oysa ben renkleri göz ardı etmek istemiştim. Sanırım benim yazdığım doğru olmaz.

opCmp işleç yüklemesini tanımlarken opEquals işleç yüklemesinide tanımlamak gerekiyor diyor derste. Ama ben tanımlamadan derleyebiliyorum.

O konu, programın doğruluğu ile ilgilidir. Tür için eşitlik, sıralama, veya hash hesabını bir kere kendimiz yazmaya başlamışsak; her üçünün birbirleriyle tutarlı olmalarını sağlamamız gerekir. Yoksa, o nesnelerin kullanıldığı algoritmalar yanlış çalışabilirler.

O yüzden, yukarıda benim yazdığım toHash'in doğru olup olmadığından şimdi emin değilim. opEquals ve opCmp renk'i gözardı ediyorlar ama derleyicinin yazdığı hash hesabı bunu bilmiyor.

Şimdi zamanım yok ama bunun doğru olup olmadığını öğrenip yazacağım. (Bana hatırlatın! :) )

Ali
canalpay (Moderatör) #7
Kullanıcı başlığı: Can Alpay Çiftçi
Üye Tem 2009 tarihinden beri · 1133 mesaj · Konum: İzmir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Şimdi zamanım yok ama bunun doğru olup olmadığını öğrenip yazacağım. (Bana hatırlatın! :) )

Tamam ben hatırlatırım :-)

Göstergeye gelince daha ilk soruda tıkandım. Derside okumak istemiyorum.
canalpay (Moderatör) #8
Kullanıcı başlığı: Can Alpay Çiftçi
Üye Tem 2009 tarihinden beri · 1133 mesaj · Konum: İzmir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
foreach'te opApply'den birinci soruyu yaptım(Unutmamak için yazıyorum.) :

import std.stdio;
 
void main()
{
    foreach (sayı; Aralık(0, 10, 2)) {
        write(sayı, ' ');
    }
 
}
 
struct Aralık
{
    int baş;
    int son;
    int atlama;
    this(int baş, int son, int atlama)
    {
        this.baş = baş;
        this.son = son;
        this.atlama=atlama;
    }
 
 
    bool empty() const
    {
        // baş, son'a eşit olduğunda aralık tükenmiş demektir
        return baş == son;
    }
 
    void popFront()
    {
        baş+=2;
    }
 
    int front() const
    {
        // Aralığın başındaki değer, baş'ın kendisidir
        return baş;
    }
}

2.soruda delegate anahtar sözcüğünü görünce daha dersi okumadan bıraktım. Artık yarın yapamadığım tüm soruları yapmaya çalışırım.
acehreli (Moderatör) #9
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
canalpay:
        this.atlama=atlama;
//...
    void popFront()
    {
        baş+=2;
    }

Çok ufak bir hata: 2 yerine 'atlama' olacak tabii...

2.soruda delegate anahtar sözcüğünü görünce daha dersi okumadan bıraktım.

Bence foreach'in delegate ile kullanımı, D'nin en zor konularından birisi. Programcının yazdığı foreach bloğu ile sınıf içinde yazılan opApply'ın paslaşmaları filan çok zorlayıcı konular. :)

Bence o problem aslında çok güzel, çünkü foreach'i nasıl farklı parametrelerle kullanabildiğimizi öğretiyor.

Örneğin, bir eşleme tablosunda tek parametre kullanırsak değer oluyor; iki parametre kullanırsak indeks (veya 'anahtar') ve değer oluyor:

foreach (değer; tablo) {
    // ...
}
 
foreach (indeks, değer; tablo) {
    // ...
}

Ali
canalpay (Moderatör) #10
Kullanıcı başlığı: Can Alpay Çiftçi
Üye Tem 2009 tarihinden beri · 1133 mesaj · Konum: İzmir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Tamam ben hatırlatırım :-)

Hatırlatayım dedim :-) (http://ddili.org/forum/post/2264)
Sanırım doğru kodlamışsınız. Sizin toHash işlevinide ekledim ve soruda verilen assertleride ekledim ve hatasız çalıştı:

void main()
{
        enum Renk { mavi, yeşil, kırmızı };
 
    class Nokta
    {
        int x;
        int y;
        Renk renk;
 
        this(int x, int y, Renk renk)
        {
            this.x = x;
            this.y = y;
            this.renk = renk;
        }
        override int opCmp(Object o)const
        {
            auto sağdaki = cast(const Nokta)o;
            if(x != sağdaki.x ) {
                return x - sağdaki.x;
            } else {
                if ( y != sağdaki.y ) {
                    return y - sağdaki.y;
                } else {
                    return 0;
                }
            }
        }
        
        override bool opEquals(Object o) const
        {
            auto sağdaki = cast(const Nokta)o;
 
            return ((x == sağdaki.x)
                    &&
                    (y == sağdaki.y));
        }
 
 
 
    }
    auto maviNokta = new Nokta(1, 2, Renk.mavi);
    auto yeşilNokta = new Nokta(1, 2, Renk.yeşil); 
    auto kırmızıNokta = new Nokta(1,2, Renk.kırmızı);
 
 
    
    class ÜçgenBölge
    {
        Nokta[3] noktalar;
 
        this(Nokta bir, Nokta iki, Nokta üç)
        {
            noktalar = [ bir, iki, üç ];
        }
        
        override bool opEquals(Object o) const
        {
            auto sağdaki = cast(const ÜçgenBölge)o;
 
            return ((noktalar[0] == sağdaki.noktalar[0])
                    &&
                    (noktalar[1] == sağdaki.noktalar[1])
                    &&
                    (noktalar[2] == sağdaki.noktalar[2] ));
        }
        
    override const int opCmp(Object o)
    {
        auto sağdaki = cast(const ÜçgenBölge)o;
 
        foreach (i, nokta; noktalar) {
            const int karşılaştırma =
                nokta.opCmp(sağdaki.noktalar[i]);
 
            if (karşılaştırma != 0) {
                return karşılaştırma;
            }
        }
 
        return 0;
    }
 
    
 
        override hash_t toHash() const
        {
            return typeid(noktalar).getHash(&noktalar);
        }
        
    }
 
    
    auto kırmızıNokta1 = new Nokta(-1, 10, Renk.kırmızı);
    auto kırmızıNokta2 = new Nokta(-2, 10, Renk.kırmızı);
    auto kırmızıNokta3 = new Nokta(-27, Renk.kırmızı);
 
        /*
      Farklı ama aynı değerli noktalarla kuruluyorlar.
 
      Hatırlatma: maviNokta ve yeşilNokta değer olarak eşit
                  kabul ediliyorlardı.
    */
    auto bölge1 =
        new ÜçgenBölge(maviNokta, yeşilNokta, kırmızıNokta1);
    auto bölge2 =
        new ÜçgenBölge(yeşilNokta, maviNokta, kırmızıNokta1);
 
    // Yine de eşitler
    assert(bölge1 == bölge2);
 
    // Bir eşleme tablosu
    double[ÜçgenBölge] bölgeler;
 
    // bölge1 ile indeksleniyor
    bölgeler[bölge1] = 1.25;
 
    // bölge2 ile de aynı veriye erişiliyor
    assert(bölge2 in bölgeler);
    assert(bölgeler[bölge2] == 1.25);
 
}
acehreli (Moderatör) #11
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Evet, düşündüm ve benim yanıtımın yanlış olduğuna karar verdim. :)

ÜçgenBölge sınıfının toHash işlevi, noktaların bütün üyelerini göze alamaz. Ama yanlışlık aslında ÜçgenBölge'de değil. Yanlışlık, Nokta'nın toHash işlevinin bulunmamasından kaynaklanıyor. Çünkü eşitlik ve sıra karşılaştırmalarını tanımladığı halde onlarla uyumlu bir toHash işlevi tanımlamamış.

Bunu görmek için yukarıdaki kodlardan oluşan aşağıdaki programı yazdım. 'hatasız' isimli bir version bloğu var; program ancak onu etkinleştirince doğru çalışıyor:

import std.stdio;
import std.random;
import std.string;
import std.conv;
 
enum Renk { mavi, yeşil, kırmızı };
 
class Nokta
{
    int x;
    int y;
    Renk renk;
 
    this(int x, int y, Renk renk)
    {
        this.x = x;
        this.y = y;
        this.renk = renk;
    }
 
    override string toString() const
    {
        return format("(%s,%s,%s)", x, y, to!string(renk));
    }
 
    override const bool opEquals(Object o)
    {
        auto sağdaki = cast(const Nokta)o;
 
        return (x == sağdaki.x) && (y == sağdaki.y);
    }
 
    override const int opCmp(Object o)
    {
        auto sağdaki = cast(const Nokta)o;
 
        return (x != sağdaki.x
                ? x - sağdaki.x
                : y - sağdaki.y);
    }
 
    version (hatasız)
    {
    override const hash_t toHash()
    {
        return x + y;
    }
    } // version hatasız
}
 
class ÜçgenBölge
{
    Nokta[3] noktalar;
 
    this(Nokta bir, Nokta iki, Nokta üç)
    {
        noktalar = [ bir, iki, üç ];
    }
 
    override string toString() const
    {
        return format("%s", noktalar);
    }
 
    override const bool opEquals(Object o)
    {
        auto sağdaki = cast(const ÜçgenBölge)o;
        return noktalar == sağdaki.noktalar;
    }
 
    override const int opCmp(Object o)
    {
        auto sağdaki = cast(const ÜçgenBölge)o;
 
        foreach (i, nokta; noktalar) {
            const int karşılaştırma =
                nokta.opCmp(sağdaki.noktalar[i]);
 
            if (karşılaştırma != 0) {
                return karşılaştırma;
            }
        }
 
        return 0;
    }
 
    override const hash_t toHash()
    {
        return typeid(noktalar).getHash(&noktalar);
    }
}
 
Nokta merkezdeRenkliNokta()
{
    return new Nokta(0, 0, cast(Renk)uniform(0, Renk.max + 1));
}
 
ÜçgenBölge merkezdeÜçgenBölge()
{
    return new ÜçgenBölge(merkezdeRenkliNokta(),
                          merkezdeRenkliNokta(),
                          merkezdeRenkliNokta());
}
 
void main()
{
    int[ÜçgenBölge] tablo;
 
    /*
     * Tabloya aynı x ve y değerlerine sahip ama rastgele renkli noktalar
     * yerleştiriyoruz
     */
    foreach (sayaç; 0 .. 10) {
        auto bölge = merkezdeÜçgenBölge();
        tablo[bölge] = sayaç;
    }
 
    writeln("Bütün tablo:");
    foreach (indeks, değer; tablo) {
        writeln(indeks, ": ", değer);
    }
 
    /*
     * Rastgele renkli başka noktalar da hep tabloda çıkmalılar
     */
    foreach (sayaç; 0 .. 10) {
        assert(merkezdeÜçgenBölge() in tablo);
    }
}

O programı normal olarak derleyip çalıştırırsak çıktısı şöyle oluyor:

Bütün tablo:
[(0,0,mavi),(0,0,yeşil),(0,0,kırmızı)]: 0
[(0,0,yeşil),(0,0,yeşil),(0,0,mavi)]: 1
[(0,0,mavi),(0,0,yeşil),(0,0,kırmızı)]: 2
[(0,0,yeşil),(0,0,kırmızı),(0,0,yeşil)]: 3
[(0,0,yeşil),(0,0,kırmızı),(0,0,kırmızı)]: 4
[(0,0,mavi),(0,0,kırmızı),(0,0,mavi)]: 5
[(0,0,kırmızı),(0,0,yeşil),(0,0,mavi)]: 6
[(0,0,kırmızı),(0,0,mavi),(0,0,kırmızı)]: 7
[(0,0,kırmızı),(0,0,kırmızı),(0,0,kırmızı)]: 8
[(0,0,yeşil),(0,0,yeşil),(0,0,mavi)]: 9
core.exception.AssertError@deneme(16662): Assertion failure

Yani tabloya 10 farklı nesne yerleşmiş; yani yanlış olmuş. Çünkü renklerin önemsiz olmalarını istiyorduk.

Programı -version=hatasız seçeneğiyle derlersek, Noktalar'ın toHash işlevi de etkinleşiyor ve bu sefer tabloda tek bir eleman bulunuyor. Çünkü Noktalar'ın toHash işlevi, diğer ikisi gibi rengi gözardı edecek şekilde yazılmış:

$ dmd deneme.d -version=hatasız -w
$ ./deneme
Bütün tablo:
[(0,0,kırmızı),(0,0,kırmızı),(0,0,mavi)]: 9

Özet: bu üç özel işlevin birisi bile tanımlanmışsa, her üçünün de uyumlu olarak tanımlanmaları gerekir.

Ali
erdem (Moderatör) #12
Üye Tem 2009 tarihinden beri · 978 mesaj · Konum: Eskişehir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
http://ddili.org/ders/d/do_while.html

Aslında burada sayı dizisinin tam ortasındaki değer alınarak da yapılabilir belki ama ben bilgisayara da tahmin ettirdim :)

import std.stdio;
import std.random;
 
void main()
{
    int sayı = uniform (1, 100);
 
    writeln ("1'den 100'e kadar bir sayı tuttum!...");
 
    int tahmin;
    int altAralık = 1;
    int üstAralık = 100;
    
    
    do
    {
        writeln ("Tahmininiz nedir? ");
        
        tahmin = uniform (altAralık, üstAralık);
        if (tahmin == altAralık)
            tahmin +=1;
        write ("Bilgisayar: Tahmin ediyorum: ");
        writeln ("[", altAralık, " - ", üstAralık, " ]");
        writeln (tahmin);
        
 
        if (sayı < tahmin) {
            write ("Tuttuğum sayı daha küçük; ");
            üstAralık = tahmin;
                                    
        } else if (sayı > tahmin) {
            write ("Tuttuğum sayı daha büyük; ");
            
            if ((üstAralık > tahmin) && (altAralık < tahmin))
                altAralık = tahmin;
 
            else if ((üstAralık > tahmin) && (altAralık > tahmin)) 
                üstAralık = tahmin; 
            
        }
 
    } while (tahmin != sayı);
 
    writeln ("Buldun!");
    writeln ("Tuttuğum sayı ", sayı, " idi");
        
}
acehreli (Moderatör) #13
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Çok güzel. :) Bilgisayara akıllı işler yaptırmak her zaman zevkli oluyor. Paylaştığın için teşekkürler.

Söylediğin gibi: tahmin olarak orta değeri kullanmak en hızlısı olur. O zaman baştaki aralıkta N sayı varsa, en fazla log(N) denemede bulunur. (Yani 1024 değer için 10 deneme, 65536 için 16 deneme gibi.)

Notlar:

- altAralık yerine altDeğer gibi bir isim daha mı uygun olur acaba? Çünkü tek aralık ve iki sınır değer var.

- Alışık olduğum kodlama standartlarında işlevlerden sonra boşluk bırakılmıyor: writeln("a") ama parantezli deyimlerden sonra bırakılıyor: if (koşul). Hiç önemli değil tabii ama birisine alışınca hemen göze batıyor... :)

- uniform()'u daha doğal kullanabiliriz sanki. Herhalde uniform() ikinci parametre değerini seçmediği için tahmin'i bir arttırman gerekmiş, değil mi? (Yine de garip geliyor.) Bence şu kullanım daha doğal: uniform(altAralık, üstAralık + 1). Böylece hep yasal değerlerden seçer.

Not: Aslında uniform()'un şablon parametresi, işlev parametrelerinin aralığa dahil edilip edilmediğini belirleyebiliyor:

uniform!"()"(10, 20)    // seçtiği değerler: 11-19
uniform!"[)"(10, 20)    // seçtiği değerler: 10-19 (varsayılan davranış)
uniform!"(]"(10, 20)    // seçtiği değerler: 11-20
uniform!"[]"(10, 20)    // seçtiği değerler: 10-20 

- Belki de bir önceki konu nedeniyle else if (sayı > tahmin) bloğu sanki fazla karmaşık olmuş. altAralık = tahmin; yeterlidir herhalde, değil mi? Hmmm... Aslında altAralık = tahmin + 1 daha doğru olur; çünkü tahmin'in doğru olmadığını da biliyoruz (Aynı nedenle if (sayı < tahmin) bloğunda da üstAralık = tahmin - 1 olmalı)

- En son olarak, benim söylediklerimi uygulayınca şöyle pek de akıllıca olmayan davranışlar da olabiliyor: :)

...
Bilgisayar: Tahmin ediyorum: [32 - 32 ] <-- !
32
Buldun!
Tuttuğum sayı 32 idi


Ali
erdem (Moderatör) #14
Üye Tem 2009 tarihinden beri · 978 mesaj · Konum: Eskişehir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
acehreli:
- Alışık olduğum kodlama standartlarında işlevlerden sonra boşluk bırakılmıyor: writeln("a") ama parantezli deyimlerden sonra bırakılıyor: if (koşul). Hiç önemli değil tabii ama birisine alışınca hemen göze batıyor... :)

Aslında böyle inci gibi dizi dizi kod yazanlara hasta oluyorum :)

Ama bir türlü kendimi bir kodlama standardına adapte edemedim sanırım. Yukarda bahsettiğiniz boşluklara pek dikkat etmiyorum ama özellikle dizilerde illa bir boşluk bırakıyorum. Hatta bazı programlara tekrar boşluk koyduğum oldu :)

    auto bazıSayılar = [2, 3, 5, 7, 9, 11, 13, 15];
 
    auto dizi = new int [100];
    auto kopya = dizi.dup;

acehreli:
- uniform()'u daha doğal kullanabiliriz sanki. Herhalde uniform() ikinci parametre değerini seçmediği için tahmin'i bir arttırman gerekmiş, değil mi?

Aslında gene alttaki örneği düşünürsek varsayılan davranışla [10, 20) aralığında bazen bir kaç defa 10 tahmin edebiliyor.

acehreli:
uniform!"()"(10, 20)    // seçtiği değerler: 11-19
uniform!"[)"(10, 20)    // seçtiği değerler: 10-19 (varsayılan davranış) 
Benim istediğim ise (10, 20) aralığında birinci örnekteki gibi 11-19 arasından seçim yapması. Aslında dökümanlarına da baktım ama ya böyle bir örnek yoktu ya da ben görememiş olabilirim.

Yorumlar için teşekkürler :)
erdem (Moderatör) #15
Üye Tem 2009 tarihinden beri · 978 mesaj · Konum: Eskişehir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #3
acehreli on 2010-06-23, 09:30:
canalpay:
1. Soru : sayılar ve çiftler dizinide aynı nesneye erişim sağlıyor. Burada çiftler sayıların dilimi.

Doğru.

Ben de bu sınıflarla ilgili soruların çözümünü yapmaya çalıştım. Bana açıkça biraz karışık ve zor geldi :)
Hatta DigitalMars'ta sorulacak türden bir soru galiba. Kodu biraz daha basitleştirmeye çalıştım.
    Sayı[] sayılar = null;
    Sayı[] çiftler = null;
 
    auto sayı = new Sayı(0);
    sayılar ~= sayı;
    
    // referansı sayılar[0] da tutuyoruz
    assert(sayılar[0] is sayı);
 
    çiftler ~= sayı;
    assert((sayı is sayılar[0] && sayı is çiftler[0]));
 
    // burası biraz karışık gibi :(
    // şimdi yeni bir nesne oluşturduk ve ilk
    // referansımızı bu yeni nesneyi gösterecek şekilde değiştirdik
    // o zaman sayılar[0] ve çiftler[0]'da tutulan referansların
    // geçerli bir referans olduğunu söyleyebilirmiyiz
    
    sayı = new Sayı(1);
 
    
    swap(sayılar[0], çiftler[0]);
    // referansları yerdeğiştirsek bile her ikisi de aynı nesneyi
    // gösteriyor
    
    assert(sayılar !is çiftler); // bence bu çiftler sayıların dilimi değil
    assert(sayılar == çiftler)// ama içerikleri eşit şimdilik 
Benim buradan anladıklarım sayılar ve çiftler aslında nesneleri değil referansları tutuyor. Bana sanki gene çiftler sayılar'ın dilimi değil gibi geldi.

Bir de asıl önemli nokta sayı = new Sayı(1); dediğimizde sayılar[0] ve çiftler[0]'da kalan referansların geçerli bir referans olduklarını söyleyebilirmiyiz.

Bana burdaki işlem şu örnekteki gibi geliyor.
 class A {
    int x = 42;
}
 
unittest {
    auto a1 = new A;
    assert(a1.x == 42);
    auto a2 = a1;       // yeni bir A nesnesi oluşturulmaz sadece A nesnesi
                        // a2 tarafından da gösterilmeye başlanır
    assert(a1 is a2);   
    assert(a1 == a2);
    
    a2.x = 100;
    assert(a1.x == 100);
}

Yani dolaylı olarak bir nesneyi gösteren iki referans oluşmasına izin verdik. Ama böyle bir durumda örnekteki gibi beklenmeyen  bir şekilde referans değiştiği zaman uygulamanın bir yerinde olan sürpriz değişiklikler diğer tarafına da yansıyabilir.

Kısacası demek istediğim aslında aynı nesneyi gösteren birden fazla referans olmasına izin vermememiz gerekmiyor mu.

acehreli on 2010-06-23, 09:30:
2. Artık aynı nesneye değil farklı nesneye erişim sağlıyor.

Evet.

(Kolaylık olsun diye, şuradaki 2 numaralı problemle ilgili konuşuyoruz: http://ddili.org/ders/d/siniflar.html)

İkinci foreach içinde

eleman = new Sayı(uniform(0, 20));

yazınca, eleman o noktada yeni bir Sayı nesnesine erişim sağlamaya başlıyor. Bu eleman'ın yaşamı çok kısa: yaşamı, döngünün kapama parantezinde son buluyor.

Evet haklısınız. Ama burada yaptığımız aslında 21'inci 22'inci Sayı nesnelerini oluşturup sayılar dizisindeki referansların bu yeni nesneleri göstermesini sağlamak değil mi. Ama amacımız sayılar dizgisindeki değerleri çiftler dizgisindeki değerler değişmeden 5 arttırmak olsaydı sanırım kolay bir şekilde yapamazdık.

Dediğim gibi bu örnek bana hem biraz karışık, hem de derste anlatılanları tam pekiştiremiyor gibi geldi  :huh:

O yüzden daha ilginç ve daha basit bir örnekle değiştirilmesini öneriyorum :)

Teşekkürler..
Doğrulama Kodu: VeriCode Lütfen resimde gördüğünüz doğrulama kodunu girin:
İfadeler: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Özel Karakterler:
Sayfa:  1  2  sonraki 
Forum: Ders Arası RSS
Bağlı değilsiniz. · Şifremi unuttum · ÜYELİK
This board is powered by the Unclassified NewsBoard software, 20100516-dev, © 2003-10 by Yves Goergen
Şu an: 2017-11-19, 06:03:23 (UTC -08:00)