initial commit
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/target
|
||||||
|
**/*.rs.bk
|
15
Cargo.toml
Normal file
15
Cargo.toml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
[package]
|
||||||
|
name = "levtree"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Walter Oggioni <oggioni.walter@gmail.com>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "linked_list"
|
||||||
|
path = "src/linked_list.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "levtree"
|
||||||
|
#path = "src/test.rs"
|
||||||
|
path = "src/main.rs"
|
145
src/levtree.rs
Normal file
145
src/levtree.rs
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
struct Node {
|
||||||
|
key: char,
|
||||||
|
row: Vec<u32>,
|
||||||
|
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<String>,
|
||||||
|
distance: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for Result {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||||
|
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<Result>,
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//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<Node>,
|
||||||
|
checker: fn(c1: char, c2: char) -> bool,
|
||||||
|
distance_calculator: fn() -> usize,
|
||||||
|
words : HashMap<usize, String>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Tree {
|
||||||
|
pub fn new(words: Vec<String>) -> 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<String>) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
153
src/linked_list.rs
Normal file
153
src/linked_list.rs
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
use std::mem;
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
pub struct List<T> {
|
||||||
|
list_head: Option<Box<Node<T>>>,
|
||||||
|
list_tail: Rawlink<Node<T>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Rawlink<T> { p: *mut T }
|
||||||
|
|
||||||
|
impl<T> Copy for Rawlink<T> {}
|
||||||
|
|
||||||
|
impl<T> Clone for Rawlink<T> {
|
||||||
|
fn clone(&self) -> Self { Rawlink { p: self.p } }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Node<T> {
|
||||||
|
next: Option<Box<Node<T>>>,
|
||||||
|
prev: Rawlink<Node<T>>,
|
||||||
|
value: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> List<T> {
|
||||||
|
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<T> {
|
||||||
|
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<Node<T>>) {
|
||||||
|
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<T> Node<T> {
|
||||||
|
fn new(v: T) -> Node<T> {
|
||||||
|
Node{value: v, next: None, prev: Rawlink::none()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Rawlink is a type like Option<T> but for holding a raw pointer
|
||||||
|
impl<T> Rawlink<T> {
|
||||||
|
/// Like Option::None for Rawlink
|
||||||
|
fn none() -> Rawlink<T> {
|
||||||
|
Rawlink{p: ptr::null_mut()}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Like Option::Some for Rawlink
|
||||||
|
fn some(n: &mut T) -> Rawlink<T> {
|
||||||
|
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<T> {
|
||||||
|
mem::replace(self, Rawlink::none())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ListIterator<'a, T: 'a> {
|
||||||
|
head: &'a Option<Box<Node<T>>>,
|
||||||
|
tail: Rawlink<Node<T>>,
|
||||||
|
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<usize>) {
|
||||||
|
(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() {
|
||||||
|
}
|
20
src/main.rs
Normal file
20
src/main.rs
Normal file
@@ -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<String> = 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());
|
||||||
|
}
|
6
src/test.rs
Normal file
6
src/test.rs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
fn main(){
|
||||||
|
let mut ints = vec!(1,2,3,4,5,6);
|
||||||
|
ints[4] = 2;
|
||||||
|
}
|
Reference in New Issue
Block a user