Forum: D Programlama Dili RSS
Satranç Tahtasında Kalenin Kesmediği Hücre Sayısını Bulma
kerdemdemir #1
Üye Eyl 2013 tarihinden beri · 125 mesaj · Konum: Danimarka
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: Satranç Tahtasında Kalenin Kesmediği Hücre Sayısını Bulma
Selam Yeniden,

Bu seferki amaçımız dinamik boyutlu bir satranç tahtasının(3'e 3 de olabilir 5'e 5 de) herhangi bir noktasına bir kale yerleştirdikten sonra kalenin kesmediği hücrelerin sayısını bulmak.

Örneğin 3'e 3 bir tahtada 1. satır ve 1 sütüna bir kale koyduğumuz zaman kalenin kesmediği hüçreler solda giri ile gösterilmiş. Sonra ikinci bir kale 3. satır birinci sütüna koyulunca sadece iki tane kesilmeyen hücre kalmış.
[Resim: http://codeforces.com/predownloaded/a3/a5/a3a52ec7278de7644c87dc9cb19b4d18eacefebd.png]

İlişkili dizileri kullanarak güzel bir algoritma düşünmüştüm ama dildeki yetersizliğim soruyu çözebilmemi engelledi.
Benim bitiremediğim çözümüm :

import std.stdio;
import std.string;
import std.algorithm;
import std.exception;
import std.conv;
import std.array;
import std.range;
 
bool[int] tahtaİliskiliDizisi;
int tahtaBoyutu = 0;
 
void satirIleIsaretle( int satir )
{
    foreach( i; iota( satir*tahtaBoyutu, (satir+1)*tahtaBoyutu ))
        tahtaİliskiliDizisi[i] = true;
    //iota( satir*tahtaBoyutu, (satir+1)*tahtaBoyutu ) .map!( a => tahtaİliskiliDizisi[a] = true );
}
 
void sutunIleIsaretle( int sutun )
{
    foreach( i; iota( sutun, tahtaBoyutu*tahtaBoyutu, tahtaBoyutu))
        tahtaİliskiliDizisi[i] = true;
    //iota( sutun, tahtaBoyutu*tahtaBoyutu, tahtaBoyutu) .map!( a => tahtaİliskiliDizisi[a] = true );
 
}
 
void isaretleVeSay( int satir, int sutun )
{
    satirIleIsaretle( satir );
    sutunIleIsaretle( sutun );
 
    write(tahtaBoyutu*tahtaBoyutu - tahtaİliskiliDizisi.keys.length, " " ); 
}
 
void main() {
 
    auto ilkSatir = stdin.readln.strip.split().map!(a => to!int(a)).array();
    tahtaBoyutu = ilkSatir[0];
    auto kaleSayisi  = ilkSatir[1];
 
    int[][] kalePosizyonlari;
    //kalePosizyonlari ~= stdin.byLine().take(kaleSayisi-1).to!dstring.strip.split.map!(a => to!int(a)).array();
    int sayici = 0;
    string line;
    while ((line = stdin.readln()) !is null)
    {
        kalePosizyonlari ~= line.to!dstring.strip.split.map!(a => to!int(a)).array();
        if (++sayici >= kaleSayisi) 
            break;
    }
    writeln(kalePosizyonlari);
    foreach ( posizyon; kalePosizyonlari)
        isaretleVeSay( posizyon[0], posizyon[1] );
    //kalePosizyonlari.map!( a=> isaretleVeSay(a[0], a[1]) );
}

Burda sizlere sorularım olacak :

1 - kalePosizyonlari ~= stdin.byLine().take(kaleSayisi-1).to!dstring.strip.split.map!(a => to!int(a)).array();
bu çalışmadığı için bir sürü while yok efendim "sayici" değişkeni  koşul ifadeleri filan eklemek sorunda kaldım.
acaba ne eksik yapıyorum take yerine until mi kullanmalıydım ?

2- ben map methodunu foreach kullanmağa tercih ediyorum fakat map methodlarım çalışmadı örn:
iota( satir*tahtaBoyutu, (satir+1)*tahtaBoyutu ) .map!( a => tahtaİliskiliDizisi[a] = true ); ne kadar güzel değil mi ?
fakat associative array i yazdırdığım bomboş oluyor sonuç bunlar yerine hep foreach kullanmak zorunda kaldım ve D'nin bütün güzelliği gidiyor gerçekten böle olunca.

3 - Başka tavsiyeniz olurmu acaba?

Sevgiler
Erdemdem
acehreli (Moderatör) #2
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4538 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
kerdemdemir:
1 - kalePosizyonlari ~= stdin.byLine().take(kaleSayisi-1).to!dstring.strip.split.map!(a => to!int(a)).array();
bu çalışmadığı için

Şu çalıştı:
    int[][] kalePosizyonlari = stdin
                               .byLine()
                               .take(kaleSayisi)
                               .map!(line => line
                                     .split
                                     .map!(a => to!int(a))
                                     .array())
                               .array;

2- ben map methodunu foreach kullanmağa tercih ediyorum fakat map methodlarım çalışmadı örn:
iota( satir*tahtaBoyutu, (satir+1)*tahtaBoyutu ) .map!( a => tahtaİliskiliDizisi[a] = true ); ne kadar güzel değil mi ?

Neden olduğunu anlamadım ama 'map' değer üretir, 'each' yan etki... Şu çalıştı:
    iota( satir*tahtaBoyutu, (satir+1)*tahtaBoyutu ).each!(i => tahtaİliskiliDizisi[i] = true );
Ama şu daha mantıklı geliyor (özellikle diğer işlevde):
    iota(0, tahtaBoyutu)
        .map!(sutun => satir * tahtaBoyutu + sutun)
        .each!(i => tahtaİliskiliDizisi[i] = true );

main'in son satırındaki sorun da buydu. Tekrar özet: map bir sonraki algoritma için değer üretir; each o eleman ile işlem yapar (değer döndürürse göz ardı edilir; dolayısıyla => işleciyle kullanımı kafa karıştırır.)

3 - Başka tavsiyeniz olurmu acaba?
* Tek bitlik bilgiler için indeks hesabını elle yapmak yerine std.bitmanip.BitArray kullanılabilir. Hem her eleman için tek bit ayırır.

  • Bir de std.experimental.ndslice var ama onun tek bit için özellemesi olup olmadığını bilmiyorum. O modülde "şu sütunu şu değere ata" gibi tek çağrı bile olabilir ama henüz hiç incelemedim.

  • kalePosizyonlari'nı dizi olarak tutmaya gerek yok çünkü tek kere ilerliyoruz.
import std.stdio;
import std.string;
import std.algorithm;
import std.conv;
import std.range;
import std.bitmanip;
 
BitArray tahtaİliskiliDizisi;
int tahtaBoyutu = 0;
 
void satirIleIsaretle( int satir )
{
    iota(0, tahtaBoyutu)
        .map!(sutun => satir * tahtaBoyutu + sutun)
        .each!(i => tahtaİliskiliDizisi[i] = true );
}
 
void sutunIleIsaretle( int sutun )
{
    iota(0, tahtaBoyutu)
        .map!(satir => satir * tahtaBoyutu + sutun)
        .each!(i => tahtaİliskiliDizisi[i] = true );
}
 
void isaretleVeSay( int satir, int sutun )
{
    satirIleIsaretle( satir );
    sutunIleIsaretle( sutun );
 
    writeln(tahtaİliskiliDizisi);
}
 
void main() {
 
    const ilkSatir = stdin.readln.strip.split().map!(a => to!int(a)).array();
    tahtaBoyutu = ilkSatir[0];
    const kaleSayisi  = ilkSatir[1];
 
    tahtaİliskiliDizisi.length = tahtaBoyutu * tahtaBoyutu;
 
    auto kalePosizyonlari = stdin
                            .byLine()
                            .take(kaleSayisi)
                            .map!(line => line
                                  .split
                                  .map!(a => to!int(a))
                                  .array());
 
    kalePosizyonlari.each!( a=> isaretleVeSay(a[0], a[1]) );
}
Ali
kerdemdemir #3
Üye Eyl 2013 tarihinden beri · 125 mesaj · Konum: Danimarka
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Aslında düşününce niye ilişkili dizi kullandığımı bende sorguluyorum. Sanıyorsam iş yerinde genelde daha dinamik problemler olduğundan dolayı elim hep hashmap'lere gidiyor. Ayrıca bitArray sınıfını öğrendiğime çok sevindim. Acaba BitArray bir alias mi(C++'daki vector<bool> gibi) yoksa ayrı bir sınıfmı?

Ne zaman "each" ne zaman "map" kullanıcağı anladım bu sefer.
Hala anlayamadığım tam olarak ne zaman .array() kullanmam gerektiği şimdilik derleyici ne zaman hata verirse o zaman kullanıyorum. 

Erdemdem
acehreli (Moderatör) #4
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4538 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
BitArray başlıbaşına bir tür:

  https://github.com/dlang/phobos/blob/master/std/bitmanip.d…

.array, bir sonraki işlem RandomAccessRange gerektirdiğinde kullanılıyor. Ama, eğer bir sonraki işlem o dizide değişiklik yapacaksa o da olmuyor çünkü .array'in döndürdüğü bir rvalue'dur. O zaman .array'in döndürdüğü bir değişkene atanıyor, vs. Aslında ben de seninle aynı durumdayım: Olabildiğince kaçınıyorum, gerekiyorsa kullanıyorum. :)

Ali
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:
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-12-16, 16:37:13 (UTC -08:00)