summaryrefslogtreecommitdiff
path: root/009/ch2.pl
blob: fa2a1b024c56b2eb24dc6899d16cce5c6755a297 (plain) (blame)
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
#!/usr/bin/env perl
#
# Write a script to perform different types of ranking as described below:
#
# 1. Standard Ranking (1224): Items that compare equal receive the same ranking
# number, and then a gap is left in the ranking numbers.
# 2. Modified Ranking (1334): It is done by leaving the gaps in the ranking
# numbers before the sets of equal-ranking items.
# 3. Dense Ranking (1223): Items that compare equally receive the same ranking
# number, and the next item(s) receive the immediately following ranking number.
#
# (https://en.wikipedia.org/wiki/Ranking)
##############################################################################

use strict;
use warnings;

sub rank {
    my $rank_type = shift;
    my @points = sort @_;

    my %ranks;
    my $rank = $rank_type eq "modified" ? 0 : 1;

    my $interval_begin = 0;
    my $i;
    for ($i = 0; $i < @points; $i++) {
        my $point = $points[$i];
        if ($point != $points[$interval_begin]) {
            my @points_to_add = @points[$interval_begin .. ($i-1)];
            $rank += @points_to_add if $rank_type eq "modified";
            $ranks{$rank} = \@points_to_add;
            if ($rank_type eq "standard") {
                $rank += @points_to_add;
            } elsif ($rank_type eq "dense") {
                $rank = $rank + 1;
            }
            $interval_begin = $i;
        }
    }
    my @points_to_add = @points[$interval_begin .. ($i-1)];
    $rank += @points_to_add if $rank_type eq "modified";
    $ranks{$rank} = \@points_to_add;
    return \%ranks;
}

# Get rank type and points as CLI arguments
my $rank_type = shift || "";
grep /^$rank_type$/, qw(modified standard dense)
    or die "Usage: $0 {modified, standard, dense} rank1 rank2 ...";
my @points = @ARGV;

# Compute rankings
my $ranks = rank($rank_type, @points);

# Display rankings
foreach my $rank (sort (keys %$ranks)) {
    my @positions = @{$ranks->{$rank}};
    print "$rank. @positions\n";
}