Generating competition rankings

Descriptions of the various ranking strategies can be found here: Wikipedia: Ranking

Standard competition ranking, "1224"

Idea: Start with ranking 1, assign same as previous if score is equal, otherwise assign index + 1.

// scores = [10, 15, 15, 20]  (sorted)
int[] rankings = new int[scores.length];
rankings[0] = 1;
for (int i = 1; i < rankings.length; i++)
    rankings[i] = scores[i] == scores[i - 1] ? rankings[i - 1] : i + 1;
// rankings = [1, 2, 2, 4]

Modified competition ranking, "1334"

Idea: Same as above, but start from the end:

int[] rankings = new int[scores.length];
rankings[scores.length - 1] = scores.length;
for (int i = rankings.length - 2; i >= 0; i--)
    rankings[i] = scores[i] == scores[i + 1] ? rankings[i + 1] : i + 1;
// rankings = [1, 3, 3, 4]

Dense ranking, "1223"

Idea: Increment ranking only if current score differs from previous:

int[] rankings = new int[scores.length];
rankings[0] = 1;
for (int i = 1, r = 1; i < rankings.length; i++)
    rankings[i] = scores[i] == scores[i - 1] ? r : ++r;
// rankings = [1, 2, 2, 3]

Ordinal ranking, "1234"

Trivial: Ranking equals index + 1.

The key desirable property in ordinal ranking is that it's stable. Luckily Arrays.sort, Collections.sort and List.sort are all stable.

Fractional ranking, "1 2½ 2½ 4"

List<Integer> clusters = new ArrayList<>();
clusters.add(1);
for (int i = 1; i < scores.length; i++) {
    if (scores[i] == scores[i - 1]) {
        int last = clusters.size() - 1;
        clusters.set(last, clusters.get(last) + 1);
    } else {
        clusters.add(1);
    }
}
double[] rankings = new double[scores.length];
int index = 0;
for (int cluster : clusters) {
    double ranking = index + (1 + cluster) / 2.0;
    Arrays.fill(rankings, index, index += cluster, ranking);
}
// rankings = [1, 2.5, 2.5, 4]

Comments

Be the first to comment!