diff options
| author | Charles <sircharlesaze@gmail.com> | 2020-06-25 18:17:41 +0200 |
|---|---|---|
| committer | Charles <sircharlesaze@gmail.com> | 2020-06-25 18:17:41 +0200 |
| commit | 063afb1650160c8973de51603be0acca53b39e5d (patch) | |
| tree | 4e7b41397bba9a048b32f26bf3259b266c3da513 /src | |
| download | huffman-063afb1650160c8973de51603be0acca53b39e5d.tar.gz huffman-063afb1650160c8973de51603be0acca53b39e5d.tar.bz2 huffman-063afb1650160c8973de51603be0acca53b39e5d.zip | |
Initial commit: Rewrite in Rust
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.rs | 12 | ||||
| -rw-r--r-- | src/symbols.rs | 122 | ||||
| -rw-r--r-- | src/tree.rs | 22 |
3 files changed, 156 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..2b4e6c5 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,12 @@ +use std::env; + +pub mod symbols; +// pub mod tree; +// +use symbols::Tree; + +fn main() { + let file_path = env::args().nth(1).unwrap(); + let tree = Tree::from_file(&file_path).unwrap(); + tree.put(); +} diff --git a/src/symbols.rs b/src/symbols.rs new file mode 100644 index 0000000..cd8fd52 --- /dev/null +++ b/src/symbols.rs @@ -0,0 +1,122 @@ +use std::fs; +use std::io; +use std::io::Read; +use std::collections::{BinaryHeap, HashMap}; + +pub struct Node { + occurences: usize, + content: Content, +} + +impl Node { + fn join(left: Node, right: Node) -> Node { + Node { + occurences: left.occurences + right.occurences, + content: Content::Parent { + left: Box::new(left), + right: Box::new(right), + } + } + } +} + +enum Content { + Leaf(u8), + Parent { + left: Box<Node>, + right: Box<Node>, + }, +} + +pub type Tree = Node; + +impl Tree { + pub fn from_file(file_path: &str) -> io::Result<Tree> { + let mut symbols = Symbols::from_file(file_path)?; + Ok(Tree::from_symbols(&mut symbols)) + } + + fn from_symbols(symbols: &mut Symbols) -> Tree { + while symbols.0.len() >= 2 { + let first = symbols.0.pop().unwrap(); + let second = symbols.0.pop().unwrap(); + let n = Node::join(first, second); + symbols.0.push(n); + } + let ret = symbols.0.pop().unwrap(); + ret + } + + pub fn put(&self) { + self.put_with_level(0); + } + + fn put_with_level(&self, level: usize) { + match &self.content { + Content::Leaf(b) => { + // Tree::put_spaces(level); + print!("{} {}\n", self.occurences, b); + }, + Content::Parent { left, right } => { + print!("NODE {}\n", self.occurences); + Tree::put_spaces(level); + print!("left: "); + left.put_with_level(level + 1); + Tree::put_spaces(level); + print!("right: "); + right.put_with_level(level + 1); + }, + } + } + + fn put_spaces(n: usize) { + for _ in 0..(n * 2) { + print!(" "); + } + } +} + +struct Symbols(BinaryHeap<Node>); + +impl Symbols { + fn from_file(file_path: &str) -> io::Result<Symbols> { + let f = fs::File::open(file_path)?; + let mut counter: HashMap<u8, usize> = HashMap::new(); + for b in f.bytes() { + let k = b?; + let v = match counter.get(&k) { + Some(count) => count + 1, + None => 1, + }; + counter.insert(k, v); + } + let heap: BinaryHeap<Node> = counter + .iter() + .map(|(k, v)| Node { occurences: *v, content: Content::Leaf(*k) }) + .collect(); + Ok(Symbols(heap)) + } +} + +use std::cmp::Ordering; + +impl Ord for Node { + fn cmp(&self, other: &Self) -> Ordering { + // self.occurences.cmp(&other.occurences) + other.occurences.cmp(&self.occurences) // dirty hack for min-heap + } +} + +impl PartialOrd for Node { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +impl Eq for Node {} + +impl PartialEq for Node { + fn eq(&self, other: &Self) -> bool { + self.occurences == other.occurences + } +} diff --git a/src/tree.rs b/src/tree.rs new file mode 100644 index 0000000..d3cca22 --- /dev/null +++ b/src/tree.rs @@ -0,0 +1,22 @@ +use super::symbols::Symbols; + +struct Node { + occurence: usize, + content: Content, +} + +enum Content { + Leaf(i8), + Parent { + left: Box<Node>, + right: Box<Node>, + }, +} + +type Tree = Node; + +// impl Tree { +// fn from_symbols(symbols: Symbols) -> Tree { +// symbols.0 +// } +// } |
