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
///#Description
///Rank and Fetch adds generic vector ranking and fetching  features.  It adds vector.rank() and vector.fetch(&my_vec__usize_picks) functionality.
///rank() counts the number of items in a generic vector and returns the a vector of counts for each item greater than itself.  Useful for nonparametric statistics with order rather than distances.
///fetch() is intended for user specified subsampling of generic data, and tolerates index errors, but could be used for building old school 8bit character based  levels.
/// 
/// This is the early days in rust for me, and my first published crate.  I like what it does and it seems to work well enough.  Please leave feedback if
/// 
/// #License
/// Creative Commons Zero.  Use at your own risk, I'm basically a sweaty gorilla that can press computer keys and this is my first published crate.  

///  Oh, bonus:  fn sockball is used to pair an index value to a generic value.  Useful, but maybe only if you want to couple tuples for reversing a vector sort.
pub 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 us 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 scrolling levels out of 8 bit character bitmaps (maybe?)
/// use one of two ways:  genericvector.fetch(&vector_usize_index_picks)    or  from the function with fetch_guard(&genericvector, &your_usize_picklist) 
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 {
        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;
}
///
pub trait FetchGuards<T: Clone> {
    //A new trait to apply to data
    fn fetch(&self, index: &Vec<usize>) -> Vec<T>; //index: &Vec<usize> is pretty specific and not very flexible or DRY.
} //Dry means Don't Repeat Yourself.  Re-write for use with [boxes] or hashes or whatever.

impl<T> FetchGuards<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_guard(&self, &index) //Note it borrows the original vector.
    }
}

pub trait Rankable<T>: Clone + PartialOrd {
    fn rank(&self) -> Vec<usize>;
}
impl<T> Rankable<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;
}