August 31, 2016

Merhaba,

Yeni işim dolayısıyla Ubuntu kurdum ve DMD yükledim.

Aşağıdaki gibi basit bir kodda bir sorunla karşılaştım.

Şu aralık :

   auto busRows = 			stdin
                           .byLine()
                           .take(busRowCount)
                           .map!(line => line
                                 .splitter("|")
                                 .map!( a => busRowOperation(a) )
                                 .array());

writeln(busRows); satırında çalışmaya başlıyor. Fakat aralık çalışırken güncellediğim "isHasSeat" boolean'ı ne yazıkki güncellenmemiş ve yanlış yazılmış oluyor. Bu durumun önüne nasıl geçebilirim sizce ?

Bir sorumda bütün aralığı dolaşan map fonksiyonu yerine duruma bağlı olarak sadece bir kere çalışacak bir iterasyon method'u varmıdır? Aslında aşağıda görüleceği gibi isHasSeat değişkeni bir kere true 'ya çekildikten sonra hep return yapıyorum. Sizce bunun önüne geçebilirmiyim?


import std.stdio;
import std.string;
import std.algorithm;
import std.conv;
import std.range;
import std.bitmanip;

bool isHasSeat = false;

char[] busRowOperation( char[] singleRow )
{
	if ( isHasSeat )
		return singleRow;

	if ( singleRow.equal( "OO" ) )
	{
		isHasSeat = true;
		return "++".dup;
	}

	return singleRow;
}


void main() {

   const int busRowCount = stdin.readln.strip.to!int;


   auto busRows = 			stdin
                           .byLine()
                           .take(busRowCount)
                           .map!(line => line
                                 .splitter("|")
                                 .map!( a => busRowOperation(a) )
                                 .array());
   if ( isHasSeat )
		writeln("YES");
	else
		writeln("NO");

   writeln(busRows);

}

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

August 31, 2016

array her eleman için çağrılıyor ama bütün aralık için çağrılmıyor. Dolayısıyla, busRows hevesli değil. Onun sonuna da .array eklersen YES'i baştan göreceksin.

Ama tabii, "OO"yu görene kadar çok sayıda veri varsa ve amacımız yalnızca çıktıya bir şeyler yazmaksa o kadar kopya üzücü. :) Yapacak başka bir şey de yok: veri stdin gibi çektikçe kaybolan bir kaynaktan geliyorsa işleyip bir kenara kopyalamaktan başka çare yok.

Durum bu kadar karmaşık olunca zorla aralık kullanmak yerine foreach filan daha mantıklı olabilir. :) Ama sanırım aşağıdaki doğru:

import std.stdio;
import std.string;
import std.algorithm;
import std.conv;
import std.range;

enum pattern = "OO";

bool rowHasSeat(const(char)[] row) {
   return row.canFind(pattern);
}

void main() {
   const int busRowCount = stdin.readln.strip.to!int;

   // Bütün giriş bu
   auto r = stdin.byLine;

   // Ya busRowCount adet kopyalayacağız ya da koşul sağlanana kadar.
   auto firstPart = r
                    .take(busRowCount)
                    .until!rowHasSeat(OpenRight.no)
                    // Girişin geri kalanında bu kopyaya gerek olmayacak:
                    .map!(row => row.dup)
                    .array;

   bool hasSeat() {
       // Hiç satır yok muydu? (Bunu daha önce de denetleyebilirdik)
       if (busRowCount == 0) return false;

       // Erken durduysak bulmuşuz demektir
       if (firstPart.length < busRowCount) return true;

       // Sonuncu eleman tuttu mu?
       if (rowHasSeat(firstPart.back)) return true;

       // Diğer durumda bulamamışız demektir
       return false;
   }

   if ( hasSeat )
       writeln("YES");
   else
       writeln("NO");

   // Baş tarafıyla geri kalanını birleştirip uygun işlemleri uyguluyoruz
   writeln(chain(firstPart,
                 r.take(busRowCount - firstPart.length))
           .map!(line => line
                 .splitter("|")
                 .map!( a => (a == pattern) ? "++" : a) ));
}

Ali

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