-2

I'm a bit rusted with c++ and after one day of thinking I coulnd't come out with an efficient way of computing this problem.

Suppose I have an array of 5 float values

lints[5]={0, 0.5, 3, 0, 0.6};

I would like to introduce a new array: ranks[5] that contains the ascending rank of the non-0 values of the array lints.

in this case the answer would read

ranks[1]=0;

ranks[2]=1;

ranks[3]=3;

ranks[4]=0;

ranks[5]=2;

In this example the 0 values returns rank 0 but they're not relevant since i only need the rank of positive values.

Thanks in advance

edit: Thanks to everybody for help, this is what I found suiting my needs in case you have the same task :)

double lengths[5], ranks[5];
double temp;
int i,j;

lengths[0] = 2,lengths[1] = 0,lengths[2] = 1,lengths[3] = 0,lengths[4] = 4;
ranks[0] = 1, ranks[1] = 2, ranks[2] = 3, ranks[3] = 4, ranks[4] = 5;

for(i=0;i<4;i++){
    for(j=0;j<4-i;j++){
        if((lengths[j]>lengths[j+1] && lengths[j+1]) || lengths[j]==0){
            // swap lenghts
            temp=lengths[j];
            lengths[j]=lengths[j+1];
            lengths[j+1]=temp;
            // swap ranks
            temp=ranks[j];
            ranks[j]=ranks[j+1];
            ranks[j+1]=temp;
        } 
    }
}    

cheers.

  • you can sort a vector of a struct that contains the numbers and the original position in the array. After sorting this, you can use the original index to create the wanted array – 463035818_is_not_an_ai Dec 16 '16 at 14:37
  • 2
    `ranks[5]=2;` You have undefined behaviour – Guillaume Racicot Dec 16 '16 at 14:38
  • he means ranks[4] == 2 should be true – cokceken Dec 16 '16 at 14:40
  • The solution could be a sorted index array that points to the data, with zeros for ignored values. An answer to a [similar question](http://stackoverflow.com/questions/1577475/c-sorting-and-keeping-track-of-indexes) could help. – Lyth Dec 16 '16 at 14:41

3 Answers3

0

You can use any sorting algorithm with a simple addition. When swapping 2 values you can swap index values too.

Create index values for initial indexes

ranks[5] = {1,2,3,4,5}; //or 0,1,2,3,4

for (int i = 0 ; i < 5 ; i++){
    for(int j = 0 ; j < 5 ; j++){
        //if array[i] < array[j]
        //swap array[i] - array[j]
        //swap ranks[i] - ranks[j]
    }
}
cokceken
  • 2,068
  • 11
  • 22
0

As @cokceken said (I know answers shouldn't refer to other answers but I'm not a high enough Stack Overflow rank to comment on answers :/ ), use any simple sorting algorithm, and simply add in your own functionality for any special cases, such as values of 0 or negative values in your example.

For example, assuming you don't actually want to sort the original array and just create a new array that links indices in the array to their sorted rank,

array[arraySize] = // insert array here;
ranks[arraySize];

for (int i = 0; i < arraySize; i++){
    int indexRank = 0;
    for (int j = 0; j < arraySize; j++){
        if (array[j] < array[i]){
            indexRank++;
        }
    }
    if (array[i] <= 0) {
        ranks[i] = -1 // or whatever implementation you want here
    } else {
        ranks[i] = indexRank;
    }
}

(note that arraySize must be a value and not a variable, since C++ does not let you statically define an array with a variable size)

aitalo
  • 13
  • 3
0

I found this was easier if you keep separate values for the value, original position and the rank in a class:

#include <vector>
#include <iostream>
#include <algorithm>

struct Item {
    float value;
    int original_position;
    int rank;
};

int main() {
    float lints[5] = {0, 0.5, 3, 0, 0.6};
    std::vector<Item> items{};
    int index{};
    for(auto i : lints)
        items.push_back(Item{i,index++,0}); // assign index to original_position
    std::sort(items.begin(), items.end(), [](auto& l, auto& r) {return l.value < r.value; }); // sort by float value
    auto it = std::find_if(items.begin(), items.end(), [](auto& i) {return i.value > 0; }); // find first non-zero position (as iterator)
    int new_rank_value{1}; // start numbering non-zero numbers from 1
    std::for_each(it, items.end(), [&new_rank_value](auto& i) {i.rank = new_rank_value++; }); // assign non-zero numbers a rank value
    std::sort(items.begin(), items.end(), [](auto& l, auto& r) {return l.original_position < r.original_position ; }); // sort by original position again
    for(auto i : items) 
        std::cout << "ranks[" << i.original_position << "]=" << i.rank << ";\n";
}

Output:

ranks[0]=0;
ranks[1]=1;
ranks[2]=3;
ranks[3]=0;
ranks[4]=2;
wally
  • 10,717
  • 5
  • 39
  • 72