July 12, 2012

number.length'in türü size_t, i'nin türü int olduğu için toDecimal() içinde derleme hatası alınca i'yi size_t olarak değiştirdim.

Ama o zaman da number.length sıfır olduğunda number.length-1'in çok büyük bir değer olma tehlikesi var. Üstelik size_t türündeki bir değer zaten hep >=0 olur:

Ben de daha kolay olduğu için foreach kullandım ama azalan yöndeki sayı aralıklarında onun da sorunu oluyor çünkü (number.length-1)..0 yazınca bu sefer de 0 aralığa dahil olmuyor.

Şu çalıştı:

ubyte toDecimal(string number)
in
{
   assert(number.length != 0);
}
body
{
   ubyte result;

   foreach (i; 0 .. number.length) {
       if (number[i] == '1') {
           result += 2 ^^ (number.length - 1 - i);
       }
   }

   return result;
}

Dosya boyuyla ilgili olarak: Tamam, artık '1' ve '0' karakterleri yazmıyorsun ama değerleri yine de metin halinde yazıyorsun. Örneğin 245 değerini dosyaya o değerdeki tek bayt olarak değil; '2', '4', ve '5' karakterleri olarak yazıyorsun. writef() ile formatlı olarak değil, rawWrite() ile çiğ olarak yazabilirsin:

               compressedFile_.rawWrite([ toDecimal(compressedText[0 .. 8]) ]);

Şimdi dosyanın boyu örneğin 15 yerine 5 oluyor.

Ali

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

July 12, 2012

Alıntı (Kadir Can):

>

writef()'e byte türünden değer verdiğimde byte yazılacağını düşünmüştüm.

Ama her zaman için insanın okuyabileceği biçimde. Hem byte ile int aynı sayılırlar; tek farkları bit uzunlukları. Dikkat edersen, write() ve arkadaşları 42 gibi bir int değerini de '4' ve '2' rakamları olarak yazarlar.

Alıntı:

>

hangi seçenekleri kullanmalıyız?Ben sadece -w ve -g kullanıyordum.

Bu tür hatalar derleme zamanında yakalanamaz. Olsa olsa birim testleri ile olabilir ama onun için de File gibi işleyen ama gerçek bir dosyaya değil de belleğe yazan bir tür olsa iyi olur. O zaman o File'dan okuyarak denetlenebilir. (Aslında std.stream.MemoryStream var ama uzun zaman önce muştulanmış ;) olan eşdeğerleri geleceğin için bütün std.stream modülünü gözardı ediyorum.)

Ayrıca -g'nin hata yakalama ile doğrudan ilgisi yok. O gdb gibi araçlarda kullanılabilsin diye kaynak koddaki isimleri programın içine yerleştirir.

Ali

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

July 13, 2012

-g'yi çalışma zamanı hatalarında hangi işlevde sorun olduğunu görebilmek için kullanıyorum.
Bu arada aşağıdaki kod ile yazdığımız baytları okuyamırum.Hata nedir acaba?

module huffman.d;
import std.stdio;
import std.conv;
import std.algorithm;
import std.string;
import std.math;
struct HuffmanTree
{
	private
	{
		uint[string] compressTable_;
		string[uint] decompressTable_;
		Node top_;
		File fileToCompress_;
		File compressedFile_;
		File decompressedFile_;
		string fileName_;
	}

	public this(string fileName)
	{
		fileName_ = fileName;
		fileToCompress_.open(fileName ~ ".had", "r");
		compressedFile_.open(fileName ~ "compressed" ~ ".had", "w+");
		decompressedFile_.open(fileName ~ "decompressed.hda", "w");
	}

	public ~this()
	{
		auto tables = File("tables.had", "w");
		tables.writeln(compressTable_);
		tables.writeln(decompressTable_);
		fileToCompress_.close();
		compressedFile_.close();
		decompressedFile_.close();
	}

	public void setTables(Node top)
	{
		compressTable_ = top_.returnTable;
		foreach(key, value; compressTable_){
			decompressTable_[value] = key;
		}
	}

	public void compressFile()
	{
		string lines;
		while(!fileToCompress_.eof()){
			lines ~= fileToCompress_.readln();
		}
		auto nodes = searchLetters(lines);
		top_ = createTree(nodes);
		top_.setBinaryCodes();
		setTables(top_);
		string compressedText;
		foreach(letter; lines){
			compressedText ~= format("%b", compressTable_[to!string(letter)]);
			if(compressedText.length >= 8){
				compressedFile_.rawWrite([toDecimal(compressedText[0 .. 8])]);
				compressedText = compressedText[8 .. $];
			}
		}
		compressedFile_.rawWrite([toDecimal(compressedText[0 .. $])]);
	}

	public void decompressFile()
	{
		ubyte[1024] buffer;
		ubyte[] data;
		while(!compressedFile_.eof()){
			data ~= compressedFile_.rawRead(buffer);
		}
		writeln(buffer);
		writeln(data);
	}
}

ubyte toDecimal(string number)
in
{
   assert(number.length != 0);
}
body
{
   ubyte result;

   foreach (i; 0 .. number.length) {
       if (number[i] == '1') {
           result += 2 ^^ (number.length - 1 - i);
       }
   }

   return result;
}

struct Node
{
	private
	{
		string value_;
		uint binaryCode_;
		uint frequency_;
		Node* right_;
		Node* left_;
	}

	public this(const uint frequence, string value)
	{
		value_ = value;
		frequency_ = frequence;
	}

	public int opCmp(Node another) const
	{
		return frequency_ == another.frequency_ ? cmp(value_, another.value_) : frequency_ - another.frequency_ ;
	}

	public string toString() const
	{
		string result;
		result ~= "Binary code: " ~ to!string(binaryCode_) ~ "\n";
		result ~= "Letter: " ~ value_ ~ "\n";
		return result;
	}

	public void setBinaryCodes()
	{
		if(right_ && left_)
		{
			right_.binaryCode_ = binaryCode_;
			left_.binaryCode_ = binaryCode_;
			right_.binaryCode_ <<= 1;
			left_.binaryCode_ <<= 1;
			right_.binaryCode_ |= 1;
			right_.setBinaryCodes();
			left_.setBinaryCodes();
		}
	}

	public uint[string] returnTable() const @property
	{
		uint[string] result;
		result[value_] = binaryCode_;
		if(right_ && left_)
		{
			foreach(index, value; left_.returnTable()){
				if(index.length==1){
				    result[index] = value;
				}
			}
			foreach(index, value; right_.returnTable()){
				if(index.length==1){
					result[index] = value;
				}
			}
		}
		foreach(index, value; result){
			if(index.length != 1){
				result.remove(index);
			}
		}
		return result;
	}
}

Node[] searchLetters(string text)
{
	uint[char] letters;
	Node[] result;
	foreach(character; text){
		if(character in letters){
		    ++letters[character];
		} else {
			letters[character] = 1;
		}
	}
	foreach(index, value; letters){
		result ~= Node(value, to!string(index));
	}
	return result;
}

Node createTree(Node[] nodes)
{
	while(nodes.length > 1)
	{
		nodes.sort();
		auto newNode = Node((nodes[0].frequency_ + nodes[1].frequency_), (nodes[0].value_ ~ nodes[1].value_));
		newNode.left_ = &nodes[0];
		newNode.right_ = &nodes[1];
		nodes ~= newNode;
		nodes = nodes[2 .. $];
	}
	return nodes[0];
}

void main()
{
   string fileName = "text";
   auto tree = HuffmanTree(fileName);
   tree.compressFile();
   tree.decompressFile();
}

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

July 13, 2012

O sorunu düzelttim şimdi, ama buradaki sorun sanırım farklı. Dosyaya rawWrite() ile bayt bayt yazdığımız değerleri rawRead() ile aynı şekilde okumaya çalışıyorum ama ne buffer değişkeninde ne de data değişkeninde okuduğum değerleri göremiyorum.
Bunu nasıl çözebiliriz?

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

July 13, 2012

Evet, aynı dosya nesnesini kullanıyorum, bu nedenle dosyayı "w+" yetkisi ile açtım. Acaba sorun aynı nesnenin kullanılması olabilir mi?

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

July 13, 2012

Teşekkürler, şimdi okuyabildim. :)

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

July 13, 2012

Hemen görebildiğim: .had dosyasını türün sonlandırıcı işlevinde oluşturuyorsun. Dolayısıyla senin örneğindeki dosya main'deki işlemlerden sonra oluşacaktır. Yani tree.decompressFile() çağrısından sonra!

Ali

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

July 13, 2012

Aynı dosya nesnesini mi kullanıyorsun? Şu çalışıyor:

import std.stdio;

void yaz(string isim, size_t adet)
{
   auto dosya = File(isim, "w");

   foreach (i; 0 .. adet) {
       immutable bayt = cast(ubyte)i;
       dosya.rawWrite([ bayt ]);
   }
}

void oku(string isim, size_t adet)
{
   auto dosya = File(isim, "r");

   auto okunan = new ubyte[](adet);

   dosya.rawRead(okunan);

   foreach (ubyte bayt; okunan) {
       writefln("%02x", bayt);
   }
}

void main()
{
   yaz("rawWrite_denemesi", 100);
   oku("rawWrite_denemesi", 100);
}

Ali

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

July 13, 2012

Okuma kafasını rewind() ile başa götürmek gerek:

import std.stdio;

void yaz(File dosya, size_t adet)
{
   foreach (i; 0 .. adet) {
       immutable bayt = cast(ubyte)i;
       dosya.rawWrite([ bayt ]);
   }
}

void oku(File dosya, size_t adet)
{
   auto okunan = new ubyte[](adet);

   dosya.rawRead(okunan);

   foreach (ubyte bayt; okunan) {
       writefln("%02x", bayt);
   }
}

void main()
{
   auto dosya = File("rawWrite_denemesi", "w+");

   yaz(dosya, 100);

   dosya.rewind();    // <-- şart!

   oku(dosya, 100);
}

Ali

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

July 18, 2012

Bu konuyu ilgiyle takip ediyorum.

Bu arada Kadir Can'ın D konusundaki gelişimini, ve yazdığı kodları çok beğendiğimi söylemeliyim :-)

Kodun nasıl çalıştığına bakarken ben de öylesine tekrardan yazdım kodları..

import std.stdio;

void harflereBöl (dstring metin)
{
   int [dchar] harfler = [ 'a' : 1 ];

   foreach (karakter; metin) {
       if (karakter in harfler) {
           ++harfler[karakter];
       } else {
           harfler[karakter] = 1;
       }
   }

   foreach (harf, kaçtane; harfler) {
       writeln(harf, " : ", kaçtane);
   }
}


void main()
{
   harflereBöl("Fıstıkçı şahap");
}

Zaten benim beğendiğim kodlama tarzı olduğu için hiç değiştirmedim kodları.

Huffman algoritmasını kodlarken çokuzluları kullanabilirmiydik acaba. Bir de bir karakterin ne kadar tekrarlandığı ya da frekansını kaydetmemize gerek var mı.

Açıkçası Huffman algoritmasını farklı yöntemler, veri yapıları kullanarak kodlayan varsa dinlemeye hazırım ;-)

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