Forum: Ders Arası RSS
Baklava dilimi çizimi
hkntrt #1
Üye Nis 2012 tarihinden beri · 18 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: Baklava dilimi çizimi
Merhabalar :)
for döngüsünü bildiğime eminim daha doğrusu emindim ama derslerdeki baklava dilimi çizimi sorusu beni biraz zorladı.Acaba ben bu döngüyü mü bilmiyor dedim :) çok çaylakça birşeyler yazmaya çalıştım , asıl soru bundan başka nasıl çizilebilir daha kolay bir yol ?

import std.stdio;
 
void main () {
    for (int satır = 0 ; satır != 9 ; ++satır) {
        int uzunluk = satır + 1;
        for ( int i = satır ; i != 9 ; ++i) {
            write(" "); }
        for ( int yıldız = 0 ; yıldız != uzunluk ; ++yıldız ) {
            write("*"); }
        for ( int sag = 0 ; sag != uzunluk ; ++sag) {
            write("*");
            }writeln();}
            
    for (int satır = 0 ; satır != 9 ; ++satır) {
        int uzunluk = satır +1;
        for (int sol_alt = 0; sol_alt != uzunluk ; ++sol_alt) {
            write(" ");
        }
        for (int sol_alt_yıldız = 10 ; sol_alt_yıldız != uzunluk ; --sol_alt_yıldız) {
            write("*");
        }
        for (int sag_alt =10 ; sag_alt != uzunluk ; --sag_alt) {
            write("*");
        }writeln();}}

Çıktısı ise şöyle birşey oluyor :

         **
        ****
       ******
      ********
     **********
    ************
   **************
  ****************
 ******************
 ******************
  ****************
   **************
    ************
     **********
      ********
       ******
        ****
         **
acehreli (Moderatör) #2
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ı
Bana zor geldi. :) Yalnızca for döngüsünün kullanılabilmesi de olayı daha zorlaştırıyor.

Şu anda ilk aklıma gelen, satırı iki parça olarak düşünmek oldu: önce boşluk ve yıldızlar. Yıldızların uzunluğu artarken boşlukların uzunluğu azalıyor. Ne yazık ki pek temiz kod olmadı. Önce bu haliyle göstereyim sonra daha güzelleştiririz:
import std.stdio;
 
void main()
{
    int genişlik = 11;
    int boşlukUzunluğu = genişlik / 2;
    int yıldızUzunluğu = 1;
    bool ilkYarı_mı = true;
 
    for (int satır = 0; satır != genişlik; ++satır) {
        for (int i = 0; i != boşlukUzunluğu; ++i) {
            write(".");
        }
 
        for (int i = 0; i != yıldızUzunluğu; ++i) {
            write("*");
        }
 
        writeln();
 
        if (ilkYarı_mı) {
            --boşlukUzunluğu;
            yıldızUzunluğu += 2;
 
            if (boşlukUzunluğu == 0) {
                ilkYarı_mı = false;
            }
 
        } else {
            ++boşlukUzunluğu;
            yıldızUzunluğu -= 2;
        }
    }
}
Ali
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ı
Senin çözümünde ilk göze batan 9'un tekrarlanmış olması. Onun dışında bir sorun görünmüyor. :)

Ali
acehreli (Moderatör) #4
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ı
Bir tane de olabildiğince tembel aralıklarla yazmaya çalıştım:
import std.stdio;
import std.range;
import std.algorithm;
import std.conv;
import std.exception;
import std.string;
 
/*
 * Boşluk ve yıldız uzunluklarını hesaplayan bu iki işlev ilginç bir biçimde
 * birbirlerinden yararlanıyorlar. İlk yarıda yıldız uzunluğunu, ikinci yarıda
 * da boşluk uzunluğunu hesaplamak kolay.
 */
size_t yıldızUzunluğu(size_t genişlik, size_t satır)
in {
    assert(genişlik % 2);
    assert(satır < genişlik);
 
} out(sonuç) {
    assert(sonuç <= genişlik);
 
} body {
    if (satır <= (genişlik / 2)) {
        return (2 * satır) + 1;
 
    } else {
        return genişlik - (2 * boşlukUzunluğu(genişlik, satır));
    }
}
 
unittest
{
    assert(yıldızUzunluğu(3, 0) == 1);
    assert(yıldızUzunluğu(3, 1) == 3);
    assert(yıldızUzunluğu(3, 2) == 1);
}
 
size_t boşlukUzunluğu(size_t genişlik, size_t satır)
in {
    assert(genişlik % 2);
    assert(satır < genişlik);
 
} out(sonuç) {
    assert(sonuç <= genişlik);
 
} body {
    if (satır <= (genişlik / 2)) {
        return (genişlik - yıldızUzunluğu(genişlik, satır)) / 2;
 
    } else {
        return satır - (genişlik / 2);
    }
}
 
unittest
{
    assert(boşlukUzunluğu(11, 0) == 5);
    assert(boşlukUzunluğu(11, 5) == 0);
    assert(boşlukUzunluğu(11, 10) == 5);
}
 
auto baklavaDilimi(size_t genişlik)
{
    /* Not: Bu denetim yerine 'genişlik' çift olduğunda değerini bir azaltarak
     *      kendimiz tek sayı da elde edebilirdik.
     */
    enforce(
        genişlik % 2,
        format("Baklava dilimi genişliği çift sayı olamaz. (%s)", genişlik));
 
    /* Baklava dilimini üç parça halinde oluşturacağız:
     *
     * 1) İlk yarısı olan üçgeni oluşturan aralık
     * 2) Ortasındaki uzun satır
     * 3) İlk yarısının tersi olan üçgeni oluşturan aralık
     *
     * Not: Aşağıda üç yerde text kullanmak zorunda kalmış olmak canımı
     *      sıkıyor. Onların yerine tembel aralıklar kullanmayı
     *      beceremedim. (?)
     */
 
    auto ilkYarı = iota(genişlik / 2)
                   .map!(satır =>
                         ' '.repeat(boşlukUzunluğu(genişlik, satır)).text ~
                         '*'.repeat(yıldızUzunluğu(genişlik, satır)).text);
 
    auto uzunSatır = '*'.repeat(genişlik).text.only;
 
    auto sonYarı = ilkYarı.retro;
 
    return chain(ilkYarı, uzunSatır, sonYarı).joiner("\n");
}
 
void main()
{
    writeln(baklavaDilimi(11));
}
Ali
hkntrt #5
Üye Nis 2012 tarihinden beri · 18 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
çok teşekkür ederim @acehreli ,  ikinci yazdığınız kodu yazmak için benim daha çok yolum var gibi :)
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ı
hkntrt:
ikinci yazdığınız kodu yazmak için benim daha çok yolum var gibi :)

Ama öyle yazmaya hiç gerek yok ve zaten istediğim gibi de olamadı. (?) "print a diamond pattern" diye aratınca başka dillerde programlar da bulunuyor.

Ali
hkntrt #7
Üye Nis 2012 tarihinden beri · 18 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
acehreli:
Ama öyle yazmaya hiç gerek yok ve zaten istediğim gibi de olamadı. (?) "print a diamond pattern" diye aratınca başka dillerde programlar da bulunuyor.

Ali

Her zamanki gibi yine alçakgönüllüsünüz :)
acehreli (Moderatör) #8
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ı
Dlang haber gruplarında sordum. Bakalım başka ne çözümler gelecek:

  http://forum.dlang.org/thread/lgfmbf$v7c$1@digitalmars.com…

Ali
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ı
Dlang'daki konudan iki yöntem öğrendim:

1) Önce artan sonra azalan yıldız uzunluğunu sağlamak için chain ile birbirine bağlanmış iki iota aralığı kullanılabilir.

2) Boşlukları halletmek çok kolay: std.string modülündeki center verilen dizgiyi verilen genişlikte ortalıyor.

N genişliğindeki baklava dilimini şöyle oluşturabiliriz:

1) 1'den N'e kadar artan ve sonra N'den 1'e kadar azalan yıldız genişlikleri oluştur (iki iota'yı chain'le bağlayarak).

2) Her yıldız genişliği değeri için yıldız karakterini tekrarla (karakteri repeat ile tekrarlayarak).

3) Tekrarlanan karakterlerden dizgi oluştur (text ile).

4) Oluşturan dizgiyi satırda ortala (center ile).

Yukarıdaki işlemler bize tembel olarak işleyecek olan bir aralık verir. Bütün sonucu tek dizgi olarak baştan sunmamanın bir yararı hız başka bir yararı da satırları belki başka amaç için de kullanılabilmesidir.

Bu aralığı kendi amacımız için kullanmanın bir yolu, çıktı düzeninde "%(" ve "%)" gruplama belirteçlerini kullanmaktır.

Aşağıdaki programdaki import'ları da aslında daha temiz bir uygulama olduğundan hem kullanıldıkları işlevlerin içine yazdım hem de modüllerdeki bütün isimleri değil, yalnızca kullanılan isimleri import ettim.
auto baklavaDilimi(size_t N)
{
    import std.range : chain, iota, repeat;
    import std.algorithm : map;
    import std.conv : text;
    import std.string : center, format;
    import std.exception : enforce;
 
    enforce(N % 2, format("Baklava dilimi genişliği çift olamaz. (%s)", N));
 
    return
        chain(iota(1, N, 2),         // 1, 3, ..., N-2 değerleri
              iota(N, 0, -2))        // N, N-2, ..., 1 değerleri
                                     // (ve onların chain ile bağlanmaları)
 
        .map!(i => '*'.repeat(i))    // '*' karakterinin her değer için tekrarı
 
        .map!(s => s.text)           // Tekrarlanan karakterlerden dizgi
                                     // oluşturulması
 
        .map!(s => s.center(N));     // Dizginin satırda ortalanması
}
 
void main()
{
    import std.stdio : writefln;
 
    writefln("%-(%s\n%)", baklavaDilimi(11));
 
    /*
     * Yukarıdaki düzen dizgisinin anlamı: Aralıktaki her elemanı %( ve %)
     * arasında belirtilen düzende yazdır. (Not: Bu aralığın her elemanı dizgi
     * olduğundan ve dizgiler normalde çift tırnaklar arasında
     * yazdırıldıklarından %( değil, %-( kullanılıyor. Yani, o aradaki tire
     * işareti "çift tırnak olmasın" anlamına geliyor.)
     *
     * Her eleman için kullanılan düzen de şu: %s\n. Yani, her birisinden
     * sonra yeni satıra geçiliyor.
     */
}
Ali
hkntrt #10
Üye Nis 2012 tarihinden beri · 18 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Dlang'de açtığınız konuya baktım.Son yazdığınız kod oldukça mantıklı, dilin olanaklarından yararlanılarak yazılabilecek en sade ve şık kod bu galiba :)
Mengu (Moderatör) #11
Kullanıcı başlığı: NONSERVIAM
Üye Tem 2009 tarihinden beri · 347 mesaj · Konum: Dersaadet
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
iota nedir abi? insan suna daha guzel bir isim bulamaz mi?

allah tas etsin bu ismi vereni diyecegim. ben su metoda ilk baktigimda mumkun degil verilen aralikta bir range urettigini anlamam. incelemem gerek ciktisini. insan derki range(1, 10) ya da ne bileyim 1.upto(10) ya da 10.downto(1).

ben bunu http://linux.die.net/man/3/inet_ntoa sununla karistiriyorum arkadas hep. kardesi de bu: http://linux.die.net/man/3/inet_aton
http://www.mengu.net - some kind of monster
acehreli (Moderatör) #12
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ı
Tamamen haklısın. :) Tartışmaları olmuştu. O ismi Andrei'nin bulduğunu sanıyorum. En azından karşı çıkmıyor. Uzun bir konunun ortasından bir alıntı:

I don't find the name "iota" stupid.

  http://forum.dlang.org/thread/iit0os$1nhe$1@digi…?page=4…

Ali
Mengu (Moderatör) #13
Kullanıcı başlığı: NONSERVIAM
Üye Tem 2009 tarihinden beri · 347 mesaj · Konum: Dersaadet
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
acehreli:
Tamamen haklısın. :) Tartışmaları olmuştu. O ismi Andrei'nin bulduğunu sanıyorum. En azından karşı çıkmıyor. Uzun bir konunun ortasından bir alıntı:

I don't find the name "iota" stupid.

  http://forum.dlang.org/thread/iit0os$1nhe$1@digi…?page=4…

Ali

konuyu mahvettim ozur diliyorum.

ufcs kullanaraktan:

auto upto(int from, int to) {
  return iota(from, to);
}
 
auto downto(int from, int to) {
  return iota(to, from).array.reverse;
}
 
void main(string args[]) {
  writeln(1.upto(10).filter!(i => i % 2 == 0));
  writeln(10.downto(1).map!(i => i * 2));
}

boylesi benim icin daha zevkli. andrei iota'nin acilimini bir kendi biliyor galiba? :)
http://www.mengu.net - some kind of monster
acehreli (Moderatör) #14
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ı
upto ve downto kabul! :)

Ben de aşağıdaki programda artanAzalan ve azalanArtan diye iki işlev yazdım. Böylece boşlukların 2, 1, 0, 1, 2 diye önce azalan ve sonra artan genişliklerini ve yıldızların 1, 3, 5, 3, 1 diye önce artan ve sonra azalan genişliklerini ifade edebiliriz.

Bu iki genişlik dizisini zip ile birleştirdiğimizde de çokuzlu sayı dizileri elde etmiş oluruz. Örneğin, genişliği 5 olan baklava dilimi için:
    writefln("%(%s\n%)", zip(azalanArtan(0, 2, 1),
                             artanAzalan(1, 5, 2)));
Çokuzluların birinci elemanları boşluk genişliğini, ikinci elemanları da yıldız genişliğini veriyor:

Tuple!(int, int)(2, 1)
Tuple!(int, int)(1, 3)
Tuple!(int, int)(0, 5)
Tuple!(int, int)(1, 3)
Tuple!(int, int)(2, 1)

Şimdi o çokuzluları boşluk ve yıldız karakterleri üreten bir map'e verirsek bu işi daha farklı ama yine temiz bir biçimde halletmiş oluyoruz:
import std.range;
import std.algorithm;
import std.conv;
import std.string;
import std.exception;
import std.stdio;
import std.traits;
 
/* Küçük değerden büyük değere doğru artan ve sonra tekrar küçük değere doğru
 * azalan değerler üretir. */
auto artanAzalan(T)(T küçük, T büyük, T adım = 1)
    if (isSigned!T)
{
    return chain(iota(küçük, büyük, adım),
                 iota(büyük, küçük - 1, -adım));
}
 
unittest
{
    assert(artanAzalan(1, 7, 2).equal([ 1, 3, 5, 7, 5, 3, 1 ]));
}
 
/* Büyük değerden küçük değere doğru azalan ve sonra tekrar büyük değere doğru
 * artan değerler üretir. */
auto azalanArtan(T)(T küçük, T büyük, T adım = 1)
    if (isSigned!T)
{
    return chain(iota(büyük, küçük, -adım),
                 iota(küçük, büyük + 1, adım));
}
 
unittest
{
    assert(azalanArtan(10, 20, 5).equal([ 20, 15, 10, 15, 20 ]));
}
 
auto baklavaDilimi(size_t N)
{
    enforce(N % 2, format("Baklava dilimi genişliği çift olamaz. (%s)", N));
 
    return zip(azalanArtan(0, N.to!int / 2, 1),
               artanAzalan(1, N.to!int, 2))
 
           .map!(genişlikler => chain(' '.repeat(genişlikler[0]),
                                      '*'.repeat(genişlikler[1])));
}
 
void main()
{
    writefln("%(%s\n%)", baklavaDilimi(9));
}
Bu kodu daha çok beğeniyorum çünkü .text ile hevesli dizgi üretimi yok ve .center ile satır sonundaki boşlukları bulunmuyor. (İstendiğinde sona da boşluk eklenebilir.) Dolayısıyla, sonuçtaki aralığın elemanları artık dizgi olmadıklarından, en sondaki düzen dizgisinde "%-(" kullanmak da gerekmedi.

Ali
Bu mesaj acehreli tarafından değiştirildi; zaman: 2014-03-21, 17:11.
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:
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-22, 02:57:32 (UTC -08:00)