Explorar o código

Getting some stuff done

AvariceLHubris hai 1 ano
pai
achega
8df599a388
Modificáronse 5 ficheiros con 243 adicións e 83 borrados
  1. 9 0
      Cargo.lock
  2. 1 0
      Cargo.toml
  3. 96 0
      src/hufftree.rs
  4. 2 83
      src/lib.rs
  5. 135 0
      src/node.rs

+ 9 - 0
Cargo.lock

@@ -2,6 +2,15 @@
 # It is not intended for manual editing.
 version = 3
 
+[[package]]
+name = "bit-vec"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
+
 [[package]]
 name = "huffman"
 version = "0.1.0"
+dependencies = [
+ "bit-vec",
+]

+ 1 - 0
Cargo.toml

@@ -4,3 +4,4 @@ version = "0.1.0"
 edition = "2021"
 
 [dependencies]
+bit-vec = "0.8"

+ 96 - 0
src/hufftree.rs

@@ -0,0 +1,96 @@
+use std::collections::HashMap;
+
+use bit_vec::BitVec;
+
+use crate::node::Node;
+
+pub struct Hufftree {
+    root: Node,
+}
+
+impl Hufftree {
+    pub fn new(chars_and_freq: HashMap<char, i32>) -> Hufftree {
+        let mut nodes: Vec<Node> = Vec::new();
+
+        for (c, f) in chars_and_freq {
+            nodes.push(Node::new_with_character(c, f));
+        }
+
+        nodes.sort();
+        nodes.reverse();
+
+        while nodes.len() > 1 {
+            let n1 = nodes.pop().expect("There was no node left in the vector.");
+            let n2 = nodes.pop().expect("There was no node left in the vector.");
+
+            let mut new_node = Node::new();
+
+            new_node.join_left(Box::new(n1));
+            new_node.join_right(Box::new(n2));
+
+            nodes.push(new_node);
+
+            // TODO: Optimize this later.
+            nodes.sort();
+            nodes.reverse();
+        }
+
+        Hufftree {
+            root: nodes.pop().expect("There was no node in the vector."),
+        }
+    }
+
+    pub fn get_character_code(&self, character: char) -> Result<BitVec, &str> {
+        match self.root.get_character_code(character) {
+            Ok(code) => {
+                let code = code.iter().rev().collect();
+                Ok(code)
+            }
+            Err(e) => Err(e),
+        }
+    }
+
+    pub fn convert_text(&self, text: String) -> Result<BitVec, &str> {
+        let mut output = BitVec::new();
+        for character in text.chars() {
+            let mut code = self.get_character_code(character)?;
+            output.append(&mut code);
+        }
+
+        Ok(output)
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+
+    #[test]
+    fn make_simple_tree() {
+        let mut chars_and_freq: HashMap<char, i32> = HashMap::new();
+        chars_and_freq.insert('a', 25);
+        chars_and_freq.insert('b', 14);
+        chars_and_freq.insert('c', 5);
+
+        let huff = Hufftree::new(chars_and_freq);
+        assert_eq!(huff.root.get_frequency(), 44)
+    }
+
+    #[test]
+    fn make_simple_tree_with_correct_codes() {
+        let mut chars_and_freq: HashMap<char, i32> = HashMap::new();
+        chars_and_freq.insert('a', 25);
+        chars_and_freq.insert('b', 14);
+        chars_and_freq.insert('c', 5);
+
+        let huff = Hufftree::new(chars_and_freq);
+        assert_eq!(huff.root.get_frequency(), 44);
+
+        let a_code = huff.get_character_code('a').unwrap();
+        let b_code = huff.get_character_code('b').unwrap();
+        let c_code = huff.get_character_code('c').unwrap();
+        assert_eq!(a_code.to_string(), "1");
+        assert_eq!(b_code.to_string(), "01");
+        assert_eq!(c_code.to_string(), "00");
+    }
+}

+ 2 - 83
src/lib.rs

@@ -1,83 +1,2 @@
-// pub struct hufftree {
-// }
-
-struct Node {
-    left: Option<Box<Self>>,
-    right: Option<Box<Self>>,
-    character: Option<char>,
-    frequency: i32,
-}
-
-impl Node {
-    pub fn new() -> Node {
-        Self {
-            left: None,
-            right: None,
-            character: None,
-            frequency: 0,
-        }
-    }
-
-    pub fn new_with_character(character: char, frequency: i32) -> Node {
-        Self {
-            character: Some(character),
-            left: None,
-            right: None,
-            frequency
-        }
-    }
-
-    pub fn join_left(self: &mut Node, left: Box<Node>) {
-        self.frequency += left.get_frequency();
-        self.left = Some(left);
-    }
-
-    pub fn join_right(self: &mut Node, right: Box<Node>) {
-        self.frequency += right.get_frequency();
-        self.right = Some(right);
-    }
-
-    pub fn is_leaf(self: &Node) -> bool {
-        self.left.is_none() & self.right.is_none()
-    }
-
-    pub fn get_frequency(self: &Node) -> i32 {
-        self.frequency
-    }
-
-    pub fn get_character(self: &Node) -> Result<char, &str> {
-        if !self.is_leaf() {
-            return Err("This node is not a leaf node.");
-        }
-
-        Ok(self.character.unwrap())
-    }
-}
-
-#[cfg(test)]
-mod test {
-    #[test]
-    fn make_new_node_with_character_works() {
-        use crate::Node;
-
-        let example = Node::new_with_character('a', 5);
-        assert!(example.is_leaf());
-        assert_eq!(example.get_character().unwrap(), 'a');
-    }
-
-    #[test]
-    fn make_small_tree_with_leaf_nodes() {
-        use crate::Node;
-
-        let mut root = Node::new();
-        let left = Node::new_with_character('a', 5);
-        let right = Node::new_with_character('b', 10);
-
-
-        root.join_left(Box::new(left));
-        root.join_right(Box::new(right));
-
-        assert!(!root.is_leaf());
-        assert_eq!(root.get_frequency(), 15);
-    }
-}
+pub mod node;
+pub mod hufftree;

+ 135 - 0
src/node.rs

@@ -0,0 +1,135 @@
+use bit_vec::{self, BitVec};
+
+#[derive(Debug)]
+pub struct Node {
+    left: Option<Box<Self>>,
+    right: Option<Box<Self>>,
+    character: Option<char>,
+    frequency: i32,
+}
+
+impl Node {
+    pub fn new() -> Node {
+        Self {
+            left: None,
+            right: None,
+            character: None,
+            frequency: 0,
+        }
+    }
+
+    pub fn new_with_character(character: char, frequency: i32) -> Node {
+        Self {
+            character: Some(character),
+            left: None,
+            right: None,
+            frequency
+        }
+    }
+
+    pub fn join_left(self: &mut Node, left: Box<Node>) {
+        assert!(self.left.is_none(), "Tried to join a node to the left, but the branch was not empty.");
+        self.frequency += left.get_frequency();
+        self.left = Some(left);
+    }
+
+    pub fn join_right(self: &mut Node, right: Box<Node>) {
+        assert!(self.right.is_none(), "Tried to join a node to the right, but the branch was not empty.");
+        self.frequency += right.get_frequency();
+        self.right = Some(right);
+    }
+
+    pub fn is_leaf(self: &Node) -> bool {
+        self.left.is_none() & self.right.is_none()
+    }
+
+    pub fn get_frequency(self: &Node) -> i32 {
+        self.frequency
+    }
+
+    pub fn get_character(self: &Node) -> Result<char, &str> {
+        if !self.is_leaf() {
+            return Err("This node is not a leaf node.");
+        }
+
+        Ok(self.character.unwrap())
+    }
+
+    pub fn get_character_code(self: &Node, character: char) -> Result<BitVec, &str> {
+        let output = BitVec::new();
+        if self.is_leaf() && self.get_character().unwrap() == character {
+            return Ok(output);
+        }
+
+        if let Some(n) = &self.left {
+            let left = n.get_character_code(character);
+            if left.is_ok() {
+                let mut bit_result = left.unwrap();
+                bit_result.push(false);
+                return Ok(bit_result)
+            }
+
+        }
+
+        if let Some(n) = &self.right {
+            let right = n.get_character_code(character);
+            if right.is_ok() {
+                let mut bit_result = right.unwrap();
+                bit_result.push(true);
+                return Ok(bit_result)
+            }
+        }
+
+        Err("Could not find character.")
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+
+    #[test]
+    fn make_new_node_with_character_works() {
+
+        let example = Node::new_with_character('a', 5);
+        assert!(example.is_leaf());
+        assert_eq!(example.get_character().unwrap(), 'a');
+    }
+
+    #[test]
+    fn make_small_tree_with_leaf_nodes() {
+
+        let mut root = Node::new();
+        let left = Node::new_with_character('a', 5);
+        let right = Node::new_with_character('b', 10);
+
+
+        root.join_left(Box::new(left));
+        root.join_right(Box::new(right));
+
+        assert!(!root.is_leaf());
+        assert_eq!(root.get_frequency(), 15);
+    }
+}
+
+impl Ord for Node {
+    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
+        return self.frequency.cmp(&other.frequency)
+    }
+}
+
+impl PartialOrd for Node {
+    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
+        return Some(self.frequency.cmp(&other.frequency))
+    }
+}
+
+impl Eq for Node {
+
+}
+
+impl PartialEq for Node {
+    fn eq(&self, other: &Self) -> bool {
+        return self.frequency == other.frequency
+    }
+}