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;
}