1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
/// #License /// MIT or APPACHE 2. Use at your own risk, I'm basically a sweaty gorilla that can press computer keys and this is my first published crate. fn sockball<T>(a: usize, b: T) -> (T, usize) { //couples any type T with a usize index value return (b, a); //returns a unnamed tupple type, INDEX last } /// vector.rank() borrows a generic vector and returns a usize vector list of the count of greater items for each item. A rank system described by Wassily Hoeffding in 1947 that's like the olympics, but with a zeroth place instead of gold. /// the intended use for rank() is nonparametric statistics. pub fn rank_count_greater<T: PartialOrd + Clone>(vector: &Vec<T>) -> Vec<usize> { //pass in a vector, pass out a sorted list of positions, not values A,C,B -> 1,3,2 if vector.len() < 2 { if vector.is_empty() { let temp: Vec<usize> = vec![]; return temp; } //empty vector for empty vector return vec![0usize]; //return zero as nothing else is larger than first element. } let index: Vec<usize> = (0..vector.len()).collect(); let mut tups = vec![]; for i in 0..index.len() { tups.push(sockball(index[i], vector[i].clone())); //need to clone borrowed vector to sort //note: sockball takes index and vector and returns [vector and index] } tups.sort_by(|a, b| a.partial_cmp(b).unwrap()); //now tups is sorted and index has become elemental position order from low to high let mut fetchorder: Vec<usize> = vec![]; let mut fetchclone: Vec<usize> = vec![]; let mut ranking: Vec<usize> = vec![0]; //first or largest element must be zero for each in tups { let indey = each.1; let index = each.1; fetchorder.push(index); // pull apart tups into fetch ordering and value vector; fetchclone.push(indey); } let mut rank: usize = 0; //three preinit's before while loop let mut same: usize = 0; let mut last: usize = fetchorder.pop().unwrap(); //Already insured vector contains two elements, so unwrap while !fetchorder.is_empty() { let next: usize = fetchorder.pop().unwrap(); //while loop exits when empty so ok to unwrap & does not run on None() condition if vector[last] > vector[next] { rank = rank + 1 + same; same = 0; ranking.push(rank); // print!(">{} ",last); } else { same = same + 1; //print!("={} ",last); ranking.push(rank); } last = next; } //count of greater than items now exists that may be correlated unsorted order //fetchorder is empty let _iterator = 0usize; let mut fetchorder: Vec<usize> = vec![]; for _i in 0..vector.len() { // simple costs "do twice" brush up on box fetchorder.push(0usize); } for i in fetchclone { fetchorder[i] = ranking.pop().unwrap(); //ranking built in reverse order } //rebuild fetchorder return fetchorder; } /// vector.fetch(&my_borrowed_usize_list) will return a vector of your usized picks. Error tollerant and useful for user guided selective statistics, computation of quatriles and building custom scrolling levels out of 8 bit character bitmaps from selections that previously caused the most player deaths (maybe?) /// use one of two ways: genericvector.fetch(&vector_usize_index_picks) or from the function with fetch_guard(&genericvector, &your_usize_picklist) /// #Example /// use frank::Fetching; /// fn test_fetch() { /// let a = vec!["oh", "1", "two", "3", "four"]; /// let pick = vec![4usize, 0, 4]; /// let lost = a.fetch(&pick); /// println!("{:?}", lost); /// } pub fn fetch_guard<T: Clone>(vector: &Vec<T>, picks: &Vec<usize>) -> Vec<T> { //a error tollerant function that gathers picks items from a vector list let limit = vector.len(); let mut result = vec![]; for each in picks { //I don't like the idea of checking each item to be within bounds for production software, but I also write genetic algorithms and expect unforseen behavior. if *each < limit { result.push(vector[*each].clone()) } else { eprint!("!Warn! fn fetch_guard: No item index {} in vec list of {} items. Returning computable results!\n",*each,limit); } } return result; } /// fetch_fast has no slow branching if-then checks on index values, it just returns what it is asked to and terminates program if out of index. pub fn fetch_fast<T: Clone>(vector: &Vec<T>, picks: &Vec<usize>) -> Vec<T> { // picks items from a vector list let limit = vector.len(); let mut result = vec![]; for each in picks { result.push(vector[*each].clone()) } return result; } /// frank::Fetching can be implemented for generic vectors that support Clone with 'use frank::Fetching;' It allows vector.fetch(&your_picks_vec_usize) and vector.fetch_guard(&your_picks_vec_usize). fetch is fast and fetch_guard is index guarded, won't terminate but does eprint!'s index errors and still returns computable results. pub trait Fetching<T: Clone> { //A new trait to apply to data fn fetch(&self, index: &Vec<usize>) -> Vec<T>; fn fetch_guard(&self, index: &Vec<usize>) -> Vec<T>; //index: &Vec<usize> is pretty specific and not very flexible or DRY. } impl<T> Fetching<T> for Vec<T> //This line is high idea density. <T> may refer to the memory lifetime of the type or the Vector of type <T> where T: Clone, //T needs to have a trait 'Clone' (can be copied) for FetchGuards to work. Not all situations allow memory safely faithfully copies { fn fetch(&self, index: &Vec<usize>) -> Vec<T> { //the method will be implemented thus: myvector.fetch( picklist ) and return a new vector of type <T> fetch_fast(&self, &index) //Note it borrows the original vector. } fn fetch_guard(&self, index: &Vec<usize>) -> Vec<T> { //the method will be implemented thus: myvector.fetch( picklist ) and return a new vector of type <T> fetch_guard(&self, &index) //Note it borrows the original vector. } } /// frank::Ranking can be used with any generic vector that implements PartialOrd and Clone, and will return rankings from "greatest = 0" to least. just 'use frank::Ranking' for bolt on vector ranking functions like 'let myranks = myvector.rank();' Useful for non-parametric statistics like the difference between vec![82, 65, 78, 69, 68].rank() and vec!["r","a","n","k","ed"].rank() pub trait Ranking<T>: Clone + PartialOrd { fn rank(&self) -> Vec<usize>; } impl<T> Ranking<T> for Vec<T> where T: Clone + PartialOrd, { fn rank(&self) -> Vec<usize> { rank_count_greater(self) } } fn main() { /// RRANK is a crate that does "counts of greater values" in the style of Wassily Hoeffding for generic vectors. /// Code by Dustan Doud of Cancellogic.com /// #Examples /// /// let let mut avec = vec![167, 205, 98, 9, 205]; /// let mut avec = vec![167, 205, 98, 9, 205]; ///{ /// println!("vector: {:?} and ranks:{:?}", &avec, avec.rank() ); /// } /// avec.push(5); /// let mut bvec:Vec<f64> = vec![]; /// for each in avec {bvec.push(each as f64)}; /// println!("a vector of floating points:\n {:?} and ranks {:?}",&bvec,bvec.rank() ); /// let svec = vec!["r","a","n","k","ed"]; /// println!("a vector of floating points:\n {:?} and ranks {:?}",&svec,svec.rank() ); /// println!("A Wassily Hoeffding style ranking crate for generic vectors that counts number of greater values for each item in a vector and returns a vector of usize with counts. \n Coded by Dustan Doud cancellogic.com \n example vec![11,5,2].rank() = {:?}",vec![11,5,2].rank()); /// let avec = vec!["s","o","r","t"]; /// let picklist = vec![2,1,3,1,2,0]; /// let restructured = avec.fetch(&picklist); /// let empty:Vec<f64> = vec![0.0]; /// println!["test of vector.fetch() functionality: {:?}",empty.fetch(&picklist)]; let _are_we_done_yet = true; }