July 10, 2012

Bu durumda çıktısı aşağıdaki gibi oluyor. Öyleyse decompress olayına girsek de katmerlesek mi...:)
'
d:00000000
a:00000001
dabc:00000000
b:00000010
c:00000011
'

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

July 10, 2012

Kadir eline sağlık, senin kodlamaların hoşuma gidiyor. Bir itirafta bulunmak gerekirse Huffman konusunu Salih ilk açtıgında bende kodlamayı denemiştim ama becerememiştim :blush:

Bence çözme (decompress) olayından sonra bu kodlardan deneysel küçük bir program bile çıkar ;)

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

July 11, 2012

Şimdi sıkıştırma özelliğini de ekledim ama çıkan sonuç çok şaşırtıcı; programa verilen metin dosyasının boyutunu yaklaşık olarak 3 kat artırıyor. :( Acaba gözden kaçan bir nokta mı var?

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

	public this(string fileName)
	{
		fileToCompress_.open(fileName ~ ".txt", "r");
		compressedFile_.open(fileName ~ "compressed" ~ ".txt", "w");
		fileName_ = fileName ~ ".txt";
	}

	~this()
	{
		auto tables = File("tables.had", "w");
		tables.writeln(compressTable_);
		tables.writeln(decompressTable_);
		fileToCompress_.close();
		compressedFile_.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_);
		foreach(letter; lines){
			compressedFile_.writef("%b",compressTable_[to!string(letter)]);
		}
	}
}

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 uint 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();
}

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

July 11, 2012

Teşekkürler, sanırım ben algoritmalardaki o kısmı atlamışım.
Yarın açma işlemlerini de hazırlayıp yeni veritabanı çalışmamıza göndermiş olurum.

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

July 11, 2012

Bu program binary sonucu metin halinde yazdırıyor:

'11011110110101111101111101111001111100011100'

Oysa onları sekizer sekizer kullanarak baytlar halinde yazdırmalı. Örneğin ilk sekizli olan 11011110'ın karşılığı olan değer (sanırım 255 - 32 - 1 = 222) yazılmalı. vs.

Ali

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

July 12, 2012

Sıkıştırma işlemini dediğiniz gibi yaptım ama hala ya çok az sıkıştırıyor, ya da çok az boyutunu artırıyor.Bu sizce algoritma ile mi alakalı, yoksa programda bir hata mı var?

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_;
		string fileName_;
	}

	public this(string fileName)
	{
		fileToCompress_.open(fileName ~ ".txt", "r");
		compressedFile_.open(fileName ~ "compressed" ~ ".txt", "w");
		fileName_ = fileName ~ ".txt";
	}

	~this()
	{
		auto tables = File("tables.had", "w");
		tables.writeln(compressTable_);
		tables.writeln(decompressTable_);
		fileToCompress_.close();
		compressedFile_.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_.writef("%s", toDecimal(compressedText[0 .. 8]));
				compressedText = compressedText[8 .. $];
			}
		}
	}
}

ubyte toDecimal(string number)
{
	ubyte result;
	for(int i = number.length - 1; i >= 0; --i ){
		result += to!ubyte(number[i]) * (pow(2, i));
	}
	return result;
}
unittest
{
	assert(toDecimal("110") == 6);
	assert(toDecimal("001") == 1);
}

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();
}

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

July 12, 2012

@erdem;
Söylediğin hatayı dosya boşken alıyoruz, uyardığın için teşekkür ederim. Dosyanın boş olup olmadığını kontrol eden bir işlev ekliyorum hemen.

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

July 12, 2012

Can çok güzel bir konu seçmişsin kendine. Ben de Huffman algoritmasını ilk kez duymuş oldum :-)

Aslında algoritmayı öğrenip uğraşmak isterdim ama şimdilik ben de başka şeylerle uğraşıyorum.

Kod derleniyor. Ancak çalıştırdığım zaman ilkönce 'text.txt' isimli bir dosyanın olmadığından yakınıyor.
Alıntı:

>

std.exception.ErrnoException@std\stdio.d(288): Cannot open file text.txt' in mode r' (No such file or directory)

41CDEC
41CC77
402C03
40C7D0
40C80A
40C42B
421639

text isimli bir dosya oluşturduktan sonra ise şu hatayı veriyor.

Alıntı:

>

core.exception.RangeError@huffman.d(176): Range violation

41CDEC
41CC77
402B9B
4022D4
402C12
40C7D0
40C80A
40C42B
421639

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

July 12, 2012

Teşekkürler, ben writef()'e byte türünden değer verdiğimde byte yazılacağını düşünmüştüm.
Bu arada ben derlerken hiç hata almadım. Bu tarz hataları yakalayabilmek için hangi seçenekleri kullanmalıyız?Ben sadece -w ve -g kullanıyordum.

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

July 12, 2012

Evet haklısın dosya boşken hata veriyor

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