Thread overview
Satranç Tahtasında Kalenin Kesmediği Hücre Sayısını Bulma
Jul 22, 2016
kerdemdemir
Jul 23, 2016
kerdemdemir
July 22, 2016

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ış.
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

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 22, 2016

Alıntı (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;

Alıntı:

>

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.)

Alıntı:

>

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

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 24, 2016

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 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

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 24, 2016

BitArray başlıbaşına bir tür:

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

'.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

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]