Merhaba,
Son günlerdeki okuma maratonunu biraz genişlettim; geçmişe, taa 2010'a kadar götürdüm. Ali hocanın o zamanlar yaptığı çok güzel bir kod var. Eski başlığı hortlatmak yerine, biraz günümüze uyarlayarak (kodun orijinaline* sadık kalarak) burada ön plana çıkarmak istedim...
Aslında yaptığı basit gibi görünse de aralıkların kullanılarak yapılması kodu çok kıymetli hale getiriyor. Hatta başlangıçta yoğunluğu arttırılan ardışık sayıların frekansını düşürmek mümkün:
import std.format, std.string, std.stdio;
import std.algorithm, std.range;
/**
* Kendisine verilen aralıktaki elemanların
* belirtilen sayıda art arda tekrarlandığı
* bir giriş aralığı (InputRange) döndürür.
**/
struct DenkTekrarlayan(Aralık)
if(isInputRange!Aralık)
{
Aralık asılAralık;
int tekrarSayısı;
private int sayaç;
ElementType!Aralık şimdikiEleman;
this(Aralık asılAralık, int tekrarSayısı) {
this.asılAralık = asılAralık;
this.tekrarSayısı = tekrarSayısı;
if(!asılAralık.empty) {
şimdikiEleman = this.asılAralık.front;
}
}
bool empty() {
return asılAralık.empty;
}
ElementType!Aralık front() {
return şimdikiEleman;
}
void popFront() {
if(++sayaç == tekrarSayısı) {
/**
* Tekrarlarımızı tamamladık; asıl aralıktaki
* bir sonraki elemana geçmemiz gerekiyor...
**/
while(!asılAralık.empty &&
(asılAralık.front == şimdikiEleman))
{
asılAralık.popFront();
}
if(!asılAralık.empty) {
şimdikiEleman = asılAralık.front;
}
sayaç = 0;
}
}
}
auto denkTekrarlı(R)(R e, int t) if (isInputRange!R)
{
return DenkTekrarlayan!R(e, t);
}
struct SonsuzSayaç(type)
{
type sayaç;
enum empty = false;
type front() const { return sayaç; }
void popFront() { ++sayaç;}
}
void main()
{
auto elemanlar = [ 0, 1, 1, 1, 2, 0 ];
write("(1) - Elemanları ikişer kere tekrarla:\n\t");
writeln(elemanlar.denkTekrarlı(2));
write("(2) - ve baştaki üç tanesini seç:\n\t");
writeln(elemanlar.denkTekrarlı(2).take(3));
writeln;
"(3) * ilk iki çifti seç, ve beşer kere tekrarla\n\t".
write(
[ 2, 4, 6 ].take(2).denkTekrarlı(5)
);
writeln; writeln(`
Sonsuza kadar artan değerler üret,
her birisini dörder kere tekrarla,
ve baştaki yirmi tanesini seç:`);
SonsuzSayaç!uint sonsuzSayaç;
auto sonTest = sonsuzSayaç.denkTekrarlı(4).take(20);
writefln("%-(%s %)", sonTest);/* Orijinal örnek:
writeln(take(denkTekrarlı(sonsuzSayaç, 4), 10));//*/
auto testlerBitmez = sonTest.denkTekrarlı(2);
testlerBitmez.writeln; // :)
}
/* ÇIKTISI:
(1) - Elemanları ikişer kere tekrarla:
[0, 0, 1, 1, 2, 2, 0, 0]
(2) - ve baştaki üç tanesini seç:
[0, 0, 1]
(3) * ilk iki çifti seç, ve beşer kere tekrarla
[2, 2, 2, 2, 2, 4, 4, 4, 4, 4]
Sonsuza kadar artan değerler üret,
her birisini dörder kere tekrarla,
ve baştaki yirmi tanesini seç:
0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4
[0, 0, 1, 1, 2, 2, 3, 3, 4, 4]
*/
(*) Emin değilim (biraz zaman geçti) ama sanırım bazı kolaylık işlevlerini iptal ettim ve UFCS nimetlerini olabildiğince göstermek istedim. Özetle kodun orijnalinden azıcık uzaklaşmış olabilirim.
>Çıktısı:
'"Elemanları ikişer kere tekrarla"
[0, 0, 1, 1, 2, 2, 0, 0]
"Elemanları ikişer kere tekrarla, ve baştaki üç tanesini seç"
[0, 0, 1]
"Baştaki dört tanesini seç, ve beşer kere tekrarla"
[3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 1, 1, 1, 1, 1]
"Sonsuza kadar artan değerler üret, her birisini dörder kere tekrarla, ve baştaki on tanesini seç"
[0, 0, 0, 0, 1, 1, 1, 1, 2, 2]
'
Devamı gelecek... :p
Ali
Sanırım devamını ben getirmiş oldum. Ali hocada bir kahinlik seziyorum. Nereden bildi acaba devamının geleceğini :)
Şaka bir yana (1) ve (2)'nci örneklerin sonucu orijinali ile aynı. Sonrasında biraz doğaçlamaya gitmek istemişim. Ayrınca sınıfı yapıya çevirip bazı const
'ları iptal ettim. Çünkü testlerBitmez
örneğinde hata verdi. İsterseniz üzerinde biraz yazışalım?
Sevgiler, saygılar...