commit 2188ade9c73ce38936617ab22536dc3941be1d3f Author: Walter Oggioni Date: Sat Dec 28 16:50:04 2019 +0100 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..53eaa21 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +**/*.rs.bk diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..e969c28 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "levtree" +version = "0.1.0" +authors = ["Walter Oggioni "] + +[dependencies] + +[[bin]] +name = "linked_list" +path = "src/linked_list.rs" + +[[bin]] +name = "levtree" +#path = "src/test.rs" +path = "src/main.rs" diff --git a/src/levtree.rs b/src/levtree.rs new file mode 100644 index 0000000..4b20979 --- /dev/null +++ b/src/levtree.rs @@ -0,0 +1,145 @@ +use std::collections::HashMap; + +struct Node { + key: char, + row: Vec, + prev: usize, + next: usize, + child: usize, + parent: usize, + processed: bool +} + +impl Node { + fn new(key: char) -> Node { + Node { + key, + row: Vec::new(), + prev: 0, + next: 0, + child: 0, + parent: 0, + processed: false, + } + } +} + +pub struct Result { + word: std::rc::Rc, + distance: usize, +} + +impl PartialOrd for Result { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.distance.cmp(&other.distance)) + } +} + +impl PartialEq for Result { + fn eq(&self, other: &Self) -> bool { + self.distance == other.distance + } +} + +impl Eq for Result {} + +impl Ord for Result { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.distance.cmp(&other.distance) + } +} +//struct Standing { +// size: usize, +// results: Vec, +//} +// +//impl Standing { +// pub fn new(size: usize) -> Standing { +// Standing { +// size, +// results: BTreeSet::new(), +// } +// } +// +// pub fn addResult(&mut self, res: Result) { +// self.results.push(res) +// } +//} + +pub struct Tree { + maxsize: usize, + allocated: bool, + torealloc: bool, + nodes : Vec, + checker: fn(c1: char, c2: char) -> bool, + distance_calculator: fn() -> usize, + words : HashMap +} + +impl Tree { + pub fn new(words: Vec) -> Tree { + let mut result = Tree { + maxsize: words.len(), + allocated: false, + torealloc: false, + nodes : vec!(Node::new('\0')), + checker: |c1: char, c2: char| c1 == c2, + distance_calculator: || -> usize { 0 }, + words : HashMap::new() + }; + result.build_tree(words); + result + } + + fn root(&mut self) -> &mut Node { + &mut self.nodes[0] + } + + fn add_child(&mut self, parent_index : usize, key : char) -> usize { + let mut new_child = Node::new(key); + new_child.parent = parent_index; + let mut child = self.nodes[parent_index].child; + let mut prev = child; + while child != 0 { + prev = child; + child = self.nodes[child].next + } + new_child.prev = prev; + self.nodes.push(new_child); + let new_child_index = self.nodes.len(); + if prev != 0 { + self.nodes[prev].next = new_child_index; + } + if self.nodes[parent_index].child == 0 { + self.nodes[parent_index].child = new_child_index + } + self.nodes.len() - 1 + } + + fn build_tree(&mut self, words : Vec) { + for word in words { + let mut nindex = 0; + for c in word.chars() { + if self.nodes[nindex].child == 0 { + nindex = self.add_child(nindex, c); + } else { + nindex = self.nodes[nindex].child; + loop { + if self.nodes[nindex].key == c { + break + } else { + if self.nodes[nindex].next == 0 { + nindex = self.add_child(nindex, c); + break + } else { + nindex = self.nodes[nindex].next; + } + } + } + } + } + let leaf = self.add_child(nindex, '\0'); + self.words.insert(leaf, word); + } + } +} diff --git a/src/linked_list.rs b/src/linked_list.rs new file mode 100644 index 0000000..5803494 --- /dev/null +++ b/src/linked_list.rs @@ -0,0 +1,153 @@ +use std::mem; +use std::ptr; + +pub struct List { + list_head: Option>>, + list_tail: Rawlink>, +} + +struct Rawlink { p: *mut T } + +impl Copy for Rawlink {} + +impl Clone for Rawlink { + fn clone(&self) -> Self { Rawlink { p: self.p } } +} + +pub struct Node { + next: Option>>, + prev: Rawlink>, + value: T, +} + +impl List { + pub fn is_empty(&self) -> bool { + self.list_head.is_none() + } + + pub fn len(&self) -> usize { + let mut node = &self.list_head; + let mut i = 0; + loop { + match *node { + Some(ref n) => { + i+=1; + node=&n.next; + } + None => { + return i; + } + } + } + } + + /// Create an empty DList + pub fn new() -> List { + List{list_head: None, list_tail: Rawlink::none()} + } + + pub fn push_front(&mut self, elt: T) { + self.push_front_node(Box::new(Node::new(elt))) + } + + pub fn push_front_node(&mut self, mut new_head: Box>) { + match self.list_head { + None => { + self.list_tail = Rawlink::some(&mut new_head); + new_head.prev = Rawlink::none(); + self.list_head = Some(new_head); + } + Some(ref mut head) => { + new_head.prev = Rawlink::none(); + head.prev = Rawlink::some(&mut new_head); + mem::swap(head, &mut new_head); + head.next = Some(new_head); + } + } + } + + /// Provide a forward iterator + #[inline] + pub fn iter<'a>(&'a self) -> ListIterator<'a, T> { + ListIterator{nelem: self.len(), head: &self.list_head, tail: self.list_tail} + } +} + +impl Node { + fn new(v: T) -> Node { + Node{value: v, next: None, prev: Rawlink::none()} + } +} + +/// Rawlink is a type like Option but for holding a raw pointer +impl Rawlink { + /// Like Option::None for Rawlink + fn none() -> Rawlink { + Rawlink{p: ptr::null_mut()} + } + + /// Like Option::Some for Rawlink + fn some(n: &mut T) -> Rawlink { + Rawlink{p: n as *mut T} + } + + /// Convert the `Rawlink` into an Option value + fn resolve_immut<'a>(&self) -> Option<&'a T> { + unsafe { self.p.as_ref() } + } + + /// Convert the `Rawlink` into an Option value + fn resolve<'a>(&mut self) -> Option<&'a mut T> { + unsafe { self.p.as_mut() } + } + + /// Return the `Rawlink` and replace with `Rawlink::none()` + fn take(&mut self) -> Rawlink { + mem::replace(self, Rawlink::none()) + } +} + +pub struct ListIterator<'a, T: 'a> { + head: &'a Option>>, + tail: Rawlink>, + nelem: usize, +} + +impl<'a, A> Iterator for ListIterator<'a, A> { + type Item = &'a A; + + #[inline] + fn next(&mut self) -> Option<&'a A> { + if self.nelem == 0 { + return None; + } + self.head.as_ref().map(|head| { + self.nelem -= 1; + self.head = &head.next; + &head.value + }) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + (self.nelem, Some(self.nelem)) + } +} + +impl<'a, A> DoubleEndedIterator for ListIterator<'a, A> { + #[inline] + fn next_back(&mut self) -> Option<&'a A> { + if self.nelem == 0 { + return None; + } + let tmp = self.tail.resolve_immut(); + tmp.as_ref().map(|prev| { + self.nelem -= 1; + self.tail = prev.prev; + &prev.value + }) + } +} + +fn main() { +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..b52b8c7 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,20 @@ +mod levtree; + +use std::fs::File; +//use std::io::prelude::*; +use std::io::BufReader; +use std::io::BufRead; + +fn main() { + //let mut words : Vec = Vec::new(); + //let infile : File = try!(File::open("/usr/share/dict/cracklib-small")); + let filename = "/usr/share/dict/cracklib-small"; + let infile : File = File::open(filename).expect( + &format!("Error opening {}:", &filename) + ); + let reader = BufReader::new(infile); + let tree = levtree::Tree::new( + reader.lines() + .map(|line| line.unwrap()) + .collect()); +} diff --git a/src/test.rs b/src/test.rs new file mode 100644 index 0000000..fa4ab23 --- /dev/null +++ b/src/test.rs @@ -0,0 +1,6 @@ + + +fn main(){ + let mut ints = vec!(1,2,3,4,5,6); + ints[4] = 2; +} \ No newline at end of file