Ranking methods: Difference between revisions
m (→{{header|Wren}}: Minor tidy) |
|||
(57 intermediate revisions by 23 users not shown) | |||
Line 1: | Line 1: | ||
{{task}} |
{{task|Sorting Algorithms}} |
||
[[Category:Sorting]] |
|||
{{Sorting Algorithm}} |
|||
The numerical rank of competitors in a competition shows if one is better than, equal to, or worse than another based on their results in a competition. |
The numerical rank of competitors in a competition shows if one is better than, equal to, or worse than another based on their results in a competition. |
||
The numerical rank of a competitor can be assigned in several [[wp:Ranking|different ways]]. |
The numerical rank of a competitor can be assigned in several [[wp:Ranking|different ways]]. |
||
;Task: |
;Task: |
||
Line 20: | Line 24: | ||
# Ordinal. ((Competitors take the next available integer. Ties are not treated otherwise). |
# Ordinal. ((Competitors take the next available integer. Ties are not treated otherwise). |
||
# Fractional. (Ties share the mean of what would have been their ordinal numbers). |
# Fractional. (Ties share the mean of what would have been their ordinal numbers). |
||
<br> |
|||
See the [[wp:Ranking|wikipedia article]] for a fuller description. |
See the [[wp:Ranking|wikipedia article]] for a fuller description. |
||
Show here, on this page, the ranking of the test scores under each of the numbered ranking methods. |
Show here, on this page, the ranking of the test scores under each of the numbered ranking methods. |
||
<br><br> |
|||
=={{header|11l}}== |
|||
{{trans|Python}} |
|||
<syntaxhighlight lang="11l">F mc_rank([(Int, String)] iterable) |
|||
‘Modified competition ranking’ |
|||
[(Float, (Int, String))] r |
|||
V lastresult = -1 |
|||
[(Int, String)] fifo |
|||
L(item) iterable |
|||
I item[0] == lastresult |
|||
fifo [+]= item |
|||
E |
|||
V n = L.index |
|||
L !fifo.empty |
|||
r.append((n, fifo.pop(0))) |
|||
lastresult = item[0] |
|||
fifo [+]= item |
|||
L !fifo.empty |
|||
r.append((iterable.len, fifo.pop(0))) |
|||
R r |
|||
F sc_rank([(Int, String)] iterable) |
|||
‘Standard competition ranking’ |
|||
[(Float, (Int, String))] r |
|||
V lastresult = -1 |
|||
V lastrank = -1 |
|||
L(item) iterable |
|||
I item[0] == lastresult |
|||
r.append((lastrank, item)) |
|||
E |
|||
V n = L.index + 1 |
|||
r.append((n, item)) |
|||
lastresult = item[0] |
|||
lastrank = n |
|||
R r |
|||
F d_rank([(Int, String)] iterable) |
|||
‘Dense ranking’ |
|||
[(Float, (Int, String))] r |
|||
V lastresult = -1 |
|||
V lastrank = 0 |
|||
L(item) iterable |
|||
I item[0] == lastresult |
|||
r.append((lastrank, item)) |
|||
E |
|||
lastresult = item[0] |
|||
lastrank++ |
|||
r.append((lastrank, item)) |
|||
R r |
|||
F o_rank([(Int, String)] iterable) |
|||
‘Ordinal ranking’ |
|||
R enumerate(iterable, 1).map((i, item) -> ((Float(i), item))) |
|||
F f_rank([(Int, String)] iterable) |
|||
‘Fractional ranking’ |
|||
[(Float, (Int, String))] r |
|||
V last = -1 |
|||
[(Int, (Int, String))] fifo |
|||
L(item) iterable |
|||
I item[0] != last |
|||
I !fifo.empty |
|||
V mean = Float(sum(fifo.map(f -> f[0]))) / fifo.len |
|||
L !fifo.empty |
|||
r.append((mean, fifo.pop(0)[1])) |
|||
last = item[0] |
|||
fifo.append((L.index + 1, item)) |
|||
I !fifo.empty |
|||
V mean = sum(fifo.map(f -> f[0])) / fifo.len |
|||
L !fifo.empty |
|||
r.append((mean, fifo.pop(0)[1])) |
|||
R r |
|||
V scores = [(44, ‘Solomon’), |
|||
(42, ‘Jason’), |
|||
(42, ‘Errol’), |
|||
(41, ‘Garry’), |
|||
(41, ‘Bernard’), |
|||
(41, ‘Barry’), |
|||
(39, ‘Stephen’)] |
|||
print("\nScores to be ranked (best first):") |
|||
L(n, s) scores |
|||
print(‘ #2 #.’.format(n, s)) |
|||
L(ranker, ranking_method) [(sc_rank, ‘Standard competition ranking’), |
|||
(mc_rank, ‘Modified competition ranking’), |
|||
(d_rank, ‘Dense ranking’), |
|||
(o_rank, ‘Ordinal ranking’), |
|||
(f_rank, ‘Fractional ranking’)] |
|||
print("\n#.:".format(ranking_method)) |
|||
L(rank, score) ranker(scores) |
|||
print(‘ #3, (#., #.)’.format(rank, score[0], score[1]))</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Scores to be ranked (best first): |
|||
44 Solomon |
|||
42 Jason |
|||
42 Errol |
|||
41 Garry |
|||
41 Bernard |
|||
41 Barry |
|||
39 Stephen |
|||
Standard competition ranking: |
|||
1, (44, Solomon) |
|||
2, (42, Jason) |
|||
2, (42, Errol) |
|||
4, (41, Garry) |
|||
4, (41, Bernard) |
|||
4, (41, Barry) |
|||
7, (39, Stephen) |
|||
Modified competition ranking: |
|||
1, (44, Solomon) |
|||
3, (42, Jason) |
|||
3, (42, Errol) |
|||
6, (41, Garry) |
|||
6, (41, Bernard) |
|||
6, (41, Barry) |
|||
7, (39, Stephen) |
|||
Dense ranking: |
|||
1, (44, Solomon) |
|||
2, (42, Jason) |
|||
2, (42, Errol) |
|||
3, (41, Garry) |
|||
3, (41, Bernard) |
|||
3, (41, Barry) |
|||
4, (39, Stephen) |
|||
Ordinal ranking: |
|||
1, (44, Solomon) |
|||
2, (42, Jason) |
|||
3, (42, Errol) |
|||
4, (41, Garry) |
|||
5, (41, Bernard) |
|||
6, (41, Barry) |
|||
7, (39, Stephen) |
|||
Fractional ranking: |
|||
1, (44, Solomon) |
|||
2.5, (42, Jason) |
|||
2.5, (42, Errol) |
|||
5, (41, Garry) |
|||
5, (41, Bernard) |
|||
5, (41, Barry) |
|||
7, (39, Stephen) |
|||
</pre> |
|||
=={{header|ALGOL 68}}== |
|||
As with some but not all of the other samples, the ranking procedures here assume the data is already sorted. The procedures do check for empty data sets, though. |
|||
<syntaxhighlight lang="algol68"> |
|||
BEGIN # rank some scores by various methods # |
|||
# MODE to hold the scores # |
|||
MODE RESULT = STRUCT( INT score, STRING name ); |
|||
# returns the standard ranking of s # |
|||
PROC standard ranking = ( []RESULT s )[]INT: |
|||
IF LWB s > UPB s THEN []INT() # no scores # |
|||
ELSE # have some scores # |
|||
[ LWB s : UPB s ]INT ranked; |
|||
INT position := 1; |
|||
ranked[ LWB s ] := position; |
|||
FOR i FROM LWB s + 1 TO UPB s DO |
|||
ranked[ i ] := IF score OF s[ i ] = score OF s[ i - 1 ] THEN |
|||
# same score as the previous # |
|||
position |
|||
ELSE |
|||
# different score, increase the position # |
|||
position := i |
|||
FI |
|||
OD; |
|||
ranked |
|||
FI # standard ranking # ; |
|||
# returns the modified ranking of s # |
|||
PROC modified ranking = ( []RESULT s )[]INT: |
|||
IF LWB s > UPB s THEN []INT() # no scores # |
|||
ELSE # have some scores # |
|||
[ LWB s : UPB s ]INT ranked; |
|||
INT position := ( UPB s + 1 ) - LWB s; |
|||
ranked[ UPB s ] := position; |
|||
FOR i FROM UPB s - 1 BY -1 TO LWB s DO |
|||
ranked[ i ] := IF score OF s[ i ] = score OF s[ i + 1 ] THEN |
|||
# same score as the previous # |
|||
position |
|||
ELSE |
|||
# different score, decrease the position # |
|||
position := i |
|||
FI |
|||
OD; |
|||
ranked |
|||
FI # modified ranking # ; |
|||
# returns the debse ranking of s # |
|||
PROC dense ranking = ( []RESULT s )[]INT: |
|||
IF LWB s > UPB s THEN []INT() # no scores # |
|||
ELSE # have some scores # |
|||
[ LWB s : UPB s ]INT ranked; |
|||
INT position := 1; |
|||
ranked[ LWB s ] := position; |
|||
FOR i FROM LWB s + 1 TO UPB s DO |
|||
ranked[ i ] := IF score OF s[ i ] = score OF s[ i - 1 ] THEN |
|||
# same score as the previous # |
|||
position |
|||
ELSE |
|||
# different score, increase the position # |
|||
position +:= 1 |
|||
FI |
|||
OD; |
|||
ranked |
|||
FI # dense ranking # ; |
|||
# returns the ordinal ranking of s # |
|||
PROC ordinal ranking = ( []RESULT s )[]INT: |
|||
IF LWB s > UPB s THEN []INT() # no scores # |
|||
ELSE # have some scores # |
|||
[ LWB s : UPB s ]INT ranked; |
|||
INT position := 0; |
|||
FOR i FROM LWB s TO UPB s DO |
|||
ranked[ i ] := position +:= 1 |
|||
OD; |
|||
ranked |
|||
FI # ordinal ranking # ; |
|||
# regturns the fractional ranking of s # |
|||
PROC fractional ranking = ( []RESULT s )[]REAL: |
|||
IF LWB s > UPB s THEN []REAL() # no scores # |
|||
ELSE # have some scores # |
|||
[ LWB s : UPB s ]REAL ranked; |
|||
REAL position := 1; |
|||
FOR i FROM LWB s TO UPB s DO |
|||
ranked[ i ] |
|||
:= IF IF i = LWB s |
|||
THEN FALSE |
|||
ELSE score OF s[ i ] = score OF s[ i - 1 ] |
|||
FI |
|||
THEN |
|||
# same score as the previous # |
|||
ranked[ i - 1 ] |
|||
ELSE |
|||
# first score or different score to the previous # |
|||
INT same count := 1; |
|||
INT sum := i; |
|||
FOR j FROM i + 1 TO UPB s |
|||
WHILE score OF s[ i ] = score OF s[ j ] |
|||
DO |
|||
same count +:= 1; |
|||
sum +:= j |
|||
OD; |
|||
sum / same count |
|||
FI |
|||
OD; |
|||
ranked |
|||
FI # fractional ranking # ; |
|||
# shows the integer ranking of some scores # |
|||
PROC show integral ranking = ( []RESULT s, []INT ranking, STRING title )VOID: |
|||
BEGIN |
|||
print( ( title, " competition ranking:", newline ) ); |
|||
FOR i FROM LWB s TO UPB s DO |
|||
print( ( whole( ranking[ i ], -3 ) |
|||
, ": " |
|||
, whole( score OF s[ i ], -3 ) |
|||
, " " |
|||
, name OF s[ i ] |
|||
, newline |
|||
) |
|||
) |
|||
OD; |
|||
print( ( newline ) ) |
|||
END # show integral ranking # ; |
|||
# shows the real ranking of some scores # |
|||
PROC show real ranking = ( []RESULT s, []REAL ranking, STRING title )VOID: |
|||
BEGIN |
|||
print( ( title, " competition ranking:", newline ) ); |
|||
FOR i FROM LWB s TO UPB s DO |
|||
print( ( IF INT integer rank = ENTIER ranking[ i ]; |
|||
integer rank = ranking[ i ] |
|||
THEN |
|||
whole( integer rank, -3 ) + " " |
|||
ELSE |
|||
fixed( ranking[ i ], -6, 2 ) |
|||
FI |
|||
, ": " |
|||
, whole( score OF s[ i ], -3 ), " " |
|||
, name OF s[ i ] |
|||
, newline |
|||
) |
|||
) |
|||
OD; |
|||
print( ( newline ) ) |
|||
END # show real ranking # ; |
|||
# scores to rank - task test cases # |
|||
[]RESULT scores = ( ( 44, "Solomon" ) |
|||
, ( 42, "Jason" ) |
|||
, ( 42, "Errol" ) |
|||
, ( 41, "Garry" ) |
|||
, ( 41, "Bernard" ) |
|||
, ( 41, "Barry" ) |
|||
, ( 39, "Stephen" ) |
|||
); |
|||
show integral ranking( scores, standard ranking( scores ), "standard" ); |
|||
show integral ranking( scores, modified ranking( scores ), "modified" ); |
|||
show integral ranking( scores, dense ranking( scores ), "dense" ); |
|||
show integral ranking( scores, ordinal ranking( scores ), "ordinal" ); |
|||
show real ranking( scores, fractional ranking( scores ), "fractional" ) |
|||
END |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
standard competition ranking: |
|||
1: 44 Solomon |
|||
2: 42 Jason |
|||
2: 42 Errol |
|||
4: 41 Garry |
|||
4: 41 Bernard |
|||
4: 41 Barry |
|||
7: 39 Stephen |
|||
modified competition ranking: |
|||
1: 44 Solomon |
|||
3: 42 Jason |
|||
3: 42 Errol |
|||
6: 41 Garry |
|||
6: 41 Bernard |
|||
6: 41 Barry |
|||
7: 39 Stephen |
|||
dense competition ranking: |
|||
1: 44 Solomon |
|||
2: 42 Jason |
|||
2: 42 Errol |
|||
3: 41 Garry |
|||
3: 41 Bernard |
|||
3: 41 Barry |
|||
4: 39 Stephen |
|||
ordinal competition ranking: |
|||
1: 44 Solomon |
|||
2: 42 Jason |
|||
3: 42 Errol |
|||
4: 41 Garry |
|||
5: 41 Bernard |
|||
6: 41 Barry |
|||
7: 39 Stephen |
|||
fractional competition ranking: |
|||
1 : 44 Solomon |
|||
2.50: 42 Jason |
|||
2.50: 42 Errol |
|||
5 : 41 Garry |
|||
5 : 41 Bernard |
|||
5 : 41 Barry |
|||
7 : 39 Stephen |
|||
</pre> |
|||
=={{header|AppleScript}}== |
|||
<syntaxhighlight lang="applescript">use AppleScript version "2.3.1" -- Mac OS 10.9 (Mavericks) or later. |
|||
use sorter : script ¬ |
|||
"Custom Iterative Ternary Merge Sort" -- <www.macscripter.net/t/timsort-and-nigsort/71383/3> |
|||
(* The ranking methods are implemented as script objects sharing inherited code. *) |
|||
script standardRanking |
|||
-- Properties and handlers inherited or overridden by the other script objects. |
|||
-- The 'reference' is to a value that won't exist until 'results' is set to a list. |
|||
-- 'me' and 'my' pertain to the script object using the code at the time. |
|||
property results : missing value |
|||
property startIndex : 1 |
|||
property endIndex : a reference to my results's length |
|||
property step : 1 |
|||
property currentRank : missing value |
|||
property currentScore : missing value |
|||
-- Main handler. |
|||
on resultsFrom(theScores) |
|||
copy theScores to my results |
|||
tell sorter to sort(my results, my startIndex, my endIndex, {comparer:me}) |
|||
set my currentScore to my results's item (my startIndex)'s score |
|||
set my currentRank to my startIndex's contents |
|||
repeat with i from (my startIndex) to (my endIndex) by (my step) |
|||
my rankResult(i) |
|||
end repeat |
|||
set r to my results |
|||
set my results to missing value |
|||
return r |
|||
end resultsFrom |
|||
-- Comparison handler used by the sort. |
|||
on isGreater(a, b) |
|||
if (a's score < b's score) then return true |
|||
return ((a's score = b's score) and (a's competitor comes after b's competitor)) |
|||
end isGreater |
|||
-- Ranking handler. Inherited by the modifiedRanking script; overridden by the others. |
|||
on rankResult(i) |
|||
set thisResult to my results's item i |
|||
set thisScore to thisResult's score |
|||
if (thisScore is not currentScore) then |
|||
set my currentRank to i |
|||
set my currentScore to thisScore |
|||
end if |
|||
set my results's item i to thisResult & {rank:my currentRank} |
|||
end rankResult |
|||
end script |
|||
script modifiedRanking |
|||
property parent : standardRanking |
|||
property startIndex : a reference to my results's length |
|||
property endIndex : 1 |
|||
property step : -1 |
|||
end script |
|||
script denseRanking |
|||
property parent : standardRanking |
|||
on rankResult(i) |
|||
set thisResult to my results's item i |
|||
set thisScore to thisResult's score |
|||
if (thisScore is not my currentScore) then |
|||
set my currentRank to (my currentRank) + 1 |
|||
set my currentScore to thisScore |
|||
end if |
|||
set my results's item i to thisResult & {rank:my currentRank} |
|||
end rankResult |
|||
end script |
|||
script ordinalRanking |
|||
property parent : standardRanking |
|||
on rankResult(i) |
|||
set my results's item i to (my results's item i) & {rank:i} |
|||
end rankResult |
|||
end script |
|||
script fractionalRanking |
|||
property parent : standardRanking |
|||
on rankResult(i) |
|||
set thisResult to my results's item i |
|||
set thisScore to thisResult's score |
|||
if (thisScore is not my currentScore) then |
|||
-- The average of any run of consecutive integers is that of the first and last. |
|||
set average to (i - 1 + (my currentRank)) / 2 |
|||
repeat with j from (my currentRank) to (i - 1) |
|||
set my results's item j's rank to average |
|||
end repeat |
|||
set my currentRank to i |
|||
set my currentScore to thisScore |
|||
end if |
|||
set my results's item i to thisResult & {rank:i as real} |
|||
end rankResult |
|||
end script |
|||
-- Task code: |
|||
on formatRankings(type, theResults) |
|||
set rankings to {type} |
|||
repeat with thisResult in theResults |
|||
set end of rankings to (thisResult's rank as text) & tab & ¬ |
|||
thisResult's competitor & " (" & thisResult's score & ")" |
|||
end repeat |
|||
return join(rankings, linefeed) |
|||
end formatRankings |
|||
on join(lst, delim) |
|||
set astid to AppleScript's text item delimiters |
|||
set AppleScript's text item delimiters to delim |
|||
set txt to lst as text |
|||
set AppleScript's text item delimiters to astid |
|||
return txt |
|||
end join |
|||
local theScores, output |
|||
set theScores to {{score:44, competitor:"Solomon"}, {score:42, competitor:"Jason"}, ¬ |
|||
{score:42, competitor:"Errol"}, {score:41, competitor:"Garry"}, {score:41, competitor:"Bernard"}, ¬ |
|||
{score:41, competitor:"Barry"}, {score:39, competitor:"Stephen"}} |
|||
set output to {¬ |
|||
formatRankings("Standard ranking:", standardRanking's resultsFrom(theScores)), ¬ |
|||
formatRankings("Modified ranking:", modifiedRanking's resultsFrom(theScores)), ¬ |
|||
formatRankings("Dense ranking:", denseRanking's resultsFrom(theScores)), ¬ |
|||
formatRankings("Ordinal ranking:", ordinalRanking's resultsFrom(theScores)), ¬ |
|||
formatRankings("Fractional ranking:", fractionalRanking's resultsFrom(theScores)) ¬ |
|||
} |
|||
return join(output, linefeed & linefeed)</syntaxhighlight> |
|||
{{output}} |
|||
<syntaxhighlight lang="applescript">"Standard ranking: |
|||
1 Solomon (44) |
|||
2 Errol (42) |
|||
2 Jason (42) |
|||
4 Barry (41) |
|||
4 Bernard (41) |
|||
4 Garry (41) |
|||
7 Stephen (39) |
|||
Modified ranking: |
|||
1 Solomon (44) |
|||
3 Errol (42) |
|||
3 Jason (42) |
|||
6 Barry (41) |
|||
6 Bernard (41) |
|||
6 Garry (41) |
|||
7 Stephen (39) |
|||
Dense ranking: |
|||
1 Solomon (44) |
|||
2 Errol (42) |
|||
2 Jason (42) |
|||
3 Barry (41) |
|||
3 Bernard (41) |
|||
3 Garry (41) |
|||
4 Stephen (39) |
|||
Ordinal ranking: |
|||
1 Solomon (44) |
|||
2 Errol (42) |
|||
3 Jason (42) |
|||
4 Barry (41) |
|||
5 Bernard (41) |
|||
6 Garry (41) |
|||
7 Stephen (39) |
|||
Fractional ranking: |
|||
1.0 Solomon (44) |
|||
2.5 Errol (42) |
|||
2.5 Jason (42) |
|||
5.0 Barry (41) |
|||
5.0 Bernard (41) |
|||
5.0 Garry (41) |
|||
7.0 Stephen (39)"</syntaxhighlight> |
|||
=={{header|AutoHotkey}}== |
=={{header|AutoHotkey}}== |
||
< |
<syntaxhighlight lang="autohotkey">Rank(data, opt:=1){ ; opt = 1 Standard (default), 2 Modified, 3 Dense, 4 Ordinal, 5 Fractional |
||
for index, val in StrSplit(data, "`n", "`r") { |
for index, val in StrSplit(data, "`n", "`r") { |
||
RegExMatch(val, "^(\d+)\s+(.*)", Match) |
RegExMatch(val, "^(\d+)\s+(.*)", Match) |
||
Line 46: | Line 584: | ||
} |
} |
||
return Res%opt% |
return Res%opt% |
||
}</ |
}</syntaxhighlight> |
||
Example:< |
Example:<syntaxhighlight lang="autohotkey">data = |
||
( |
( |
||
44 Solomon |
44 Solomon |
||
Line 64: | Line 602: | ||
. "`nOrdinal Ranking:`n" Rank(data, 4) |
. "`nOrdinal Ranking:`n" Rank(data, 4) |
||
. "`nFractional Ranking:`n" Rank(data, 5) |
. "`nFractional Ranking:`n" Rank(data, 5) |
||
return</ |
return</syntaxhighlight> |
||
Output:<pre>Standard Ranking: |
Output:<pre>Standard Ranking: |
||
1 44 Solomon |
1 44 Solomon |
||
Line 109: | Line 647: | ||
5 41 Barry |
5 41 Barry |
||
7 39 Stephen</pre> |
7 39 Stephen</pre> |
||
=={{header|APL}}== |
|||
{{works with|Dyalog APL}} |
|||
These functions each take a 2-by-N matrix, where the first column contains |
|||
the score, and the second column contains the name. They return a 3-by-N |
|||
matrix, with the ranking added. |
|||
<syntaxhighlight lang="apl">standard ← ∊∘(⌊\¨⊢⊂⍳∘≢)∘(1,2≠/⊢)∘(1⌷[2]⊢),⊢ |
|||
modified ← ∊∘(⌈\∘⌽¨⊢⊂⍳∘≢)∘(1,2≠/⊢)∘(1⌷[2]⊢),⊢ |
|||
dense ← (+\1,2≠/1⌷[2]⊢),⊢ |
|||
ordinal ← ⍳∘≢,⊢ |
|||
fractional ← ∊∘((≢(/∘⊢)+/÷≢)¨⊢⊂⍳∘≢)∘(1,2≠/⊢)∘(1⌷[2]⊢),⊢</syntaxhighlight> |
|||
{{out}} |
|||
<pre> ⍝ Input scores table from task: |
|||
scores←⍉⍪44,⊂'Solomon' |
|||
scores⍪←42,⊂'Jason' |
|||
scores⍪←42,⊂'Errol' |
|||
scores⍪←41,⊂'Garry' |
|||
scores⍪←41,⊂'Bernard' |
|||
scores⍪←41,⊂'Barry' |
|||
scores⍪←39,⊂'Stephen' |
|||
⍝ Apply each function to it |
|||
standard scores |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
2 42 Errol |
|||
4 41 Garry |
|||
4 41 Bernard |
|||
4 41 Barry |
|||
7 39 Stephen |
|||
modified scores |
|||
1 44 Solomon |
|||
3 42 Jason |
|||
3 42 Errol |
|||
6 41 Garry |
|||
6 41 Bernard |
|||
6 41 Barry |
|||
7 39 Stephen |
|||
dense scores |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
2 42 Errol |
|||
3 41 Garry |
|||
3 41 Bernard |
|||
3 41 Barry |
|||
4 39 Stephen |
|||
ordinal scores |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
3 42 Errol |
|||
4 41 Garry |
|||
5 41 Bernard |
|||
6 41 Barry |
|||
7 39 Stephen |
|||
fractional scores |
|||
1 44 Solomon |
|||
2.5 42 Jason |
|||
2.5 42 Errol |
|||
5 41 Garry |
|||
5 41 Bernard |
|||
5 41 Barry |
|||
7 39 Stephen </pre> |
|||
=={{header|AWK}}== |
=={{header|AWK}}== |
||
{{trans|Python}} |
{{trans|Python}} |
||
This uses separate files for each method of ranking: |
This uses separate files for each method of ranking: |
||
< |
<syntaxhighlight lang="awk">## |
||
## Dense ranking in file: ranking_d.awk |
## Dense ranking in file: ranking_d.awk |
||
## |
## |
||
Line 213: | Line 821: | ||
} |
} |
||
//{sc_rank()} |
//{sc_rank()} |
||
</syntaxhighlight> |
|||
</lang> |
|||
The input as a file <code>ranking.txt</code>: |
The input as a file <code>ranking.txt</code>: |
||
Line 271: | Line 879: | ||
C:\Users\RC\Code></pre> |
C:\Users\RC\Code></pre> |
||
=={{header|BASIC}}== |
|||
<syntaxhighlight lang="basic">10 READ N |
|||
20 DIM S(N),N$(N),R(N) |
|||
30 FOR I=1 TO N: READ S(I),N$(I): NEXT |
|||
40 PRINT "--- Standard ranking ---": GOSUB 100: GOSUB 400 |
|||
50 PRINT "--- Modified ranking ---": GOSUB 150: GOSUB 400 |
|||
60 PRINT "--- Dense ranking ---": GOSUB 200: GOSUB 400 |
|||
70 PRINT "--- Ordinal ranking ---": GOSUB 250: GOSUB 400 |
|||
80 PRINT "--- Fractional ranking ---": GOSUB 300: GOSUB 400 |
|||
90 END |
|||
100 REM |
|||
101 REM ** Ordinal ranking ** |
|||
110 R(1)=1 |
|||
120 FOR I=2 TO N |
|||
130 IF S(I)=S(I-1) THEN R(I)=R(I-1) ELSE R(I)=I |
|||
140 NEXT: RETURN |
|||
150 REM |
|||
151 REM ** Modified ranking ** |
|||
160 R(N)=N |
|||
170 FOR I=N-1 TO 1 STEP -1 |
|||
180 IF S(I)=S(I+1) THEN R(I)=R(I+1) ELSE R(I)=I |
|||
190 NEXT: RETURN |
|||
200 REM |
|||
201 REM ** Dense ranking ** |
|||
210 R(1)=1 |
|||
220 FOR I=2 TO N: R(I)=R(I-1)-(S(I)<>S(I-1)): NEXT |
|||
230 RETURN |
|||
250 REM |
|||
251 REM ** Ordinal ranking ** |
|||
260 FOR I=1 TO N: R(I)=I: NEXT: RETURN |
|||
300 REM |
|||
301 REM ** Fractional ranking ** |
|||
310 I=1: J=2 |
|||
320 IF J<=N THEN IF S(J-1)=S(J) THEN J=J+1: GOTO 320 |
|||
330 FOR K=I TO J-1: R(K) = (I+J-1)/2: NEXT |
|||
340 I=J: J=J+1: IF I<=N THEN 320 |
|||
350 RETURN |
|||
400 REM |
|||
401 REM ** Print the table *** |
|||
410 FOR I=1 TO N |
|||
420 PRINT USING "\ \ ##, \ \";STR$(R(I));S(I);N$(I) |
|||
430 NEXT |
|||
440 PRINT: RETURN |
|||
500 DATA 7 |
|||
510 DATA 44,Solomon |
|||
520 DATA 42,Jason |
|||
530 DATA 42,Errol |
|||
540 DATA 41,Garry |
|||
550 DATA 41,Bernard |
|||
560 DATA 41,Barry |
|||
570 DATA 39,Stephen</syntaxhighlight> |
|||
{{out}} |
|||
<pre>--- Standard ranking --- |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
2 42 Errol |
|||
4 41 Garry |
|||
4 41 Bernard |
|||
4 41 Barry |
|||
7 39 Stephen |
|||
--- Modified ranking --- |
|||
1 44 Solomon |
|||
3 42 Jason |
|||
3 42 Errol |
|||
6 41 Garry |
|||
6 41 Bernard |
|||
6 41 Barry |
|||
7 39 Stephen |
|||
--- Dense ranking --- |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
2 42 Errol |
|||
3 41 Garry |
|||
3 41 Bernard |
|||
3 41 Barry |
|||
4 39 Stephen |
|||
--- Ordinal ranking --- |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
3 42 Errol |
|||
4 41 Garry |
|||
5 41 Bernard |
|||
6 41 Barry |
|||
7 39 Stephen |
|||
--- Fractional ranking --- |
|||
1 44 Solomon |
|||
2.5 42 Jason |
|||
2.5 42 Errol |
|||
5 41 Garry |
|||
5 41 Bernard |
|||
5 41 Barry |
|||
7 39 Stephen</pre> |
|||
=={{header|C}}== |
|||
Takes the scores as input via a file, prints out usage on incorrect invocation. |
|||
<syntaxhighlight lang="c"> |
|||
#include<stdlib.h> |
|||
#include<stdio.h> |
|||
typedef struct{ |
|||
int score; |
|||
char name[100]; |
|||
}entry; |
|||
void ordinalRanking(entry* list,int len){ |
|||
int i; |
|||
printf("\n\nOrdinal Ranking\n---------------"); |
|||
for(i=0;i<len;i++) |
|||
printf("\n%d\t%d\t%s",i+1,list[i].score,list[i].name); |
|||
} |
|||
void standardRanking(entry* list,int len){ |
|||
int i,j=1; |
|||
printf("\n\nStandard Ranking\n----------------"); |
|||
for(i=0;i<len;i++){ |
|||
printf("\n%d\t%d\t%s",j,list[i].score,list[i].name); |
|||
if(list[i+1].score<list[i].score) |
|||
j = i+2; |
|||
} |
|||
} |
|||
void denseRanking(entry* list,int len){ |
|||
int i,j=1; |
|||
printf("\n\nDense Ranking\n-------------"); |
|||
for(i=0;i<len;i++){ |
|||
printf("\n%d\t%d\t%s",j,list[i].score,list[i].name); |
|||
if(list[i+1].score<list[i].score) |
|||
j++; |
|||
} |
|||
} |
|||
void modifiedRanking(entry* list,int len){ |
|||
int i,j,count; |
|||
printf("\n\nModified Ranking\n----------------"); |
|||
for(i=0;i<len-1;i++){ |
|||
if(list[i].score!=list[i+1].score){ |
|||
printf("\n%d\t%d\t%s",i+1,list[i].score,list[i].name); |
|||
count = 1; |
|||
for(j=i+1;list[j].score==list[j+1].score && j<len-1;j++) |
|||
count ++; |
|||
for(j=0;j<count-1;j++) |
|||
printf("\n%d\t%d\t%s",i+count+1,list[i+j+1].score,list[i+j+1].name); |
|||
i += (count-1); |
|||
} |
|||
} |
|||
printf("\n%d\t%d\t%s",len,list[len-1].score,list[len-1].name); |
|||
} |
|||
void fractionalRanking(entry* list,int len){ |
|||
int i,j,count; |
|||
float sum = 0; |
|||
printf("\n\nFractional Ranking\n------------------"); |
|||
for(i=0;i<len;i++){ |
|||
if(i==len-1 || list[i].score!=list[i+1].score) |
|||
printf("\n%.1f\t%d\t%s",(float)(i+1),list[i].score,list[i].name); |
|||
else if(list[i].score==list[i+1].score){ |
|||
sum = i; |
|||
count = 1; |
|||
for(j=i;list[j].score==list[j+1].score;j++){ |
|||
sum += (j+1); |
|||
count ++; |
|||
} |
|||
for(j=0;j<count;j++) |
|||
printf("\n%.1f\t%d\t%s",sum/count + 1,list[i+j].score,list[i+j].name); |
|||
i += (count-1); |
|||
} |
|||
} |
|||
} |
|||
void processFile(char* fileName){ |
|||
FILE* fp = fopen(fileName,"r"); |
|||
entry* list; |
|||
int i,num; |
|||
fscanf(fp,"%d",&num); |
|||
list = (entry*)malloc(num*sizeof(entry)); |
|||
for(i=0;i<num;i++) |
|||
fscanf(fp,"%d%s",&list[i].score,list[i].name); |
|||
fclose(fp); |
|||
ordinalRanking(list,num); |
|||
standardRanking(list,num); |
|||
denseRanking(list,num); |
|||
modifiedRanking(list,num); |
|||
fractionalRanking(list,num); |
|||
} |
|||
int main(int argC,char* argV[]) |
|||
{ |
|||
if(argC!=2) |
|||
printf("Usage %s <score list file>"); |
|||
else |
|||
processFile(argV[1]); |
|||
return 0; |
|||
} |
|||
</syntaxhighlight> |
|||
Input file, first row is number of records : |
|||
<pre> |
|||
7 |
|||
44 Solomon |
|||
42 Jason |
|||
42 Errol |
|||
41 Garry |
|||
41 Bernard |
|||
41 Barry |
|||
39 Stephen |
|||
</pre> |
|||
Output : |
|||
<pre> |
|||
C:\rosettaCode>ranking.exe rankData.txt |
|||
Ordinal Ranking |
|||
--------------- |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
3 42 Errol |
|||
4 41 Garry |
|||
5 41 Bernard |
|||
6 41 Barry |
|||
7 39 Stephen |
|||
Standard Ranking |
|||
---------------- |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
2 42 Errol |
|||
4 41 Garry |
|||
4 41 Bernard |
|||
4 41 Barry |
|||
7 39 Stephen |
|||
Dense Ranking |
|||
------------- |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
2 42 Errol |
|||
3 41 Garry |
|||
3 41 Bernard |
|||
3 41 Barry |
|||
4 39 Stephen |
|||
Modified Ranking |
|||
---------------- |
|||
1 44 Solomon |
|||
3 42 Jason |
|||
3 42 Errol |
|||
6 41 Garry |
|||
6 41 Bernard |
|||
6 41 Barry |
|||
7 39 Stephen |
|||
Fractional Ranking |
|||
------------------ |
|||
1.0 44 Solomon |
|||
2.5 42 Jason |
|||
2.5 42 Errol |
|||
5.0 41 Garry |
|||
5.0 41 Bernard |
|||
5.0 41 Barry |
|||
7.0 39 Stephen |
|||
</pre> |
|||
=={{header|C sharp|C#}}== |
|||
{{trans|D}} |
|||
<syntaxhighlight lang="csharp">using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
namespace RankingMethods { |
|||
class Program { |
|||
static void Main(string[] args) { |
|||
Dictionary<string, int> scores = new Dictionary<string, int> { |
|||
["Solomon"] = 44, |
|||
["Jason"] = 42, |
|||
["Errol"] = 42, |
|||
["Gary"] = 41, |
|||
["Bernard"] = 41, |
|||
["Barry"] = 41, |
|||
["Stephen"] = 39, |
|||
}; |
|||
StandardRank(scores); |
|||
ModifiedRank(scores); |
|||
DenseRank(scores); |
|||
OrdinalRank(scores); |
|||
FractionalRank(scores); |
|||
} |
|||
static void StandardRank(Dictionary<string, int> data) { |
|||
Console.WriteLine("Standard Rank"); |
|||
var list = data.Values.Distinct().ToList(); |
|||
list.Sort((a, b) => b.CompareTo(a)); |
|||
int rank = 1; |
|||
foreach (var value in list) { |
|||
int temp = rank; |
|||
foreach (var k in data.Keys) { |
|||
if (data[k] == value) { |
|||
Console.WriteLine("{0} {1} {2}", temp, value, k); |
|||
rank++; |
|||
} |
|||
} |
|||
} |
|||
Console.WriteLine(); |
|||
} |
|||
static void ModifiedRank(Dictionary<string, int> data) { |
|||
Console.WriteLine("Modified Rank"); |
|||
var list = data.Values.Distinct().ToList(); |
|||
list.Sort((a, b) => b.CompareTo(a)); |
|||
int rank = 0; |
|||
foreach (var value in list) { |
|||
foreach (var k in data.Keys) { |
|||
if (data[k] == value) { |
|||
rank++; |
|||
} |
|||
} |
|||
foreach (var k in data.Keys) { |
|||
if (data[k] == value) { |
|||
Console.WriteLine("{0} {1} {2}", rank, data[k], k); |
|||
} |
|||
} |
|||
} |
|||
Console.WriteLine(); |
|||
} |
|||
static void DenseRank(Dictionary<string, int> data) { |
|||
Console.WriteLine("Dense Rank"); |
|||
var list = data.Values.Distinct().ToList(); |
|||
list.Sort((a, b) => b.CompareTo(a)); |
|||
int rank = 1; |
|||
foreach (var value in list) { |
|||
foreach (var k in data.Keys) { |
|||
if (data[k] == value) { |
|||
Console.WriteLine("{0} {1} {2}", rank, data[k], k); |
|||
} |
|||
} |
|||
rank++; |
|||
} |
|||
Console.WriteLine(); |
|||
} |
|||
static void OrdinalRank(Dictionary<string, int> data) { |
|||
Console.WriteLine("Ordinal Rank"); |
|||
var list = data.Values.Distinct().ToList(); |
|||
list.Sort((a, b) => b.CompareTo(a)); |
|||
int rank = 1; |
|||
foreach (var value in list) { |
|||
foreach (var k in data.Keys) { |
|||
if (data[k] == value) { |
|||
Console.WriteLine("{0} {1} {2}", rank, data[k], k); |
|||
rank++; |
|||
} |
|||
} |
|||
} |
|||
Console.WriteLine(); |
|||
} |
|||
static void FractionalRank(Dictionary<string, int> data) { |
|||
Console.WriteLine("Fractional Rank"); |
|||
var list = data.Values.Distinct().ToList(); |
|||
list.Sort((a, b) => b.CompareTo(a)); |
|||
int rank = 0; |
|||
foreach (var value in list) { |
|||
double avg = 0; |
|||
int cnt = 0; |
|||
foreach (var k in data.Keys) { |
|||
if (data[k] == value) { |
|||
rank++; |
|||
cnt++; |
|||
avg += rank; |
|||
} |
|||
} |
|||
avg /= cnt; |
|||
foreach (var k in data.Keys) { |
|||
if (data[k] == value) { |
|||
Console.WriteLine("{0:F1} {1} {2}", avg, data[k], k); |
|||
} |
|||
} |
|||
} |
|||
Console.WriteLine(); |
|||
} |
|||
} |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Standard Rank |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
2 42 Errol |
|||
4 41 Gary |
|||
4 41 Bernard |
|||
4 41 Barry |
|||
7 39 Stephen |
|||
Modified Rank |
|||
1 44 Solomon |
|||
3 42 Jason |
|||
3 42 Errol |
|||
6 41 Gary |
|||
6 41 Bernard |
|||
6 41 Barry |
|||
7 39 Stephen |
|||
Dense Rank |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
2 42 Errol |
|||
3 41 Gary |
|||
3 41 Bernard |
|||
3 41 Barry |
|||
4 39 Stephen |
|||
Ordinal Rank |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
3 42 Errol |
|||
4 41 Gary |
|||
5 41 Bernard |
|||
6 41 Barry |
|||
7 39 Stephen |
|||
Fractional Rank |
|||
1.0 44 Solomon |
|||
2.5 42 Jason |
|||
2.5 42 Errol |
|||
5.0 41 Gary |
|||
5.0 41 Bernard |
|||
5.0 41 Barry |
|||
7.0 39 Stephen</pre> |
|||
=={{header|C++}}== |
|||
{{trans|C#}} |
|||
<syntaxhighlight lang="cpp">#include <algorithm> |
|||
#include <iomanip> |
|||
#include <iostream> |
|||
#include <map> |
|||
#include <ostream> |
|||
#include <set> |
|||
#include <vector> |
|||
template<typename T> |
|||
std::ostream& print(std::ostream& os, const T& src) { |
|||
auto it = src.cbegin(); |
|||
auto end = src.cend(); |
|||
os << "["; |
|||
if (it != end) { |
|||
os << *it; |
|||
it = std::next(it); |
|||
} |
|||
while (it != end) { |
|||
os << ", " << *it; |
|||
it = std::next(it); |
|||
} |
|||
return os << "]"; |
|||
} |
|||
typedef std::map<std::string, int> Map; |
|||
typedef Map::value_type MapEntry; |
|||
void standardRank(const Map& scores) { |
|||
std::cout << "Standard Rank" << std::endl; |
|||
std::vector<int> list; |
|||
for (auto& elem : scores) { |
|||
list.push_back(elem.second); |
|||
} |
|||
std::sort(list.begin(), list.end(), std::greater<int>{}); |
|||
list.erase(std::unique(list.begin(), list.end()), list.end()); |
|||
int rank = 1; |
|||
for (auto value : list) { |
|||
int temp = rank; |
|||
for (auto& e : scores) { |
|||
if (e.second == value) { |
|||
std::cout << temp << " " << value << " " << e.first.c_str() << std::endl; |
|||
rank++; |
|||
} |
|||
} |
|||
} |
|||
std::cout << std::endl; |
|||
} |
|||
void modifiedRank(const Map& scores) { |
|||
std::cout << "Modified Rank" << std::endl; |
|||
std::vector<int> list; |
|||
for (auto& elem : scores) { |
|||
list.push_back(elem.second); |
|||
} |
|||
std::sort(list.begin(), list.end(), std::greater<int>{}); |
|||
list.erase(std::unique(list.begin(), list.end()), list.end()); |
|||
int rank = 0; |
|||
for (auto value : list) { |
|||
rank += std::count_if(scores.begin(), scores.end(), [value](const MapEntry& e) { return e.second == value; }); |
|||
for (auto& e : scores) { |
|||
if (e.second == value) { |
|||
std::cout << rank << " " << value << " " << e.first.c_str() << std::endl; |
|||
} |
|||
} |
|||
} |
|||
std::cout << std::endl; |
|||
} |
|||
void denseRank(const Map& scores) { |
|||
std::cout << "Dense Rank" << std::endl; |
|||
std::vector<int> list; |
|||
for (auto& elem : scores) { |
|||
list.push_back(elem.second); |
|||
} |
|||
std::sort(list.begin(), list.end(), std::greater<int>{}); |
|||
list.erase(std::unique(list.begin(), list.end()), list.end()); |
|||
int rank = 1; |
|||
for (auto value : list) { |
|||
for (auto& e : scores) { |
|||
if (e.second == value) { |
|||
std::cout << rank << " " << value << " " << e.first.c_str() << std::endl; |
|||
} |
|||
} |
|||
rank++; |
|||
} |
|||
std::cout << std::endl; |
|||
} |
|||
void ordinalRank(const Map& scores) { |
|||
std::cout << "Ordinal Rank" << std::endl; |
|||
std::vector<int> list; |
|||
for (auto& elem : scores) { |
|||
list.push_back(elem.second); |
|||
} |
|||
std::sort(list.begin(), list.end(), std::greater<int>{}); |
|||
list.erase(std::unique(list.begin(), list.end()), list.end()); |
|||
int rank = 1; |
|||
for (auto value : list) { |
|||
for (auto& e : scores) { |
|||
if (e.second == value) { |
|||
std::cout << rank++ << " " << value << " " << e.first.c_str() << std::endl; |
|||
} |
|||
} |
|||
} |
|||
std::cout << std::endl; |
|||
} |
|||
void fractionalRank(const Map& scores) { |
|||
std::cout << "Ordinal Rank" << std::endl; |
|||
std::vector<int> list; |
|||
for (auto& elem : scores) { |
|||
list.push_back(elem.second); |
|||
} |
|||
std::sort(list.begin(), list.end(), std::greater<int>{}); |
|||
list.erase(std::unique(list.begin(), list.end()), list.end()); |
|||
int rank = 0; |
|||
for (auto value : list) { |
|||
double avg = 0.0; |
|||
int cnt = 0; |
|||
for (auto& e : scores) { |
|||
if (e.second == value) { |
|||
rank++; |
|||
cnt++; |
|||
avg += rank; |
|||
} |
|||
} |
|||
avg /= cnt; |
|||
for (auto& e : scores) { |
|||
if (e.second == value) { |
|||
std::cout << std::setprecision(1) << std::fixed << avg << " " << value << " " << e.first.c_str() << std::endl; |
|||
} |
|||
} |
|||
} |
|||
std::cout << std::endl; |
|||
} |
|||
int main() { |
|||
using namespace std; |
|||
map<string, int> scores{ |
|||
{"Solomon", 44}, |
|||
{"Jason", 42}, |
|||
{"Errol", 42}, |
|||
{"Gary", 41}, |
|||
{"Bernard", 41}, |
|||
{"Barry", 41}, |
|||
{"Stephen", 39} |
|||
}; |
|||
standardRank(scores); |
|||
modifiedRank(scores); |
|||
denseRank(scores); |
|||
ordinalRank(scores); |
|||
fractionalRank(scores); |
|||
return 0; |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Standard Rank |
|||
1 44 Solomon |
|||
2 42 Errol |
|||
2 42 Jason |
|||
4 41 Barry |
|||
4 41 Bernard |
|||
4 41 Gary |
|||
7 39 Stephen |
|||
Modified Rank |
|||
1 44 Solomon |
|||
3 42 Errol |
|||
3 42 Jason |
|||
6 41 Barry |
|||
6 41 Bernard |
|||
6 41 Gary |
|||
7 39 Stephen |
|||
Dense Rank |
|||
1 44 Solomon |
|||
2 42 Errol |
|||
2 42 Jason |
|||
3 41 Barry |
|||
3 41 Bernard |
|||
3 41 Gary |
|||
4 39 Stephen |
|||
Ordinal Rank |
|||
1 44 Solomon |
|||
2 42 Errol |
|||
3 42 Jason |
|||
4 41 Barry |
|||
5 41 Bernard |
|||
6 41 Gary |
|||
7 39 Stephen |
|||
Ordinal Rank |
|||
1.0 44 Solomon |
|||
2.5 42 Errol |
|||
2.5 42 Jason |
|||
5.0 41 Barry |
|||
5.0 41 Bernard |
|||
5.0 41 Gary |
|||
7.0 39 Stephen</pre> |
|||
=={{header|Cowgol}}== |
|||
<syntaxhighlight lang="cowgol">include "cowgol.coh"; |
|||
# List of competitors |
|||
record Competitor is |
|||
score: uint8; |
|||
name: [uint8]; |
|||
end record; |
|||
var cs: Competitor[] := { |
|||
{44, "Solomon"}, |
|||
{42, "Jason"}, |
|||
{42, "Errol"}, |
|||
{41, "Garry"}, |
|||
{41, "Bernard"}, |
|||
{41, "Barry"}, |
|||
{39, "Stephen"} |
|||
}; |
|||
# Rank competitors given ranking method |
|||
interface Ranking(c: [Competitor], |
|||
n: intptr, |
|||
len: intptr, |
|||
last: uint16): (rank: uint16); |
|||
sub Rank(cs: [Competitor], num: intptr, r: Ranking) is |
|||
var last: uint16 := 0; |
|||
var idx: intptr := 0; |
|||
while idx < num loop |
|||
last := r(cs, idx, num, last); |
|||
if last < 100 then |
|||
print_i16(last); |
|||
else |
|||
# print fixed-point rank nicely |
|||
print_i16(last / 100); |
|||
print_char('.'); |
|||
print_i16((last % 100) / 10); |
|||
print_i16(last % 10); |
|||
end if; |
|||
print(". "); |
|||
print_i8(cs.score); |
|||
print(", "); |
|||
print(cs.name); |
|||
print_nl(); |
|||
idx := idx + 1; |
|||
cs := @next cs; |
|||
end loop; |
|||
end sub; |
|||
# Standard ranking |
|||
var stdcount: uint16 := 0; |
|||
sub Standard implements Ranking is |
|||
if n==0 then stdcount := 0; end if; |
|||
stdcount := stdcount + 1; |
|||
if n>0 and c.score == [@prev c].score then |
|||
rank := last; |
|||
else |
|||
rank := stdcount; |
|||
end if; |
|||
end sub; |
|||
# Modified ranking |
|||
sub Modified implements Ranking is |
|||
rank := last; |
|||
if n == 0 or c.score != [@prev c].score then |
|||
while n < len loop |
|||
rank := rank + 1; |
|||
c := @next c; |
|||
if c.score != [@prev c].score then |
|||
break; |
|||
end if; |
|||
n := n + 1; |
|||
end loop; |
|||
end if; |
|||
end sub; |
|||
# Dense ranking |
|||
sub Dense implements Ranking is |
|||
if n>0 and c.score == [@prev c].score then |
|||
rank := last; |
|||
else |
|||
rank := last + 1; |
|||
end if; |
|||
end sub; |
|||
# Ordinal ranking |
|||
sub Ordinal implements Ranking is |
|||
rank := last + 1; |
|||
end sub; |
|||
# Fractional ranking (with fixed point arithmetic) |
|||
sub Fractional implements Ranking is |
|||
rank := last; |
|||
if n==0 or c.score != [@prev c].score then |
|||
var sum: uint16 := 0; |
|||
var ct: uint16 := 0; |
|||
while n < len loop |
|||
sum := sum + (n as uint16 + 1); |
|||
ct := ct + 1; |
|||
c := @next c; |
|||
if c.score != [@prev c].score then |
|||
break; |
|||
end if; |
|||
n := n + 1; |
|||
end loop; |
|||
rank := (sum * 100) / (ct as uint16); |
|||
end if; |
|||
end sub; |
|||
record Method is |
|||
name: [uint8]; |
|||
method: Ranking; |
|||
end record; |
|||
var methods: Method[] := { |
|||
{"Standard", Standard}, |
|||
{"Modified", Modified}, |
|||
{"Dense", Dense}, |
|||
{"Ordinal", Ordinal}, |
|||
{"Fractional", Fractional} |
|||
}; |
|||
var n: @indexof methods := 0; |
|||
while n < @sizeof methods loop |
|||
print("--- "); |
|||
print(methods[n].name); |
|||
print(" ---\n"); |
|||
Rank(&cs[0], @sizeof cs, methods[n].method); |
|||
print_nl(); |
|||
n := n + 1; |
|||
end loop;</syntaxhighlight> |
|||
{{out}} |
|||
<pre>--- Standard --- |
|||
1. 44, Solomon |
|||
2. 42, Jason |
|||
2. 42, Errol |
|||
4. 41, Garry |
|||
4. 41, Bernard |
|||
4. 41, Barry |
|||
7. 39, Stephen |
|||
--- Modified --- |
|||
1. 44, Solomon |
|||
3. 42, Jason |
|||
3. 42, Errol |
|||
6. 41, Garry |
|||
6. 41, Bernard |
|||
6. 41, Barry |
|||
7. 39, Stephen |
|||
--- Dense --- |
|||
1. 44, Solomon |
|||
2. 42, Jason |
|||
2. 42, Errol |
|||
3. 41, Garry |
|||
3. 41, Bernard |
|||
3. 41, Barry |
|||
4. 39, Stephen |
|||
--- Ordinal --- |
|||
1. 44, Solomon |
|||
2. 42, Jason |
|||
3. 42, Errol |
|||
4. 41, Garry |
|||
5. 41, Bernard |
|||
6. 41, Barry |
|||
7. 39, Stephen |
|||
--- Fractional --- |
|||
1.00. 44, Solomon |
|||
2.50. 42, Jason |
|||
2.50. 42, Errol |
|||
5.00. 41, Garry |
|||
5.00. 41, Bernard |
|||
5.00. 41, Barry |
|||
7.00. 39, Stephen</pre> |
|||
=={{header|D}}== |
|||
<syntaxhighlight lang="d">import std.algorithm; |
|||
import std.stdio; |
|||
void main() { |
|||
immutable scores = [ |
|||
"Solomon": 44, |
|||
"Jason": 42, |
|||
"Errol": 42, |
|||
"Garry": 41, |
|||
"Bernard": 41, |
|||
"Barry": 41, |
|||
"Stephen": 39 |
|||
]; |
|||
scores.standardRank; |
|||
scores.modifiedRank; |
|||
scores.denseRank; |
|||
scores.ordinalRank; |
|||
scores.fractionalRank; |
|||
} |
|||
/* |
|||
Standard ranking |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
2 42 Errol |
|||
4 41 Garry |
|||
4 41 Bernard |
|||
4 41 Barry |
|||
7 39 Stephen |
|||
*/ |
|||
void standardRank(const int[string] data) { |
|||
writeln("Standard Rank"); |
|||
int rank = 1; |
|||
foreach (value; data.values.dup.sort!"a>b".uniq) { |
|||
int temp = rank; |
|||
foreach(k,v; data) { |
|||
if (v==value) { |
|||
writeln(temp, " ", v, " ", k); |
|||
rank++; |
|||
} |
|||
} |
|||
} |
|||
writeln; |
|||
} |
|||
/* |
|||
Modified ranking |
|||
1 44 Solomon |
|||
3 42 Jason |
|||
3 42 Errol |
|||
6 41 Garry |
|||
6 41 Bernard |
|||
6 41 Barry |
|||
7 39 Stephen |
|||
*/ |
|||
void modifiedRank(const int[string] data) { |
|||
writeln("Modified Rank"); |
|||
int rank = 0; |
|||
foreach (value; data.values.dup.sort!"a>b".uniq) { |
|||
foreach(k,v; data) { |
|||
if (v==value) { |
|||
rank++; |
|||
} |
|||
} |
|||
foreach(k,v; data) { |
|||
if (v==value) { |
|||
writeln(rank, " ", v, " ", k); |
|||
} |
|||
} |
|||
} |
|||
writeln; |
|||
} |
|||
/* |
|||
Dense ranking |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
2 42 Errol |
|||
3 41 Garry |
|||
3 41 Bernard |
|||
3 41 Barry |
|||
4 39 Stephen |
|||
*/ |
|||
void denseRank(const int[string] data) { |
|||
writeln("Dense Rank"); |
|||
int rank = 1; |
|||
foreach (value; data.values.dup.sort!"a>b".uniq) { |
|||
foreach(k,v; data) { |
|||
if (v==value) { |
|||
writeln(rank, " ", v, " ", k); |
|||
} |
|||
} |
|||
rank++; |
|||
} |
|||
writeln; |
|||
} |
|||
/* |
|||
Ordinal ranking |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
3 42 Errol |
|||
4 41 Garry |
|||
5 41 Bernard |
|||
6 41 Barry |
|||
7 39 Stephen |
|||
*/ |
|||
void ordinalRank(const int[string] data) { |
|||
writeln("Ordinal Rank"); |
|||
int rank = 1; |
|||
foreach (value; data.values.dup.sort!"a>b".uniq) { |
|||
foreach(k,v; data) { |
|||
if (v==value) { |
|||
writeln(rank, " ", v, " ", k); |
|||
rank++; |
|||
} |
|||
} |
|||
} |
|||
writeln; |
|||
} |
|||
/* |
|||
Fractional ranking |
|||
1,0 44 Solomon |
|||
2,5 42 Jason |
|||
2,5 42 Errol |
|||
5,0 41 Garry |
|||
5,0 41 Bernard |
|||
5,0 41 Barry |
|||
7,0 39 Stephen |
|||
*/ |
|||
void fractionalRank(const int[string] data) { |
|||
writeln("Fractional Rank"); |
|||
int rank = 0; |
|||
foreach (value; data.values.dup.sort!"a>b".uniq) { |
|||
real avg = 0; |
|||
int cnt; |
|||
foreach(k,v; data) { |
|||
if (v==value) { |
|||
rank++; |
|||
cnt++; |
|||
avg+=rank; |
|||
} |
|||
} |
|||
avg /= cnt; |
|||
foreach(k,v; data) { |
|||
if (v==value) { |
|||
writef("%0.1f ", avg); |
|||
writeln(v, " ", k); |
|||
} |
|||
} |
|||
} |
|||
writeln; |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Standard Rank |
|||
1 44 Solomon |
|||
2 42 Errol |
|||
2 42 Jason |
|||
4 41 Garry |
|||
4 41 Bernard |
|||
4 41 Barry |
|||
7 39 Stephen |
|||
Modified Rank |
|||
1 44 Solomon |
|||
3 42 Errol |
|||
3 42 Jason |
|||
6 41 Garry |
|||
6 41 Bernard |
|||
6 41 Barry |
|||
7 39 Stephen |
|||
Dense Rank |
|||
1 44 Solomon |
|||
2 42 Errol |
|||
2 42 Jason |
|||
3 41 Garry |
|||
3 41 Bernard |
|||
3 41 Barry |
|||
4 39 Stephen |
|||
Ordinal Rank |
|||
1 44 Solomon |
|||
2 42 Errol |
|||
3 42 Jason |
|||
4 41 Garry |
|||
5 41 Bernard |
|||
6 41 Barry |
|||
7 39 Stephen |
|||
Fractional Rank |
|||
1.0 44 Solomon |
|||
2.5 42 Errol |
|||
2.5 42 Jason |
|||
5.0 41 Garry |
|||
5.0 41 Bernard |
|||
5.0 41 Barry |
|||
7.0 39 Stephen</pre> |
|||
=={{header|Elixir}}== |
|||
{{trans|Ruby}} |
|||
<syntaxhighlight lang="elixir">defmodule Ranking do |
|||
def methods(data) do |
|||
IO.puts "stand.\tmod.\tdense\tord.\tfract." |
|||
Enum.group_by(data, fn {score,_name} -> score end) |
|||
|> Enum.map(fn {score,pairs} -> |
|||
names = Enum.map(pairs, fn {_,name} -> name end) |> Enum.reverse |
|||
{score, names} |
|||
end) |
|||
|> Enum.sort_by(fn {score,_} -> -score end) |
|||
|> Enum.with_index |
|||
|> Enum.reduce({1,0,0}, fn {{score, names}, i}, {s_rnk, m_rnk, o_rnk} -> |
|||
d_rnk = i + 1 |
|||
m_rnk = m_rnk + length(names) |
|||
f_rnk = ((s_rnk + m_rnk) / 2) |> to_string |> String.replace(".0","") |
|||
o_rnk = Enum.reduce(names, o_rnk, fn name,acc -> |
|||
IO.puts "#{s_rnk}\t#{m_rnk}\t#{d_rnk}\t#{acc+1}\t#{f_rnk}\t#{score} #{name}" |
|||
acc + 1 |
|||
end) |
|||
{s_rnk+length(names), m_rnk, o_rnk} |
|||
end) |
|||
end |
|||
end |
|||
~w"44 Solomon |
|||
42 Jason |
|||
42 Errol |
|||
41 Garry |
|||
41 Bernard |
|||
41 Barry |
|||
39 Stephen" |
|||
|> Enum.chunk(2) |
|||
|> Enum.map(fn [score,name] -> {String.to_integer(score),name} end) |
|||
|> Ranking.methods</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
stand. mod. dense ord. fract. |
|||
1 1 1 1 1 44 Solomon |
|||
2 3 2 2 2.5 42 Jason |
|||
2 3 2 3 2.5 42 Errol |
|||
4 6 3 4 5 41 Garry |
|||
4 6 3 5 5 41 Bernard |
|||
4 6 3 6 5 41 Barry |
|||
7 7 4 7 7 39 Stephen |
|||
</pre> |
|||
=={{header|Factor}}== |
|||
{{works with|Factor|0.99 2019-07-10}} |
|||
<syntaxhighlight lang="factor">USING: arrays assocs formatting fry generalizations io kernel |
|||
math math.ranges math.statistics math.vectors sequences |
|||
splitting.monotonic ; |
|||
IN: rosetta-code.ranking |
|||
CONSTANT: ranks { |
|||
{ 44 "Solomon" } { 42 "Jason" } { 42 "Errol" } |
|||
{ 41 "Garry" } { 41 "Bernard" } { 41 "Barry" } |
|||
{ 39 "Stephen" } |
|||
} |
|||
: rank ( seq quot -- seq' ) |
|||
'[ [ = ] monotonic-split [ length ] map dup @ [ <array> ] |
|||
2map concat ] call ; inline |
|||
: standard ( seq -- seq' ) [ cum-sum0 1 v+n ] rank ; |
|||
: modified ( seq -- seq' ) [ cum-sum ] rank ; |
|||
: dense ( seq -- seq' ) [ length [1,b] ] rank ; |
|||
: ordinal ( seq -- seq' ) length [1,b] ; |
|||
: fractional ( seq -- seq' ) |
|||
[ dup cum-sum swap [ dupd - [a,b) mean ] 2map ] rank ; |
|||
: .rank ( quot -- ) |
|||
[ ranks dup keys ] dip call swap |
|||
[ first2 "%5u %d %s\n" printf ] 2each ; inline |
|||
: ranking-demo ( -- ) |
|||
"Standard ranking" [ standard ] |
|||
"Modified ranking" [ modified ] |
|||
"Dense ranking" [ dense ] |
|||
"Ordinal ranking" [ ordinal ] |
|||
"Fractional ranking" [ fractional ] |
|||
[ [ print ] [ .rank nl ] bi* ] 2 5 mnapply ; |
|||
MAIN: ranking-demo</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Standard ranking |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
2 42 Errol |
|||
4 41 Garry |
|||
4 41 Bernard |
|||
4 41 Barry |
|||
7 39 Stephen |
|||
Modified ranking |
|||
1 44 Solomon |
|||
3 42 Jason |
|||
3 42 Errol |
|||
6 41 Garry |
|||
6 41 Bernard |
|||
6 41 Barry |
|||
7 39 Stephen |
|||
Dense ranking |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
2 42 Errol |
|||
3 41 Garry |
|||
3 41 Bernard |
|||
3 41 Barry |
|||
4 39 Stephen |
|||
Ordinal ranking |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
3 42 Errol |
|||
4 41 Garry |
|||
5 41 Bernard |
|||
6 41 Barry |
|||
7 39 Stephen |
|||
Fractional ranking |
|||
1 44 Solomon |
|||
2+1/2 42 Jason |
|||
2+1/2 42 Errol |
|||
5 41 Garry |
|||
5 41 Bernard |
|||
5 41 Barry |
|||
7 39 Stephen |
|||
</pre> |
|||
=={{header|FreeBASIC}}== |
|||
<syntaxhighlight lang="freebasic"> |
|||
Data 44,"Solomon", 42,"Jason", 42,"Errol", 41,"Garry" |
|||
Data 41,"Bernard", 41,"Barry", 39,"Stephen" |
|||
Dim Shared As Integer n = 7 |
|||
Dim Shared As Integer puntos(n), i |
|||
Dim Shared As Single ptosnom(n) |
|||
Dim Shared As String nombre(n) |
|||
Print "Puntuaciones a clasificar (mejores primero):" |
|||
For i = 1 To n |
|||
Read puntos(i), nombre(i) |
|||
Print Using " ##, \ \"; puntos(i); nombre(i) |
|||
Next i |
|||
Print |
|||
Sub MostarTabla |
|||
For i = 1 To n |
|||
Print Using " \ \ ##, \ \"; Str(ptosnom(i)); puntos(i); nombre(i) |
|||
Next i |
|||
Print |
|||
End Sub |
|||
Print "--- Standard ranking ---" |
|||
ptosnom(1) = 1 |
|||
For i = 2 To n |
|||
If puntos(i) = puntos(i-1) Then ptosnom(i) = ptosnom(i-1) Else ptosnom(i) = i |
|||
Next i |
|||
MostarTabla |
|||
Print "--- Modified ranking ---" |
|||
ptosnom(n) = n |
|||
For i = n-1 To 1 Step -1 |
|||
If puntos(i) = puntos(i+1) Then ptosnom(i) = ptosnom(i+1) Else ptosnom(i) = i |
|||
Next i |
|||
MostarTabla |
|||
Print "--- Dense ranking ---" |
|||
ptosnom(1) = 1 |
|||
For i = 2 To n |
|||
ptosnom(i) = ptosnom(i-1) - (puntos(i) <> puntos(i-1)) |
|||
Next i |
|||
MostarTabla |
|||
Print "--- Ordinal ranking ---" |
|||
For i = 1 To n |
|||
ptosnom(i) = i |
|||
Next i |
|||
MostarTabla |
|||
Print "--- Fractional ranking ---" |
|||
i = 1 |
|||
Dim As Integer j = 2 |
|||
Do |
|||
If j <= n Then If (puntos(j-1) = puntos(j)) Then j += 1 |
|||
For k As Integer = i To j-1 |
|||
ptosnom(k) = (i+j-1) / 2 |
|||
Next k |
|||
i = j |
|||
j += 1 |
|||
Loop While i <= n |
|||
MostarTabla |
|||
Sleep |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Puntuaciones a clasificar (mejores primero): |
|||
44 Solomon |
|||
42 Jason |
|||
42 Errol |
|||
41 Garry |
|||
41 Bernard |
|||
41 Barry |
|||
39 Stephen |
|||
--- Standard ranking --- |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
2 42 Errol |
|||
4 41 Garry |
|||
4 41 Bernard |
|||
4 41 Barry |
|||
7 39 Stephen |
|||
--- Modified ranking --- |
|||
1 44 Solomon |
|||
3 42 Jason |
|||
3 42 Errol |
|||
6 41 Garry |
|||
6 41 Bernard |
|||
6 41 Barry |
|||
7 39 Stephen |
|||
--- Dense ranking --- |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
2 42 Errol |
|||
3 41 Garry |
|||
3 41 Bernard |
|||
3 41 Barry |
|||
4 39 Stephen |
|||
--- Ordinal ranking --- |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
3 42 Errol |
|||
4 41 Garry |
|||
5 41 Bernard |
|||
6 41 Barry |
|||
7 39 Stephen |
|||
--- Fractional ranking --- |
|||
1 44 Solomon |
|||
2.5 42 Jason |
|||
2.5 42 Errol |
|||
4.5 41 Garry |
|||
4.5 41 Bernard |
|||
6 41 Barry |
|||
7 39 Stephen |
|||
</pre> |
|||
=={{header|Go}}== |
=={{header|Go}}== |
||
< |
<syntaxhighlight lang="go">package main |
||
import ( |
import ( |
||
Line 385: | Line 2,342: | ||
show("\nOrdinal", OrdinalRank) |
show("\nOrdinal", OrdinalRank) |
||
show("\nFractional", FractionalRank) |
show("\nFractional", FractionalRank) |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 435: | Line 2,392: | ||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
<syntaxhighlight lang="haskell">import Data.List (groupBy, sortBy, intercalate) |
|||
<lang Haskell> |
|||
import Data.List (groupBy, sort, intercalate) |
|||
type Item |
type Item = (Int, String) |
||
type ItemList = [Item] |
|||
type |
type ItemList = [Item] |
||
type RankItem a = (a, Int, String) |
|||
type |
type ItemGroups = [ItemList] |
||
type RankItem a = (a, Int, String) |
|||
type RankItemList a = [RankItem a] |
|||
-- make sure the input is ordered and grouped by score |
-- make sure the input is ordered and grouped by score |
||
prepare :: ItemList -> ItemGroups |
prepare :: ItemList -> ItemGroups |
||
prepare = groupBy gf . |
prepare = groupBy gf . sortBy (flip compare) |
||
where |
|||
where gf (a, _) (b, _) = a == b |
|||
gf (a, _) (b, _) = a == b |
|||
-- give an item a rank |
-- give an item a rank |
||
rank |
|||
rank :: Num a => a -> Item -> RankItem a |
|||
:: Num a |
|||
=> a -> Item -> RankItem a |
|||
rank n (a, b) = (n, a, b) |
rank n (a, b) = (n, a, b) |
||
-- ranking methods |
-- ranking methods |
||
standard, modified, dense, ordinal :: ItemGroups -> RankItemList Int |
standard, modified, dense, ordinal :: ItemGroups -> RankItemList Int |
||
standard = ms 1 |
|||
where |
|||
ms _ [] = [] |
ms _ [] = [] |
||
ms n (x:xs) = |
ms n (x:xs) = (rank n <$> x) ++ ms (n + length x) xs |
||
modified = md 1 |
modified = md 1 |
||
where |
|||
md _ [] = [] |
md _ [] = [] |
||
md n (x:xs) = |
md n (x:xs) = |
||
let l = length x |
|||
nl = n + l |
|||
nl1 = nl - 1 |
|||
in (rank nl1 <$> x) ++ md (n + l) xs |
|||
dense = md 1 |
dense = md 1 |
||
where |
|||
md _ [] = [] |
md _ [] = [] |
||
md n (x:xs) = map (rank n) x ++ md (n + 1) xs |
md n (x:xs) = map (rank n) x ++ md (n + 1) xs |
||
ordinal = zipWith rank [1..] . concat |
ordinal = zipWith rank [1 ..] . concat |
||
fractional :: ItemGroups -> RankItemList Double |
fractional :: ItemGroups -> RankItemList Double |
||
fractional = mf 1.0 |
fractional = mf 1.0 |
||
where |
|||
mf _ [] = [] |
mf _ [] = [] |
||
mf n (x:xs) = |
mf n (x:xs) = |
||
let l = length x |
|||
o = take l [n ..] |
|||
ld = fromIntegral l |
|||
a = sum o / ld |
|||
in map (rank a) x ++ mf (n + ld) xs |
|||
-- sample data |
-- sample data |
||
test :: ItemGroups |
test :: ItemGroups |
||
test = |
test = |
||
prepare |
|||
[ (44, "Solomon") |
[ (44, "Solomon") |
||
, (42, "Jason") |
, (42, "Jason") |
||
Line 491: | Line 2,460: | ||
, (41, "Bernard") |
, (41, "Bernard") |
||
, (41, "Barry") |
, (41, "Barry") |
||
, (39, "Stephen") |
, (39, "Stephen") |
||
] |
|||
-- print rank items nicely |
-- print rank items nicely |
||
nicePrint |
|||
nicePrint :: Show a => String -> RankItemList a -> IO () |
|||
:: Show a |
|||
=> String -> RankItemList a -> IO () |
|||
nicePrint xs items = do |
nicePrint xs items = do |
||
putStrLn xs |
|||
mapM_ np items |
|||
putStr "\n" |
|||
where |
|||
where np (a, b, c) = putStrLn $ intercalate "\t" [show a, show b, c] |
|||
np (a, b, c) = putStrLn $ intercalate "\t" [show a, show b, c] |
|||
main :: IO () |
main :: IO () |
||
main = do |
main = do |
||
nicePrint "Standard:" $ standard test |
|||
nicePrint "Modified:" $ modified test |
|||
nicePrint "Dense:" $ dense test |
|||
nicePrint "Ordinal:" $ ordinal test |
|||
nicePrint "Fractional:" $ fractional test</syntaxhighlight> |
|||
{{Out}} |
|||
</lang> |
|||
<pre>Standard: |
|||
Output: |
|||
<pre> |
|||
Standard: |
|||
1 44 Solomon |
1 44 Solomon |
||
2 42 Jason |
2 42 Jason |
||
Line 554: | Line 2,525: | ||
5.0 41 Bernard |
5.0 41 Bernard |
||
5.0 41 Barry |
5.0 41 Barry |
||
7.0 39 Stephen |
7.0 39 Stephen</pre> |
||
</pre> |
|||
=={{header|J}}== |
=={{header|J}}== |
||
Implementation: |
Implementation: |
||
< |
<syntaxhighlight lang="j">competitors=:<;._1;._2]0 :0 |
||
44 Solomon |
44 Solomon |
||
42 Jason |
42 Jason |
||
Line 577: | Line 2,548: | ||
fractional=: #/.~ # ] (+/%#)/. #\ |
fractional=: #/.~ # ] (+/%#)/. #\ |
||
rank=:1 :'<"0@u@:scores,.]'</ |
rank=:1 :'<"0@u@:scores,.]'</syntaxhighlight> |
||
Note that we assume that the competitors are already in the right order. Also, of course (as is common when using J) we use the J command line, because that is portable across operating systems (for example: the OS command line is difficult to use on phones). |
Note that we assume that the competitors are already in the right order. Also, of course (as is common when using J) we use the J command line, because that is portable across operating systems (for example: the OS command line is difficult to use on phones). |
||
Line 583: | Line 2,554: | ||
Task examples: |
Task examples: |
||
< |
<syntaxhighlight lang="j"> standard rank competitors |
||
┌─┬──┬───────┐ |
┌─┬──┬───────┐ |
||
│1│44│Solomon│ |
│1│44│Solomon│ |
||
Line 662: | Line 2,633: | ||
├───┼──┼───────┤ |
├───┼──┼───────┤ |
||
│7 │39│Stephen│ |
│7 │39│Stephen│ |
||
└───┴──┴───────┘</ |
└───┴──┴───────┘</syntaxhighlight> |
||
=={{header|Java}}== |
=={{header|Java}}== |
||
{{works with|Java|8}} |
{{works with|Java|8}} |
||
< |
<syntaxhighlight lang="java">import java.util.*; |
||
public class RankingMethods { |
public class RankingMethods { |
||
Line 740: | Line 2,711: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
<pre>Standard ranking |
<pre>Standard ranking |
||
Line 786: | Line 2,757: | ||
5,0 41 Barry |
5,0 41 Barry |
||
7,0 39 Stephen</pre> |
7,0 39 Stephen</pre> |
||
=={{header|JavaScript}}== |
=={{header|JavaScript}}== |
||
=== |
===ES5=== |
||
The task formulation doesn't seem to directly explain or determine the order of listing for players whose score is the same. |
|||
<lang JavaScript>(function () { |
|||
( This version chooses to use a secondary (alphabetic) sort after the numeric sort by score. That does, of course, affect the ordinal placements for some players) |
|||
<syntaxhighlight lang="javascript">(function () { |
|||
var xs = 'Solomon Jason Errol Garry Bernard Barry Stephen'.split(' '), |
var xs = 'Solomon Jason Errol Garry Bernard Barry Stephen'.split(' '), |
||
ns = [44, 42, 42, 41, 41, 41, 39], |
ns = [44, 42, 42, 41, 41, 41, 39], |
||
sorted = xs.map(function (x, i) { |
|||
return { name: x, score: ns[i] }; |
|||
}).sort(function (a, b) { |
|||
var c = b.score - a.score; |
|||
return c ? c : a.name < b.name ? -1 : a.name > b.name ? 1 : 0; |
|||
}), |
}), |
||
names = sorted.map(function (x) { return x.name; }), |
|||
scores = sorted.map(function (x) { return x.score; }), |
|||
reversed = scores.slice(0).reverse(), |
|||
unique = scores.filter(function (x, i) { |
|||
return scores.indexOf(x) === i; |
|||
}); |
|||
// RANKINGS AS FUNCTIONS OF SCORES: SORTED, REVERSED AND UNIQUE |
|||
var rankings = function (score, index) { |
|||
return { |
return { |
||
name: |
name: names[index], |
||
score: score, |
score: score, |
||
Ordinal: index + 1, |
|||
Standard: |
Standard: function (n) { |
||
return scores.indexOf(n) + 1; |
|||
}(score), |
|||
Modified: |
Modified: function (n) { |
||
return reversed.length - reversed.indexOf(n); |
|||
}(score), |
|||
Dense: |
Dense: function (n) { |
||
return unique.indexOf(n) + 1; |
|||
}(score), |
|||
Fractional: function (n) { |
|||
return ( |
|||
(scores.indexOf(n) + 1) + |
|||
( |
(reversed.length - reversed.indexOf(n)) |
||
) / 2; |
|||
) |
}(score) |
||
}; |
}; |
||
}, |
}, |
||
tbl = [ |
tbl = [ |
||
'Name Score Standard Modified Dense Ordinal Fractional'.split(' ') |
'Name Score Standard Modified Dense Ordinal Fractional'.split(' ') |
||
].concat( |
].concat(scores.map(rankings).reduce(function (a, x) { |
||
return a.concat([ |
|||
[x.name, x.score, |
|||
x.Standard, x.Modified, x.Dense, x.Ordinal, x.Fractional |
|||
] |
|||
]); |
|||
x.Standard, x.Modified, x.Dense, |
|||
}, [])), |
|||
x.Ordinal, x.Fractional |
|||
] |
|||
]); |
|||
}, [] |
|||
) |
|||
), |
|||
//[[a]] -> bool -> s -> s |
//[[a]] -> bool -> s -> s |
||
wikiTable = function (lstRows, blnHeaderRow, strStyle) { |
wikiTable = function (lstRows, blnHeaderRow, strStyle) { |
||
Line 846: | Line 2,832: | ||
) + lstRows.map(function (lstRow, iRow) { |
) + lstRows.map(function (lstRow, iRow) { |
||
var strDelim = ((blnHeaderRow && !iRow) ? '!' : '|'); |
var strDelim = ((blnHeaderRow && !iRow) ? '!' : '|'); |
||
return '\n|-\n' + strDelim + ' ' + lstRow.map(function (v) { |
return '\n|-\n' + strDelim + ' ' + lstRow.map(function (v) { |
||
return typeof v === 'undefined' ? ' ' : v; |
return typeof v === 'undefined' ? ' ' : v; |
||
Line 852: | Line 2,838: | ||
}).join('') + '\n|}'; |
}).join('') + '\n|}'; |
||
}; |
}; |
||
return wikiTable(tbl, true, 'text-align:center'); |
return wikiTable(tbl, true, 'text-align:center'); |
||
})();</ |
})();</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 865: | Line 2,851: | ||
| Solomon || 44 || 1 || 1 || 1 || 1 || 1 |
| Solomon || 44 || 1 || 1 || 1 || 1 || 1 |
||
|- |
|- |
||
| |
| Errol || 42 || 2 || 3 || 2 || 2 || 2.5 |
||
|- |
|- |
||
| |
| Jason || 42 || 2 || 3 || 2 || 3 || 2.5 |
||
|- |
|- |
||
| |
| Barry || 41 || 4 || 6 || 3 || 4 || 5 |
||
|- |
|- |
||
| Bernard || 41 || 4 || 6 || 3 || 5 || 5 |
| Bernard || 41 || 4 || 6 || 3 || 5 || 5 |
||
|- |
|- |
||
| |
| Garry || 41 || 4 || 6 || 3 || 6 || 5 |
||
|- |
|- |
||
| Stephen || 39 || 7 || 7 || 4 || 7 || 7 |
| Stephen || 39 || 7 || 7 || 4 || 7 || 7 |
||
|} |
|} |
||
===ES6=== |
|||
<syntaxhighlight lang="javascript">((() => { |
|||
const xs = 'Solomon Jason Errol Garry Bernard Barry Stephen'.split(' '), |
|||
ns = [44, 42, 42, 41, 41, 41, 39]; |
|||
const sorted = xs.map((x, i) => ({ |
|||
name: x, |
|||
score: ns[i] |
|||
})) |
|||
.sort((a, b) => { |
|||
const c = b.score - a.score; |
|||
return c ? c : a.name < b.name ? -1 : a.name > b.name ? 1 : 0; |
|||
}); |
|||
const names = sorted.map(x => x.name), |
|||
scores = sorted.map(x => x.score), |
|||
reversed = scores.slice(0) |
|||
.reverse(), |
|||
unique = scores.filter((x, i) => scores.indexOf(x) === i); |
|||
// RANKINGS AS FUNCTIONS OF SCORES: SORTED, REVERSED AND UNIQUE |
|||
// rankings :: Int -> Int -> Dictonary |
|||
const rankings = (score, index) => ({ |
|||
name: names[index], |
|||
score, |
|||
Ordinal: index + 1, |
|||
Standard: scores.indexOf(score) + 1, |
|||
Modified: reversed.length - reversed.indexOf(score), |
|||
Dense: unique.indexOf(score) + 1, |
|||
Fractional: (n => ( |
|||
(scores.indexOf(n) + 1) + |
|||
(reversed.length - reversed.indexOf(n)) |
|||
) / 2)(score) |
|||
}); |
|||
// tbl :: [[[a]]] |
|||
const tbl = [ |
|||
'Name Score Standard Modified Dense Ordinal Fractional'.split(' ') |
|||
].concat(scores.map(rankings) |
|||
.reduce((a, x) => a.concat([ |
|||
[x.name, x.score, |
|||
x.Standard, x.Modified, x.Dense, x.Ordinal, x.Fractional |
|||
] |
|||
]), [])); |
|||
// wikiTable :: [[[a]]] -> Bool -> String -> String |
|||
const wikiTable = (lstRows, blnHeaderRow, strStyle) => |
|||
`{| class="wikitable" ${strStyle ? 'style="' + strStyle + '"' : ''} |
|||
${lstRows.map((lstRow, iRow) => { |
|||
const strDelim = ((blnHeaderRow && !iRow) ? '!' : '|'); |
|||
return '\n|-\n' + strDelim + ' ' + lstRow |
|||
.map(v => typeof v === 'undefined' ? ' ' : v) |
|||
.join(' ' + strDelim + strDelim + ' '); |
|||
}).join('')}\n|}`; |
|||
return wikiTable(tbl, true, 'text-align:center'); |
|||
}))();</syntaxhighlight> |
|||
{| class="wikitable" style="text-align:center" |
|||
|- |
|||
! Name !! Score !! Standard !! Modified !! Dense !! Ordinal !! Fractional |
|||
|- |
|||
| Solomon || 44 || 1 || 1 || 1 || 1 || 1 |
|||
|- |
|||
| Errol || 42 || 2 || 3 || 2 || 2 || 2.5 |
|||
|- |
|||
| Jason || 42 || 2 || 3 || 2 || 3 || 2.5 |
|||
|- |
|||
| Barry || 41 || 4 || 6 || 3 || 4 || 5 |
|||
|- |
|||
| Bernard || 41 || 4 || 6 || 3 || 5 || 5 |
|||
|- |
|||
| Garry || 41 || 4 || 6 || 3 || 6 || 5 |
|||
|- |
|||
| Stephen || 39 || 7 || 7 || 4 || 7 || 7 |
|||
|} |
|||
{{Out}} |
|||
=={{header|jq}}== |
=={{header|jq}}== |
||
Line 884: | Line 2,953: | ||
For the sake of brevity, only the ranks are printed. |
For the sake of brevity, only the ranks are printed. |
||
<syntaxhighlight lang="jq"> |
|||
<lang jq> |
|||
# Ties share what would have been their first ordinal number |
# Ties share what would have been their first ordinal number |
||
def standard_ranking: |
def standard_ranking: |
||
Line 941: | Line 3,010: | ||
else [ resolve, [ $i + 1 ] ] |
else [ resolve, [ $i + 1 ] ] |
||
end ) |
end ) |
||
| resolve ;</ |
| resolve ;</syntaxhighlight>Task<syntaxhighlight lang="jq">def raw: |
||
[ |
[ |
||
"Solomon", 44, |
"Solomon", 44, |
||
Line 960: | Line 3,029: | ||
task |
task |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{Out}} |
{{Out}} |
||
standard: [1,2,2,4,4,4,7] |
standard: [1,2,2,4,4,4,7] |
||
Line 970: | Line 3,039: | ||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
'''ties''', a helper function used by some of the ranking methods. It lists any duplicated scores. |
'''ties''', a helper function used by some of the ranking methods. It lists any duplicated scores. |
||
<syntaxhighlight lang="julia"> |
|||
<lang Julia> |
|||
function ties{T<:Real}(a::Array{T,1}) |
function ties{T<:Real}(a::Array{T,1}) |
||
unique(a[2:end][a[2:end] .== a[1:end-1]]) |
unique(a[2:end][a[2:end] .== a[1:end-1]]) |
||
end |
end |
||
</syntaxhighlight> |
|||
</lang> |
|||
<code>ties</code> assumes that the there are at least 2 scores in the list to be checked, and the calling functions are designed to avoid calls to it in this case. |
<code>ties</code> assumes that the there are at least 2 scores in the list to be checked, and the calling functions are designed to avoid calls to it in this case. |
||
'''Standard Ranking Function''' |
'''Standard Ranking Function''' |
||
<syntaxhighlight lang="julia"> |
|||
<lang Julia> |
|||
function rankstandard{T<:Real}(a::Array{T,1}) |
function rankstandard{T<:Real}(a::Array{T,1}) |
||
r = collect(1:length(a)) |
r = collect(1:length(a)) |
||
Line 987: | Line 3,056: | ||
return r |
return r |
||
end |
end |
||
</syntaxhighlight> |
|||
</lang> |
|||
'''Modified Ranking Function''' |
'''Modified Ranking Function''' |
||
<syntaxhighlight lang="julia"> |
|||
<lang Julia> |
|||
function rankmodified{T<:Real}(a::Array{T,1}) |
function rankmodified{T<:Real}(a::Array{T,1}) |
||
indexin(a, a) |
indexin(a, a) |
||
end |
end |
||
</syntaxhighlight> |
|||
</lang> |
|||
'''Dense Ranking Function''' |
'''Dense Ranking Function''' |
||
<syntaxhighlight lang="julia"> |
|||
<lang Julia> |
|||
function rankdense{T<:Real}(a::Array{T,1}) |
function rankdense{T<:Real}(a::Array{T,1}) |
||
indexin(a, unique(a)) |
indexin(a, unique(a)) |
||
end |
end |
||
</syntaxhighlight> |
|||
</lang> |
|||
'''Ordinal Ranking Function''' |
'''Ordinal Ranking Function''' |
||
<syntaxhighlight lang="julia"> |
|||
<lang Julia> |
|||
function rankordinal{T<:Real}(a::Array{T,1}) |
function rankordinal{T<:Real}(a::Array{T,1}) |
||
collect(1:length(a)) |
collect(1:length(a)) |
||
end |
end |
||
</syntaxhighlight> |
|||
</lang> |
|||
For ordinal ranking, there are a variety of ways of handling tied scores. I've taken the easy way out and assumed that the position in the list already reflects any tie-breaking policy. In this case, there is not much that needs to be done. |
For ordinal ranking, there are a variety of ways of handling tied scores. I've taken the easy way out and assumed that the position in the list already reflects any tie-breaking policy. In this case, there is not much that needs to be done. |
||
'''Fractional Ranking Function''' |
'''Fractional Ranking Function''' |
||
<syntaxhighlight lang="julia"> |
|||
<lang Julia> |
|||
function rankfractional{T<:Real}(a::Array{T,1}) |
function rankfractional{T<:Real}(a::Array{T,1}) |
||
r = float64(collect(1:length(a))) |
r = float64(collect(1:length(a))) |
||
Line 1,021: | Line 3,090: | ||
return r |
return r |
||
end |
end |
||
</syntaxhighlight> |
|||
</lang> |
|||
'''Main''' |
'''Main''' |
||
<syntaxhighlight lang="julia"> |
|||
<lang Julia> |
|||
scores = [44, 42, 42, 41, 41, 41, 39] |
scores = [44, 42, 42, 41, 41, 41, 39] |
||
names = ["Solomon", "Jason", "Errol", "Garry", |
names = ["Solomon", "Jason", "Errol", "Garry", |
||
Line 1,046: | Line 3,115: | ||
println() |
println() |
||
end |
end |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
Line 1,060: | Line 3,129: | ||
</pre> |
</pre> |
||
=={{header| |
=={{header|Kotlin}}== |
||
<syntaxhighlight lang="scala">// version 1.0.6 |
|||
<lang perl6>my @scores = |
|||
Solomon => 44, |
|||
Jason => 42, |
|||
Errol => 42, |
|||
Garry => 41, |
|||
Bernard => 41, |
|||
Barry => 41, |
|||
Stephen => 39; |
|||
/* all ranking functions assume the array of Pairs is non-empty and already sorted by decreasing order of scores |
|||
sub tiers (@s) { @s.classify(*.value).pairs.sort.reverse.map: { [.value».key] } } |
|||
and then, if the scores are equal, by reverse alphabetic order of names |
|||
*/ |
|||
fun standardRanking(scores: Array<Pair<Int, String>>): IntArray { |
|||
sub standard (@s) { |
|||
val rankings = IntArray(scores.size) |
|||
rankings[0] = 1 |
|||
for (i in 1 until scores.size) rankings[i] = if (scores[i].first == scores[i - 1].first) rankings[i - 1] else i + 1 |
|||
return rankings |
|||
} |
|||
fun modifiedRanking(scores: Array<Pair<Int, String>>): IntArray { |
|||
val rankings = IntArray(scores.size) |
|||
rankings[0] = 1 |
|||
for (i in 1 until scores.size) { |
|||
rankings[i] = i + 1 |
|||
val currScore = scores[i].first |
|||
for (j in i - 1 downTo 0) { |
|||
if (currScore != scores[j].first) break |
|||
rankings[j] = i + 1 |
|||
} |
|||
} |
|||
return rankings |
|||
} |
|||
fun denseRanking(scores: Array<Pair<Int, String>>): IntArray { |
|||
val rankings = IntArray(scores.size) |
|||
rankings[0] = 1 |
|||
var prevRanking = 1 |
|||
for (i in 1 until scores.size) rankings[i] = if (scores[i].first == scores[i - 1].first) prevRanking else ++prevRanking |
|||
return rankings |
|||
} |
|||
fun ordinalRanking(scores: Array<Pair<Int, String>>) = IntArray(scores.size) { it + 1 } |
|||
fun fractionalRanking(scores: Array<Pair<Int, String>>): DoubleArray { |
|||
val rankings = DoubleArray(scores.size) |
|||
rankings[0] = 1.0 |
|||
for (i in 1 until scores.size) { |
|||
var k = i |
|||
val currScore = scores[i].first |
|||
for (j in i - 1 downTo 0) { |
|||
if (currScore != scores[j].first) break |
|||
k = j |
|||
} |
|||
val avg = (k..i).average() + 1.0 |
|||
for (m in k..i) rankings[m] = avg |
|||
} |
|||
return rankings |
|||
} |
|||
fun printRankings(title: String, rankings: IntArray, scores: Array<Pair<Int, String>>) { |
|||
println(title + ":") |
|||
for (i in 0 until rankings.size) { |
|||
print ("${rankings[i]} ") |
|||
println(scores[i].toString().removeSurrounding("(", ")").replace(",", "")) |
|||
} |
|||
println() |
|||
} |
|||
fun printFractionalRankings(title: String, rankings: DoubleArray, scores: Array<Pair<Int, String>>) { |
|||
println(title + ":") |
|||
for (i in 0 until rankings.size) { |
|||
print ("${"%3.2f".format(rankings[i])} ") |
|||
println(scores[i].toString().removeSurrounding("(", ")").replace(",", "")) |
|||
} |
|||
println() |
|||
} |
|||
fun main(args: Array<String>) { |
|||
val scores = arrayOf(44 to "Solomon", 42 to "Jason", 42 to "Errol", 41 to "Garry", |
|||
41 to "Bernard", 41 to "Barry", 39 to "Stephen") |
|||
printRankings("Standard ranking", standardRanking(scores), scores) |
|||
printRankings("Modified ranking", modifiedRanking(scores), scores) |
|||
printRankings("Dense ranking", denseRanking(scores), scores) |
|||
printRankings("Ordinal ranking", ordinalRanking(scores), scores) |
|||
printFractionalRankings("Fractional ranking", fractionalRanking(scores), scores) |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Standard ranking: |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
2 42 Errol |
|||
4 41 Garry |
|||
4 41 Bernard |
|||
4 41 Barry |
|||
7 39 Stephen |
|||
Modified ranking: |
|||
1 44 Solomon |
|||
3 42 Jason |
|||
3 42 Errol |
|||
6 41 Garry |
|||
6 41 Bernard |
|||
6 41 Barry |
|||
7 39 Stephen |
|||
Dense ranking: |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
2 42 Errol |
|||
3 41 Garry |
|||
3 41 Bernard |
|||
3 41 Barry |
|||
4 39 Stephen |
|||
Ordinal ranking: |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
3 42 Errol |
|||
4 41 Garry |
|||
5 41 Bernard |
|||
6 41 Barry |
|||
7 39 Stephen |
|||
Fractional ranking: |
|||
1.00 44 Solomon |
|||
2.50 42 Jason |
|||
2.50 42 Errol |
|||
5.00 41 Garry |
|||
5.00 41 Bernard |
|||
5.00 41 Barry |
|||
7.00 39 Stephen |
|||
</pre> |
|||
=={{header|Ksh}}== |
|||
<syntaxhighlight lang="ksh"> |
|||
#!/bin/ksh |
|||
exec 2> /tmp/Ranking_methods.err |
|||
# Ranking methods |
|||
# |
|||
# # Standard. (Ties share what would have been their first ordinal number). |
|||
# # Modified. (Ties share what would have been their last ordinal number). |
|||
# # Dense. (Ties share the next available integer). |
|||
# # Ordinal. ((Competitors take the next available integer. Ties are not treated otherwise). |
|||
# # Fractional. (Ties share the mean of what would have been their ordinal numbers) |
|||
# # Variables: |
|||
# |
|||
typeset -a arr=( '44 Solomon' '42 Jason' '42 Errol' '41 Garry' '41 Bernard' '41 Barry' '39 Stephen' ) |
|||
integer i |
|||
# # Functions: |
|||
# |
|||
# # Function _rankStandard(arr, rankarr) - retun arr with standard ranking |
|||
# |
|||
function _rankStandard { |
|||
typeset _ranked ; nameref _ranked="$1" |
|||
typeset _i _j _scr _currank _prevscr _shelf |
|||
integer _i _j _scr _currank=1 _prevscr |
|||
typeset -a _shelf |
|||
for ((_i=0; _i<${#arr[*]}; _i++)); do |
|||
_scr=${arr[_i]%\ *} |
|||
if (( _i>0 )) && (( _scr != _prevscr )); then |
|||
for ((_j=0; _j<${#_shelf[*]}; _j++)); do |
|||
_ranked+=( "${_currank} ${_shelf[_j]}" ) |
|||
done |
|||
(( _currank+=${#_shelf[*]} )) |
|||
unset _shelf ; typeset -a _shelf |
|||
fi |
|||
_shelf+=( "${arr[_i]}" ) |
|||
_prevscr=${_scr} |
|||
done |
|||
for ((_j=0; _j<${#_shelf[*]}; _j++)); do |
|||
_ranked+=( "${_currank} ${_shelf[_j]}" ) |
|||
done |
|||
} |
|||
# # Function _rankModified(arr, rankarr) - retun arr with modified ranking |
|||
# |
|||
function _rankModified { |
|||
typeset _ranked ; nameref _ranked="$1" |
|||
typeset _i _j _scr _currank _prevscr _shelf |
|||
integer _i _j _scr _currank=0 _prevscr |
|||
typeset -a _shelf |
|||
for ((_i=0; _i<${#arr[*]}; _i++)); do |
|||
_scr=${arr[_i]%\ *} |
|||
if (( _i>0 )) && (( _scr != _prevscr )); then |
|||
for ((_j=0; _j<${#_shelf[*]}; _j++)); do |
|||
_ranked+=( "${_currank} ${_shelf[_j]}" ) |
|||
done |
|||
unset _shelf ; typeset -a _shelf |
|||
fi |
|||
_shelf+=( "${arr[_i]}" ) |
|||
(( _currank++ )) |
|||
_prevscr=${_scr} |
|||
done |
|||
for ((_j=0; _j<${#_shelf[*]}; _j++)); do |
|||
_ranked+=( "${_currank} ${_shelf[_j]}" ) |
|||
done |
|||
} |
|||
# # Function _rankDense(arr, rankarr) - retun arr with dense ranking |
|||
# |
|||
function _rankDense { |
|||
typeset _ranked ; nameref _ranked="$1" |
|||
typeset _i _j _scr _currank _prevscr _shelf |
|||
integer _i _j _scr _currank=0 _prevscr |
|||
typeset -a _shelf |
|||
for ((_i=0; _i<${#arr[*]}; _i++)); do |
|||
_scr=${arr[_i]%\ *} |
|||
if (( _i>0 )) && (( _scr != _prevscr )); then |
|||
(( _currank++ )) |
|||
for ((_j=0; _j<${#_shelf[*]}; _j++)); do |
|||
_ranked+=( "${_currank} ${_shelf[_j]}" ) |
|||
done |
|||
unset _shelf ; typeset -a _shelf |
|||
fi |
|||
_shelf+=( "${arr[_i]}" ) |
|||
_prevscr=${_scr} |
|||
done |
|||
(( _currank++ )) |
|||
for ((_j=0; _j<${#_shelf[*]}; _j++)); do |
|||
_ranked+=( "${_currank} ${_shelf[_j]}" ) |
|||
done |
|||
} |
|||
# # Function _rankOrdinal(arr, rankarr) - retun arr with ordinal ranking |
|||
# |
|||
function _rankOrdinal { |
|||
typeset _ranked ; nameref _ranked="$1" |
|||
typeset _i ; integer _i |
|||
for ((_i=0; _i<${#arr[*]}; _i++)); do |
|||
_ranked+=( "$(( _i + 1 )) ${arr[_i]}" ) |
|||
done |
|||
} |
|||
# # Function _rankFractional(arr, rankarr) - retun arr with Fractional ranking |
|||
# |
|||
function _rankFractional { |
|||
typeset _ranked ; nameref _ranked="$1" |
|||
typeset _i _j _scr _currank _prevscr _shelf |
|||
integer _i _j _scr _prevscr |
|||
typeset -F1 _currank=1.0 |
|||
typeset -a _shelf |
|||
for ((_i=0; _i<${#arr[*]}; _i++)); do |
|||
_scr=${arr[_i]%\ *} |
|||
if (( _i>0 )) && (( _scr != _prevscr )); then |
|||
(( _currank/=${#_shelf[*]} )) |
|||
for ((_j=0; _j<${#_shelf[*]}; _j++)); do |
|||
_ranked+=( "${_currank} ${_shelf[_j]}" ) |
|||
done |
|||
_currank=0.0 |
|||
unset _shelf ; typeset -a _shelf |
|||
fi |
|||
(( _i>0 )) && (( _currank+=_i + 1 )) |
|||
_shelf+=( "${arr[_i]}" ) |
|||
_prevscr=${_scr} |
|||
done |
|||
for ((_j=0; _j<${#_shelf[*]}; _j++)); do |
|||
(( _currank/=${#_shelf[*]} )) |
|||
_ranked+=( "${_currank} ${_shelf[_j]}" ) |
|||
done |
|||
} |
|||
###### |
|||
# main # |
|||
###### |
|||
printf "\n\nInput Data: ${#arr[*]} records\n---------------------\n" |
|||
for ((i=0; i< ${#arr[*]}; i++)); do |
|||
print ${arr[i]} |
|||
done |
|||
typeset -a rankedarr |
|||
_rankStandard rankedarr |
|||
printf "\n\nStandard Ranking\n----------------\n" |
|||
for ((i=0; i< ${#rankedarr[*]}; i++)); do |
|||
print ${rankedarr[i]} |
|||
done |
|||
unset rankedarr ; typeset -a rankedarr |
|||
_rankModified rankedarr |
|||
printf "\n\nModified Ranking\n----------------\n" |
|||
for ((i=0; i< ${#rankedarr[*]}; i++)); do |
|||
print ${rankedarr[i]} |
|||
done |
|||
unset rankedarr ; typeset -a rankedarr |
|||
_rankDense rankedarr |
|||
printf "\n\nDense Ranking\n-------------\n" |
|||
for ((i=0; i< ${#rankedarr[*]}; i++)); do |
|||
print ${rankedarr[i]} |
|||
done |
|||
unset rankedarr ; typeset -a rankedarr |
|||
_rankOrdinal rankedarr |
|||
printf "\n\nOrdinal Ranking\n---------------\n" |
|||
for ((i=0; i< ${#rankedarr[*]}; i++)); do |
|||
print ${rankedarr[i]} |
|||
done |
|||
unset rankedarr ; typeset -a rankedarr |
|||
_rankFractional rankedarr |
|||
printf "\n\nFractional Ranking\n------------------\n" |
|||
for ((i=0; i< ${#rankedarr[*]}; i++)); do |
|||
print ${rankedarr[i]} |
|||
done</syntaxhighlight> |
|||
{{out}}<pre> |
|||
Input Data: 7 records |
|||
--------------------- |
|||
44 Solomon |
|||
42 Jason |
|||
42 Errol |
|||
41 Garry |
|||
41 Bernard |
|||
41 Barry |
|||
39 Stephen |
|||
Standard Ranking |
|||
---------------- |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
2 42 Errol |
|||
4 41 Garry |
|||
4 41 Bernard |
|||
4 41 Barry |
|||
7 39 Stephen |
|||
Modified Ranking |
|||
---------------- |
|||
1 44 Solomon |
|||
3 42 Jason |
|||
3 42 Errol |
|||
6 41 Garry |
|||
6 41 Bernard |
|||
6 41 Barry |
|||
7 39 Stephen |
|||
Dense Ranking |
|||
------------- |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
2 42 Errol |
|||
3 41 Garry |
|||
3 41 Bernard |
|||
3 41 Barry |
|||
4 39 Stephen |
|||
Ordinal Ranking |
|||
--------------- |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
3 42 Errol |
|||
4 41 Garry |
|||
5 41 Bernard |
|||
6 41 Barry |
|||
7 39 Stephen |
|||
Fractional Ranking |
|||
------------------ |
|||
1.0 44 Solomon |
|||
2.5 42 Jason |
|||
2.5 42 Errol |
|||
5.0 41 Garry |
|||
5.0 41 Bernard |
|||
5.0 41 Barry |
|||
7.0 39 Stephen</pre> |
|||
=={{header|M2000 Interpreter}}== |
|||
<syntaxhighlight lang="m2000 interpreter"> |
|||
Module Ranking (output$, orderlist) { |
|||
Open output$ for output as #k |
|||
Gosub getdata |
|||
Print #k, "Standard ranking:" |
|||
skip=true |
|||
rankval=1 |
|||
oldrank=0 |
|||
For i=1 to items |
|||
Read rank, name$ |
|||
if skip then |
|||
skip=false |
|||
else.if oldrank<>rank then |
|||
rankval=i |
|||
end if |
|||
oldrank=rank |
|||
Print #k, Format$("{0::-5} {2} ({1})", rankval, rank, name$) |
|||
Next |
|||
Gosub getdata |
|||
Print #k, "Modified ranking:" |
|||
skip=true |
|||
rankval=Items |
|||
oldrank=0 |
|||
ShiftBack 1, -items*2 ' reverse stack items |
|||
For i=items to 1 |
|||
Read name$, rank |
|||
if skip then |
|||
skip=false |
|||
else.if oldrank<>rank then |
|||
rankval=i |
|||
end if |
|||
oldrank=rank |
|||
Data Format$("{0::-5} {2} ({1})", rankval, rank, name$) |
|||
Next |
|||
ShiftBack 1, -items ' reverse stack items |
|||
For i=1 to items |
|||
Print #k, letter$ |
|||
Next i |
|||
Gosub getdata |
|||
Print #k, "Dense ranking:" |
|||
skip=true |
|||
Dense=Stack |
|||
acc=1 |
|||
oldrank=0 |
|||
For i=1 to items |
|||
Read rank, name$ |
|||
if skip then |
|||
skip=false |
|||
oldrank=rank |
|||
else.if oldrank<>rank then |
|||
oldrank=rank |
|||
Gosub dense |
|||
acc=i |
|||
end if |
|||
Stack Dense {data Format$(" {0} ({1})",name$, rank)} |
|||
Next |
|||
Gosub dense |
|||
Gosub getdata |
|||
Print #k, "Ordinal ranking:" |
|||
For i=1 to items |
|||
Print #k, Format$("{0::-5} {2} ({1})", i, Number, letter$) |
|||
Next |
|||
Gosub getdata |
|||
Print #k, "Fractional ranking:" |
|||
skip=true |
|||
Frac=Stack |
|||
acc=1 |
|||
oldrank=0 |
|||
For i=1 to items |
|||
Read rank, name$ |
|||
if skip then |
|||
skip=false |
|||
oldrank=rank |
|||
else.if oldrank<>rank then |
|||
oldrank=rank |
|||
Gosub Fractional |
|||
acc=I |
|||
end if |
|||
Stack Frac {data Format$(" {0} ({1})",name$, rank)} |
|||
Next |
|||
Gosub Fractional |
|||
Close #k |
|||
End |
|||
Fractional: |
|||
val=((len(Frac)+1)/2+(acc-1)) |
|||
Stack Frac { |
|||
while not empty |
|||
Print #k, format$("{0:1:-5}{1}", val, letter$) |
|||
end while |
|||
} |
|||
Return |
|||
dense: |
|||
Stack Dense { |
|||
while not empty |
|||
Print #k, format$("{0::-5}{1}", acc, letter$) |
|||
end while |
|||
} |
|||
Return |
|||
getdata: |
|||
flush |
|||
stack stack(orderlist) // place a copy of items to current stack |
|||
items=stack.size/2 |
|||
Return |
|||
} |
|||
Flush |
|||
Data 44, "Solomon", 42, "Jason", 42, "Errol" |
|||
Data 41, "Garry", 41, "Bernard", 41, "Barry" |
|||
Data 39, "Stephen" |
|||
// get all items from current stack to a new stack |
|||
alist=[] |
|||
// To screen |
|||
Ranking "", alist |
|||
// To file |
|||
Ranking "ranking.txt", alist |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Standard ranking: |
|||
1 Solomon (44) |
|||
2 Jason (42) |
|||
2 Errol (42) |
|||
4 Garry (41) |
|||
4 Bernard (41) |
|||
4 Barry (41) |
|||
7 Stephen (39) |
|||
Modified ranking: |
|||
1 Solomon (44) |
|||
3 Jason (42) |
|||
3 Errol (42) |
|||
6 Garry (41) |
|||
6 Bernard (41) |
|||
6 Barry (41) |
|||
7 Stephen (39) |
|||
Dense ranking: |
|||
1 Solomon (44) |
|||
2 Jason (42) |
|||
2 Errol (42) |
|||
4 Garry (41) |
|||
4 Bernard (41) |
|||
4 Barry (41) |
|||
7 Stephen (39) |
|||
Ordinal ranking: |
|||
1 Solomon (44) |
|||
2 Jason (42) |
|||
3 Errol (42) |
|||
4 Garry (41) |
|||
5 Bernard (41) |
|||
6 Barry (41) |
|||
7 Stephen (39) |
|||
Fractional ranking: |
|||
1.0 Solomon (44) |
|||
2.5 Jason (42) |
|||
2.5 Errol (42) |
|||
5.0 Garry (41) |
|||
5.0 Bernard (41) |
|||
5.0 Barry (41) |
|||
7.0 Stephen (39) |
|||
</pre> |
|||
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
|||
<syntaxhighlight lang="mathematica">data = Transpose@{{44, 42, 42, 41, 41, 41, 39}, {"Solomon", "Jason", |
|||
"Errol", "Garry", "Bernard", "Barry", "Stephen"}}; |
|||
rank[data_, type_] := |
|||
Module[{t = Transpose@{Sort@data, Range[Length@data, 1, -1]}}, |
|||
Switch[type, |
|||
"standard", data/.Rule@@@First/@SplitBy[t, First], |
|||
"modified", data/.Rule@@@Last/@SplitBy[t, First], |
|||
"dense", data/.Thread[#->Range[Length@#]]&@SplitBy[t, First][[All, 1, 1]], |
|||
"ordinal", Reverse@Ordering[data], |
|||
"fractional", data/.Rule@@@(Mean[#]/.{a_Rational:>N[a]}&)/@ SplitBy[t, First]]] |
|||
fmtRankedData[data_, type_] := |
|||
Labeled[Grid[ |
|||
SortBy[ArrayFlatten@{{Transpose@{rank[data[[All, 1]], type]}, |
|||
data}}, First], Alignment->Left], type<>" ranking:", Top] |
|||
Grid@{fmtRankedData[data, #] & /@ {"standard", "modified", "dense", |
|||
"ordinal", "fractional"}}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>standard ranking: |
|||
1 44 Solomon |
|||
3 42 Errol |
|||
3 42 Jason |
|||
6 41 Barry |
|||
6 41 Bernard |
|||
6 41 Garry |
|||
7 39 Stephen |
|||
modified ranking: |
|||
1 44 Solomon |
|||
2 42 Errol |
|||
2 42 Jason |
|||
4 41 Barry |
|||
4 41 Bernard |
|||
4 41 Garry |
|||
7 39 Stephen |
|||
dense ranking: |
|||
1 39 Stephen |
|||
2 41 Barry |
|||
2 41 Bernard |
|||
2 41 Garry |
|||
3 42 Errol |
|||
3 42 Jason |
|||
4 44 Solomon |
|||
ordinal ranking: |
|||
1 44 Solomon |
|||
2 42 Errol |
|||
3 42 Jason |
|||
4 41 Barry |
|||
5 41 Bernard |
|||
6 41 Garry |
|||
7 39 Stephen |
|||
fractional ranking: |
|||
1 44 Solomon |
|||
2.5 42 Errol |
|||
2.5 42 Jason |
|||
5 41 Barry |
|||
5 41 Bernard |
|||
5 41 Garry |
|||
7 39 Stephen</pre> |
|||
=={{header|Modula-2}}== |
|||
{{trans|C}} |
|||
<syntaxhighlight lang="modula2">MODULE RankingMethods; |
|||
FROM FormatString IMPORT FormatString; |
|||
FROM RealStr IMPORT RealToFixed; |
|||
FROM Terminal IMPORT WriteString,WriteLn,ReadChar; |
|||
PROCEDURE WriteCard(c : CARDINAL); |
|||
VAR buf : ARRAY[0..15] OF CHAR; |
|||
BEGIN |
|||
FormatString("%c", buf, c); |
|||
WriteString(buf) |
|||
END WriteCard; |
|||
TYPE Entry = RECORD |
|||
name : ARRAY[0..15] OF CHAR; |
|||
score : CARDINAL; |
|||
END; |
|||
PROCEDURE OrdinalRanking(CONST entries : ARRAY OF Entry); |
|||
VAR |
|||
buf : ARRAY[0..31] OF CHAR; |
|||
i : CARDINAL; |
|||
BEGIN |
|||
WriteString("Ordinal Ranking"); |
|||
WriteLn; |
|||
WriteString("---------------"); |
|||
WriteLn; |
|||
FOR i:=0 TO HIGH(entries) DO |
|||
FormatString("%c\t%c\t%s\n", buf, i + 1, entries[i].score, entries[i].name); |
|||
WriteString(buf) |
|||
END; |
|||
WriteLn |
|||
END OrdinalRanking; |
|||
PROCEDURE StandardRanking(CONST entries : ARRAY OF Entry); |
|||
VAR |
|||
buf : ARRAY[0..31] OF CHAR; |
|||
i,j : CARDINAL; |
|||
BEGIN |
|||
WriteString("Standard Ranking"); |
|||
WriteLn; |
|||
WriteString("---------------"); |
|||
WriteLn; |
|||
j := 1; |
|||
FOR i:=0 TO HIGH(entries) DO |
|||
FormatString("%c\t%c\t%s\n", buf, j, entries[i].score, entries[i].name); |
|||
WriteString(buf); |
|||
IF entries[i+1].score < entries[i].score THEN |
|||
j := i + 2 |
|||
END |
|||
END; |
|||
WriteLn |
|||
END StandardRanking; |
|||
PROCEDURE DenseRanking(CONST entries : ARRAY OF Entry); |
|||
VAR |
|||
buf : ARRAY[0..31] OF CHAR; |
|||
i,j : CARDINAL; |
|||
BEGIN |
|||
WriteString("Dense Ranking"); |
|||
WriteLn; |
|||
WriteString("---------------"); |
|||
WriteLn; |
|||
j := 1; |
|||
FOR i:=0 TO HIGH(entries) DO |
|||
FormatString("%c\t%c\t%s\n", buf, j, entries[i].score, entries[i].name); |
|||
WriteString(buf); |
|||
IF entries[i+1].score < entries[i].score THEN |
|||
INC(j) |
|||
END |
|||
END; |
|||
WriteLn |
|||
END DenseRanking; |
|||
PROCEDURE ModifiedRanking(CONST entries : ARRAY OF Entry); |
|||
VAR |
|||
buf : ARRAY[0..31] OF CHAR; |
|||
i,j,count : CARDINAL; |
|||
BEGIN |
|||
WriteString("Modified Ranking"); |
|||
WriteLn; |
|||
WriteString("---------------"); |
|||
WriteLn; |
|||
i := 0; |
|||
j := 1; |
|||
WHILE i < HIGH(entries) DO |
|||
IF entries[i].score # entries[i+1].score THEN |
|||
FormatString("%c\t%c\t%s\n", buf, i+1, entries[i].score, entries[i].name); |
|||
WriteString(buf); |
|||
count := 1; |
|||
FOR j:=i+1 TO HIGH(entries)-1 DO |
|||
IF entries[j].score # entries[j+1].score THEN |
|||
BREAK |
|||
END; |
|||
INC(count) |
|||
END; |
|||
j := 0; |
|||
WHILE j < count-1 DO |
|||
FormatString("%c\t%c\t%s\n", buf, i+count+1, entries[i+j+1].score, entries[i+j+1].name); |
|||
WriteString(buf); |
|||
INC(j) |
|||
END; |
|||
i := i + count - 1 |
|||
END; |
|||
INC(i) |
|||
END; |
|||
FormatString("%c\t%c\t%s\n\n", buf, HIGH(entries)+1, entries[HIGH(entries)].score, entries[HIGH(entries)].name); |
|||
WriteString(buf) |
|||
END ModifiedRanking; |
|||
PROCEDURE FractionalRanking(CONST entries : ARRAY OF Entry); |
|||
VAR |
|||
buf : ARRAY[0..32] OF CHAR; |
|||
i,j,count : CARDINAL; |
|||
sum : REAL; |
|||
BEGIN |
|||
WriteString("Fractional Ranking"); |
|||
WriteLn; |
|||
WriteString("---------------"); |
|||
WriteLn; |
|||
sum := 0.0; |
|||
i := 0; |
|||
WHILE i <= HIGH(entries) DO |
|||
IF (i = HIGH(entries) - 1) OR (entries[i].score # entries[i+1].score) THEN |
|||
RealToFixed(FLOAT(i+1),1,buf); |
|||
WriteString(buf); |
|||
FormatString("\t%c\t%s\n", buf, entries[i].score, entries[i].name); |
|||
WriteString(buf) |
|||
ELSE |
|||
sum := FLOAT(i); |
|||
count := 1; |
|||
j := i; |
|||
WHILE entries[j].score = entries[j+1].score DO |
|||
sum := sum + FLOAT(j + 1); |
|||
INC(count); |
|||
INC(j) |
|||
END; |
|||
FOR j:=0 TO count-1 DO |
|||
RealToFixed(sum/FLOAT(count)+1.0,1,buf); |
|||
WriteString(buf); |
|||
FormatString("\t%c\t%s\n", buf, entries[i+j].score, entries[i+j].name); |
|||
WriteString(buf) |
|||
END; |
|||
i := i + count - 1 |
|||
END; |
|||
INC(i) |
|||
END |
|||
END FractionalRanking; |
|||
(* Main *) |
|||
TYPE EA = ARRAY[0..6] OF Entry; |
|||
VAR entries : EA; |
|||
BEGIN |
|||
entries := EA{ |
|||
{"Solomon", 44}, |
|||
{"Jason", 42}, |
|||
{"Errol", 42}, |
|||
{"Garry", 41}, |
|||
{"Bernard", 41}, |
|||
{"Barry", 41}, |
|||
{"Stephen", 39} |
|||
}; |
|||
OrdinalRanking(entries); |
|||
StandardRanking(entries); |
|||
DenseRanking(entries); |
|||
ModifiedRanking(entries); |
|||
FractionalRanking(entries); |
|||
ReadChar |
|||
END RankingMethods.</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Ordinal Ranking |
|||
--------------- |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
3 42 Errol |
|||
4 41 Garry |
|||
5 41 Bernard |
|||
6 41 Barry |
|||
7 39 Stephen |
|||
Standard Ranking |
|||
--------------- |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
2 42 Errol |
|||
4 41 Garry |
|||
4 41 Bernard |
|||
5 41 Barry |
|||
7 39 Stephen |
|||
Dense Ranking |
|||
--------------- |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
2 42 Errol |
|||
3 41 Garry |
|||
3 41 Bernard |
|||
3 41 Barry |
|||
4 39 Stephen |
|||
Modified Ranking |
|||
--------------- |
|||
1 44 Solomon |
|||
3 42 Jason |
|||
3 42 Errol |
|||
6 41 Garry |
|||
6 41 Bernard |
|||
6 41 Barry |
|||
7 39 Stephen |
|||
Fractional Ranking |
|||
--------------- |
|||
1.0 44 Solomon |
|||
2.5 42 Jason |
|||
2.5 42 Errol |
|||
5.0 41 Garry |
|||
5.0 41 Bernard |
|||
5.0 41 Barry |
|||
7.0 39 Stephen</pre> |
|||
=={{header|Nim}}== |
|||
===Using an auxiliary table=== |
|||
To simplify, it’s convenient to build a table giving for each score the list of competitor names. |
|||
<syntaxhighlight lang="nim">import algorithm, sequtils, stats, tables |
|||
type |
|||
Record = tuple[score: int; name: string] # Input data. |
|||
Groups = OrderedTable[int, seq[string]] # Maps score to list of names. |
|||
Rank = tuple[rank: int; name: string; score: int] # Result. |
|||
FractRank = tuple[rank: float; name: string; score: int] # Result (fractional). |
|||
func cmp(a, b: (int, seq[string])): int = |
|||
## Comparison function needed to sort the groups. |
|||
cmp(a[0], b[0]) |
|||
func toGroups(records: openArray[Record]): Groups = |
|||
## Build a "Groups" table from the records. |
|||
for record in records: |
|||
result.mgetOrPut(record.score, @[]).add record.name |
|||
# Sort the list of names by alphabetic order. |
|||
for score in result.keys: |
|||
sort(result[score]) |
|||
# Sort the groups by decreasing score. |
|||
result.sort(cmp, Descending) |
|||
func standardRanks(groups: Groups): seq[Rank] = |
|||
var rank = 1 |
|||
for score, names in groups.pairs: |
|||
for name in names: |
|||
result.add (rank, name, score) |
|||
inc rank, names.len |
|||
func modifiedRanks(groups: Groups): seq[Rank] = |
|||
var rank = 0 |
|||
for score, names in groups.pairs: |
|||
inc rank, names.len |
|||
for name in names: |
|||
result.add (rank, name, score) |
|||
func denseRanks(groups: Groups): seq[Rank] = |
|||
var rank = 0 |
|||
for score, names in groups.pairs: |
|||
inc rank |
|||
for name in names: |
|||
result.add (rank, name, score) |
|||
func ordinalRanks(groups: Groups): seq[Rank] = |
|||
var rank = 0 |
|||
for score, names in groups.pairs: |
|||
for name in names: |
|||
inc rank |
|||
result.add (rank, name, score) |
|||
func fractionalRanks(groups: Groups): seq[FractRank] = |
|||
var rank = 1 |
|||
for score, names in groups.pairs: |
|||
let fRank = mean(toSeq(rank..(rank + names.high))) |
|||
for name in names: |
|||
result.add (fRank, name, score) |
|||
inc rank, names.len |
|||
when isMainModule: |
|||
const Data = [(44, "Solomon"), (42, "Jason"), (42, "Errol"), |
|||
(41, "Garry"), (41, "Bernard"), (41, "Barry"), (39, "Stephen")] |
|||
let groups = Data.toGroups() |
|||
echo "Standard ranking:" |
|||
for (rank, name, score) in groups.standardRanks(): |
|||
echo rank, ": ", name, " ", score |
|||
echo() |
|||
echo "Modified ranking:" |
|||
for (rank, name, score) in groups.modifiedRanks(): |
|||
echo rank, ": ", name, " ", score |
|||
echo() |
|||
echo "Dense ranking:" |
|||
for (rank, name, score) in groups.denseRanks(): |
|||
echo rank, ": ", name, " ", score |
|||
echo() |
|||
echo "Ordinal ranking:" |
|||
for (rank, name, score) in groups.ordinalRanks(): |
|||
echo rank, ": ", name, " ", score |
|||
echo() |
|||
echo "Fractional ranking:" |
|||
for (rank, name, score) in groups.fractionalRanks(): |
|||
echo rank, ": ", name, " ", score</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Standard ranking: |
|||
1: Solomon 44 |
|||
2: Errol 42 |
|||
2: Jason 42 |
|||
4: Barry 41 |
|||
4: Bernard 41 |
|||
4: Garry 41 |
|||
7: Stephen 39 |
|||
Modified ranking: |
|||
1: Solomon 44 |
|||
3: Errol 42 |
|||
3: Jason 42 |
|||
6: Barry 41 |
|||
6: Bernard 41 |
|||
6: Garry 41 |
|||
7: Stephen 39 |
|||
Dense ranking: |
|||
1: Solomon 44 |
|||
2: Errol 42 |
|||
2: Jason 42 |
|||
3: Barry 41 |
|||
3: Bernard 41 |
|||
3: Garry 41 |
|||
4: Stephen 39 |
|||
Ordinal ranking: |
|||
1: Solomon 44 |
|||
2: Errol 42 |
|||
3: Jason 42 |
|||
4: Barry 41 |
|||
5: Bernard 41 |
|||
6: Garry 41 |
|||
7: Stephen 39 |
|||
Fractional ranking: |
|||
1.0: Solomon 44 |
|||
2.5: Errol 42 |
|||
2.5: Jason 42 |
|||
5.0: Barry 41 |
|||
5.0: Bernard 41 |
|||
5.0: Garry 41 |
|||
7.0: Stephen 39</pre> |
|||
===Without an auxiliary table=== |
|||
But it is possible to do the ranking without an auxiliary table. |
|||
<syntaxhighlight lang="nim">import algorithm |
|||
type |
|||
Record = tuple[score: int; name: string] # Input data. |
|||
Rank = tuple[rank: int; name: string; score: int] # Result. |
|||
FractRank = tuple[rank: float; name: string; score: int] # Result (fractional). |
|||
func cmp(a, b: Record): int = |
|||
## Record comparison function (needed for sorting). |
|||
result = cmp(b[0], a[0]) # Reverse order. |
|||
if result == 0: |
|||
result = cmp(a.name, b.name) # Alphabetical order. |
|||
func standardRanks(records: openArray[Record]): seq[Rank] = |
|||
let records = sorted(records, cmp) |
|||
var rank = 1 |
|||
var currScore = records[0].score |
|||
for idx, (score, name) in records: |
|||
if score != currScore: |
|||
rank = idx + 1 |
|||
currScore = score |
|||
result.add (rank, name, score) |
|||
func modifiedRanks(records: openArray[Record]): seq[Rank] = |
|||
let records = sorted(records, cmp) |
|||
var rank = records.len |
|||
var currScore = records[^1].score |
|||
for idx in countdown(records.high, 0): |
|||
let (score, name) = records[idx] |
|||
if score != currScore: |
|||
rank = idx + 1 |
|||
currScore = score |
|||
result.add (rank, name, score) |
|||
result.reverse() |
|||
func denseRanks(records: openArray[Record]): seq[Rank] = |
|||
let records = sorted(records, cmp) |
|||
var rank = 1 |
|||
var currScore = records[0].score |
|||
for (score, name) in records: |
|||
if score != currScore: |
|||
inc rank |
|||
currScore = score |
|||
result.add (rank, name, score) |
|||
func ordinalRanks(records: openArray[Record]): seq[Rank] = |
|||
let records = sorted(records, cmp) |
|||
var rank = 0 |
|||
for (score, name) in records: |
|||
inc rank |
|||
result.add (rank, name, score) |
|||
func fractionalRanks(records: openArray[Record]): seq[FractRank] = |
|||
let records = sorted(records, cmp) |
|||
# Build a list of ranks. |
|||
var currScore = records[0].score |
|||
var sum = 0 |
|||
var ranks: seq[float] |
|||
var count = 0 |
|||
for idx, record in records: |
|||
if record.score == currScore: |
|||
inc count |
|||
inc sum, idx + 1 |
|||
else: |
|||
ranks.add sum / count |
|||
count = 1 |
|||
currScore = record.score |
|||
sum = idx + 1 |
|||
ranks.add sum / count |
|||
# Give a rank to each record. |
|||
currScore = records[0].score |
|||
var rankIndex = 0 |
|||
for (score, name) in records: |
|||
if score != currScore: |
|||
inc rankIndex |
|||
currScore = score |
|||
result.add (ranks[rankIndex], name, score) |
|||
when isMainModule: |
|||
const Data = [(44, "Solomon"), (42, "Jason"), (42, "Errol"), |
|||
(41, "Garry"), (41, "Bernard"), (41, "Barry"), (39, "Stephen")] |
|||
echo "Standard ranking:" |
|||
for (rank, name, score) in Data.standardRanks(): |
|||
echo rank, ": ", name, " ", score |
|||
echo() |
|||
echo "Modified ranking:" |
|||
for (rank, name, score) in Data.modifiedRanks(): |
|||
echo rank, ": ", name, " ", score |
|||
echo() |
|||
echo "Dense ranking:" |
|||
for (rank, name, score) in Data.denseRanks(): |
|||
echo rank, ": ", name, " ", score |
|||
echo() |
|||
echo "Ordinal ranking:" |
|||
for (rank, name, score) in Data.ordinalRanks(): |
|||
echo rank, ": ", name, " ", score |
|||
echo() |
|||
echo "Fractional ranking:" |
|||
for (rank, name, score) in Data.fractionalRanks(): |
|||
echo rank, ": ", name, " ", score</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Same output as with other version.</pre> |
|||
=={{header|PARI/GP}}== |
|||
Replace "2" with "2.0" in <code>fractional</code> if you prefer decimal to fractional. |
|||
<syntaxhighlight lang="parigp">standard(v)=v=vecsort(v,1,4); my(last=v[1][1]+1); for(i=1,#v, v[i][1]=if(v[i][1]<last,last=v[i][1]; i, v[i-1][1])); v; |
|||
modified(v)=v=vecsort(v,1,4); my(last=v[#v][1]-1); forstep(i=#v,1,-1, v[i][1]=if(v[i][1]>last,last=v[i][1]; i, v[i+1][1])); v; |
|||
dense(v)=v=vecsort(v,1,4); my(last=v[1][1]+1,rank); for(i=1,#v, v[i][1]=if(v[i][1]<last,last=v[i][1]; rank++, rank)); v; |
|||
ordinal(v)=v=vecsort(v,1,4); for(i=1,#v,v[i][1]=i); v; |
|||
fractional(v)=my(a=standard(v),b=modified(v)); vector(#v,i,[(a[i][1]+b[i][1])/2,v[i][2]]); |
|||
v=[[44,"Solomon"], [42,"Jason"], [42,"Errol"], [41,"Garry"], [41,"Bernard"], [41,"Barry"], [39,"Stephen"]]; |
|||
standard(v) |
|||
modified(v) |
|||
dense(v) |
|||
ordinal(v) |
|||
fractional(v)</syntaxhighlight> |
|||
{{out}} |
|||
<pre>%1 = [[1, "Solomon"], [2, "Errol"], [2, "Jason"], [4, "Barry"], [4, "Bernard"], [4, "Garry"], [7, "Stephen"]] |
|||
%2 = [[1, "Solomon"], [3, "Errol"], [3, "Jason"], [6, "Barry"], [6, "Bernard"], [6, "Garry"], [7, "Stephen"]] |
|||
%3 = [[1, "Solomon"], [2, "Errol"], [2, "Jason"], [3, "Barry"], [3, "Bernard"], [3, "Garry"], [4, "Stephen"]] |
|||
%4 = [[1, "Solomon"], [2, "Errol"], [3, "Jason"], [4, "Barry"], [5, "Bernard"], [6, "Garry"], [7, "Stephen"]] |
|||
%5 = [[1, "Solomon"], [5/2, "Jason"], [5/2, "Errol"], [5, "Garry"], [5, "Bernard"], [5, "Barry"], [7, "Stephen"]]</pre> |
|||
=={{header|Perl}}== |
|||
{{trans|Raku}} |
|||
<syntaxhighlight lang="perl">my %scores = ( |
|||
'Solomon' => 44, |
|||
'Jason' => 42, |
|||
'Errol' => 42, |
|||
'Garry' => 41, |
|||
'Bernard' => 41, |
|||
'Barry' => 41, |
|||
'Stephen' => 39 |
|||
); |
|||
sub tiers { |
|||
my(%s) = @_; my(%h); |
|||
push @{$h{$s{$_}}}, $_ for keys %s; |
|||
@{\%h}{reverse sort keys %h}; |
|||
} |
|||
sub standard { |
|||
my(%s) = @_; my($result); |
|||
my $rank = 1; |
my $rank = 1; |
||
for my $players (tiers %s) { |
|||
$result .= "$rank " . join(', ', sort @$players) . "\n"; |
|||
$rank += @$players; |
|||
} |
} |
||
return $result; |
|||
} |
} |
||
sub modified |
sub modified { |
||
my(%s) = @_; my($result); |
|||
my $rank = 0; |
my $rank = 0; |
||
for my $players (tiers %s) { |
|||
$rank += @$players; |
|||
$result .= "$rank " . join(', ', sort @$players) . "\n"; |
|||
} |
} |
||
return $result; |
|||
} |
} |
||
sub dense { |
|||
sub dense (@s) { tiers(@s).map: { ++$_ => @^players } } |
|||
my(%s) = @_; my($n,$result); |
|||
$result .= sprintf "%d %s\n", ++$n, join(', ', sort @$_) for tiers %s; |
|||
return $result; |
|||
} |
|||
sub ordinal |
sub ordinal { |
||
my(%s) = @_; my($n,$result); |
|||
for my $players (tiers %s) { |
|||
$result .= sprintf "%d %s\n", ++$n, $_ for sort @$players; |
|||
} |
|||
return $result; |
|||
} |
|||
sub fractional |
sub fractional { |
||
my(%s) = @_; my($result); |
|||
my $rank = 1; |
my $rank = 1; |
||
for my $players (tiers %s) { |
|||
my $beg = $rank; |
|||
my $end = $rank += @$players; |
|||
my $avg = 0; |
|||
take [+]($beg ..^ $end) / @players => @players; |
|||
$avg += $_/@$players for $beg .. $end-1; |
|||
$result .= sprintf "%3.1f %s\n", $avg, join ', ', sort @$players; |
|||
} |
} |
||
return $result; |
|||
} |
} |
||
print "Standard:\n" . standard(%scores) . "\n"; |
|||
print "Modified:\n" . modified(%scores) . "\n"; |
|||
print "Dense:\n" . dense(%scores) . "\n"; |
|||
print "Ordinal:\n" . ordinal(%scores) . "\n"; |
|||
print "Fractional:\n" . fractional(%scores) . "\n";</syntaxhighlight> |
|||
{{out}} |
{{out}} |
||
<pre>Standard: |
<pre style="height:35ex">Standard: |
||
1 |
1 Solomon |
||
2 |
2 Errol, Jason |
||
4 |
4 Barry, Bernard, Garry |
||
7 |
7 Stephen |
||
Modified: |
Modified: |
||
1 |
1 Solomon |
||
3 |
3 Errol, Jason |
||
6 |
6 Barry, Bernard, Garry |
||
7 |
7 Stephen |
||
Dense: |
Dense: |
||
1 |
1 Solomon |
||
2 |
2 Errol, Jason |
||
3 |
3 Barry, Bernard, Garry |
||
4 |
4 Stephen |
||
Ordinal: |
Ordinal: |
||
1 |
1 Solomon |
||
2 Errol |
|||
2 => "Jason" |
|||
3 Jason |
|||
3 => "Errol" |
|||
4 Barry |
|||
4 => "Garry" |
|||
5 |
5 Bernard |
||
6 Garry |
|||
6 => "Barry" |
|||
7 |
7 Stephen |
||
Fractional: |
Fractional: |
||
1.0 |
1.0 Solomon |
||
2.5 |
2.5 Errol, Jason |
||
5.0 |
5.0 Barry, Bernard, Garry |
||
7.0 |
7.0 Stephen</pre> |
||
=={{header|Phix}}== |
|||
<!--<syntaxhighlight lang="phix">(phixonline)--> |
|||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">ties</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">scores</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">t</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span> <span style="color: #000080;font-style:italic;">-- {start,num} pairs</span> |
|||
<span style="color: #000000;">tdx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">scores</span><span style="color: #0000FF;">))</span> |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">last</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">scores</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">curr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">scores</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">curr</span><span style="color: #0000FF;">=</span><span style="color: #000000;">last</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #000000;">t</span><span style="color: #0000FF;">[$][</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span> |
|||
<span style="color: #008080;">else</span> |
|||
<span style="color: #000000;">t</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">})</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #000000;">tdx</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">last</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">curr</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<span style="color: #000080;font-style:italic;">-- eg <nowiki>{{</nowiki>{1,1},{2,2},{4,3},{7,1<nowiki>}}</nowiki>, |
|||
-- {1,2,2,3,3,3,4<nowiki>}}</nowiki></span> |
|||
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tdx</span><span style="color: #0000FF;">}</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #008080;">enum</span> <span style="color: #000000;">STANDARD</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- eg {1,2,2,4,4,4,7}</span> |
|||
<span style="color: #000000;">MODIFIED</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- eg {1,3,3,6,6,6,7}</span> |
|||
<span style="color: #000000;">DENSE</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (==tdx)</span> |
|||
<span style="color: #000000;">ORDINAL</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- eg {1,2,3,4,5,6,7}</span> |
|||
<span style="color: #000000;">FRACTION</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- {1,2.5,2.5,5,5,5,7}</span> |
|||
<span style="color: #000000;">METHODS</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">$</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">rank</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">method</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tdx</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">idx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tdx</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span> |
|||
<span style="color: #0000FF;">{</span><span style="color: #000000;">tx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tn</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">]</span> |
|||
<span style="color: #008080;">switch</span> <span style="color: #000000;">method</span> |
|||
<span style="color: #008080;">case</span> <span style="color: #000000;">STANDARD</span><span style="color: #0000FF;">:</span> <span style="color: #008080;">return</span> <span style="color: #000000;">tx</span> |
|||
<span style="color: #008080;">case</span> <span style="color: #000000;">MODIFIED</span><span style="color: #0000FF;">:</span> <span style="color: #008080;">return</span> <span style="color: #000000;">tx</span><span style="color: #0000FF;">+</span><span style="color: #000000;">tn</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> |
|||
<span style="color: #008080;">case</span> <span style="color: #000000;">DENSE</span> <span style="color: #0000FF;">:</span> <span style="color: #008080;">return</span> <span style="color: #000000;">idx</span> |
|||
<span style="color: #008080;">case</span> <span style="color: #000000;">ORDINAL</span> <span style="color: #0000FF;">:</span> <span style="color: #008080;">return</span> <span style="color: #000000;">i</span> |
|||
<span style="color: #008080;">case</span> <span style="color: #000000;">FRACTION</span><span style="color: #0000FF;">:</span> <span style="color: #008080;">return</span> <span style="color: #000000;">tx</span><span style="color: #0000FF;">+(</span><span style="color: #000000;">tn</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">2</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #008080;">constant</span> <span style="color: #000000;">scores</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">44</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Solomon"</span><span style="color: #0000FF;">},</span> |
|||
<span style="color: #0000FF;">{</span><span style="color: #000000;">42</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Jason"</span><span style="color: #0000FF;">},</span> |
|||
<span style="color: #0000FF;">{</span><span style="color: #000000;">42</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Errol"</span><span style="color: #0000FF;">},</span> |
|||
<span style="color: #0000FF;">{</span><span style="color: #000000;">41</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Garry"</span><span style="color: #0000FF;">},</span> |
|||
<span style="color: #0000FF;">{</span><span style="color: #000000;">41</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Bernard"</span><span style="color: #0000FF;">},</span> |
|||
<span style="color: #0000FF;">{</span><span style="color: #000000;">41</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Barry"</span><span style="color: #0000FF;">},</span> |
|||
<span style="color: #0000FF;">{</span><span style="color: #000000;">39</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Stephen"</span><span style="color: #0000FF;">}}</span> |
|||
<span style="color: #004080;">sequence</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tdx</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ties</span><span style="color: #0000FF;">(</span><span style="color: #000000;">scores</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" score name standard modified dense ordinal fractional\n"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">scores</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">ranks</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">METHODS</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">method</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">METHODS</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #000000;">ranks</span><span style="color: #0000FF;">[</span><span style="color: #000000;">method</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rank</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">method</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tdx</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%5d %-7s "</span><span style="color: #0000FF;">,</span><span style="color: #000000;">scores</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span> |
|||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%6g %8g %6g %6g %9g\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ranks</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<!--</syntaxhighlight>--> |
|||
{{out}} |
|||
<pre> |
|||
score name standard modified dense ordinal fractional |
|||
44 Solomon 1 1 1 1 1 |
|||
42 Jason 2 3 2 2 2.5 |
|||
42 Errol 2 3 2 3 2.5 |
|||
41 Garry 4 6 3 4 5 |
|||
41 Bernard 4 6 3 5 5 |
|||
41 Barry 4 6 3 6 5 |
|||
39 Stephen 7 7 4 7 7 |
|||
</pre> |
|||
=={{header|PowerShell}}== |
|||
<syntaxhighlight lang="powershell"> |
|||
function Get-Ranking |
|||
{ |
|||
[CmdletBinding(DefaultParameterSetName="Standard")] |
|||
[OutputType([PSCustomObject])] |
|||
Param |
|||
( |
|||
[Parameter(Mandatory=$true, |
|||
ValueFromPipeline=$true, |
|||
ValueFromPipelineByPropertyName=$true, |
|||
Position=0)] |
|||
[string] |
|||
$InputObject, |
|||
[Parameter(Mandatory=$false, |
|||
ParameterSetName="Standard")] |
|||
[switch] |
|||
$Standard, |
|||
[Parameter(Mandatory=$false, |
|||
ParameterSetName="Modified")] |
|||
[switch] |
|||
$Modified, |
|||
[Parameter(Mandatory=$false, |
|||
ParameterSetName="Dense")] |
|||
[switch] |
|||
$Dense, |
|||
[Parameter(Mandatory=$false, |
|||
ParameterSetName="Ordinal")] |
|||
[switch] |
|||
$Ordinal, |
|||
[Parameter(Mandatory=$false, |
|||
ParameterSetName="Fractional")] |
|||
[switch] |
|||
$Fractional |
|||
) |
|||
Begin |
|||
{ |
|||
function Get-OrdinalRank ([PSCustomObject[]]$Values) |
|||
{ |
|||
for ($i = 0; $i -lt $Values.Count; $i++) |
|||
{ |
|||
$Values[$i].Rank = $i + 1 |
|||
} |
|||
$Values |
|||
} |
|||
function Get-Rank ([PSCustomObject[]]$Scores) |
|||
{ |
|||
foreach ($score in $Scores) |
|||
{ |
|||
$score.Group | ForEach-Object {$_.Rank = $score.Rank} |
|||
} |
|||
$Scores.Group |
|||
} |
|||
function New-Competitor ([string]$Name, [int]$Score, [int]$Rank = 0) |
|||
{ |
|||
[PSCustomObject]@{ |
|||
Name = $Name |
|||
Score = $Score |
|||
Rank = $Rank |
|||
} |
|||
} |
|||
$competitors = @() |
|||
$scores = @() |
|||
} |
|||
Process |
|||
{ |
|||
@($input) | ForEach-Object {$competitors += New-Competitor -Name $_.Split()[1] -Score $_.Split()[0]} |
|||
} |
|||
End |
|||
{ |
|||
$scores = $competitors | |
|||
Sort-Object -Property Score -Descending | |
|||
Group-Object -Property Score | |
|||
Select-Object -Property @{Name="Score"; Expression={[int]$_.Name}}, @{Name="Rank"; Expression={0}}, Count, Group |
|||
switch ($PSCmdlet.ParameterSetName) |
|||
{ |
|||
"Standard" |
|||
{ |
|||
$rank = 1 |
|||
for ($i = 0; $i -lt $scores.Count; $i++) |
|||
{ |
|||
$scores[$i].Rank = $rank |
|||
$rank += $scores[$i].Count |
|||
} |
|||
Get-Rank $scores |
|||
} |
|||
"Modified" |
|||
{ |
|||
$rank = 0 |
|||
foreach ($score in $scores) |
|||
{ |
|||
$rank = $score.Count + $rank |
|||
$score.Rank = $rank |
|||
} |
|||
Get-Rank $scores |
|||
} |
|||
"Dense" |
|||
{ |
|||
for ($i = 0; $i -lt $scores.Count; $i++) |
|||
{ |
|||
$scores[$i].Rank = $i + 1 |
|||
} |
|||
Get-Rank $scores |
|||
} |
|||
"Ordinal" |
|||
{ |
|||
Get-OrdinalRank $competitors |
|||
} |
|||
"Fractional" |
|||
{ |
|||
Get-OrdinalRank $competitors | Group-Object -Property Score | ForEach-Object { |
|||
if ($_.Count -gt 1) |
|||
{ |
|||
$rank = ($_.Group.Rank | Measure-Object -Average).Average |
|||
foreach ($competitor in $_.Group) |
|||
{ |
|||
$competitor.Rank = $rank |
|||
} |
|||
} |
|||
} |
|||
$competitors |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
<syntaxhighlight lang="powershell"> |
|||
$scores = "44 Solomon","42 Jason","42 Errol","41 Garry","41 Bernard","41 Barry","39 Stephen" |
|||
</syntaxhighlight> |
|||
<syntaxhighlight lang="powershell"> |
|||
$scores | Get-Ranking -Standard |
|||
</syntaxhighlight> |
|||
{{Out}} |
|||
<pre> |
|||
Name Score Rank |
|||
---- ----- ---- |
|||
Solomon 44 1 |
|||
Jason 42 2 |
|||
Errol 42 2 |
|||
Garry 41 4 |
|||
Bernard 41 4 |
|||
Barry 41 4 |
|||
Stephen 39 7 |
|||
</pre> |
|||
<syntaxhighlight lang="powershell"> |
|||
$scores | Get-Ranking -Modified |
|||
</syntaxhighlight> |
|||
{{Out}} |
|||
<pre> |
|||
Name Score Rank |
|||
---- ----- ---- |
|||
Solomon 44 1 |
|||
Jason 42 3 |
|||
Errol 42 3 |
|||
Garry 41 6 |
|||
Bernard 41 6 |
|||
Barry 41 6 |
|||
Stephen 39 7 |
|||
</pre> |
|||
<syntaxhighlight lang="powershell"> |
|||
$scores | Get-Ranking -Dense |
|||
</syntaxhighlight> |
|||
{{Out}} |
|||
<pre> |
|||
Name Score Rank |
|||
---- ----- ---- |
|||
Solomon 44 1 |
|||
Jason 42 2 |
|||
Errol 42 2 |
|||
Garry 41 3 |
|||
Bernard 41 3 |
|||
Barry 41 3 |
|||
Stephen 39 4 |
|||
</pre> |
|||
<syntaxhighlight lang="powershell"> |
|||
$scores | Get-Ranking -Ordinal |
|||
</syntaxhighlight> |
|||
{{Out}} |
|||
<pre> |
|||
Name Score Rank |
|||
---- ----- ---- |
|||
Solomon 44 1 |
|||
Jason 42 2 |
|||
Errol 42 3 |
|||
Garry 41 4 |
|||
Bernard 41 5 |
|||
Barry 41 6 |
|||
Stephen 39 7 |
|||
</pre> |
|||
<syntaxhighlight lang="powershell"> |
|||
$scores | Get-Ranking -Fractional |
|||
</syntaxhighlight> |
|||
{{Out}} |
|||
<pre> |
|||
Name Score Rank |
|||
---- ----- ---- |
|||
Solomon 44 1 |
|||
Jason 42 2.5 |
|||
Errol 42 2.5 |
|||
Garry 41 5 |
|||
Bernard 41 5 |
|||
Barry 41 5 |
|||
Stephen 39 7 |
|||
</pre> |
|||
=={{header|Python}}== |
=={{header|Python}}== |
||
< |
<syntaxhighlight lang="python">def mc_rank(iterable, start=1): |
||
"""Modified competition ranking""" |
"""Modified competition ranking""" |
||
lastresult, fifo = None, [] |
lastresult, fifo = None, [] |
||
Line 1,214: | Line 4,711: | ||
print('\n%s:' % ranker.__doc__) |
print('\n%s:' % ranker.__doc__) |
||
for rank, score in ranker(scores): |
for rank, score in ranker(scores): |
||
print(' %3g, %r' % (rank, score))</ |
print(' %3g, %r' % (rank, score))</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,272: | Line 4,769: | ||
=={{header|Racket}}== |
=={{header|Racket}}== |
||
< |
<syntaxhighlight lang="racket">#lang racket |
||
;; Tim-brown 2014-09-11 |
;; Tim-brown 2014-09-11 |
||
Line 1,348: | Line 4,845: | ||
(caddr r) |
(caddr r) |
||
(cdddr r))) |
(cdddr r))) |
||
(newline))</ |
(newline))</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,395: | Line 4,892: | ||
= 5 41 Barry |
= 5 41 Barry |
||
7 39 Stephen</pre> |
7 39 Stephen</pre> |
||
=={{header|Raku}}== |
|||
(formerly Perl 6) |
|||
<syntaxhighlight lang="raku" line>my @scores = |
|||
Solomon => 44, |
|||
Jason => 42, |
|||
Errol => 42, |
|||
Garry => 41, |
|||
Bernard => 41, |
|||
Barry => 41, |
|||
Stephen => 39; |
|||
sub tiers (@s) { @s.classify(*.value).pairs.sort.reverse.map: { .value».key } } |
|||
sub standard (@s) { |
|||
my $rank = 1; |
|||
gather for tiers @s -> @players { |
|||
take $rank => @players; |
|||
$rank += @players; |
|||
} |
|||
} |
|||
sub modified (@s) { |
|||
my $rank = 0; |
|||
gather for tiers @s -> @players { |
|||
$rank += @players; |
|||
take $rank => @players; |
|||
} |
|||
} |
|||
sub dense (@s) { tiers(@s).map: { ++$_ => @^players } } |
|||
sub ordinal (@s) { @s.map: ++$_ => *.key } |
|||
sub fractional (@s) { |
|||
my $rank = 1; |
|||
gather for tiers @s -> @players { |
|||
my $beg = $rank; |
|||
my $end = $rank += @players; |
|||
take [+]($beg ..^ $end) / @players => @players; |
|||
} |
|||
} |
|||
say "Standard:"; .perl.say for standard @scores; |
|||
say "\nModified:"; .perl.say for modified @scores; |
|||
say "\nDense:"; .perl.say for dense @scores; |
|||
say "\nOrdinal:"; .perl.say for ordinal @scores; |
|||
say "\nFractional:"; .perl.say for fractional @scores;</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Standard: |
|||
1 => ["Solomon"] |
|||
2 => ["Jason", "Errol"] |
|||
4 => ["Garry", "Bernard", "Barry"] |
|||
7 => ["Stephen"] |
|||
Modified: |
|||
1 => ["Solomon"] |
|||
3 => ["Jason", "Errol"] |
|||
6 => ["Garry", "Bernard", "Barry"] |
|||
7 => ["Stephen"] |
|||
Dense: |
|||
1 => ["Solomon"] |
|||
2 => ["Jason", "Errol"] |
|||
3 => ["Garry", "Bernard", "Barry"] |
|||
4 => ["Stephen"] |
|||
Ordinal: |
|||
1 => "Solomon" |
|||
2 => "Jason" |
|||
3 => "Errol" |
|||
4 => "Garry" |
|||
5 => "Bernard" |
|||
6 => "Barry" |
|||
7 => "Stephen" |
|||
Fractional: |
|||
1.0 => ["Solomon"] |
|||
2.5 => ["Jason", "Errol"] |
|||
5.0 => ["Garry", "Bernard", "Barry"] |
|||
7.0 => ["Stephen"]</pre> |
|||
=={{header|REXX}}== |
=={{header|REXX}}== |
||
< |
<syntaxhighlight lang="rexx">/************************** |
||
44 Solomon 1 1 1 1 1 |
44 Solomon 1 1 1 1 1 |
||
42 Jason 2 3 2 2 2.5 |
42 Jason 2 3 2 2 2.5 |
||
Line 1,445: | Line 5,023: | ||
cp=p |
cp=p |
||
End |
End |
||
Say cnt.ok 'correct lines'</ |
Say cnt.ok 'correct lines'</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>44 Solomon 1 1 1 1 1 |
<pre>44 Solomon 1 1 1 1 1 |
||
Line 1,457: | Line 5,035: | ||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
< |
<syntaxhighlight lang="ruby">ar = "44 Solomon |
||
42 Jason |
42 Jason |
||
42 Errol |
42 Errol |
||
Line 1,464: | Line 5,042: | ||
41 Barry |
41 Barry |
||
39 Stephen".lines.map{|line| line.split} |
39 Stephen".lines.map{|line| line.split} |
||
grouped = ar.group_by{|pair| pair.shift.to_i} |
|||
grouped = ar.group_by{|pair| pair.delete_at(0).to_i} |
|||
s_rnk = 1 |
s_rnk = 1 |
||
m_rnk = |
m_rnk = o_rnk = 0 |
||
puts "stand.\tmod.\tdense\tord.\tfract." |
puts "stand.\tmod.\tdense\tord.\tfract." |
||
grouped.each.with_index do |(score, names), |
grouped.each.with_index(1) do |(score, names), d_rnk| |
||
d_rnk = i + 1 |
|||
m_rnk += names.flatten!.size |
m_rnk += names.flatten!.size |
||
f_rnk = (s_rnk + m_rnk)/2.0 |
f_rnk = (s_rnk + m_rnk)/2.0 |
||
names.each do |name| |
names.each do |name| |
||
o_rnk += 1 |
o_rnk += 1 |
||
puts "#{s_rnk}\t#{m_rnk}\t#{d_rnk}\t#{o_rnk}\t#{f_rnk.to_s. |
puts "#{s_rnk}\t#{m_rnk}\t#{d_rnk}\t#{o_rnk}\t#{f_rnk.to_s.sub(".0","")}\t#{score} #{name}" |
||
end |
end |
||
s_rnk += names.size |
s_rnk += names.size |
||
end</ |
end</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
|||
<pre>stand. mod. dense ord. fract. |
|||
stand. mod. dense ord. fract. |
|||
1 1 1 1 1 44 Solomon |
1 1 1 1 1 44 Solomon |
||
2 3 2 2 2.5 42 Jason |
2 3 2 2 2.5 42 Jason |
||
Line 1,490: | Line 5,067: | ||
7 7 4 7 7 39 Stephen |
7 7 4 7 7 39 Stephen |
||
</pre> |
</pre> |
||
=={{header|Scala}}== |
=={{header|Scala}}== |
||
This example uses a type-safe singly-linked object model with no mutable state variables, which makes it longer than the Ruby version above, but demonstrates an object-oriented functional programming approach. |
This example uses a type-safe singly-linked object model with no mutable state variables, which makes it longer than the Ruby version above, but demonstrates an object-oriented functional programming approach. |
||
< |
<syntaxhighlight lang="scala">object RankingMethods extends App { |
||
case class Score(score: Int, name: String) // incoming data |
case class Score(score: Int, name: String) // incoming data |
||
case class Rank[Precision](rank: Precision, names: List[String]) // outgoing results (can be int or double) |
case class Rank[Precision](rank: Precision, names: List[String]) // outgoing results (can be int or double) |
||
Line 1,535: | Line 5,113: | ||
println(rankFractional(test) mkString "\n") |
println(rankFractional(test) mkString "\n") |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>Standard: |
<pre>Standard: |
||
Line 1,569: | Line 5,147: | ||
Rank(5.0,List(Garry, Bernard, Barry)) |
Rank(5.0,List(Garry, Bernard, Barry)) |
||
Rank(7.0,List(Stephen))</pre> |
Rank(7.0,List(Stephen))</pre> |
||
=={{header|Sidef}}== |
|||
{{trans|Raku}} |
|||
<syntaxhighlight lang="ruby">var scores = [ |
|||
Pair(Solomon => 44), |
|||
Pair(Jason => 42), |
|||
Pair(Errol => 42), |
|||
Pair(Garry => 41), |
|||
Pair(Bernard => 41), |
|||
Pair(Barry => 41), |
|||
Pair(Stephen => 39), |
|||
] |
|||
func tiers(s) { |
|||
s.group_by { .value }.kv.sort.flip.map { .value.map{.key} } |
|||
} |
|||
func standard(s) { |
|||
var rank = 1 |
|||
gather { |
|||
for players in tiers(s) { |
|||
take(Pair(rank, players)) |
|||
rank += players.len |
|||
} |
|||
} |
|||
} |
|||
func modified(s) { |
|||
var rank = 0 |
|||
gather { |
|||
for players in tiers(s) { |
|||
rank += players.len |
|||
take(Pair(rank, players)) |
|||
} |
|||
} |
|||
} |
|||
func dense(s) { |
|||
tiers(s).map_kv { |k,v| Pair(k+1, v) } |
|||
} |
|||
func ordinal(s) { |
|||
s.map_kv { |k,v| Pair(k+1, v.key) } |
|||
} |
|||
func fractional(s) { |
|||
var rank = 1 |
|||
gather { |
|||
for players in tiers(s) { |
|||
var beg = rank |
|||
var end = (rank += players.len) |
|||
take(Pair(sum(beg ..^ end) / players.len, players)) |
|||
} |
|||
} |
|||
} |
|||
func display(r) { |
|||
say r.map {|a| '%3s : %s' % a... }.join("\n") |
|||
} |
|||
say "Standard:"; display( standard(scores)) |
|||
say "\nModified:"; display( modified(scores)) |
|||
say "\nDense:"; display( dense(scores)) |
|||
say "\nOrdinal:"; display( ordinal(scores)) |
|||
say "\nFractional:"; display(fractional(scores))</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Standard: |
|||
1 : ["Solomon"] |
|||
2 : ["Jason", "Errol"] |
|||
4 : ["Garry", "Bernard", "Barry"] |
|||
7 : ["Stephen"] |
|||
Modified: |
|||
1 : ["Solomon"] |
|||
3 : ["Jason", "Errol"] |
|||
6 : ["Garry", "Bernard", "Barry"] |
|||
7 : ["Stephen"] |
|||
Dense: |
|||
1 : ["Solomon"] |
|||
2 : ["Jason", "Errol"] |
|||
3 : ["Garry", "Bernard", "Barry"] |
|||
4 : ["Stephen"] |
|||
Ordinal: |
|||
1 : Solomon |
|||
2 : Jason |
|||
3 : Errol |
|||
4 : Garry |
|||
5 : Bernard |
|||
6 : Barry |
|||
7 : Stephen |
|||
Fractional: |
|||
1 : ["Solomon"] |
|||
2.5 : ["Jason", "Errol"] |
|||
5 : ["Garry", "Bernard", "Barry"] |
|||
7 : ["Stephen"] |
|||
</pre> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
< |
<syntaxhighlight lang="tcl">proc rank {rankingMethod sortedList} { |
||
# Extract the groups in the data (this is pointless for ordinal...) |
# Extract the groups in the data (this is pointless for ordinal...) |
||
set s [set group [set groups {}]] |
set s [set group [set groups {}]] |
||
Line 1,626: | Line 5,304: | ||
puts " $rank\t$score\t$who" |
puts " $rank\t$score\t$who" |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,675: | Line 5,353: | ||
7 39 Stephen |
7 39 Stephen |
||
</pre> |
</pre> |
||
=={{header|True BASIC}}== |
|||
{{trans|BASIC}} |
|||
<syntaxhighlight lang="basic"> |
|||
LET n = 7 |
|||
DIM puntos(7), ptosnom(7), nombre$(7) |
|||
SUB MostarTabla |
|||
FOR i = 1 to n |
|||
PRINT str$(ptosnom(i)); " "; puntos(i); " "; nombre$(i) |
|||
NEXT i |
|||
PRINT |
|||
END SUB |
|||
PRINT "Puntuaciones a clasificar (mejores primero):" |
|||
FOR i = 1 to n |
|||
READ puntos(i), nombre$(i) |
|||
PRINT " "; puntos(i); " "; nombre$(i) |
|||
NEXT i |
|||
PRINT |
|||
PRINT "--- Standard ranking ---" |
|||
LET ptosnom(1) = 1 |
|||
FOR i = 2 to n |
|||
NEXT i |
|||
CALL MostarTabla |
|||
PRINT "--- Modified ranking ---" |
|||
LET ptosnom(n) = n |
|||
FOR i = n-1 to 1 step -1 |
|||
IF puntos(i) = puntos(i+1) then LET ptosnom(i) = ptosnom(i+1) else LET ptosnom(i) = i |
|||
NEXT i |
|||
CALL MostarTabla |
|||
PRINT "--- Ordinal ranking ---" |
|||
FOR i = 1 to n |
|||
LET ptosnom(i) = i |
|||
NEXT i |
|||
CALL MostarTabla |
|||
PRINT "--- Fractional ranking ---" |
|||
LET i = 1 |
|||
LET j = 2 |
|||
DO |
|||
IF j <= n then |
|||
IF (puntos(j-1) = puntos(j)) then |
|||
LET j = j + 1 |
|||
END IF |
|||
END IF |
|||
FOR k = i to j-1 |
|||
LET ptosnom(k) = (i+j-1) / 2 |
|||
NEXT k |
|||
LET i = j |
|||
LET j = j + 1 |
|||
LOOP UNTIL i > n |
|||
CALL MOSTARTABLA |
|||
DATA 44, "Solomon", 42, "Jason", 42, "Errol", 41, "Garry", 41, "Bernard", 41, "Barry", 39, "Stephen" |
|||
END |
|||
</syntaxhighlight> |
|||
=={{header|Visual FoxPro}}== |
=={{header|Visual FoxPro}}== |
||
< |
<syntaxhighlight lang="vfp"> |
||
#DEFINE CTAB CHR(9) |
#DEFINE CTAB CHR(9) |
||
#DEFINE CRLF CHR(13) + CHR(10) |
#DEFINE CRLF CHR(13) + CHR(10) |
||
Line 1,780: | Line 5,521: | ||
ENDFOR |
ENDFOR |
||
ENDPROC |
ENDPROC |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,792: | Line 5,533: | ||
7 7 4 7 7.0 39 "Stephen" |
7 7 4 7 7.0 39 "Stephen" |
||
</pre> |
</pre> |
||
=={{header|Wren}}== |
|||
{{trans|Kotlin}} |
|||
{{libheader|Wren-math}} |
|||
{{libheader|Wren-fmt}} |
|||
<syntaxhighlight lang="wren">import "./math" for Nums |
|||
import "./fmt" for Fmt |
|||
/* all ranking functions assume the array of Pairs is non-empty and already sorted |
|||
by decreasing order of scores and then, if the scores are equal, by reverse |
|||
alphabetic order of names |
|||
*/ |
|||
var standardRanking = Fn.new { |scores| |
|||
var rankings = List.filled(scores.count, 0) |
|||
rankings[0] = 1 |
|||
for (i in 1...scores.count) { |
|||
rankings[i] = (scores[i][0] == scores[i-1][0]) ? rankings[i-1] : i + 1 |
|||
} |
|||
return rankings |
|||
} |
|||
var modifiedRanking = Fn.new { |scores| |
|||
var rankings = List.filled(scores.count, 0) |
|||
rankings[0] = 1 |
|||
for (i in 1...scores.count) { |
|||
rankings[i] = i + 1 |
|||
var currScore = scores[i][0] |
|||
for (j in i-1..0) { |
|||
if (currScore != scores[j][0]) break |
|||
rankings[j] = i + 1 |
|||
} |
|||
} |
|||
return rankings |
|||
} |
|||
var denseRanking = Fn.new { |scores| |
|||
var rankings = List.filled(scores.count, 0) |
|||
rankings[0] = 1 |
|||
var prevRanking = 1 |
|||
for (i in 1...scores.count) { |
|||
rankings[i] = (scores[i][0] == scores[i-1][0]) ? prevRanking : (prevRanking = prevRanking+1) |
|||
} |
|||
return rankings |
|||
} |
|||
var ordinalRanking = Fn.new { |scores| (1..scores.count).toList } |
|||
var fractionalRanking = Fn.new { |scores| |
|||
var rankings = List.filled(scores.count, 0) |
|||
rankings[0] = 1 |
|||
for (i in 1...scores.count) { |
|||
var k = i |
|||
var currScore = scores[i][0] |
|||
for (j in i-1..0) { |
|||
if (currScore != scores[j][0]) break |
|||
k = j |
|||
} |
|||
var avg = Nums.mean(k..i) + 1 |
|||
for (m in k..i) rankings[m] = avg |
|||
} |
|||
return rankings |
|||
} |
|||
var printRankings = Fn.new { |title, rankings, scores| |
|||
System.print(title + ":") |
|||
for (i in 0...rankings.count) { |
|||
System.print("%(rankings[i]) %(scores[i][0]) %(scores[i][1])") |
|||
} |
|||
System.print() |
|||
} |
|||
var printFractionalRankings = Fn.new { |title, rankings, scores| |
|||
System.print(title + ":") |
|||
for (i in 0...rankings.count) { |
|||
Fmt.print("$3.2f $d $s", rankings[i], scores[i][0], scores[i][1]) |
|||
} |
|||
System.print() |
|||
} |
|||
var scores = [[44, "Solomon"], [42, "Jason"], [42, "Errol"], [41, "Garry"], |
|||
[41, "Bernard"], [41, "Barry"], [39, "Stephen"]] |
|||
printRankings.call("Standard ranking", standardRanking.call(scores), scores) |
|||
printRankings.call("Modified ranking", modifiedRanking.call(scores), scores) |
|||
printRankings.call("Dense ranking", denseRanking.call(scores), scores) |
|||
printRankings.call("Ordinal ranking", ordinalRanking.call(scores), scores) |
|||
printFractionalRankings.call("Fractional ranking", fractionalRanking.call(scores), scores)</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Standard ranking: |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
2 42 Errol |
|||
4 41 Garry |
|||
4 41 Bernard |
|||
4 41 Barry |
|||
7 39 Stephen |
|||
Modified ranking: |
|||
1 44 Solomon |
|||
3 42 Jason |
|||
3 42 Errol |
|||
6 41 Garry |
|||
6 41 Bernard |
|||
6 41 Barry |
|||
7 39 Stephen |
|||
Dense ranking: |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
2 42 Errol |
|||
3 41 Garry |
|||
3 41 Bernard |
|||
3 41 Barry |
|||
4 39 Stephen |
|||
Ordinal ranking: |
|||
1 44 Solomon |
|||
2 42 Jason |
|||
3 42 Errol |
|||
4 41 Garry |
|||
5 41 Bernard |
|||
6 41 Barry |
|||
7 39 Stephen |
|||
Fractional ranking: |
|||
1.00 44 Solomon |
|||
2.50 42 Jason |
|||
2.50 42 Errol |
|||
5.00 41 Garry |
|||
5.00 41 Bernard |
|||
5.00 41 Barry |
|||
7.00 39 Stephen |
|||
</pre> |
|||
=={{header|Yabasic}}== |
|||
<syntaxhighlight lang="yabasic"> |
|||
n = 7 |
|||
dim puntos(7), ptosnom(7), nombre$(7) |
|||
sub MostarTabla() |
|||
for i = 1 to n |
|||
print str$(ptosnom(i)), " ", puntos(i), " ", nombre$(i) |
|||
next i |
|||
print |
|||
end sub |
|||
print "Puntuaciones a clasificar (mejores primero):" |
|||
for i = 1 to n |
|||
read puntos(i), nombre$(i) |
|||
print " ", puntos(i), " ", nombre$(i) |
|||
next i |
|||
print |
|||
print "--- Standard ranking ---" |
|||
ptosnom(1) = 1 |
|||
for i = 2 to n |
|||
if puntos(i) = puntos(i-1) then ptosnom(i) = ptosnom(i-1) else ptosnom(i) = i : fi |
|||
next i |
|||
MostarTabla() |
|||
print "--- Modified ranking ---" |
|||
ptosnom(n) = n |
|||
for i = n-1 to 1 step -1 |
|||
if puntos(i) = puntos(i+1) then ptosnom(i) = ptosnom(i+1) else ptosnom(i) = i : fi |
|||
next i |
|||
MostarTabla() |
|||
print "--- Ordinal ranking ---" |
|||
for i = 1 to n |
|||
ptosnom(i) = i |
|||
next i |
|||
MostarTabla() |
|||
print "--- Fractional ranking ---" |
|||
i = 1 |
|||
j = 2 |
|||
repeat |
|||
if j <= n then |
|||
if (puntos(j-1) = puntos(j)) then j = j + 1 : fi |
|||
end if |
|||
for k = i to j-1 |
|||
ptosnom(k) = (i+j-1) / 2 |
|||
next k |
|||
i = j |
|||
j = j + 1 |
|||
until i > n |
|||
MostarTabla() |
|||
data 44, "Solomon", 42, "Jason", 42, "Errol", 41, "Garry", 41, "Bernard", 41, "Barry", 39, "Stephen" |
|||
end |
|||
</syntaxhighlight> |
|||
=={{header|zkl}}== |
=={{header|zkl}}== |
||
< |
<syntaxhighlight lang="zkl">fcn group(scores){ // group like scores into one list --> list of lists |
||
sink:=List(); |
sink:=List(); |
||
scores.reduce('wrap(ps,sn,buf){ |
scores.reduce('wrap(ps,sn,buf){ |
||
Line 1,827: | Line 5,763: | ||
print(group,"%5.2f".fmt(r)); |
print(group,"%5.2f".fmt(r)); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
< |
<syntaxhighlight lang="zkl"> // these are sorted!?! |
||
scores:=T(T(44,"Solomon"), T(42,"Jason"), T(42,"Errol"), T(41,"Garry"), |
scores:=T(T(44,"Solomon"), T(42,"Jason"), T(42,"Errol"), T(41,"Garry"), |
||
T(41,"Bernard"),T(41,"Barry"),T(39,"Stephen"),); |
T(41,"Bernard"),T(41,"Barry"),T(39,"Stephen"),); |
||
Line 1,835: | Line 5,771: | ||
"Dense:" .println(); rankViaDense(scores); |
"Dense:" .println(); rankViaDense(scores); |
||
"Ordinal:" .println(); rankViaOrdinal(scores); |
"Ordinal:" .println(); rankViaOrdinal(scores); |
||
"Fractional:".println(); rankViaFractional(scores);</ |
"Fractional:".println(); rankViaFractional(scores);</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
Latest revision as of 10:08, 2 February 2024
You are encouraged to solve this task according to the task description, using any language you may know.
Sorting Algorithm
This is a sorting algorithm. It may be applied to a set of data in order to sort it.
For comparing various sorts, see compare sorts.
For other sorting algorithms, see sorting algorithms, or:
Heap sort | Merge sort | Patience sort | Quick sort
O(n log2n) sorts
Shell Sort
O(n2) sorts
Bubble sort |
Cocktail sort |
Cocktail sort with shifting bounds |
Comb sort |
Cycle sort |
Gnome sort |
Insertion sort |
Selection sort |
Strand sort
other sorts
Bead sort |
Bogo sort |
Common sorted list |
Composite structures sort |
Custom comparator sort |
Counting sort |
Disjoint sublist sort |
External sort |
Jort sort |
Lexicographical sort |
Natural sorting |
Order by pair comparisons |
Order disjoint list items |
Order two numerical lists |
Object identifier (OID) sort |
Pancake sort |
Quickselect |
Permutation sort |
Radix sort |
Ranking methods |
Remove duplicate elements |
Sleep sort |
Stooge sort |
[Sort letters of a string] |
Three variable sort |
Topological sort |
Tree sort
The numerical rank of competitors in a competition shows if one is better than, equal to, or worse than another based on their results in a competition.
The numerical rank of a competitor can be assigned in several different ways.
- Task
The following scores are accrued for all competitors of a competition (in best-first order):
44 Solomon 42 Jason 42 Errol 41 Garry 41 Bernard 41 Barry 39 Stephen
For each of the following ranking methods, create a function/method/procedure/subroutine... that applies the ranking method to an ordered list of scores with scorers:
- Standard. (Ties share what would have been their first ordinal number).
- Modified. (Ties share what would have been their last ordinal number).
- Dense. (Ties share the next available integer).
- Ordinal. ((Competitors take the next available integer. Ties are not treated otherwise).
- Fractional. (Ties share the mean of what would have been their ordinal numbers).
See the wikipedia article for a fuller description.
Show here, on this page, the ranking of the test scores under each of the numbered ranking methods.
11l
F mc_rank([(Int, String)] iterable)
‘Modified competition ranking’
[(Float, (Int, String))] r
V lastresult = -1
[(Int, String)] fifo
L(item) iterable
I item[0] == lastresult
fifo [+]= item
E
V n = L.index
L !fifo.empty
r.append((n, fifo.pop(0)))
lastresult = item[0]
fifo [+]= item
L !fifo.empty
r.append((iterable.len, fifo.pop(0)))
R r
F sc_rank([(Int, String)] iterable)
‘Standard competition ranking’
[(Float, (Int, String))] r
V lastresult = -1
V lastrank = -1
L(item) iterable
I item[0] == lastresult
r.append((lastrank, item))
E
V n = L.index + 1
r.append((n, item))
lastresult = item[0]
lastrank = n
R r
F d_rank([(Int, String)] iterable)
‘Dense ranking’
[(Float, (Int, String))] r
V lastresult = -1
V lastrank = 0
L(item) iterable
I item[0] == lastresult
r.append((lastrank, item))
E
lastresult = item[0]
lastrank++
r.append((lastrank, item))
R r
F o_rank([(Int, String)] iterable)
‘Ordinal ranking’
R enumerate(iterable, 1).map((i, item) -> ((Float(i), item)))
F f_rank([(Int, String)] iterable)
‘Fractional ranking’
[(Float, (Int, String))] r
V last = -1
[(Int, (Int, String))] fifo
L(item) iterable
I item[0] != last
I !fifo.empty
V mean = Float(sum(fifo.map(f -> f[0]))) / fifo.len
L !fifo.empty
r.append((mean, fifo.pop(0)[1]))
last = item[0]
fifo.append((L.index + 1, item))
I !fifo.empty
V mean = sum(fifo.map(f -> f[0])) / fifo.len
L !fifo.empty
r.append((mean, fifo.pop(0)[1]))
R r
V scores = [(44, ‘Solomon’),
(42, ‘Jason’),
(42, ‘Errol’),
(41, ‘Garry’),
(41, ‘Bernard’),
(41, ‘Barry’),
(39, ‘Stephen’)]
print("\nScores to be ranked (best first):")
L(n, s) scores
print(‘ #2 #.’.format(n, s))
L(ranker, ranking_method) [(sc_rank, ‘Standard competition ranking’),
(mc_rank, ‘Modified competition ranking’),
(d_rank, ‘Dense ranking’),
(o_rank, ‘Ordinal ranking’),
(f_rank, ‘Fractional ranking’)]
print("\n#.:".format(ranking_method))
L(rank, score) ranker(scores)
print(‘ #3, (#., #.)’.format(rank, score[0], score[1]))
- Output:
Scores to be ranked (best first): 44 Solomon 42 Jason 42 Errol 41 Garry 41 Bernard 41 Barry 39 Stephen Standard competition ranking: 1, (44, Solomon) 2, (42, Jason) 2, (42, Errol) 4, (41, Garry) 4, (41, Bernard) 4, (41, Barry) 7, (39, Stephen) Modified competition ranking: 1, (44, Solomon) 3, (42, Jason) 3, (42, Errol) 6, (41, Garry) 6, (41, Bernard) 6, (41, Barry) 7, (39, Stephen) Dense ranking: 1, (44, Solomon) 2, (42, Jason) 2, (42, Errol) 3, (41, Garry) 3, (41, Bernard) 3, (41, Barry) 4, (39, Stephen) Ordinal ranking: 1, (44, Solomon) 2, (42, Jason) 3, (42, Errol) 4, (41, Garry) 5, (41, Bernard) 6, (41, Barry) 7, (39, Stephen) Fractional ranking: 1, (44, Solomon) 2.5, (42, Jason) 2.5, (42, Errol) 5, (41, Garry) 5, (41, Bernard) 5, (41, Barry) 7, (39, Stephen)
ALGOL 68
As with some but not all of the other samples, the ranking procedures here assume the data is already sorted. The procedures do check for empty data sets, though.
BEGIN # rank some scores by various methods #
# MODE to hold the scores #
MODE RESULT = STRUCT( INT score, STRING name );
# returns the standard ranking of s #
PROC standard ranking = ( []RESULT s )[]INT:
IF LWB s > UPB s THEN []INT() # no scores #
ELSE # have some scores #
[ LWB s : UPB s ]INT ranked;
INT position := 1;
ranked[ LWB s ] := position;
FOR i FROM LWB s + 1 TO UPB s DO
ranked[ i ] := IF score OF s[ i ] = score OF s[ i - 1 ] THEN
# same score as the previous #
position
ELSE
# different score, increase the position #
position := i
FI
OD;
ranked
FI # standard ranking # ;
# returns the modified ranking of s #
PROC modified ranking = ( []RESULT s )[]INT:
IF LWB s > UPB s THEN []INT() # no scores #
ELSE # have some scores #
[ LWB s : UPB s ]INT ranked;
INT position := ( UPB s + 1 ) - LWB s;
ranked[ UPB s ] := position;
FOR i FROM UPB s - 1 BY -1 TO LWB s DO
ranked[ i ] := IF score OF s[ i ] = score OF s[ i + 1 ] THEN
# same score as the previous #
position
ELSE
# different score, decrease the position #
position := i
FI
OD;
ranked
FI # modified ranking # ;
# returns the debse ranking of s #
PROC dense ranking = ( []RESULT s )[]INT:
IF LWB s > UPB s THEN []INT() # no scores #
ELSE # have some scores #
[ LWB s : UPB s ]INT ranked;
INT position := 1;
ranked[ LWB s ] := position;
FOR i FROM LWB s + 1 TO UPB s DO
ranked[ i ] := IF score OF s[ i ] = score OF s[ i - 1 ] THEN
# same score as the previous #
position
ELSE
# different score, increase the position #
position +:= 1
FI
OD;
ranked
FI # dense ranking # ;
# returns the ordinal ranking of s #
PROC ordinal ranking = ( []RESULT s )[]INT:
IF LWB s > UPB s THEN []INT() # no scores #
ELSE # have some scores #
[ LWB s : UPB s ]INT ranked;
INT position := 0;
FOR i FROM LWB s TO UPB s DO
ranked[ i ] := position +:= 1
OD;
ranked
FI # ordinal ranking # ;
# regturns the fractional ranking of s #
PROC fractional ranking = ( []RESULT s )[]REAL:
IF LWB s > UPB s THEN []REAL() # no scores #
ELSE # have some scores #
[ LWB s : UPB s ]REAL ranked;
REAL position := 1;
FOR i FROM LWB s TO UPB s DO
ranked[ i ]
:= IF IF i = LWB s
THEN FALSE
ELSE score OF s[ i ] = score OF s[ i - 1 ]
FI
THEN
# same score as the previous #
ranked[ i - 1 ]
ELSE
# first score or different score to the previous #
INT same count := 1;
INT sum := i;
FOR j FROM i + 1 TO UPB s
WHILE score OF s[ i ] = score OF s[ j ]
DO
same count +:= 1;
sum +:= j
OD;
sum / same count
FI
OD;
ranked
FI # fractional ranking # ;
# shows the integer ranking of some scores #
PROC show integral ranking = ( []RESULT s, []INT ranking, STRING title )VOID:
BEGIN
print( ( title, " competition ranking:", newline ) );
FOR i FROM LWB s TO UPB s DO
print( ( whole( ranking[ i ], -3 )
, ": "
, whole( score OF s[ i ], -3 )
, " "
, name OF s[ i ]
, newline
)
)
OD;
print( ( newline ) )
END # show integral ranking # ;
# shows the real ranking of some scores #
PROC show real ranking = ( []RESULT s, []REAL ranking, STRING title )VOID:
BEGIN
print( ( title, " competition ranking:", newline ) );
FOR i FROM LWB s TO UPB s DO
print( ( IF INT integer rank = ENTIER ranking[ i ];
integer rank = ranking[ i ]
THEN
whole( integer rank, -3 ) + " "
ELSE
fixed( ranking[ i ], -6, 2 )
FI
, ": "
, whole( score OF s[ i ], -3 ), " "
, name OF s[ i ]
, newline
)
)
OD;
print( ( newline ) )
END # show real ranking # ;
# scores to rank - task test cases #
[]RESULT scores = ( ( 44, "Solomon" )
, ( 42, "Jason" )
, ( 42, "Errol" )
, ( 41, "Garry" )
, ( 41, "Bernard" )
, ( 41, "Barry" )
, ( 39, "Stephen" )
);
show integral ranking( scores, standard ranking( scores ), "standard" );
show integral ranking( scores, modified ranking( scores ), "modified" );
show integral ranking( scores, dense ranking( scores ), "dense" );
show integral ranking( scores, ordinal ranking( scores ), "ordinal" );
show real ranking( scores, fractional ranking( scores ), "fractional" )
END
- Output:
standard competition ranking: 1: 44 Solomon 2: 42 Jason 2: 42 Errol 4: 41 Garry 4: 41 Bernard 4: 41 Barry 7: 39 Stephen modified competition ranking: 1: 44 Solomon 3: 42 Jason 3: 42 Errol 6: 41 Garry 6: 41 Bernard 6: 41 Barry 7: 39 Stephen dense competition ranking: 1: 44 Solomon 2: 42 Jason 2: 42 Errol 3: 41 Garry 3: 41 Bernard 3: 41 Barry 4: 39 Stephen ordinal competition ranking: 1: 44 Solomon 2: 42 Jason 3: 42 Errol 4: 41 Garry 5: 41 Bernard 6: 41 Barry 7: 39 Stephen fractional competition ranking: 1 : 44 Solomon 2.50: 42 Jason 2.50: 42 Errol 5 : 41 Garry 5 : 41 Bernard 5 : 41 Barry 7 : 39 Stephen
AppleScript
use AppleScript version "2.3.1" -- Mac OS 10.9 (Mavericks) or later.
use sorter : script ¬
"Custom Iterative Ternary Merge Sort" -- <www.macscripter.net/t/timsort-and-nigsort/71383/3>
(* The ranking methods are implemented as script objects sharing inherited code. *)
script standardRanking
-- Properties and handlers inherited or overridden by the other script objects.
-- The 'reference' is to a value that won't exist until 'results' is set to a list.
-- 'me' and 'my' pertain to the script object using the code at the time.
property results : missing value
property startIndex : 1
property endIndex : a reference to my results's length
property step : 1
property currentRank : missing value
property currentScore : missing value
-- Main handler.
on resultsFrom(theScores)
copy theScores to my results
tell sorter to sort(my results, my startIndex, my endIndex, {comparer:me})
set my currentScore to my results's item (my startIndex)'s score
set my currentRank to my startIndex's contents
repeat with i from (my startIndex) to (my endIndex) by (my step)
my rankResult(i)
end repeat
set r to my results
set my results to missing value
return r
end resultsFrom
-- Comparison handler used by the sort.
on isGreater(a, b)
if (a's score < b's score) then return true
return ((a's score = b's score) and (a's competitor comes after b's competitor))
end isGreater
-- Ranking handler. Inherited by the modifiedRanking script; overridden by the others.
on rankResult(i)
set thisResult to my results's item i
set thisScore to thisResult's score
if (thisScore is not currentScore) then
set my currentRank to i
set my currentScore to thisScore
end if
set my results's item i to thisResult & {rank:my currentRank}
end rankResult
end script
script modifiedRanking
property parent : standardRanking
property startIndex : a reference to my results's length
property endIndex : 1
property step : -1
end script
script denseRanking
property parent : standardRanking
on rankResult(i)
set thisResult to my results's item i
set thisScore to thisResult's score
if (thisScore is not my currentScore) then
set my currentRank to (my currentRank) + 1
set my currentScore to thisScore
end if
set my results's item i to thisResult & {rank:my currentRank}
end rankResult
end script
script ordinalRanking
property parent : standardRanking
on rankResult(i)
set my results's item i to (my results's item i) & {rank:i}
end rankResult
end script
script fractionalRanking
property parent : standardRanking
on rankResult(i)
set thisResult to my results's item i
set thisScore to thisResult's score
if (thisScore is not my currentScore) then
-- The average of any run of consecutive integers is that of the first and last.
set average to (i - 1 + (my currentRank)) / 2
repeat with j from (my currentRank) to (i - 1)
set my results's item j's rank to average
end repeat
set my currentRank to i
set my currentScore to thisScore
end if
set my results's item i to thisResult & {rank:i as real}
end rankResult
end script
-- Task code:
on formatRankings(type, theResults)
set rankings to {type}
repeat with thisResult in theResults
set end of rankings to (thisResult's rank as text) & tab & ¬
thisResult's competitor & " (" & thisResult's score & ")"
end repeat
return join(rankings, linefeed)
end formatRankings
on join(lst, delim)
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to delim
set txt to lst as text
set AppleScript's text item delimiters to astid
return txt
end join
local theScores, output
set theScores to {{score:44, competitor:"Solomon"}, {score:42, competitor:"Jason"}, ¬
{score:42, competitor:"Errol"}, {score:41, competitor:"Garry"}, {score:41, competitor:"Bernard"}, ¬
{score:41, competitor:"Barry"}, {score:39, competitor:"Stephen"}}
set output to {¬
formatRankings("Standard ranking:", standardRanking's resultsFrom(theScores)), ¬
formatRankings("Modified ranking:", modifiedRanking's resultsFrom(theScores)), ¬
formatRankings("Dense ranking:", denseRanking's resultsFrom(theScores)), ¬
formatRankings("Ordinal ranking:", ordinalRanking's resultsFrom(theScores)), ¬
formatRankings("Fractional ranking:", fractionalRanking's resultsFrom(theScores)) ¬
}
return join(output, linefeed & linefeed)
- Output:
"Standard ranking:
1 Solomon (44)
2 Errol (42)
2 Jason (42)
4 Barry (41)
4 Bernard (41)
4 Garry (41)
7 Stephen (39)
Modified ranking:
1 Solomon (44)
3 Errol (42)
3 Jason (42)
6 Barry (41)
6 Bernard (41)
6 Garry (41)
7 Stephen (39)
Dense ranking:
1 Solomon (44)
2 Errol (42)
2 Jason (42)
3 Barry (41)
3 Bernard (41)
3 Garry (41)
4 Stephen (39)
Ordinal ranking:
1 Solomon (44)
2 Errol (42)
3 Jason (42)
4 Barry (41)
5 Bernard (41)
6 Garry (41)
7 Stephen (39)
Fractional ranking:
1.0 Solomon (44)
2.5 Errol (42)
2.5 Jason (42)
5.0 Barry (41)
5.0 Bernard (41)
5.0 Garry (41)
7.0 Stephen (39)"
AutoHotkey
Rank(data, opt:=1){ ; opt = 1 Standard (default), 2 Modified, 3 Dense, 4 Ordinal, 5 Fractional
for index, val in StrSplit(data, "`n", "`r") {
RegExMatch(val, "^(\d+)\s+(.*)", Match)
if !(Match1=prev)
n := index
prev := Match1
Res1 .= n "`t" Match "`n"
Res4 .= index "`t" Match "`n"
Temp .= n ":" index " " Match "`n"
}
n:=0
while pos := RegExMatch(Temp, "`asm)^(\d+).*?\R(?!\1)|.+", Match, pos?pos+StrLen(Match):1) {
n += StrSplit(Trim(Match, "`r`n"), "`n", "`r").MaxIndex()
Res2 .= RegExReplace(Match, "`am)^\d+:\d+", n "`t")
Res3 .= RegExReplace(Match, "`am)^\d+:\d+", A_Index "`t")
R := 0
for index, val in StrSplit(Match, "`n", "`r")
R += StrSplit(val, ":").2
Res5 .= RegExReplace(Match, "`am)^\d+:\d+", RegExReplace(R / StrSplit(Trim(Match, "`r`n"), "`n", "`r").MaxIndex(), "\.?0+$") "`t")
}
return Res%opt%
}
Example:
data =
(
44 Solomon
42 Jason
42 Errol
41 Garry
41 Bernard
41 Barry
39 Stephen
)
MsgBox, 262144, ,% ""
. "Standard Ranking:`n" Rank(data)
. "`nModified Ranking:`n" Rank(data, 2)
. "`nDense Ranking:`n" Rank(data, 3)
. "`nOrdinal Ranking:`n" Rank(data, 4)
. "`nFractional Ranking:`n" Rank(data, 5)
return
Output:
Standard Ranking: 1 44 Solomon 2 42 Jason 2 42 Errol 4 41 Garry 4 41 Bernard 4 41 Barry 7 39 Stephen Modified Ranking: 1 44 Solomon 3 42 Jason 3 42 Errol 6 41 Garry 6 41 Bernard 6 41 Barry 7 39 Stephen Dense Ranking: 1 44 Solomon 2 42 Jason 2 42 Errol 3 41 Garry 3 41 Bernard 3 41 Barry 4 39 Stephen Ordinal Ranking: 1 44 Solomon 2 42 Jason 3 42 Errol 4 41 Garry 5 41 Bernard 6 41 Barry 7 39 Stephen Fractional Ranking: 1 44 Solomon 2.5 42 Jason 2.5 42 Errol 5 41 Garry 5 41 Bernard 5 41 Barry 7 39 Stephen
APL
These functions each take a 2-by-N matrix, where the first column contains the score, and the second column contains the name. They return a 3-by-N matrix, with the ranking added.
standard ← ∊∘(⌊\¨⊢⊂⍳∘≢)∘(1,2≠/⊢)∘(1⌷[2]⊢),⊢
modified ← ∊∘(⌈\∘⌽¨⊢⊂⍳∘≢)∘(1,2≠/⊢)∘(1⌷[2]⊢),⊢
dense ← (+\1,2≠/1⌷[2]⊢),⊢
ordinal ← ⍳∘≢,⊢
fractional ← ∊∘((≢(/∘⊢)+/÷≢)¨⊢⊂⍳∘≢)∘(1,2≠/⊢)∘(1⌷[2]⊢),⊢
- Output:
⍝ Input scores table from task: scores←⍉⍪44,⊂'Solomon' scores⍪←42,⊂'Jason' scores⍪←42,⊂'Errol' scores⍪←41,⊂'Garry' scores⍪←41,⊂'Bernard' scores⍪←41,⊂'Barry' scores⍪←39,⊂'Stephen' ⍝ Apply each function to it standard scores 1 44 Solomon 2 42 Jason 2 42 Errol 4 41 Garry 4 41 Bernard 4 41 Barry 7 39 Stephen modified scores 1 44 Solomon 3 42 Jason 3 42 Errol 6 41 Garry 6 41 Bernard 6 41 Barry 7 39 Stephen dense scores 1 44 Solomon 2 42 Jason 2 42 Errol 3 41 Garry 3 41 Bernard 3 41 Barry 4 39 Stephen ordinal scores 1 44 Solomon 2 42 Jason 3 42 Errol 4 41 Garry 5 41 Bernard 6 41 Barry 7 39 Stephen fractional scores 1 44 Solomon 2.5 42 Jason 2.5 42 Errol 5 41 Garry 5 41 Bernard 5 41 Barry 7 39 Stephen
AWK
This uses separate files for each method of ranking:
##
## Dense ranking in file: ranking_d.awk
##
BEGIN{ lastresult = "!"; lastrank = 0 }
function d_rank(){
if($1==lastresult){
print lastrank, $0
}else{
lastresult = $1
print ++lastrank, $0 }
}
//{d_rank() }
##
## Fractional ranking in file: ranking_f.awk
##
BEGIN{
last = "!"
flen = 0 }
function f_rank(){
item = $0
if($1!=last){
if(flen){
sum = 0
for(fl=0; fl < flen;){
$0 = fifo[fl++]
sum += $1 }
mean = sum / flen
for(fl=0; fl < flen;){
$0 = fifo[fl++]
$1 = ""
printf("%3g %s\n", mean, $0) }
flen = 0
}}
$0 = item
last = $1
fifo[flen++] = sprintf("%i %s", FNR, item)
}
//{f_rank()}
END{ if(flen){
sum = 0
for(fl=0; fl < flen;){
$0 = fifo[fl++]
sum += $1 }
mean = sum / flen
for(fl=0; fl < flen;){
$0 = fifo[fl++]
$1 = ""
printf("%3g %s\n", mean, $0) }}}
##
## Modified competition ranking in file: ranking_mc.awk
##
BEGIN{
lastresult = "!"
flen = 0 }
function mc_rank(){
if($1==lastresult){
fifo[flen++] = $0
}else{
for(fl=0; fl < flen;){
print FNR-1, fifo[fl++]}
flen = 0
fifo[flen++] = $0
lastresult = $1}
}
//{mc_rank()}
END{ for(fl=0; fl < flen;){
print FNR, fifo[fl++]} }
##
## Ordinal ranking in file: ranking_o.awk
##
function o_rank(){ print FNR, $0 }
//{o_rank() }
##
## Standard competition ranking in file: ranking_sc.awk
##
BEGIN{ lastresult = lastrank = "!" }
function sc_rank(){
if($1==lastresult){
print lastrank, $0
}else{
print FNR, $0
lastresult = $1
lastrank = FNR}
}
//{sc_rank()}
The input as a file ranking.txt
:
44 Solomon 42 Jason 42 Errol 41 Garry 41 Bernard 41 Barry 39 Stephen
- Output:
C:\Users\RC\Code>awk -f ranking_sc.awk ranking.txt 1 44 Solomon 2 42 Jason 2 42 Errol 4 41 Garry 4 41 Bernard 4 41 Barry 7 39 Stephen C:\Users\RC\Code>awk -f ranking_mc.awk ranking.txt 1 44 Solomon 3 42 Jason 3 42 Errol 6 41 Garry 6 41 Bernard 6 41 Barry 7 39 Stephen C:\Users\RC\Code>awk -f ranking_d.awk ranking.txt 1 44 Solomon 2 42 Jason 2 42 Errol 3 41 Garry 3 41 Bernard 3 41 Barry 4 39 Stephen C:\Users\RC\Code>awk -f ranking_o.awk ranking.txt 1 44 Solomon 2 42 Jason 3 42 Errol 4 41 Garry 5 41 Bernard 6 41 Barry 7 39 Stephen C:\Users\RC\Code>awk -f ranking_f.awk ranking.txt 1 44 Solomon 2.5 42 Jason 2.5 42 Errol 5 41 Garry 5 41 Bernard 5 41 Barry 7 39 Stephen C:\Users\RC\Code>
BASIC
10 READ N
20 DIM S(N),N$(N),R(N)
30 FOR I=1 TO N: READ S(I),N$(I): NEXT
40 PRINT "--- Standard ranking ---": GOSUB 100: GOSUB 400
50 PRINT "--- Modified ranking ---": GOSUB 150: GOSUB 400
60 PRINT "--- Dense ranking ---": GOSUB 200: GOSUB 400
70 PRINT "--- Ordinal ranking ---": GOSUB 250: GOSUB 400
80 PRINT "--- Fractional ranking ---": GOSUB 300: GOSUB 400
90 END
100 REM
101 REM ** Ordinal ranking **
110 R(1)=1
120 FOR I=2 TO N
130 IF S(I)=S(I-1) THEN R(I)=R(I-1) ELSE R(I)=I
140 NEXT: RETURN
150 REM
151 REM ** Modified ranking **
160 R(N)=N
170 FOR I=N-1 TO 1 STEP -1
180 IF S(I)=S(I+1) THEN R(I)=R(I+1) ELSE R(I)=I
190 NEXT: RETURN
200 REM
201 REM ** Dense ranking **
210 R(1)=1
220 FOR I=2 TO N: R(I)=R(I-1)-(S(I)<>S(I-1)): NEXT
230 RETURN
250 REM
251 REM ** Ordinal ranking **
260 FOR I=1 TO N: R(I)=I: NEXT: RETURN
300 REM
301 REM ** Fractional ranking **
310 I=1: J=2
320 IF J<=N THEN IF S(J-1)=S(J) THEN J=J+1: GOTO 320
330 FOR K=I TO J-1: R(K) = (I+J-1)/2: NEXT
340 I=J: J=J+1: IF I<=N THEN 320
350 RETURN
400 REM
401 REM ** Print the table ***
410 FOR I=1 TO N
420 PRINT USING "\ \ ##, \ \";STR$(R(I));S(I);N$(I)
430 NEXT
440 PRINT: RETURN
500 DATA 7
510 DATA 44,Solomon
520 DATA 42,Jason
530 DATA 42,Errol
540 DATA 41,Garry
550 DATA 41,Bernard
560 DATA 41,Barry
570 DATA 39,Stephen
- Output:
--- Standard ranking --- 1 44 Solomon 2 42 Jason 2 42 Errol 4 41 Garry 4 41 Bernard 4 41 Barry 7 39 Stephen --- Modified ranking --- 1 44 Solomon 3 42 Jason 3 42 Errol 6 41 Garry 6 41 Bernard 6 41 Barry 7 39 Stephen --- Dense ranking --- 1 44 Solomon 2 42 Jason 2 42 Errol 3 41 Garry 3 41 Bernard 3 41 Barry 4 39 Stephen --- Ordinal ranking --- 1 44 Solomon 2 42 Jason 3 42 Errol 4 41 Garry 5 41 Bernard 6 41 Barry 7 39 Stephen --- Fractional ranking --- 1 44 Solomon 2.5 42 Jason 2.5 42 Errol 5 41 Garry 5 41 Bernard 5 41 Barry 7 39 Stephen
C
Takes the scores as input via a file, prints out usage on incorrect invocation.
#include<stdlib.h>
#include<stdio.h>
typedef struct{
int score;
char name[100];
}entry;
void ordinalRanking(entry* list,int len){
int i;
printf("\n\nOrdinal Ranking\n---------------");
for(i=0;i<len;i++)
printf("\n%d\t%d\t%s",i+1,list[i].score,list[i].name);
}
void standardRanking(entry* list,int len){
int i,j=1;
printf("\n\nStandard Ranking\n----------------");
for(i=0;i<len;i++){
printf("\n%d\t%d\t%s",j,list[i].score,list[i].name);
if(list[i+1].score<list[i].score)
j = i+2;
}
}
void denseRanking(entry* list,int len){
int i,j=1;
printf("\n\nDense Ranking\n-------------");
for(i=0;i<len;i++){
printf("\n%d\t%d\t%s",j,list[i].score,list[i].name);
if(list[i+1].score<list[i].score)
j++;
}
}
void modifiedRanking(entry* list,int len){
int i,j,count;
printf("\n\nModified Ranking\n----------------");
for(i=0;i<len-1;i++){
if(list[i].score!=list[i+1].score){
printf("\n%d\t%d\t%s",i+1,list[i].score,list[i].name);
count = 1;
for(j=i+1;list[j].score==list[j+1].score && j<len-1;j++)
count ++;
for(j=0;j<count-1;j++)
printf("\n%d\t%d\t%s",i+count+1,list[i+j+1].score,list[i+j+1].name);
i += (count-1);
}
}
printf("\n%d\t%d\t%s",len,list[len-1].score,list[len-1].name);
}
void fractionalRanking(entry* list,int len){
int i,j,count;
float sum = 0;
printf("\n\nFractional Ranking\n------------------");
for(i=0;i<len;i++){
if(i==len-1 || list[i].score!=list[i+1].score)
printf("\n%.1f\t%d\t%s",(float)(i+1),list[i].score,list[i].name);
else if(list[i].score==list[i+1].score){
sum = i;
count = 1;
for(j=i;list[j].score==list[j+1].score;j++){
sum += (j+1);
count ++;
}
for(j=0;j<count;j++)
printf("\n%.1f\t%d\t%s",sum/count + 1,list[i+j].score,list[i+j].name);
i += (count-1);
}
}
}
void processFile(char* fileName){
FILE* fp = fopen(fileName,"r");
entry* list;
int i,num;
fscanf(fp,"%d",&num);
list = (entry*)malloc(num*sizeof(entry));
for(i=0;i<num;i++)
fscanf(fp,"%d%s",&list[i].score,list[i].name);
fclose(fp);
ordinalRanking(list,num);
standardRanking(list,num);
denseRanking(list,num);
modifiedRanking(list,num);
fractionalRanking(list,num);
}
int main(int argC,char* argV[])
{
if(argC!=2)
printf("Usage %s <score list file>");
else
processFile(argV[1]);
return 0;
}
Input file, first row is number of records :
7 44 Solomon 42 Jason 42 Errol 41 Garry 41 Bernard 41 Barry 39 Stephen
Output :
C:\rosettaCode>ranking.exe rankData.txt Ordinal Ranking --------------- 1 44 Solomon 2 42 Jason 3 42 Errol 4 41 Garry 5 41 Bernard 6 41 Barry 7 39 Stephen Standard Ranking ---------------- 1 44 Solomon 2 42 Jason 2 42 Errol 4 41 Garry 4 41 Bernard 4 41 Barry 7 39 Stephen Dense Ranking ------------- 1 44 Solomon 2 42 Jason 2 42 Errol 3 41 Garry 3 41 Bernard 3 41 Barry 4 39 Stephen Modified Ranking ---------------- 1 44 Solomon 3 42 Jason 3 42 Errol 6 41 Garry 6 41 Bernard 6 41 Barry 7 39 Stephen Fractional Ranking ------------------ 1.0 44 Solomon 2.5 42 Jason 2.5 42 Errol 5.0 41 Garry 5.0 41 Bernard 5.0 41 Barry 7.0 39 Stephen
C#
using System;
using System.Collections.Generic;
using System.Linq;
namespace RankingMethods {
class Program {
static void Main(string[] args) {
Dictionary<string, int> scores = new Dictionary<string, int> {
["Solomon"] = 44,
["Jason"] = 42,
["Errol"] = 42,
["Gary"] = 41,
["Bernard"] = 41,
["Barry"] = 41,
["Stephen"] = 39,
};
StandardRank(scores);
ModifiedRank(scores);
DenseRank(scores);
OrdinalRank(scores);
FractionalRank(scores);
}
static void StandardRank(Dictionary<string, int> data) {
Console.WriteLine("Standard Rank");
var list = data.Values.Distinct().ToList();
list.Sort((a, b) => b.CompareTo(a));
int rank = 1;
foreach (var value in list) {
int temp = rank;
foreach (var k in data.Keys) {
if (data[k] == value) {
Console.WriteLine("{0} {1} {2}", temp, value, k);
rank++;
}
}
}
Console.WriteLine();
}
static void ModifiedRank(Dictionary<string, int> data) {
Console.WriteLine("Modified Rank");
var list = data.Values.Distinct().ToList();
list.Sort((a, b) => b.CompareTo(a));
int rank = 0;
foreach (var value in list) {
foreach (var k in data.Keys) {
if (data[k] == value) {
rank++;
}
}
foreach (var k in data.Keys) {
if (data[k] == value) {
Console.WriteLine("{0} {1} {2}", rank, data[k], k);
}
}
}
Console.WriteLine();
}
static void DenseRank(Dictionary<string, int> data) {
Console.WriteLine("Dense Rank");
var list = data.Values.Distinct().ToList();
list.Sort((a, b) => b.CompareTo(a));
int rank = 1;
foreach (var value in list) {
foreach (var k in data.Keys) {
if (data[k] == value) {
Console.WriteLine("{0} {1} {2}", rank, data[k], k);
}
}
rank++;
}
Console.WriteLine();
}
static void OrdinalRank(Dictionary<string, int> data) {
Console.WriteLine("Ordinal Rank");
var list = data.Values.Distinct().ToList();
list.Sort((a, b) => b.CompareTo(a));
int rank = 1;
foreach (var value in list) {
foreach (var k in data.Keys) {
if (data[k] == value) {
Console.WriteLine("{0} {1} {2}", rank, data[k], k);
rank++;
}
}
}
Console.WriteLine();
}
static void FractionalRank(Dictionary<string, int> data) {
Console.WriteLine("Fractional Rank");
var list = data.Values.Distinct().ToList();
list.Sort((a, b) => b.CompareTo(a));
int rank = 0;
foreach (var value in list) {
double avg = 0;
int cnt = 0;
foreach (var k in data.Keys) {
if (data[k] == value) {
rank++;
cnt++;
avg += rank;
}
}
avg /= cnt;
foreach (var k in data.Keys) {
if (data[k] == value) {
Console.WriteLine("{0:F1} {1} {2}", avg, data[k], k);
}
}
}
Console.WriteLine();
}
}
}
- Output:
Standard Rank 1 44 Solomon 2 42 Jason 2 42 Errol 4 41 Gary 4 41 Bernard 4 41 Barry 7 39 Stephen Modified Rank 1 44 Solomon 3 42 Jason 3 42 Errol 6 41 Gary 6 41 Bernard 6 41 Barry 7 39 Stephen Dense Rank 1 44 Solomon 2 42 Jason 2 42 Errol 3 41 Gary 3 41 Bernard 3 41 Barry 4 39 Stephen Ordinal Rank 1 44 Solomon 2 42 Jason 3 42 Errol 4 41 Gary 5 41 Bernard 6 41 Barry 7 39 Stephen Fractional Rank 1.0 44 Solomon 2.5 42 Jason 2.5 42 Errol 5.0 41 Gary 5.0 41 Bernard 5.0 41 Barry 7.0 39 Stephen
C++
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <map>
#include <ostream>
#include <set>
#include <vector>
template<typename T>
std::ostream& print(std::ostream& os, const T& src) {
auto it = src.cbegin();
auto end = src.cend();
os << "[";
if (it != end) {
os << *it;
it = std::next(it);
}
while (it != end) {
os << ", " << *it;
it = std::next(it);
}
return os << "]";
}
typedef std::map<std::string, int> Map;
typedef Map::value_type MapEntry;
void standardRank(const Map& scores) {
std::cout << "Standard Rank" << std::endl;
std::vector<int> list;
for (auto& elem : scores) {
list.push_back(elem.second);
}
std::sort(list.begin(), list.end(), std::greater<int>{});
list.erase(std::unique(list.begin(), list.end()), list.end());
int rank = 1;
for (auto value : list) {
int temp = rank;
for (auto& e : scores) {
if (e.second == value) {
std::cout << temp << " " << value << " " << e.first.c_str() << std::endl;
rank++;
}
}
}
std::cout << std::endl;
}
void modifiedRank(const Map& scores) {
std::cout << "Modified Rank" << std::endl;
std::vector<int> list;
for (auto& elem : scores) {
list.push_back(elem.second);
}
std::sort(list.begin(), list.end(), std::greater<int>{});
list.erase(std::unique(list.begin(), list.end()), list.end());
int rank = 0;
for (auto value : list) {
rank += std::count_if(scores.begin(), scores.end(), [value](const MapEntry& e) { return e.second == value; });
for (auto& e : scores) {
if (e.second == value) {
std::cout << rank << " " << value << " " << e.first.c_str() << std::endl;
}
}
}
std::cout << std::endl;
}
void denseRank(const Map& scores) {
std::cout << "Dense Rank" << std::endl;
std::vector<int> list;
for (auto& elem : scores) {
list.push_back(elem.second);
}
std::sort(list.begin(), list.end(), std::greater<int>{});
list.erase(std::unique(list.begin(), list.end()), list.end());
int rank = 1;
for (auto value : list) {
for (auto& e : scores) {
if (e.second == value) {
std::cout << rank << " " << value << " " << e.first.c_str() << std::endl;
}
}
rank++;
}
std::cout << std::endl;
}
void ordinalRank(const Map& scores) {
std::cout << "Ordinal Rank" << std::endl;
std::vector<int> list;
for (auto& elem : scores) {
list.push_back(elem.second);
}
std::sort(list.begin(), list.end(), std::greater<int>{});
list.erase(std::unique(list.begin(), list.end()), list.end());
int rank = 1;
for (auto value : list) {
for (auto& e : scores) {
if (e.second == value) {
std::cout << rank++ << " " << value << " " << e.first.c_str() << std::endl;
}
}
}
std::cout << std::endl;
}
void fractionalRank(const Map& scores) {
std::cout << "Ordinal Rank" << std::endl;
std::vector<int> list;
for (auto& elem : scores) {
list.push_back(elem.second);
}
std::sort(list.begin(), list.end(), std::greater<int>{});
list.erase(std::unique(list.begin(), list.end()), list.end());
int rank = 0;
for (auto value : list) {
double avg = 0.0;
int cnt = 0;
for (auto& e : scores) {
if (e.second == value) {
rank++;
cnt++;
avg += rank;
}
}
avg /= cnt;
for (auto& e : scores) {
if (e.second == value) {
std::cout << std::setprecision(1) << std::fixed << avg << " " << value << " " << e.first.c_str() << std::endl;
}
}
}
std::cout << std::endl;
}
int main() {
using namespace std;
map<string, int> scores{
{"Solomon", 44},
{"Jason", 42},
{"Errol", 42},
{"Gary", 41},
{"Bernard", 41},
{"Barry", 41},
{"Stephen", 39}
};
standardRank(scores);
modifiedRank(scores);
denseRank(scores);
ordinalRank(scores);
fractionalRank(scores);
return 0;
}
- Output:
Standard Rank 1 44 Solomon 2 42 Errol 2 42 Jason 4 41 Barry 4 41 Bernard 4 41 Gary 7 39 Stephen Modified Rank 1 44 Solomon 3 42 Errol 3 42 Jason 6 41 Barry 6 41 Bernard 6 41 Gary 7 39 Stephen Dense Rank 1 44 Solomon 2 42 Errol 2 42 Jason 3 41 Barry 3 41 Bernard 3 41 Gary 4 39 Stephen Ordinal Rank 1 44 Solomon 2 42 Errol 3 42 Jason 4 41 Barry 5 41 Bernard 6 41 Gary 7 39 Stephen Ordinal Rank 1.0 44 Solomon 2.5 42 Errol 2.5 42 Jason 5.0 41 Barry 5.0 41 Bernard 5.0 41 Gary 7.0 39 Stephen
Cowgol
include "cowgol.coh";
# List of competitors
record Competitor is
score: uint8;
name: [uint8];
end record;
var cs: Competitor[] := {
{44, "Solomon"},
{42, "Jason"},
{42, "Errol"},
{41, "Garry"},
{41, "Bernard"},
{41, "Barry"},
{39, "Stephen"}
};
# Rank competitors given ranking method
interface Ranking(c: [Competitor],
n: intptr,
len: intptr,
last: uint16): (rank: uint16);
sub Rank(cs: [Competitor], num: intptr, r: Ranking) is
var last: uint16 := 0;
var idx: intptr := 0;
while idx < num loop
last := r(cs, idx, num, last);
if last < 100 then
print_i16(last);
else
# print fixed-point rank nicely
print_i16(last / 100);
print_char('.');
print_i16((last % 100) / 10);
print_i16(last % 10);
end if;
print(". ");
print_i8(cs.score);
print(", ");
print(cs.name);
print_nl();
idx := idx + 1;
cs := @next cs;
end loop;
end sub;
# Standard ranking
var stdcount: uint16 := 0;
sub Standard implements Ranking is
if n==0 then stdcount := 0; end if;
stdcount := stdcount + 1;
if n>0 and c.score == [@prev c].score then
rank := last;
else
rank := stdcount;
end if;
end sub;
# Modified ranking
sub Modified implements Ranking is
rank := last;
if n == 0 or c.score != [@prev c].score then
while n < len loop
rank := rank + 1;
c := @next c;
if c.score != [@prev c].score then
break;
end if;
n := n + 1;
end loop;
end if;
end sub;
# Dense ranking
sub Dense implements Ranking is
if n>0 and c.score == [@prev c].score then
rank := last;
else
rank := last + 1;
end if;
end sub;
# Ordinal ranking
sub Ordinal implements Ranking is
rank := last + 1;
end sub;
# Fractional ranking (with fixed point arithmetic)
sub Fractional implements Ranking is
rank := last;
if n==0 or c.score != [@prev c].score then
var sum: uint16 := 0;
var ct: uint16 := 0;
while n < len loop
sum := sum + (n as uint16 + 1);
ct := ct + 1;
c := @next c;
if c.score != [@prev c].score then
break;
end if;
n := n + 1;
end loop;
rank := (sum * 100) / (ct as uint16);
end if;
end sub;
record Method is
name: [uint8];
method: Ranking;
end record;
var methods: Method[] := {
{"Standard", Standard},
{"Modified", Modified},
{"Dense", Dense},
{"Ordinal", Ordinal},
{"Fractional", Fractional}
};
var n: @indexof methods := 0;
while n < @sizeof methods loop
print("--- ");
print(methods[n].name);
print(" ---\n");
Rank(&cs[0], @sizeof cs, methods[n].method);
print_nl();
n := n + 1;
end loop;
- Output:
--- Standard --- 1. 44, Solomon 2. 42, Jason 2. 42, Errol 4. 41, Garry 4. 41, Bernard 4. 41, Barry 7. 39, Stephen --- Modified --- 1. 44, Solomon 3. 42, Jason 3. 42, Errol 6. 41, Garry 6. 41, Bernard 6. 41, Barry 7. 39, Stephen --- Dense --- 1. 44, Solomon 2. 42, Jason 2. 42, Errol 3. 41, Garry 3. 41, Bernard 3. 41, Barry 4. 39, Stephen --- Ordinal --- 1. 44, Solomon 2. 42, Jason 3. 42, Errol 4. 41, Garry 5. 41, Bernard 6. 41, Barry 7. 39, Stephen --- Fractional --- 1.00. 44, Solomon 2.50. 42, Jason 2.50. 42, Errol 5.00. 41, Garry 5.00. 41, Bernard 5.00. 41, Barry 7.00. 39, Stephen
D
import std.algorithm;
import std.stdio;
void main() {
immutable scores = [
"Solomon": 44,
"Jason": 42,
"Errol": 42,
"Garry": 41,
"Bernard": 41,
"Barry": 41,
"Stephen": 39
];
scores.standardRank;
scores.modifiedRank;
scores.denseRank;
scores.ordinalRank;
scores.fractionalRank;
}
/*
Standard ranking
1 44 Solomon
2 42 Jason
2 42 Errol
4 41 Garry
4 41 Bernard
4 41 Barry
7 39 Stephen
*/
void standardRank(const int[string] data) {
writeln("Standard Rank");
int rank = 1;
foreach (value; data.values.dup.sort!"a>b".uniq) {
int temp = rank;
foreach(k,v; data) {
if (v==value) {
writeln(temp, " ", v, " ", k);
rank++;
}
}
}
writeln;
}
/*
Modified ranking
1 44 Solomon
3 42 Jason
3 42 Errol
6 41 Garry
6 41 Bernard
6 41 Barry
7 39 Stephen
*/
void modifiedRank(const int[string] data) {
writeln("Modified Rank");
int rank = 0;
foreach (value; data.values.dup.sort!"a>b".uniq) {
foreach(k,v; data) {
if (v==value) {
rank++;
}
}
foreach(k,v; data) {
if (v==value) {
writeln(rank, " ", v, " ", k);
}
}
}
writeln;
}
/*
Dense ranking
1 44 Solomon
2 42 Jason
2 42 Errol
3 41 Garry
3 41 Bernard
3 41 Barry
4 39 Stephen
*/
void denseRank(const int[string] data) {
writeln("Dense Rank");
int rank = 1;
foreach (value; data.values.dup.sort!"a>b".uniq) {
foreach(k,v; data) {
if (v==value) {
writeln(rank, " ", v, " ", k);
}
}
rank++;
}
writeln;
}
/*
Ordinal ranking
1 44 Solomon
2 42 Jason
3 42 Errol
4 41 Garry
5 41 Bernard
6 41 Barry
7 39 Stephen
*/
void ordinalRank(const int[string] data) {
writeln("Ordinal Rank");
int rank = 1;
foreach (value; data.values.dup.sort!"a>b".uniq) {
foreach(k,v; data) {
if (v==value) {
writeln(rank, " ", v, " ", k);
rank++;
}
}
}
writeln;
}
/*
Fractional ranking
1,0 44 Solomon
2,5 42 Jason
2,5 42 Errol
5,0 41 Garry
5,0 41 Bernard
5,0 41 Barry
7,0 39 Stephen
*/
void fractionalRank(const int[string] data) {
writeln("Fractional Rank");
int rank = 0;
foreach (value; data.values.dup.sort!"a>b".uniq) {
real avg = 0;
int cnt;
foreach(k,v; data) {
if (v==value) {
rank++;
cnt++;
avg+=rank;
}
}
avg /= cnt;
foreach(k,v; data) {
if (v==value) {
writef("%0.1f ", avg);
writeln(v, " ", k);
}
}
}
writeln;
}
- Output:
Standard Rank 1 44 Solomon 2 42 Errol 2 42 Jason 4 41 Garry 4 41 Bernard 4 41 Barry 7 39 Stephen Modified Rank 1 44 Solomon 3 42 Errol 3 42 Jason 6 41 Garry 6 41 Bernard 6 41 Barry 7 39 Stephen Dense Rank 1 44 Solomon 2 42 Errol 2 42 Jason 3 41 Garry 3 41 Bernard 3 41 Barry 4 39 Stephen Ordinal Rank 1 44 Solomon 2 42 Errol 3 42 Jason 4 41 Garry 5 41 Bernard 6 41 Barry 7 39 Stephen Fractional Rank 1.0 44 Solomon 2.5 42 Errol 2.5 42 Jason 5.0 41 Garry 5.0 41 Bernard 5.0 41 Barry 7.0 39 Stephen
Elixir
defmodule Ranking do
def methods(data) do
IO.puts "stand.\tmod.\tdense\tord.\tfract."
Enum.group_by(data, fn {score,_name} -> score end)
|> Enum.map(fn {score,pairs} ->
names = Enum.map(pairs, fn {_,name} -> name end) |> Enum.reverse
{score, names}
end)
|> Enum.sort_by(fn {score,_} -> -score end)
|> Enum.with_index
|> Enum.reduce({1,0,0}, fn {{score, names}, i}, {s_rnk, m_rnk, o_rnk} ->
d_rnk = i + 1
m_rnk = m_rnk + length(names)
f_rnk = ((s_rnk + m_rnk) / 2) |> to_string |> String.replace(".0","")
o_rnk = Enum.reduce(names, o_rnk, fn name,acc ->
IO.puts "#{s_rnk}\t#{m_rnk}\t#{d_rnk}\t#{acc+1}\t#{f_rnk}\t#{score} #{name}"
acc + 1
end)
{s_rnk+length(names), m_rnk, o_rnk}
end)
end
end
~w"44 Solomon
42 Jason
42 Errol
41 Garry
41 Bernard
41 Barry
39 Stephen"
|> Enum.chunk(2)
|> Enum.map(fn [score,name] -> {String.to_integer(score),name} end)
|> Ranking.methods
- Output:
stand. mod. dense ord. fract. 1 1 1 1 1 44 Solomon 2 3 2 2 2.5 42 Jason 2 3 2 3 2.5 42 Errol 4 6 3 4 5 41 Garry 4 6 3 5 5 41 Bernard 4 6 3 6 5 41 Barry 7 7 4 7 7 39 Stephen
Factor
USING: arrays assocs formatting fry generalizations io kernel
math math.ranges math.statistics math.vectors sequences
splitting.monotonic ;
IN: rosetta-code.ranking
CONSTANT: ranks {
{ 44 "Solomon" } { 42 "Jason" } { 42 "Errol" }
{ 41 "Garry" } { 41 "Bernard" } { 41 "Barry" }
{ 39 "Stephen" }
}
: rank ( seq quot -- seq' )
'[ [ = ] monotonic-split [ length ] map dup @ [ <array> ]
2map concat ] call ; inline
: standard ( seq -- seq' ) [ cum-sum0 1 v+n ] rank ;
: modified ( seq -- seq' ) [ cum-sum ] rank ;
: dense ( seq -- seq' ) [ length [1,b] ] rank ;
: ordinal ( seq -- seq' ) length [1,b] ;
: fractional ( seq -- seq' )
[ dup cum-sum swap [ dupd - [a,b) mean ] 2map ] rank ;
: .rank ( quot -- )
[ ranks dup keys ] dip call swap
[ first2 "%5u %d %s\n" printf ] 2each ; inline
: ranking-demo ( -- )
"Standard ranking" [ standard ]
"Modified ranking" [ modified ]
"Dense ranking" [ dense ]
"Ordinal ranking" [ ordinal ]
"Fractional ranking" [ fractional ]
[ [ print ] [ .rank nl ] bi* ] 2 5 mnapply ;
MAIN: ranking-demo
- Output:
Standard ranking 1 44 Solomon 2 42 Jason 2 42 Errol 4 41 Garry 4 41 Bernard 4 41 Barry 7 39 Stephen Modified ranking 1 44 Solomon 3 42 Jason 3 42 Errol 6 41 Garry 6 41 Bernard 6 41 Barry 7 39 Stephen Dense ranking 1 44 Solomon 2 42 Jason 2 42 Errol 3 41 Garry 3 41 Bernard 3 41 Barry 4 39 Stephen Ordinal ranking 1 44 Solomon 2 42 Jason 3 42 Errol 4 41 Garry 5 41 Bernard 6 41 Barry 7 39 Stephen Fractional ranking 1 44 Solomon 2+1/2 42 Jason 2+1/2 42 Errol 5 41 Garry 5 41 Bernard 5 41 Barry 7 39 Stephen
FreeBASIC
Data 44,"Solomon", 42,"Jason", 42,"Errol", 41,"Garry"
Data 41,"Bernard", 41,"Barry", 39,"Stephen"
Dim Shared As Integer n = 7
Dim Shared As Integer puntos(n), i
Dim Shared As Single ptosnom(n)
Dim Shared As String nombre(n)
Print "Puntuaciones a clasificar (mejores primero):"
For i = 1 To n
Read puntos(i), nombre(i)
Print Using " ##, \ \"; puntos(i); nombre(i)
Next i
Print
Sub MostarTabla
For i = 1 To n
Print Using " \ \ ##, \ \"; Str(ptosnom(i)); puntos(i); nombre(i)
Next i
Print
End Sub
Print "--- Standard ranking ---"
ptosnom(1) = 1
For i = 2 To n
If puntos(i) = puntos(i-1) Then ptosnom(i) = ptosnom(i-1) Else ptosnom(i) = i
Next i
MostarTabla
Print "--- Modified ranking ---"
ptosnom(n) = n
For i = n-1 To 1 Step -1
If puntos(i) = puntos(i+1) Then ptosnom(i) = ptosnom(i+1) Else ptosnom(i) = i
Next i
MostarTabla
Print "--- Dense ranking ---"
ptosnom(1) = 1
For i = 2 To n
ptosnom(i) = ptosnom(i-1) - (puntos(i) <> puntos(i-1))
Next i
MostarTabla
Print "--- Ordinal ranking ---"
For i = 1 To n
ptosnom(i) = i
Next i
MostarTabla
Print "--- Fractional ranking ---"
i = 1
Dim As Integer j = 2
Do
If j <= n Then If (puntos(j-1) = puntos(j)) Then j += 1
For k As Integer = i To j-1
ptosnom(k) = (i+j-1) / 2
Next k
i = j
j += 1
Loop While i <= n
MostarTabla
Sleep
- Output:
Puntuaciones a clasificar (mejores primero): 44 Solomon 42 Jason 42 Errol 41 Garry 41 Bernard 41 Barry 39 Stephen --- Standard ranking --- 1 44 Solomon 2 42 Jason 2 42 Errol 4 41 Garry 4 41 Bernard 4 41 Barry 7 39 Stephen --- Modified ranking --- 1 44 Solomon 3 42 Jason 3 42 Errol 6 41 Garry 6 41 Bernard 6 41 Barry 7 39 Stephen --- Dense ranking --- 1 44 Solomon 2 42 Jason 2 42 Errol 3 41 Garry 3 41 Bernard 3 41 Barry 4 39 Stephen --- Ordinal ranking --- 1 44 Solomon 2 42 Jason 3 42 Errol 4 41 Garry 5 41 Bernard 6 41 Barry 7 39 Stephen --- Fractional ranking --- 1 44 Solomon 2.5 42 Jason 2.5 42 Errol 4.5 41 Garry 4.5 41 Bernard 6 41 Barry 7 39 Stephen
Go
package main
import (
"fmt"
"sort"
)
type rankable interface {
Len() int
RankEqual(int, int) bool
}
func StandardRank(d rankable) []float64 {
r := make([]float64, d.Len())
var k int
for i := range r {
if i == 0 || !d.RankEqual(i, i-1) {
k = i + 1
}
r[i] = float64(k)
}
return r
}
func ModifiedRank(d rankable) []float64 {
r := make([]float64, d.Len())
for i := range r {
k := i + 1
for j := i + 1; j < len(r) && d.RankEqual(i, j); j++ {
k = j + 1
}
r[i] = float64(k)
}
return r
}
func DenseRank(d rankable) []float64 {
r := make([]float64, d.Len())
var k int
for i := range r {
if i == 0 || !d.RankEqual(i, i-1) {
k++
}
r[i] = float64(k)
}
return r
}
func OrdinalRank(d rankable) []float64 {
r := make([]float64, d.Len())
for i := range r {
r[i] = float64(i + 1)
}
return r
}
func FractionalRank(d rankable) []float64 {
r := make([]float64, d.Len())
for i := 0; i < len(r); {
var j int
f := float64(i + 1)
for j = i + 1; j < len(r) && d.RankEqual(i, j); j++ {
f += float64(j + 1)
}
f /= float64(j - i)
for ; i < j; i++ {
r[i] = f
}
}
return r
}
type scores []struct {
score int
name string
}
func (s scores) Len() int { return len(s) }
func (s scores) RankEqual(i, j int) bool { return s[i].score == s[j].score }
func (s scores) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s scores) Less(i, j int) bool {
if s[i].score != s[j].score {
return s[i].score > s[j].score
}
return s[i].name < s[j].name
}
var data = scores{
{44, "Solomon"},
{42, "Jason"},
{42, "Errol"},
{41, "Garry"},
{41, "Bernard"},
{41, "Barry"},
{39, "Stephen"},
}
func main() {
show := func(name string, fn func(rankable) []float64) {
fmt.Println(name, "Ranking:")
r := fn(data)
for i, d := range data {
fmt.Printf("%4v - %2d %s\n", r[i], d.score, d.name)
}
}
sort.Sort(data)
show("Standard", StandardRank)
show("\nModified", ModifiedRank)
show("\nDense", DenseRank)
show("\nOrdinal", OrdinalRank)
show("\nFractional", FractionalRank)
}
- Output:
Standard Ranking: 1 - 44 Solomon 2 - 42 Errol 2 - 42 Jason 4 - 41 Barry 4 - 41 Bernard 4 - 41 Garry 7 - 39 Stephen Modified Ranking: 1 - 44 Solomon 3 - 42 Errol 3 - 42 Jason 6 - 41 Barry 6 - 41 Bernard 6 - 41 Garry 7 - 39 Stephen Dense Ranking: 1 - 44 Solomon 2 - 42 Errol 2 - 42 Jason 3 - 41 Barry 3 - 41 Bernard 3 - 41 Garry 4 - 39 Stephen Ordinal Ranking: 1 - 44 Solomon 2 - 42 Errol 3 - 42 Jason 4 - 41 Barry 5 - 41 Bernard 6 - 41 Garry 7 - 39 Stephen Fractional Ranking: 1 - 44 Solomon 2.5 - 42 Errol 2.5 - 42 Jason 5 - 41 Barry 5 - 41 Bernard 5 - 41 Garry 7 - 39 Stephen
Haskell
import Data.List (groupBy, sortBy, intercalate)
type Item = (Int, String)
type ItemList = [Item]
type ItemGroups = [ItemList]
type RankItem a = (a, Int, String)
type RankItemList a = [RankItem a]
-- make sure the input is ordered and grouped by score
prepare :: ItemList -> ItemGroups
prepare = groupBy gf . sortBy (flip compare)
where
gf (a, _) (b, _) = a == b
-- give an item a rank
rank
:: Num a
=> a -> Item -> RankItem a
rank n (a, b) = (n, a, b)
-- ranking methods
standard, modified, dense, ordinal :: ItemGroups -> RankItemList Int
standard = ms 1
where
ms _ [] = []
ms n (x:xs) = (rank n <$> x) ++ ms (n + length x) xs
modified = md 1
where
md _ [] = []
md n (x:xs) =
let l = length x
nl = n + l
nl1 = nl - 1
in (rank nl1 <$> x) ++ md (n + l) xs
dense = md 1
where
md _ [] = []
md n (x:xs) = map (rank n) x ++ md (n + 1) xs
ordinal = zipWith rank [1 ..] . concat
fractional :: ItemGroups -> RankItemList Double
fractional = mf 1.0
where
mf _ [] = []
mf n (x:xs) =
let l = length x
o = take l [n ..]
ld = fromIntegral l
a = sum o / ld
in map (rank a) x ++ mf (n + ld) xs
-- sample data
test :: ItemGroups
test =
prepare
[ (44, "Solomon")
, (42, "Jason")
, (42, "Errol")
, (41, "Garry")
, (41, "Bernard")
, (41, "Barry")
, (39, "Stephen")
]
-- print rank items nicely
nicePrint
:: Show a
=> String -> RankItemList a -> IO ()
nicePrint xs items = do
putStrLn xs
mapM_ np items
putStr "\n"
where
np (a, b, c) = putStrLn $ intercalate "\t" [show a, show b, c]
main :: IO ()
main = do
nicePrint "Standard:" $ standard test
nicePrint "Modified:" $ modified test
nicePrint "Dense:" $ dense test
nicePrint "Ordinal:" $ ordinal test
nicePrint "Fractional:" $ fractional test
- Output:
Standard: 1 44 Solomon 2 42 Jason 2 42 Errol 4 41 Garry 4 41 Bernard 4 41 Barry 7 39 Stephen Modified: 1 44 Solomon 3 42 Jason 3 42 Errol 6 41 Garry 6 41 Bernard 6 41 Barry 7 39 Stephen Dense: 1 44 Solomon 2 42 Jason 2 42 Errol 3 41 Garry 3 41 Bernard 3 41 Barry 4 39 Stephen Ordinal: 1 44 Solomon 2 42 Jason 3 42 Errol 4 41 Garry 5 41 Bernard 6 41 Barry 7 39 Stephen Fractional: 1.0 44 Solomon 2.5 42 Jason 2.5 42 Errol 5.0 41 Garry 5.0 41 Bernard 5.0 41 Barry 7.0 39 Stephen
J
Implementation:
competitors=:<;._1;._2]0 :0
44 Solomon
42 Jason
42 Errol
41 Garry
41 Bernard
41 Barry
39 Stephen
)
scores=: {."1
standard=: 1+i.~
modified=: 1+i:~
dense=: #/.~ # #\@~.
ordinal=: #\
fractional=: #/.~ # ] (+/%#)/. #\
rank=:1 :'<"0@u@:scores,.]'
Note that we assume that the competitors are already in the right order. Also, of course (as is common when using J) we use the J command line, because that is portable across operating systems (for example: the OS command line is difficult to use on phones).
Task examples:
standard rank competitors
┌─┬──┬───────┐
│1│44│Solomon│
├─┼──┼───────┤
│2│42│Jason │
├─┼──┼───────┤
│2│42│Errol │
├─┼──┼───────┤
│4│41│Garry │
├─┼──┼───────┤
│4│41│Bernard│
├─┼──┼───────┤
│4│41│Barry │
├─┼──┼───────┤
│7│39│Stephen│
└─┴──┴───────┘
modified rank competitors
┌─┬──┬───────┐
│1│44│Solomon│
├─┼──┼───────┤
│3│42│Jason │
├─┼──┼───────┤
│3│42│Errol │
├─┼──┼───────┤
│6│41│Garry │
├─┼──┼───────┤
│6│41│Bernard│
├─┼──┼───────┤
│6│41│Barry │
├─┼──┼───────┤
│7│39│Stephen│
└─┴──┴───────┘
dense rank competitors
┌─┬──┬───────┐
│1│44│Solomon│
├─┼──┼───────┤
│2│42│Jason │
├─┼──┼───────┤
│2│42│Errol │
├─┼──┼───────┤
│3│41│Garry │
├─┼──┼───────┤
│3│41│Bernard│
├─┼──┼───────┤
│3│41│Barry │
├─┼──┼───────┤
│4│39│Stephen│
└─┴──┴───────┘
ordinal rank competitors
┌─┬──┬───────┐
│1│44│Solomon│
├─┼──┼───────┤
│2│42│Jason │
├─┼──┼───────┤
│3│42│Errol │
├─┼──┼───────┤
│4│41│Garry │
├─┼──┼───────┤
│5│41│Bernard│
├─┼──┼───────┤
│6│41│Barry │
├─┼──┼───────┤
│7│39│Stephen│
└─┴──┴───────┘
fractional rank competitors
┌───┬──┬───────┐
│1 │44│Solomon│
├───┼──┼───────┤
│2.5│42│Jason │
├───┼──┼───────┤
│2.5│42│Errol │
├───┼──┼───────┤
│5 │41│Garry │
├───┼──┼───────┤
│5 │41│Bernard│
├───┼──┼───────┤
│5 │41│Barry │
├───┼──┼───────┤
│7 │39│Stephen│
└───┴──┴───────┘
Java
import java.util.*;
public class RankingMethods {
final static String[] input = {"44 Solomon", "42 Jason", "42 Errol",
"41 Garry", "41 Bernard", "41 Barry", "39 Stephen"};
public static void main(String[] args) {
int len = input.length;
Map<String, int[]> map = new TreeMap<>((a, b) -> b.compareTo(a));
for (int i = 0; i < len; i++) {
String key = input[i].split("\\s+")[0];
int[] arr;
if ((arr = map.get(key)) == null)
arr = new int[]{i, 0};
arr[1]++;
map.put(key, arr);
}
int[][] groups = map.values().toArray(new int[map.size()][]);
standardRanking(len, groups);
modifiedRanking(len, groups);
denseRanking(len, groups);
ordinalRanking(len);
fractionalRanking(len, groups);
}
private static void standardRanking(int len, int[][] groups) {
System.out.println("\nStandard ranking");
for (int i = 0, rank = 0, group = 0; i < len; i++) {
if (group < groups.length && i == groups[group][0]) {
rank = i + 1;
group++;
}
System.out.printf("%d %s%n", rank, input[i]);
}
}
private static void modifiedRanking(int len, int[][] groups) {
System.out.println("\nModified ranking");
for (int i = 0, rank = 0, group = 0; i < len; i++) {
if (group < groups.length && i == groups[group][0])
rank += groups[group++][1];
System.out.printf("%d %s%n", rank, input[i]);
}
}
private static void denseRanking(int len, int[][] groups) {
System.out.println("\nDense ranking");
for (int i = 0, rank = 0; i < len; i++) {
if (rank < groups.length && i == groups[rank][0])
rank++;
System.out.printf("%d %s%n", rank, input[i]);
}
}
private static void ordinalRanking(int len) {
System.out.println("\nOrdinal ranking");
for (int i = 0; i < len; i++)
System.out.printf("%d %s%n", i + 1, input[i]);
}
private static void fractionalRanking(int len, int[][] groups) {
System.out.println("\nFractional ranking");
float rank = 0;
for (int i = 0, tmp = 0, group = 0; i < len; i++) {
if (group < groups.length && i == groups[group][0]) {
tmp += groups[group++][1];
rank = (i + 1 + tmp) / 2.0F;
}
System.out.printf("%2.1f %s%n", rank, input[i]);
}
}
}
Standard ranking 1 44 Solomon 2 42 Jason 2 42 Errol 4 41 Garry 4 41 Bernard 4 41 Barry 7 39 Stephen Modified ranking 1 44 Solomon 3 42 Jason 3 42 Errol 6 41 Garry 6 41 Bernard 6 41 Barry 7 39 Stephen Dense ranking 1 44 Solomon 2 42 Jason 2 42 Errol 3 41 Garry 3 41 Bernard 3 41 Barry 4 39 Stephen Ordinal ranking 1 44 Solomon 2 42 Jason 3 42 Errol 4 41 Garry 5 41 Bernard 6 41 Barry 7 39 Stephen Fractional ranking 1,0 44 Solomon 2,5 42 Jason 2,5 42 Errol 5,0 41 Garry 5,0 41 Bernard 5,0 41 Barry 7,0 39 Stephen
JavaScript
ES5
The task formulation doesn't seem to directly explain or determine the order of listing for players whose score is the same.
( This version chooses to use a secondary (alphabetic) sort after the numeric sort by score. That does, of course, affect the ordinal placements for some players)
(function () {
var xs = 'Solomon Jason Errol Garry Bernard Barry Stephen'.split(' '),
ns = [44, 42, 42, 41, 41, 41, 39],
sorted = xs.map(function (x, i) {
return { name: x, score: ns[i] };
}).sort(function (a, b) {
var c = b.score - a.score;
return c ? c : a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
}),
names = sorted.map(function (x) { return x.name; }),
scores = sorted.map(function (x) { return x.score; }),
reversed = scores.slice(0).reverse(),
unique = scores.filter(function (x, i) {
return scores.indexOf(x) === i;
});
// RANKINGS AS FUNCTIONS OF SCORES: SORTED, REVERSED AND UNIQUE
var rankings = function (score, index) {
return {
name: names[index],
score: score,
Ordinal: index + 1,
Standard: function (n) {
return scores.indexOf(n) + 1;
}(score),
Modified: function (n) {
return reversed.length - reversed.indexOf(n);
}(score),
Dense: function (n) {
return unique.indexOf(n) + 1;
}(score),
Fractional: function (n) {
return (
(scores.indexOf(n) + 1) +
(reversed.length - reversed.indexOf(n))
) / 2;
}(score)
};
},
tbl = [
'Name Score Standard Modified Dense Ordinal Fractional'.split(' ')
].concat(scores.map(rankings).reduce(function (a, x) {
return a.concat([
[x.name, x.score,
x.Standard, x.Modified, x.Dense, x.Ordinal, x.Fractional
]
]);
}, [])),
//[[a]] -> bool -> s -> s
wikiTable = function (lstRows, blnHeaderRow, strStyle) {
return '{| class="wikitable" ' + (
strStyle ? 'style="' + strStyle + '"' : ''
) + lstRows.map(function (lstRow, iRow) {
var strDelim = ((blnHeaderRow && !iRow) ? '!' : '|');
return '\n|-\n' + strDelim + ' ' + lstRow.map(function (v) {
return typeof v === 'undefined' ? ' ' : v;
}).join(' ' + strDelim + strDelim + ' ');
}).join('') + '\n|}';
};
return wikiTable(tbl, true, 'text-align:center');
})();
- Output:
Name | Score | Standard | Modified | Dense | Ordinal | Fractional |
---|---|---|---|---|---|---|
Solomon | 44 | 1 | 1 | 1 | 1 | 1 |
Errol | 42 | 2 | 3 | 2 | 2 | 2.5 |
Jason | 42 | 2 | 3 | 2 | 3 | 2.5 |
Barry | 41 | 4 | 6 | 3 | 4 | 5 |
Bernard | 41 | 4 | 6 | 3 | 5 | 5 |
Garry | 41 | 4 | 6 | 3 | 6 | 5 |
Stephen | 39 | 7 | 7 | 4 | 7 | 7 |
ES6
((() => {
const xs = 'Solomon Jason Errol Garry Bernard Barry Stephen'.split(' '),
ns = [44, 42, 42, 41, 41, 41, 39];
const sorted = xs.map((x, i) => ({
name: x,
score: ns[i]
}))
.sort((a, b) => {
const c = b.score - a.score;
return c ? c : a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
});
const names = sorted.map(x => x.name),
scores = sorted.map(x => x.score),
reversed = scores.slice(0)
.reverse(),
unique = scores.filter((x, i) => scores.indexOf(x) === i);
// RANKINGS AS FUNCTIONS OF SCORES: SORTED, REVERSED AND UNIQUE
// rankings :: Int -> Int -> Dictonary
const rankings = (score, index) => ({
name: names[index],
score,
Ordinal: index + 1,
Standard: scores.indexOf(score) + 1,
Modified: reversed.length - reversed.indexOf(score),
Dense: unique.indexOf(score) + 1,
Fractional: (n => (
(scores.indexOf(n) + 1) +
(reversed.length - reversed.indexOf(n))
) / 2)(score)
});
// tbl :: [[[a]]]
const tbl = [
'Name Score Standard Modified Dense Ordinal Fractional'.split(' ')
].concat(scores.map(rankings)
.reduce((a, x) => a.concat([
[x.name, x.score,
x.Standard, x.Modified, x.Dense, x.Ordinal, x.Fractional
]
]), []));
// wikiTable :: [[[a]]] -> Bool -> String -> String
const wikiTable = (lstRows, blnHeaderRow, strStyle) =>
`{| class="wikitable" ${strStyle ? 'style="' + strStyle + '"' : ''}
${lstRows.map((lstRow, iRow) => {
const strDelim = ((blnHeaderRow && !iRow) ? '!' : '|');
return '\n|-\n' + strDelim + ' ' + lstRow
.map(v => typeof v === 'undefined' ? ' ' : v)
.join(' ' + strDelim + strDelim + ' ');
}).join('')}\n|}`;
return wikiTable(tbl, true, 'text-align:center');
}))();
Name | Score | Standard | Modified | Dense | Ordinal | Fractional |
---|---|---|---|---|---|---|
Solomon | 44 | 1 | 1 | 1 | 1 | 1 |
Errol | 42 | 2 | 3 | 2 | 2 | 2.5 |
Jason | 42 | 2 | 3 | 2 | 3 | 2.5 |
Barry | 41 | 4 | 6 | 3 | 4 | 5 |
Bernard | 41 | 4 | 6 | 3 | 5 | 5 |
Garry | 41 | 4 | 6 | 3 | 6 | 5 |
Stephen | 39 | 7 | 7 | 4 | 7 | 7 |
- Output:
jq
We assume the list of players and their scores has already been sorted, and that the list takes the form:
[ player1, score1, player2, score2, ...]
For the sake of brevity, only the ranks are printed.
# Ties share what would have been their first ordinal number
def standard_ranking:
. as $raw
| ([range(1;length;2) | $raw[.]]) as $scores
| reduce range(1; $scores|length) as $i
([1]; if $scores[$i - 1] == $scores[$i] then . + [.[-1]]
else . + [$i + 1]
end) ;
def modified_ranking:
# The helper function resolves [ranks, tentative]
# by appending the ranks of the ties to "ranks"
def resolve:
(.[1] | length) as $length
| if $length == 0 then .[0]
else .[1][-1] as $max
| .[0] + ( .[1] | map( $max) )
end ;
. as $raw
| ([range(1;length;2) | $raw[.]]) as $scores
| reduce range(1; $scores|length) as $i
# state: [ranks, tentative]
([ [], [1] ];
if $scores[$i - 1] == $scores[$i] then [.[0], .[1] + [ $i + 1 ]]
else [ resolve, [ $i + 1 ] ]
end )
| resolve ;
def dense_ranking: # next available
. as $raw
| ([range(1;length;2) | $raw[.]]) as $scores
| reduce range(1; $scores|length) as $i
([1]; if $scores[$i - 1] == $scores[$i] then . + [.[-1]]
else . + [ .[-1] + 1]
end );
def ordinal_ranking: # unfair to some!
[ range(1; 1 + length/2) ] ;
def fractional_ranking:
# The helper function resolves [ranks, tentative]
# by appending the averages of the tentative ranks to "ranks"
def resolve:
(.[1] | length) as $length
| if $length == 0 then .[0]
else (.[1] | add / $length) as $avg
| .[0] + ( .[1] | map( $avg) )
end ;
. as $raw
| ([range(1;length;2) | $raw[.]]) as $scores
| reduce range(1; $scores|length) as $i
# state: [ranks, tentative]
([ [], [1] ];
if $scores[$i - 1] == $scores[$i] then [.[0], .[1] + [ $i + 1 ]]
else [ resolve, [ $i + 1 ] ]
end )
| resolve ;
Task
def raw:
[
"Solomon", 44,
"Jason" , 42,
"Errol" , 42,
"Garry" , 41,
"Bernard", 41,
"Barry" , 41,
"Stephen", 39
] ;
def task:
"standard: \( raw | standard_ranking)",
"modified: \( raw | modified_ranking)",
"dense: \( raw | dense_ranking)",
"ordinal: \( raw | ordinal_ranking)",
"fractional: \( raw | fractional_ranking)" ;
task
- Output:
standard: [1,2,2,4,4,4,7] modified: [1,3,3,6,6,6,7] dense: [1,2,2,3,3,3,4] ordinal: [1,2,3,4,5,6,7] fractional: [1,2.5,2.5,5,5,5,7]
Julia
ties, a helper function used by some of the ranking methods. It lists any duplicated scores.
function ties{T<:Real}(a::Array{T,1})
unique(a[2:end][a[2:end] .== a[1:end-1]])
end
ties
assumes that the there are at least 2 scores in the list to be checked, and the calling functions are designed to avoid calls to it in this case.
Standard Ranking Function
function rankstandard{T<:Real}(a::Array{T,1})
r = collect(1:length(a))
1 < r[end] || return r
for i in ties(a)
r[a.==i] = r[a.==i][1]
end
return r
end
Modified Ranking Function
function rankmodified{T<:Real}(a::Array{T,1})
indexin(a, a)
end
Dense Ranking Function
function rankdense{T<:Real}(a::Array{T,1})
indexin(a, unique(a))
end
Ordinal Ranking Function
function rankordinal{T<:Real}(a::Array{T,1})
collect(1:length(a))
end
For ordinal ranking, there are a variety of ways of handling tied scores. I've taken the easy way out and assumed that the position in the list already reflects any tie-breaking policy. In this case, there is not much that needs to be done.
Fractional Ranking Function
function rankfractional{T<:Real}(a::Array{T,1})
r = float64(collect(1:length(a)))
1.0 < r[end] || return r
for i in ties(a)
r[a.==i] = mean(r[a.==i])
end
return r
end
Main
scores = [44, 42, 42, 41, 41, 41, 39]
names = ["Solomon", "Jason", "Errol", "Garry",
"Bernard", "Barry", "Stephen"]
srank = rankstandard(scores)
mrank = rankmodified(scores)
drank = rankdense(scores)
orank = rankordinal(scores)
frank = rankfractional(scores)
println(" Name Score Std Mod Den Ord Frac")
for i in 1:length(scores)
print(@sprintf(" %-7s", names[i]))
print(@sprintf("%5d ", scores[i]))
print(@sprintf("%5d", srank[i]))
print(@sprintf("%5d", mrank[i]))
print(@sprintf("%5d", drank[i]))
print(@sprintf("%5d", orank[i]))
print(@sprintf("%7.2f", frank[i]))
println()
end
- Output:
Name Score Std Mod Den Ord Frac Solomon 44 1 1 1 1 1.00 Jason 42 2 3 2 2 2.50 Errol 42 2 3 2 3 2.50 Garry 41 4 6 3 4 5.00 Bernard 41 4 6 3 5 5.00 Barry 41 4 6 3 6 5.00 Stephen 39 7 7 4 7 7.00
Kotlin
// version 1.0.6
/* all ranking functions assume the array of Pairs is non-empty and already sorted by decreasing order of scores
and then, if the scores are equal, by reverse alphabetic order of names
*/
fun standardRanking(scores: Array<Pair<Int, String>>): IntArray {
val rankings = IntArray(scores.size)
rankings[0] = 1
for (i in 1 until scores.size) rankings[i] = if (scores[i].first == scores[i - 1].first) rankings[i - 1] else i + 1
return rankings
}
fun modifiedRanking(scores: Array<Pair<Int, String>>): IntArray {
val rankings = IntArray(scores.size)
rankings[0] = 1
for (i in 1 until scores.size) {
rankings[i] = i + 1
val currScore = scores[i].first
for (j in i - 1 downTo 0) {
if (currScore != scores[j].first) break
rankings[j] = i + 1
}
}
return rankings
}
fun denseRanking(scores: Array<Pair<Int, String>>): IntArray {
val rankings = IntArray(scores.size)
rankings[0] = 1
var prevRanking = 1
for (i in 1 until scores.size) rankings[i] = if (scores[i].first == scores[i - 1].first) prevRanking else ++prevRanking
return rankings
}
fun ordinalRanking(scores: Array<Pair<Int, String>>) = IntArray(scores.size) { it + 1 }
fun fractionalRanking(scores: Array<Pair<Int, String>>): DoubleArray {
val rankings = DoubleArray(scores.size)
rankings[0] = 1.0
for (i in 1 until scores.size) {
var k = i
val currScore = scores[i].first
for (j in i - 1 downTo 0) {
if (currScore != scores[j].first) break
k = j
}
val avg = (k..i).average() + 1.0
for (m in k..i) rankings[m] = avg
}
return rankings
}
fun printRankings(title: String, rankings: IntArray, scores: Array<Pair<Int, String>>) {
println(title + ":")
for (i in 0 until rankings.size) {
print ("${rankings[i]} ")
println(scores[i].toString().removeSurrounding("(", ")").replace(",", ""))
}
println()
}
fun printFractionalRankings(title: String, rankings: DoubleArray, scores: Array<Pair<Int, String>>) {
println(title + ":")
for (i in 0 until rankings.size) {
print ("${"%3.2f".format(rankings[i])} ")
println(scores[i].toString().removeSurrounding("(", ")").replace(",", ""))
}
println()
}
fun main(args: Array<String>) {
val scores = arrayOf(44 to "Solomon", 42 to "Jason", 42 to "Errol", 41 to "Garry",
41 to "Bernard", 41 to "Barry", 39 to "Stephen")
printRankings("Standard ranking", standardRanking(scores), scores)
printRankings("Modified ranking", modifiedRanking(scores), scores)
printRankings("Dense ranking", denseRanking(scores), scores)
printRankings("Ordinal ranking", ordinalRanking(scores), scores)
printFractionalRankings("Fractional ranking", fractionalRanking(scores), scores)
}
- Output:
Standard ranking: 1 44 Solomon 2 42 Jason 2 42 Errol 4 41 Garry 4 41 Bernard 4 41 Barry 7 39 Stephen Modified ranking: 1 44 Solomon 3 42 Jason 3 42 Errol 6 41 Garry 6 41 Bernard 6 41 Barry 7 39 Stephen Dense ranking: 1 44 Solomon 2 42 Jason 2 42 Errol 3 41 Garry 3 41 Bernard 3 41 Barry 4 39 Stephen Ordinal ranking: 1 44 Solomon 2 42 Jason 3 42 Errol 4 41 Garry 5 41 Bernard 6 41 Barry 7 39 Stephen Fractional ranking: 1.00 44 Solomon 2.50 42 Jason 2.50 42 Errol 5.00 41 Garry 5.00 41 Bernard 5.00 41 Barry 7.00 39 Stephen
Ksh
#!/bin/ksh
exec 2> /tmp/Ranking_methods.err
# Ranking methods
#
# # Standard. (Ties share what would have been their first ordinal number).
# # Modified. (Ties share what would have been their last ordinal number).
# # Dense. (Ties share the next available integer).
# # Ordinal. ((Competitors take the next available integer. Ties are not treated otherwise).
# # Fractional. (Ties share the mean of what would have been their ordinal numbers)
# # Variables:
#
typeset -a arr=( '44 Solomon' '42 Jason' '42 Errol' '41 Garry' '41 Bernard' '41 Barry' '39 Stephen' )
integer i
# # Functions:
#
# # Function _rankStandard(arr, rankarr) - retun arr with standard ranking
#
function _rankStandard {
typeset _ranked ; nameref _ranked="$1"
typeset _i _j _scr _currank _prevscr _shelf
integer _i _j _scr _currank=1 _prevscr
typeset -a _shelf
for ((_i=0; _i<${#arr[*]}; _i++)); do
_scr=${arr[_i]%\ *}
if (( _i>0 )) && (( _scr != _prevscr )); then
for ((_j=0; _j<${#_shelf[*]}; _j++)); do
_ranked+=( "${_currank} ${_shelf[_j]}" )
done
(( _currank+=${#_shelf[*]} ))
unset _shelf ; typeset -a _shelf
fi
_shelf+=( "${arr[_i]}" )
_prevscr=${_scr}
done
for ((_j=0; _j<${#_shelf[*]}; _j++)); do
_ranked+=( "${_currank} ${_shelf[_j]}" )
done
}
# # Function _rankModified(arr, rankarr) - retun arr with modified ranking
#
function _rankModified {
typeset _ranked ; nameref _ranked="$1"
typeset _i _j _scr _currank _prevscr _shelf
integer _i _j _scr _currank=0 _prevscr
typeset -a _shelf
for ((_i=0; _i<${#arr[*]}; _i++)); do
_scr=${arr[_i]%\ *}
if (( _i>0 )) && (( _scr != _prevscr )); then
for ((_j=0; _j<${#_shelf[*]}; _j++)); do
_ranked+=( "${_currank} ${_shelf[_j]}" )
done
unset _shelf ; typeset -a _shelf
fi
_shelf+=( "${arr[_i]}" )
(( _currank++ ))
_prevscr=${_scr}
done
for ((_j=0; _j<${#_shelf[*]}; _j++)); do
_ranked+=( "${_currank} ${_shelf[_j]}" )
done
}
# # Function _rankDense(arr, rankarr) - retun arr with dense ranking
#
function _rankDense {
typeset _ranked ; nameref _ranked="$1"
typeset _i _j _scr _currank _prevscr _shelf
integer _i _j _scr _currank=0 _prevscr
typeset -a _shelf
for ((_i=0; _i<${#arr[*]}; _i++)); do
_scr=${arr[_i]%\ *}
if (( _i>0 )) && (( _scr != _prevscr )); then
(( _currank++ ))
for ((_j=0; _j<${#_shelf[*]}; _j++)); do
_ranked+=( "${_currank} ${_shelf[_j]}" )
done
unset _shelf ; typeset -a _shelf
fi
_shelf+=( "${arr[_i]}" )
_prevscr=${_scr}
done
(( _currank++ ))
for ((_j=0; _j<${#_shelf[*]}; _j++)); do
_ranked+=( "${_currank} ${_shelf[_j]}" )
done
}
# # Function _rankOrdinal(arr, rankarr) - retun arr with ordinal ranking
#
function _rankOrdinal {
typeset _ranked ; nameref _ranked="$1"
typeset _i ; integer _i
for ((_i=0; _i<${#arr[*]}; _i++)); do
_ranked+=( "$(( _i + 1 )) ${arr[_i]}" )
done
}
# # Function _rankFractional(arr, rankarr) - retun arr with Fractional ranking
#
function _rankFractional {
typeset _ranked ; nameref _ranked="$1"
typeset _i _j _scr _currank _prevscr _shelf
integer _i _j _scr _prevscr
typeset -F1 _currank=1.0
typeset -a _shelf
for ((_i=0; _i<${#arr[*]}; _i++)); do
_scr=${arr[_i]%\ *}
if (( _i>0 )) && (( _scr != _prevscr )); then
(( _currank/=${#_shelf[*]} ))
for ((_j=0; _j<${#_shelf[*]}; _j++)); do
_ranked+=( "${_currank} ${_shelf[_j]}" )
done
_currank=0.0
unset _shelf ; typeset -a _shelf
fi
(( _i>0 )) && (( _currank+=_i + 1 ))
_shelf+=( "${arr[_i]}" )
_prevscr=${_scr}
done
for ((_j=0; _j<${#_shelf[*]}; _j++)); do
(( _currank/=${#_shelf[*]} ))
_ranked+=( "${_currank} ${_shelf[_j]}" )
done
}
######
# main #
######
printf "\n\nInput Data: ${#arr[*]} records\n---------------------\n"
for ((i=0; i< ${#arr[*]}; i++)); do
print ${arr[i]}
done
typeset -a rankedarr
_rankStandard rankedarr
printf "\n\nStandard Ranking\n----------------\n"
for ((i=0; i< ${#rankedarr[*]}; i++)); do
print ${rankedarr[i]}
done
unset rankedarr ; typeset -a rankedarr
_rankModified rankedarr
printf "\n\nModified Ranking\n----------------\n"
for ((i=0; i< ${#rankedarr[*]}; i++)); do
print ${rankedarr[i]}
done
unset rankedarr ; typeset -a rankedarr
_rankDense rankedarr
printf "\n\nDense Ranking\n-------------\n"
for ((i=0; i< ${#rankedarr[*]}; i++)); do
print ${rankedarr[i]}
done
unset rankedarr ; typeset -a rankedarr
_rankOrdinal rankedarr
printf "\n\nOrdinal Ranking\n---------------\n"
for ((i=0; i< ${#rankedarr[*]}; i++)); do
print ${rankedarr[i]}
done
unset rankedarr ; typeset -a rankedarr
_rankFractional rankedarr
printf "\n\nFractional Ranking\n------------------\n"
for ((i=0; i< ${#rankedarr[*]}; i++)); do
print ${rankedarr[i]}
done
- Output:
Input Data: 7 records --------------------- 44 Solomon 42 Jason 42 Errol 41 Garry 41 Bernard 41 Barry 39 Stephen
Standard Ranking ---------------- 1 44 Solomon 2 42 Jason 2 42 Errol 4 41 Garry 4 41 Bernard 4 41 Barry 7 39 Stephen
Modified Ranking ---------------- 1 44 Solomon 3 42 Jason 3 42 Errol 6 41 Garry 6 41 Bernard 6 41 Barry 7 39 Stephen
Dense Ranking ------------- 1 44 Solomon 2 42 Jason 2 42 Errol 3 41 Garry 3 41 Bernard 3 41 Barry 4 39 Stephen
Ordinal Ranking --------------- 1 44 Solomon 2 42 Jason 3 42 Errol 4 41 Garry 5 41 Bernard 6 41 Barry 7 39 Stephen
Fractional Ranking ------------------ 1.0 44 Solomon 2.5 42 Jason 2.5 42 Errol 5.0 41 Garry 5.0 41 Bernard 5.0 41 Barry
7.0 39 Stephen
M2000 Interpreter
Module Ranking (output$, orderlist) {
Open output$ for output as #k
Gosub getdata
Print #k, "Standard ranking:"
skip=true
rankval=1
oldrank=0
For i=1 to items
Read rank, name$
if skip then
skip=false
else.if oldrank<>rank then
rankval=i
end if
oldrank=rank
Print #k, Format$("{0::-5} {2} ({1})", rankval, rank, name$)
Next
Gosub getdata
Print #k, "Modified ranking:"
skip=true
rankval=Items
oldrank=0
ShiftBack 1, -items*2 ' reverse stack items
For i=items to 1
Read name$, rank
if skip then
skip=false
else.if oldrank<>rank then
rankval=i
end if
oldrank=rank
Data Format$("{0::-5} {2} ({1})", rankval, rank, name$)
Next
ShiftBack 1, -items ' reverse stack items
For i=1 to items
Print #k, letter$
Next i
Gosub getdata
Print #k, "Dense ranking:"
skip=true
Dense=Stack
acc=1
oldrank=0
For i=1 to items
Read rank, name$
if skip then
skip=false
oldrank=rank
else.if oldrank<>rank then
oldrank=rank
Gosub dense
acc=i
end if
Stack Dense {data Format$(" {0} ({1})",name$, rank)}
Next
Gosub dense
Gosub getdata
Print #k, "Ordinal ranking:"
For i=1 to items
Print #k, Format$("{0::-5} {2} ({1})", i, Number, letter$)
Next
Gosub getdata
Print #k, "Fractional ranking:"
skip=true
Frac=Stack
acc=1
oldrank=0
For i=1 to items
Read rank, name$
if skip then
skip=false
oldrank=rank
else.if oldrank<>rank then
oldrank=rank
Gosub Fractional
acc=I
end if
Stack Frac {data Format$(" {0} ({1})",name$, rank)}
Next
Gosub Fractional
Close #k
End
Fractional:
val=((len(Frac)+1)/2+(acc-1))
Stack Frac {
while not empty
Print #k, format$("{0:1:-5}{1}", val, letter$)
end while
}
Return
dense:
Stack Dense {
while not empty
Print #k, format$("{0::-5}{1}", acc, letter$)
end while
}
Return
getdata:
flush
stack stack(orderlist) // place a copy of items to current stack
items=stack.size/2
Return
}
Flush
Data 44, "Solomon", 42, "Jason", 42, "Errol"
Data 41, "Garry", 41, "Bernard", 41, "Barry"
Data 39, "Stephen"
// get all items from current stack to a new stack
alist=[]
// To screen
Ranking "", alist
// To file
Ranking "ranking.txt", alist
- Output:
Standard ranking: 1 Solomon (44) 2 Jason (42) 2 Errol (42) 4 Garry (41) 4 Bernard (41) 4 Barry (41) 7 Stephen (39) Modified ranking: 1 Solomon (44) 3 Jason (42) 3 Errol (42) 6 Garry (41) 6 Bernard (41) 6 Barry (41) 7 Stephen (39) Dense ranking: 1 Solomon (44) 2 Jason (42) 2 Errol (42) 4 Garry (41) 4 Bernard (41) 4 Barry (41) 7 Stephen (39) Ordinal ranking: 1 Solomon (44) 2 Jason (42) 3 Errol (42) 4 Garry (41) 5 Bernard (41) 6 Barry (41) 7 Stephen (39) Fractional ranking: 1.0 Solomon (44) 2.5 Jason (42) 2.5 Errol (42) 5.0 Garry (41) 5.0 Bernard (41) 5.0 Barry (41) 7.0 Stephen (39)
Mathematica/Wolfram Language
data = Transpose@{{44, 42, 42, 41, 41, 41, 39}, {"Solomon", "Jason",
"Errol", "Garry", "Bernard", "Barry", "Stephen"}};
rank[data_, type_] :=
Module[{t = Transpose@{Sort@data, Range[Length@data, 1, -1]}},
Switch[type,
"standard", data/.Rule@@@First/@SplitBy[t, First],
"modified", data/.Rule@@@Last/@SplitBy[t, First],
"dense", data/.Thread[#->Range[Length@#]]&@SplitBy[t, First][[All, 1, 1]],
"ordinal", Reverse@Ordering[data],
"fractional", data/.Rule@@@(Mean[#]/.{a_Rational:>N[a]}&)/@ SplitBy[t, First]]]
fmtRankedData[data_, type_] :=
Labeled[Grid[
SortBy[ArrayFlatten@{{Transpose@{rank[data[[All, 1]], type]},
data}}, First], Alignment->Left], type<>" ranking:", Top]
Grid@{fmtRankedData[data, #] & /@ {"standard", "modified", "dense",
"ordinal", "fractional"}}
- Output:
standard ranking: 1 44 Solomon 3 42 Errol 3 42 Jason 6 41 Barry 6 41 Bernard 6 41 Garry 7 39 Stephen modified ranking: 1 44 Solomon 2 42 Errol 2 42 Jason 4 41 Barry 4 41 Bernard 4 41 Garry 7 39 Stephen dense ranking: 1 39 Stephen 2 41 Barry 2 41 Bernard 2 41 Garry 3 42 Errol 3 42 Jason 4 44 Solomon ordinal ranking: 1 44 Solomon 2 42 Errol 3 42 Jason 4 41 Barry 5 41 Bernard 6 41 Garry 7 39 Stephen fractional ranking: 1 44 Solomon 2.5 42 Errol 2.5 42 Jason 5 41 Barry 5 41 Bernard 5 41 Garry 7 39 Stephen
Modula-2
MODULE RankingMethods;
FROM FormatString IMPORT FormatString;
FROM RealStr IMPORT RealToFixed;
FROM Terminal IMPORT WriteString,WriteLn,ReadChar;
PROCEDURE WriteCard(c : CARDINAL);
VAR buf : ARRAY[0..15] OF CHAR;
BEGIN
FormatString("%c", buf, c);
WriteString(buf)
END WriteCard;
TYPE Entry = RECORD
name : ARRAY[0..15] OF CHAR;
score : CARDINAL;
END;
PROCEDURE OrdinalRanking(CONST entries : ARRAY OF Entry);
VAR
buf : ARRAY[0..31] OF CHAR;
i : CARDINAL;
BEGIN
WriteString("Ordinal Ranking");
WriteLn;
WriteString("---------------");
WriteLn;
FOR i:=0 TO HIGH(entries) DO
FormatString("%c\t%c\t%s\n", buf, i + 1, entries[i].score, entries[i].name);
WriteString(buf)
END;
WriteLn
END OrdinalRanking;
PROCEDURE StandardRanking(CONST entries : ARRAY OF Entry);
VAR
buf : ARRAY[0..31] OF CHAR;
i,j : CARDINAL;
BEGIN
WriteString("Standard Ranking");
WriteLn;
WriteString("---------------");
WriteLn;
j := 1;
FOR i:=0 TO HIGH(entries) DO
FormatString("%c\t%c\t%s\n", buf, j, entries[i].score, entries[i].name);
WriteString(buf);
IF entries[i+1].score < entries[i].score THEN
j := i + 2
END
END;
WriteLn
END StandardRanking;
PROCEDURE DenseRanking(CONST entries : ARRAY OF Entry);
VAR
buf : ARRAY[0..31] OF CHAR;
i,j : CARDINAL;
BEGIN
WriteString("Dense Ranking");
WriteLn;
WriteString("---------------");
WriteLn;
j := 1;
FOR i:=0 TO HIGH(entries) DO
FormatString("%c\t%c\t%s\n", buf, j, entries[i].score, entries[i].name);
WriteString(buf);
IF entries[i+1].score < entries[i].score THEN
INC(j)
END
END;
WriteLn
END DenseRanking;
PROCEDURE ModifiedRanking(CONST entries : ARRAY OF Entry);
VAR
buf : ARRAY[0..31] OF CHAR;
i,j,count : CARDINAL;
BEGIN
WriteString("Modified Ranking");
WriteLn;
WriteString("---------------");
WriteLn;
i := 0;
j := 1;
WHILE i < HIGH(entries) DO
IF entries[i].score # entries[i+1].score THEN
FormatString("%c\t%c\t%s\n", buf, i+1, entries[i].score, entries[i].name);
WriteString(buf);
count := 1;
FOR j:=i+1 TO HIGH(entries)-1 DO
IF entries[j].score # entries[j+1].score THEN
BREAK
END;
INC(count)
END;
j := 0;
WHILE j < count-1 DO
FormatString("%c\t%c\t%s\n", buf, i+count+1, entries[i+j+1].score, entries[i+j+1].name);
WriteString(buf);
INC(j)
END;
i := i + count - 1
END;
INC(i)
END;
FormatString("%c\t%c\t%s\n\n", buf, HIGH(entries)+1, entries[HIGH(entries)].score, entries[HIGH(entries)].name);
WriteString(buf)
END ModifiedRanking;
PROCEDURE FractionalRanking(CONST entries : ARRAY OF Entry);
VAR
buf : ARRAY[0..32] OF CHAR;
i,j,count : CARDINAL;
sum : REAL;
BEGIN
WriteString("Fractional Ranking");
WriteLn;
WriteString("---------------");
WriteLn;
sum := 0.0;
i := 0;
WHILE i <= HIGH(entries) DO
IF (i = HIGH(entries) - 1) OR (entries[i].score # entries[i+1].score) THEN
RealToFixed(FLOAT(i+1),1,buf);
WriteString(buf);
FormatString("\t%c\t%s\n", buf, entries[i].score, entries[i].name);
WriteString(buf)
ELSE
sum := FLOAT(i);
count := 1;
j := i;
WHILE entries[j].score = entries[j+1].score DO
sum := sum + FLOAT(j + 1);
INC(count);
INC(j)
END;
FOR j:=0 TO count-1 DO
RealToFixed(sum/FLOAT(count)+1.0,1,buf);
WriteString(buf);
FormatString("\t%c\t%s\n", buf, entries[i+j].score, entries[i+j].name);
WriteString(buf)
END;
i := i + count - 1
END;
INC(i)
END
END FractionalRanking;
(* Main *)
TYPE EA = ARRAY[0..6] OF Entry;
VAR entries : EA;
BEGIN
entries := EA{
{"Solomon", 44},
{"Jason", 42},
{"Errol", 42},
{"Garry", 41},
{"Bernard", 41},
{"Barry", 41},
{"Stephen", 39}
};
OrdinalRanking(entries);
StandardRanking(entries);
DenseRanking(entries);
ModifiedRanking(entries);
FractionalRanking(entries);
ReadChar
END RankingMethods.
- Output:
Ordinal Ranking --------------- 1 44 Solomon 2 42 Jason 3 42 Errol 4 41 Garry 5 41 Bernard 6 41 Barry 7 39 Stephen Standard Ranking --------------- 1 44 Solomon 2 42 Jason 2 42 Errol 4 41 Garry 4 41 Bernard 5 41 Barry 7 39 Stephen Dense Ranking --------------- 1 44 Solomon 2 42 Jason 2 42 Errol 3 41 Garry 3 41 Bernard 3 41 Barry 4 39 Stephen Modified Ranking --------------- 1 44 Solomon 3 42 Jason 3 42 Errol 6 41 Garry 6 41 Bernard 6 41 Barry 7 39 Stephen Fractional Ranking --------------- 1.0 44 Solomon 2.5 42 Jason 2.5 42 Errol 5.0 41 Garry 5.0 41 Bernard 5.0 41 Barry 7.0 39 Stephen
Nim
Using an auxiliary table
To simplify, it’s convenient to build a table giving for each score the list of competitor names.
import algorithm, sequtils, stats, tables
type
Record = tuple[score: int; name: string] # Input data.
Groups = OrderedTable[int, seq[string]] # Maps score to list of names.
Rank = tuple[rank: int; name: string; score: int] # Result.
FractRank = tuple[rank: float; name: string; score: int] # Result (fractional).
func cmp(a, b: (int, seq[string])): int =
## Comparison function needed to sort the groups.
cmp(a[0], b[0])
func toGroups(records: openArray[Record]): Groups =
## Build a "Groups" table from the records.
for record in records:
result.mgetOrPut(record.score, @[]).add record.name
# Sort the list of names by alphabetic order.
for score in result.keys:
sort(result[score])
# Sort the groups by decreasing score.
result.sort(cmp, Descending)
func standardRanks(groups: Groups): seq[Rank] =
var rank = 1
for score, names in groups.pairs:
for name in names:
result.add (rank, name, score)
inc rank, names.len
func modifiedRanks(groups: Groups): seq[Rank] =
var rank = 0
for score, names in groups.pairs:
inc rank, names.len
for name in names:
result.add (rank, name, score)
func denseRanks(groups: Groups): seq[Rank] =
var rank = 0
for score, names in groups.pairs:
inc rank
for name in names:
result.add (rank, name, score)
func ordinalRanks(groups: Groups): seq[Rank] =
var rank = 0
for score, names in groups.pairs:
for name in names:
inc rank
result.add (rank, name, score)
func fractionalRanks(groups: Groups): seq[FractRank] =
var rank = 1
for score, names in groups.pairs:
let fRank = mean(toSeq(rank..(rank + names.high)))
for name in names:
result.add (fRank, name, score)
inc rank, names.len
when isMainModule:
const Data = [(44, "Solomon"), (42, "Jason"), (42, "Errol"),
(41, "Garry"), (41, "Bernard"), (41, "Barry"), (39, "Stephen")]
let groups = Data.toGroups()
echo "Standard ranking:"
for (rank, name, score) in groups.standardRanks():
echo rank, ": ", name, " ", score
echo()
echo "Modified ranking:"
for (rank, name, score) in groups.modifiedRanks():
echo rank, ": ", name, " ", score
echo()
echo "Dense ranking:"
for (rank, name, score) in groups.denseRanks():
echo rank, ": ", name, " ", score
echo()
echo "Ordinal ranking:"
for (rank, name, score) in groups.ordinalRanks():
echo rank, ": ", name, " ", score
echo()
echo "Fractional ranking:"
for (rank, name, score) in groups.fractionalRanks():
echo rank, ": ", name, " ", score
- Output:
Standard ranking: 1: Solomon 44 2: Errol 42 2: Jason 42 4: Barry 41 4: Bernard 41 4: Garry 41 7: Stephen 39 Modified ranking: 1: Solomon 44 3: Errol 42 3: Jason 42 6: Barry 41 6: Bernard 41 6: Garry 41 7: Stephen 39 Dense ranking: 1: Solomon 44 2: Errol 42 2: Jason 42 3: Barry 41 3: Bernard 41 3: Garry 41 4: Stephen 39 Ordinal ranking: 1: Solomon 44 2: Errol 42 3: Jason 42 4: Barry 41 5: Bernard 41 6: Garry 41 7: Stephen 39 Fractional ranking: 1.0: Solomon 44 2.5: Errol 42 2.5: Jason 42 5.0: Barry 41 5.0: Bernard 41 5.0: Garry 41 7.0: Stephen 39
Without an auxiliary table
But it is possible to do the ranking without an auxiliary table.
import algorithm
type
Record = tuple[score: int; name: string] # Input data.
Rank = tuple[rank: int; name: string; score: int] # Result.
FractRank = tuple[rank: float; name: string; score: int] # Result (fractional).
func cmp(a, b: Record): int =
## Record comparison function (needed for sorting).
result = cmp(b[0], a[0]) # Reverse order.
if result == 0:
result = cmp(a.name, b.name) # Alphabetical order.
func standardRanks(records: openArray[Record]): seq[Rank] =
let records = sorted(records, cmp)
var rank = 1
var currScore = records[0].score
for idx, (score, name) in records:
if score != currScore:
rank = idx + 1
currScore = score
result.add (rank, name, score)
func modifiedRanks(records: openArray[Record]): seq[Rank] =
let records = sorted(records, cmp)
var rank = records.len
var currScore = records[^1].score
for idx in countdown(records.high, 0):
let (score, name) = records[idx]
if score != currScore:
rank = idx + 1
currScore = score
result.add (rank, name, score)
result.reverse()
func denseRanks(records: openArray[Record]): seq[Rank] =
let records = sorted(records, cmp)
var rank = 1
var currScore = records[0].score
for (score, name) in records:
if score != currScore:
inc rank
currScore = score
result.add (rank, name, score)
func ordinalRanks(records: openArray[Record]): seq[Rank] =
let records = sorted(records, cmp)
var rank = 0
for (score, name) in records:
inc rank
result.add (rank, name, score)
func fractionalRanks(records: openArray[Record]): seq[FractRank] =
let records = sorted(records, cmp)
# Build a list of ranks.
var currScore = records[0].score
var sum = 0
var ranks: seq[float]
var count = 0
for idx, record in records:
if record.score == currScore:
inc count
inc sum, idx + 1
else:
ranks.add sum / count
count = 1
currScore = record.score
sum = idx + 1
ranks.add sum / count
# Give a rank to each record.
currScore = records[0].score
var rankIndex = 0
for (score, name) in records:
if score != currScore:
inc rankIndex
currScore = score
result.add (ranks[rankIndex], name, score)
when isMainModule:
const Data = [(44, "Solomon"), (42, "Jason"), (42, "Errol"),
(41, "Garry"), (41, "Bernard"), (41, "Barry"), (39, "Stephen")]
echo "Standard ranking:"
for (rank, name, score) in Data.standardRanks():
echo rank, ": ", name, " ", score
echo()
echo "Modified ranking:"
for (rank, name, score) in Data.modifiedRanks():
echo rank, ": ", name, " ", score
echo()
echo "Dense ranking:"
for (rank, name, score) in Data.denseRanks():
echo rank, ": ", name, " ", score
echo()
echo "Ordinal ranking:"
for (rank, name, score) in Data.ordinalRanks():
echo rank, ": ", name, " ", score
echo()
echo "Fractional ranking:"
for (rank, name, score) in Data.fractionalRanks():
echo rank, ": ", name, " ", score
- Output:
Same output as with other version.
PARI/GP
Replace "2" with "2.0" in fractional
if you prefer decimal to fractional.
standard(v)=v=vecsort(v,1,4); my(last=v[1][1]+1); for(i=1,#v, v[i][1]=if(v[i][1]<last,last=v[i][1]; i, v[i-1][1])); v;
modified(v)=v=vecsort(v,1,4); my(last=v[#v][1]-1); forstep(i=#v,1,-1, v[i][1]=if(v[i][1]>last,last=v[i][1]; i, v[i+1][1])); v;
dense(v)=v=vecsort(v,1,4); my(last=v[1][1]+1,rank); for(i=1,#v, v[i][1]=if(v[i][1]<last,last=v[i][1]; rank++, rank)); v;
ordinal(v)=v=vecsort(v,1,4); for(i=1,#v,v[i][1]=i); v;
fractional(v)=my(a=standard(v),b=modified(v)); vector(#v,i,[(a[i][1]+b[i][1])/2,v[i][2]]);
v=[[44,"Solomon"], [42,"Jason"], [42,"Errol"], [41,"Garry"], [41,"Bernard"], [41,"Barry"], [39,"Stephen"]];
standard(v)
modified(v)
dense(v)
ordinal(v)
fractional(v)
- Output:
%1 = [[1, "Solomon"], [2, "Errol"], [2, "Jason"], [4, "Barry"], [4, "Bernard"], [4, "Garry"], [7, "Stephen"]] %2 = [[1, "Solomon"], [3, "Errol"], [3, "Jason"], [6, "Barry"], [6, "Bernard"], [6, "Garry"], [7, "Stephen"]] %3 = [[1, "Solomon"], [2, "Errol"], [2, "Jason"], [3, "Barry"], [3, "Bernard"], [3, "Garry"], [4, "Stephen"]] %4 = [[1, "Solomon"], [2, "Errol"], [3, "Jason"], [4, "Barry"], [5, "Bernard"], [6, "Garry"], [7, "Stephen"]] %5 = [[1, "Solomon"], [5/2, "Jason"], [5/2, "Errol"], [5, "Garry"], [5, "Bernard"], [5, "Barry"], [7, "Stephen"]]
Perl
my %scores = (
'Solomon' => 44,
'Jason' => 42,
'Errol' => 42,
'Garry' => 41,
'Bernard' => 41,
'Barry' => 41,
'Stephen' => 39
);
sub tiers {
my(%s) = @_; my(%h);
push @{$h{$s{$_}}}, $_ for keys %s;
@{\%h}{reverse sort keys %h};
}
sub standard {
my(%s) = @_; my($result);
my $rank = 1;
for my $players (tiers %s) {
$result .= "$rank " . join(', ', sort @$players) . "\n";
$rank += @$players;
}
return $result;
}
sub modified {
my(%s) = @_; my($result);
my $rank = 0;
for my $players (tiers %s) {
$rank += @$players;
$result .= "$rank " . join(', ', sort @$players) . "\n";
}
return $result;
}
sub dense {
my(%s) = @_; my($n,$result);
$result .= sprintf "%d %s\n", ++$n, join(', ', sort @$_) for tiers %s;
return $result;
}
sub ordinal {
my(%s) = @_; my($n,$result);
for my $players (tiers %s) {
$result .= sprintf "%d %s\n", ++$n, $_ for sort @$players;
}
return $result;
}
sub fractional {
my(%s) = @_; my($result);
my $rank = 1;
for my $players (tiers %s) {
my $beg = $rank;
my $end = $rank += @$players;
my $avg = 0;
$avg += $_/@$players for $beg .. $end-1;
$result .= sprintf "%3.1f %s\n", $avg, join ', ', sort @$players;
}
return $result;
}
print "Standard:\n" . standard(%scores) . "\n";
print "Modified:\n" . modified(%scores) . "\n";
print "Dense:\n" . dense(%scores) . "\n";
print "Ordinal:\n" . ordinal(%scores) . "\n";
print "Fractional:\n" . fractional(%scores) . "\n";
- Output:
Standard: 1 Solomon 2 Errol, Jason 4 Barry, Bernard, Garry 7 Stephen Modified: 1 Solomon 3 Errol, Jason 6 Barry, Bernard, Garry 7 Stephen Dense: 1 Solomon 2 Errol, Jason 3 Barry, Bernard, Garry 4 Stephen Ordinal: 1 Solomon 2 Errol 3 Jason 4 Barry 5 Bernard 6 Garry 7 Stephen Fractional: 1.0 Solomon 2.5 Errol, Jason 5.0 Barry, Bernard, Garry 7.0 Stephen
Phix
with javascript_semantics function ties(sequence scores) sequence t = {}, -- {start,num} pairs tdx = repeat(0,length(scores)) integer last = -1 for i=1 to length(scores) do integer curr = scores[i][1] if curr=last then t[$][2] += 1 else t = append(t,{i,1}) end if tdx[i] = length(t) last = curr end for -- eg {{{1,1},{2,2},{4,3},{7,1}}, -- {1,2,2,3,3,3,4}} return {t,tdx} end function enum STANDARD, -- eg {1,2,2,4,4,4,7} MODIFIED, -- eg {1,3,3,6,6,6,7} DENSE, -- (==tdx) ORDINAL, -- eg {1,2,3,4,5,6,7} FRACTION, -- {1,2.5,2.5,5,5,5,7} METHODS = $ function rank(integer i, method, sequence t, tdx) integer idx = tdx[i], {tx,tn} = t[idx] switch method case STANDARD: return tx case MODIFIED: return tx+tn-1 case DENSE : return idx case ORDINAL : return i case FRACTION: return tx+(tn-1)/2 end switch end function constant scores = {{44, "Solomon"}, {42, "Jason"}, {42, "Errol"}, {41, "Garry"}, {41, "Bernard"}, {41, "Barry"}, {39, "Stephen"}} sequence {t,tdx} = ties(scores) printf(1," score name standard modified dense ordinal fractional\n") for i=1 to length(scores) do sequence ranks = repeat(0,METHODS) for method=1 to METHODS do ranks[method] = rank(i,method,t,tdx) end for printf(1,"%5d %-7s ",scores[i]) printf(1,"%6g %8g %6g %6g %9g\n",ranks) end for
- Output:
score name standard modified dense ordinal fractional 44 Solomon 1 1 1 1 1 42 Jason 2 3 2 2 2.5 42 Errol 2 3 2 3 2.5 41 Garry 4 6 3 4 5 41 Bernard 4 6 3 5 5 41 Barry 4 6 3 6 5 39 Stephen 7 7 4 7 7
PowerShell
function Get-Ranking
{
[CmdletBinding(DefaultParameterSetName="Standard")]
[OutputType([PSCustomObject])]
Param
(
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
[string]
$InputObject,
[Parameter(Mandatory=$false,
ParameterSetName="Standard")]
[switch]
$Standard,
[Parameter(Mandatory=$false,
ParameterSetName="Modified")]
[switch]
$Modified,
[Parameter(Mandatory=$false,
ParameterSetName="Dense")]
[switch]
$Dense,
[Parameter(Mandatory=$false,
ParameterSetName="Ordinal")]
[switch]
$Ordinal,
[Parameter(Mandatory=$false,
ParameterSetName="Fractional")]
[switch]
$Fractional
)
Begin
{
function Get-OrdinalRank ([PSCustomObject[]]$Values)
{
for ($i = 0; $i -lt $Values.Count; $i++)
{
$Values[$i].Rank = $i + 1
}
$Values
}
function Get-Rank ([PSCustomObject[]]$Scores)
{
foreach ($score in $Scores)
{
$score.Group | ForEach-Object {$_.Rank = $score.Rank}
}
$Scores.Group
}
function New-Competitor ([string]$Name, [int]$Score, [int]$Rank = 0)
{
[PSCustomObject]@{
Name = $Name
Score = $Score
Rank = $Rank
}
}
$competitors = @()
$scores = @()
}
Process
{
@($input) | ForEach-Object {$competitors += New-Competitor -Name $_.Split()[1] -Score $_.Split()[0]}
}
End
{
$scores = $competitors |
Sort-Object -Property Score -Descending |
Group-Object -Property Score |
Select-Object -Property @{Name="Score"; Expression={[int]$_.Name}}, @{Name="Rank"; Expression={0}}, Count, Group
switch ($PSCmdlet.ParameterSetName)
{
"Standard"
{
$rank = 1
for ($i = 0; $i -lt $scores.Count; $i++)
{
$scores[$i].Rank = $rank
$rank += $scores[$i].Count
}
Get-Rank $scores
}
"Modified"
{
$rank = 0
foreach ($score in $scores)
{
$rank = $score.Count + $rank
$score.Rank = $rank
}
Get-Rank $scores
}
"Dense"
{
for ($i = 0; $i -lt $scores.Count; $i++)
{
$scores[$i].Rank = $i + 1
}
Get-Rank $scores
}
"Ordinal"
{
Get-OrdinalRank $competitors
}
"Fractional"
{
Get-OrdinalRank $competitors | Group-Object -Property Score | ForEach-Object {
if ($_.Count -gt 1)
{
$rank = ($_.Group.Rank | Measure-Object -Average).Average
foreach ($competitor in $_.Group)
{
$competitor.Rank = $rank
}
}
}
$competitors
}
}
}
}
$scores = "44 Solomon","42 Jason","42 Errol","41 Garry","41 Bernard","41 Barry","39 Stephen"
$scores | Get-Ranking -Standard
- Output:
Name Score Rank ---- ----- ---- Solomon 44 1 Jason 42 2 Errol 42 2 Garry 41 4 Bernard 41 4 Barry 41 4 Stephen 39 7
$scores | Get-Ranking -Modified
- Output:
Name Score Rank ---- ----- ---- Solomon 44 1 Jason 42 3 Errol 42 3 Garry 41 6 Bernard 41 6 Barry 41 6 Stephen 39 7
$scores | Get-Ranking -Dense
- Output:
Name Score Rank ---- ----- ---- Solomon 44 1 Jason 42 2 Errol 42 2 Garry 41 3 Bernard 41 3 Barry 41 3 Stephen 39 4
$scores | Get-Ranking -Ordinal
- Output:
Name Score Rank ---- ----- ---- Solomon 44 1 Jason 42 2 Errol 42 3 Garry 41 4 Bernard 41 5 Barry 41 6 Stephen 39 7
$scores | Get-Ranking -Fractional
- Output:
Name Score Rank ---- ----- ---- Solomon 44 1 Jason 42 2.5 Errol 42 2.5 Garry 41 5 Bernard 41 5 Barry 41 5 Stephen 39 7
Python
def mc_rank(iterable, start=1):
"""Modified competition ranking"""
lastresult, fifo = None, []
for n, item in enumerate(iterable, start-1):
if item[0] == lastresult:
fifo += [item]
else:
while fifo:
yield n, fifo.pop(0)
lastresult, fifo = item[0], fifo + [item]
while fifo:
yield n+1, fifo.pop(0)
def sc_rank(iterable, start=1):
"""Standard competition ranking"""
lastresult, lastrank = None, None
for n, item in enumerate(iterable, start):
if item[0] == lastresult:
yield lastrank, item
else:
yield n, item
lastresult, lastrank = item[0], n
def d_rank(iterable, start=1):
"""Dense ranking"""
lastresult, lastrank = None, start - 1,
for item in iterable:
if item[0] == lastresult:
yield lastrank, item
else:
lastresult, lastrank = item[0], lastrank + 1
yield lastrank, item
def o_rank(iterable, start=1):
"""Ordinal ranking"""
yield from enumerate(iterable, start)
def f_rank(iterable, start=1):
"""Fractional ranking"""
last, fifo = None, []
for n, item in enumerate(iterable, start):
if item[0] != last:
if fifo:
mean = sum(f[0] for f in fifo) / len(fifo)
while fifo:
yield mean, fifo.pop(0)[1]
last = item[0]
fifo.append((n, item))
if fifo:
mean = sum(f[0] for f in fifo) / len(fifo)
while fifo:
yield mean, fifo.pop(0)[1]
if __name__ == '__main__':
scores = [(44, 'Solomon'),
(42, 'Jason'),
(42, 'Errol'),
(41, 'Garry'),
(41, 'Bernard'),
(41, 'Barry'),
(39, 'Stephen')]
print('\nScores to be ranked (best first):')
for s in scores:
print(' %2i %s' % (s ))
for ranker in [sc_rank, mc_rank, d_rank, o_rank, f_rank]:
print('\n%s:' % ranker.__doc__)
for rank, score in ranker(scores):
print(' %3g, %r' % (rank, score))
- Output:
Scores to be ranked (best first): 44 Solomon 42 Jason 42 Errol 41 Garry 41 Bernard 41 Barry 39 Stephen Standard competition ranking: 1, (44, 'Solomon') 2, (42, 'Jason') 2, (42, 'Errol') 4, (41, 'Garry') 4, (41, 'Bernard') 4, (41, 'Barry') 7, (39, 'Stephen') Modified competition ranking: 1, (44, 'Solomon') 3, (42, 'Jason') 3, (42, 'Errol') 6, (41, 'Garry') 6, (41, 'Bernard') 6, (41, 'Barry') 7, (39, 'Stephen') Dense ranking: 1, (44, 'Solomon') 2, (42, 'Jason') 2, (42, 'Errol') 3, (41, 'Garry') 3, (41, 'Bernard') 3, (41, 'Barry') 4, (39, 'Stephen') Ordinal ranking: 1, (44, 'Solomon') 2, (42, 'Jason') 3, (42, 'Errol') 4, (41, 'Garry') 5, (41, 'Bernard') 6, (41, 'Barry') 7, (39, 'Stephen') Fractional ranking: 1, (44, 'Solomon') 2.5, (42, 'Jason') 2.5, (42, 'Errol') 5, (41, 'Garry') 5, (41, 'Bernard') 5, (41, 'Barry') 7, (39, 'Stephen')
Racket
#lang racket
;; Tim-brown 2014-09-11
;; produces a ranking according to ranking function: rfn
;; INPUT:
;; lst : (list (score . details))
;; rfn : (length-scores)
;; -> (values
;; ranks-added ; how many ranks to add for the next iteration
;; (idx . rest -> rank-offset)) ; function that produces the rank for the idx^th element
;; ; in the scoring (arity must be >= 1)
(define (rank-list all-scores rfn)
(let loop ((rank-0 0) (lst (sort all-scores > #:key car)) (acc empty))
(cond
[(null? lst) acc]
[else
(define 1st-score (caar lst))
(define (ties-with-1st? cand) (= (car cand) 1st-score))
(define-values (tied unranked) (splitf-at lst ties-with-1st?))
;; all ranking functions should properly handle a singleton tied list
(define tied-len (length tied))
(define tied? (> tied-len 1))
(define-values (ranks-added rank-offset-fn) (rfn tied-len))
(define ranked-tied (for/list ((t (in-list tied)) (i (in-naturals 1)))
(list* tied? (+ rank-0 (rank-offset-fn i)) t)))
(loop (+ ranks-added rank-0) unranked (append acc ranked-tied))])))
;; Ties share what would have been their first ordinal number
(define (rank-function:Standard l)
(values l (thunk* 1)))
;; Ties share what would have been their last ordinal number
(define (rank-function:Modified l)
(values l (thunk* l)))
;; Ties share the next available integer
(define (rank-function:Dense l)
(values 1 (thunk* 1)))
;; Competitors take the next available integer. Ties are not treated otherwise
(define (rank-function:Ordinal l)
(values l (λ (n . _) n)))
;; Ties share the mean of what would have been their ordinal numbers
(define (rank-function:Fractional l)
(values l (thunk* (/ (+ l 1) 2))))
(define score-board
'((44 . Solomon)
(42 . Jason)
(42 . Errol)
(41 . Garry)
(41 . Bernard)
(41 . Barry)
(39 . Stephen)))
(define format-number
(match-lambda
[(? integer? i) i]
[(and f (app numerator n) (app denominator d))
(define-values (q r) (quotient/remainder n d))
(format "~a ~a/~a" q r d)]))
(for ((fn (list
rank-function:Standard
rank-function:Modified
rank-function:Dense
rank-function:Ordinal
rank-function:Fractional)))
(printf "Function: ~s~%" fn)
(for ((r (in-list (rank-list score-board fn))))
(printf "~a ~a\t~a\t~a~%"
(if (car r) "=" " ")
(format-number (cadr r))
(caddr r)
(cdddr r)))
(newline))
- Output:
Function: #<procedure:rank-function:Standard> 1 44 Solomon = 2 42 Jason = 2 42 Errol = 4 41 Garry = 4 41 Bernard = 4 41 Barry 7 39 Stephen Function: #<procedure:rank-function:Modified> 1 44 Solomon = 3 42 Jason = 3 42 Errol = 6 41 Garry = 6 41 Bernard = 6 41 Barry 7 39 Stephen Function: #<procedure:rank-function:Dense> 1 44 Solomon = 2 42 Jason = 2 42 Errol = 3 41 Garry = 3 41 Bernard = 3 41 Barry 4 39 Stephen Function: #<procedure:rank-function:Ordinal> 1 44 Solomon = 2 42 Jason = 3 42 Errol = 4 41 Garry = 5 41 Bernard = 6 41 Barry 7 39 Stephen Function: #<procedure:rank-function:Fractional> 1 44 Solomon = 2 1/2 42 Jason = 2 1/2 42 Errol = 5 41 Garry = 5 41 Bernard = 5 41 Barry 7 39 Stephen
Raku
(formerly Perl 6)
my @scores =
Solomon => 44,
Jason => 42,
Errol => 42,
Garry => 41,
Bernard => 41,
Barry => 41,
Stephen => 39;
sub tiers (@s) { @s.classify(*.value).pairs.sort.reverse.map: { .value».key } }
sub standard (@s) {
my $rank = 1;
gather for tiers @s -> @players {
take $rank => @players;
$rank += @players;
}
}
sub modified (@s) {
my $rank = 0;
gather for tiers @s -> @players {
$rank += @players;
take $rank => @players;
}
}
sub dense (@s) { tiers(@s).map: { ++$_ => @^players } }
sub ordinal (@s) { @s.map: ++$_ => *.key }
sub fractional (@s) {
my $rank = 1;
gather for tiers @s -> @players {
my $beg = $rank;
my $end = $rank += @players;
take [+]($beg ..^ $end) / @players => @players;
}
}
say "Standard:"; .perl.say for standard @scores;
say "\nModified:"; .perl.say for modified @scores;
say "\nDense:"; .perl.say for dense @scores;
say "\nOrdinal:"; .perl.say for ordinal @scores;
say "\nFractional:"; .perl.say for fractional @scores;
- Output:
Standard: 1 => ["Solomon"] 2 => ["Jason", "Errol"] 4 => ["Garry", "Bernard", "Barry"] 7 => ["Stephen"] Modified: 1 => ["Solomon"] 3 => ["Jason", "Errol"] 6 => ["Garry", "Bernard", "Barry"] 7 => ["Stephen"] Dense: 1 => ["Solomon"] 2 => ["Jason", "Errol"] 3 => ["Garry", "Bernard", "Barry"] 4 => ["Stephen"] Ordinal: 1 => "Solomon" 2 => "Jason" 3 => "Errol" 4 => "Garry" 5 => "Bernard" 6 => "Barry" 7 => "Stephen" Fractional: 1.0 => ["Solomon"] 2.5 => ["Jason", "Errol"] 5.0 => ["Garry", "Bernard", "Barry"] 7.0 => ["Stephen"]
REXX
/**************************
44 Solomon 1 1 1 1 1
42 Jason 2 3 2 2 2.5
42 Errol 2 3 2 3 2.5
41 Garry 4 6 3 4 5
41 Bernard 4 6 3 5 5
41 Barry 4 6 3 6 5
39 Stephen 7 7 4 7 7
**************************/
Do i=1 To 7
Parse Value sourceline(i+1) With rank.i name.i .
/* say rank.i name.i */
End
pool=0
crank=0
Do i=1 To 7
If rank.i<>crank Then Do
pool=pool+1
lo.pool=i
hi.pool=i
n.pool=1
ii.pool=i
End
Else Do
n.pool=n.pool+1
hi.pool=i
ii.pool=ii.pool+i
End
crank=rank.i
pool.i=pool
End
/*
Do j=1 To pool
Say 'pool' j n.j lo.j hi.j
End
*/
cp=0
r=0
cnt.=0
Do i=1 To 7
p=pool.i
If p<>cp Then
r=r+1
res=rank.i left(name.i,8) lo.p hi.p r i ii.p/n.p
If res=sourceline(i+1) Then cnt.ok=cnt.ok+1
Say res
cp=p
End
Say cnt.ok 'correct lines'
- Output:
44 Solomon 1 1 1 1 1 42 Jason 2 3 2 2 2.5 42 Errol 2 3 2 3 2.5 41 Garry 4 6 3 4 5 41 Bernard 4 6 3 5 5 41 Barry 4 6 3 6 5 39 Stephen 7 7 4 7 7 7 correct lines
Ruby
ar = "44 Solomon
42 Jason
42 Errol
41 Garry
41 Bernard
41 Barry
39 Stephen".lines.map{|line| line.split}
grouped = ar.group_by{|pair| pair.shift.to_i}
s_rnk = 1
m_rnk = o_rnk = 0
puts "stand.\tmod.\tdense\tord.\tfract."
grouped.each.with_index(1) do |(score, names), d_rnk|
m_rnk += names.flatten!.size
f_rnk = (s_rnk + m_rnk)/2.0
names.each do |name|
o_rnk += 1
puts "#{s_rnk}\t#{m_rnk}\t#{d_rnk}\t#{o_rnk}\t#{f_rnk.to_s.sub(".0","")}\t#{score} #{name}"
end
s_rnk += names.size
end
- Output:
stand. mod. dense ord. fract. 1 1 1 1 1 44 Solomon 2 3 2 2 2.5 42 Jason 2 3 2 3 2.5 42 Errol 4 6 3 4 5 41 Garry 4 6 3 5 5 41 Bernard 4 6 3 6 5 41 Barry 7 7 4 7 7 39 Stephen
Scala
This example uses a type-safe singly-linked object model with no mutable state variables, which makes it longer than the Ruby version above, but demonstrates an object-oriented functional programming approach.
object RankingMethods extends App {
case class Score(score: Int, name: String) // incoming data
case class Rank[Precision](rank: Precision, names: List[String]) // outgoing results (can be int or double)
case class State[Precision](n: Int, done: List[Rank[Precision]]) { // internal state, no mutable variables
def next(n: Int, next: Rank[Precision]) = State(n, next :: done)
}
def grouped[Precision](list: List[Score]) = // group names together by score, with highest first
(scala.collection.immutable.TreeMap[Int, List[Score]]() ++ list.groupBy(-_.score))
.values.map(_.map(_.name)).foldLeft(State[Precision](1, Nil)) _
// Ranking methods:
def rankStandard(list: List[Score]) =
grouped[Int](list){case (state, names) => state.next(state.n+names.length, Rank(state.n, names))}.done.reverse
def rankModified(list: List[Score]) =
rankStandard(list).map(r => Rank(r.rank+r.names.length-1, r.names))
def rankDense(list: List[Score]) =
grouped[Int](list){case (state, names) => state.next(state.n+1, Rank(state.n, names))}.done.reverse
def rankOrdinal(list: List[Score]) =
list.zipWithIndex.map{case (score, n) => Rank(n+1, List(score.name))}
def rankFractional(list: List[Score]) =
rankStandard(list).map(r => Rank((2*r.rank+r.names.length-1.0)/2, r.names))
// Tests:
def parseScores(s: String) = s split "\\s+" match {case Array(s,n) => Score(s.toInt, n)}
val test = List("44 Solomon", "42 Jason", "42 Errol", "41 Garry", "41 Bernard", "41 Barry", "39 Stephen").map(parseScores)
println("Standard:")
println(rankStandard(test) mkString "\n")
println("\nModified:")
println(rankModified(test) mkString "\n")
println("\nDense:")
println(rankDense(test) mkString "\n")
println("\nOrdinal:")
println(rankOrdinal(test) mkString "\n")
println("\nFractional:")
println(rankFractional(test) mkString "\n")
}
- Output:
Standard: Rank(1,List(Solomon)) Rank(2,List(Jason, Errol)) Rank(4,List(Garry, Bernard, Barry)) Rank(7,List(Stephen)) Modified: Rank(1,List(Solomon)) Rank(3,List(Jason, Errol)) Rank(6,List(Garry, Bernard, Barry)) Rank(7,List(Stephen)) Dense: Rank(1,List(Solomon)) Rank(2,List(Jason, Errol)) Rank(3,List(Garry, Bernard, Barry)) Rank(4,List(Stephen)) Ordinal: Rank(1,List(Solomon)) Rank(2,List(Jason)) Rank(3,List(Errol)) Rank(4,List(Garry)) Rank(5,List(Bernard)) Rank(6,List(Barry)) Rank(7,List(Stephen)) Fractional: Rank(1.0,List(Solomon)) Rank(2.5,List(Jason, Errol)) Rank(5.0,List(Garry, Bernard, Barry)) Rank(7.0,List(Stephen))
Sidef
var scores = [
Pair(Solomon => 44),
Pair(Jason => 42),
Pair(Errol => 42),
Pair(Garry => 41),
Pair(Bernard => 41),
Pair(Barry => 41),
Pair(Stephen => 39),
]
func tiers(s) {
s.group_by { .value }.kv.sort.flip.map { .value.map{.key} }
}
func standard(s) {
var rank = 1
gather {
for players in tiers(s) {
take(Pair(rank, players))
rank += players.len
}
}
}
func modified(s) {
var rank = 0
gather {
for players in tiers(s) {
rank += players.len
take(Pair(rank, players))
}
}
}
func dense(s) {
tiers(s).map_kv { |k,v| Pair(k+1, v) }
}
func ordinal(s) {
s.map_kv { |k,v| Pair(k+1, v.key) }
}
func fractional(s) {
var rank = 1
gather {
for players in tiers(s) {
var beg = rank
var end = (rank += players.len)
take(Pair(sum(beg ..^ end) / players.len, players))
}
}
}
func display(r) {
say r.map {|a| '%3s : %s' % a... }.join("\n")
}
say "Standard:"; display( standard(scores))
say "\nModified:"; display( modified(scores))
say "\nDense:"; display( dense(scores))
say "\nOrdinal:"; display( ordinal(scores))
say "\nFractional:"; display(fractional(scores))
- Output:
Standard: 1 : ["Solomon"] 2 : ["Jason", "Errol"] 4 : ["Garry", "Bernard", "Barry"] 7 : ["Stephen"] Modified: 1 : ["Solomon"] 3 : ["Jason", "Errol"] 6 : ["Garry", "Bernard", "Barry"] 7 : ["Stephen"] Dense: 1 : ["Solomon"] 2 : ["Jason", "Errol"] 3 : ["Garry", "Bernard", "Barry"] 4 : ["Stephen"] Ordinal: 1 : Solomon 2 : Jason 3 : Errol 4 : Garry 5 : Bernard 6 : Barry 7 : Stephen Fractional: 1 : ["Solomon"] 2.5 : ["Jason", "Errol"] 5 : ["Garry", "Bernard", "Barry"] 7 : ["Stephen"]
Tcl
proc rank {rankingMethod sortedList} {
# Extract the groups in the data (this is pointless for ordinal...)
set s [set group [set groups {}]]
foreach {score who} $sortedList {
if {$score != $s} {
lappend groups [llength $group]
set s $score
set group {}
}
lappend group $who
}
lappend groups [llength $group]
# Construct the rankings; note that we have a zero-sized leading group
set n 1; set m 0
foreach g $groups {
switch $rankingMethod {
standard {
lappend result {*}[lrepeat $g $n]
incr n $g
}
modified {
lappend result {*}[lrepeat $g [incr m $g]]
}
dense {
lappend result {*}[lrepeat $g $m]
incr m
}
ordinal {
for {set i 0} {$i < $g} {incr i} {
lappend result [incr m]
}
}
fractional {
set val [expr {($n + [incr n $g] - 1) / 2.0}]
lappend result {*}[lrepeat $g [format %g $val]]
}
}
}
return $result
}
set data {
44 Solomon
42 Jason
42 Errol
41 Garry
41 Bernard
41 Barry
39 Stephen
}
foreach method {standard modified dense ordinal fractional} {
puts "Using method '$method'...\n Rank\tScore\tWho"
foreach rank [rank $method $data] {score who} $data {
puts " $rank\t$score\t$who"
}
}
- Output:
Using method 'standard'... Rank Score Who 1 44 Solomon 2 42 Jason 2 42 Errol 4 41 Garry 4 41 Bernard 4 41 Barry 7 39 Stephen Using method 'modified'... Rank Score Who 1 44 Solomon 3 42 Jason 3 42 Errol 6 41 Garry 6 41 Bernard 6 41 Barry 7 39 Stephen Using method 'dense'... Rank Score Who 1 44 Solomon 2 42 Jason 2 42 Errol 3 41 Garry 3 41 Bernard 3 41 Barry 4 39 Stephen Using method 'ordinal'... Rank Score Who 1 44 Solomon 2 42 Jason 3 42 Errol 4 41 Garry 5 41 Bernard 6 41 Barry 7 39 Stephen Using method 'fractional'... Rank Score Who 1 44 Solomon 2.5 42 Jason 2.5 42 Errol 5 41 Garry 5 41 Bernard 5 41 Barry 7 39 Stephen
True BASIC
LET n = 7
DIM puntos(7), ptosnom(7), nombre$(7)
SUB MostarTabla
FOR i = 1 to n
PRINT str$(ptosnom(i)); " "; puntos(i); " "; nombre$(i)
NEXT i
PRINT
END SUB
PRINT "Puntuaciones a clasificar (mejores primero):"
FOR i = 1 to n
READ puntos(i), nombre$(i)
PRINT " "; puntos(i); " "; nombre$(i)
NEXT i
PRINT
PRINT "--- Standard ranking ---"
LET ptosnom(1) = 1
FOR i = 2 to n
NEXT i
CALL MostarTabla
PRINT "--- Modified ranking ---"
LET ptosnom(n) = n
FOR i = n-1 to 1 step -1
IF puntos(i) = puntos(i+1) then LET ptosnom(i) = ptosnom(i+1) else LET ptosnom(i) = i
NEXT i
CALL MostarTabla
PRINT "--- Ordinal ranking ---"
FOR i = 1 to n
LET ptosnom(i) = i
NEXT i
CALL MostarTabla
PRINT "--- Fractional ranking ---"
LET i = 1
LET j = 2
DO
IF j <= n then
IF (puntos(j-1) = puntos(j)) then
LET j = j + 1
END IF
END IF
FOR k = i to j-1
LET ptosnom(k) = (i+j-1) / 2
NEXT k
LET i = j
LET j = j + 1
LOOP UNTIL i > n
CALL MOSTARTABLA
DATA 44, "Solomon", 42, "Jason", 42, "Errol", 41, "Garry", 41, "Bernard", 41, "Barry", 39, "Stephen"
END
Visual FoxPro
#DEFINE CTAB CHR(9)
#DEFINE CRLF CHR(13) + CHR(10)
LOCAL lcTxt As String, i As Integer
CLOSE DATABASES ALL
SET SAFETY OFF
CLEAR
CREATE CURSOR scores (score I, name V(8), rownum I AUTOINC)
INDEX ON score TAG score COLLATE "Machine"
SET ORDER TO 0
INSERT INTO scores (score, name) VALUES (44, "Solomon")
INSERT INTO scores (score, name) VALUES (42, "Jason")
INSERT INTO scores (score, name) VALUES (42, "Errol")
INSERT INTO scores (score, name) VALUES (41, "Garry")
INSERT INTO scores (score, name) VALUES (41, "Bernard")
INSERT INTO scores (score, name) VALUES (41, "Barry")
INSERT INTO scores (score, name) VALUES (39, "Stephen")
CREATE CURSOR ranks (sc_rank I, mod_rank I, dense I, ordinal I, fractional B(1), score I, name V(8))
INDEX ON score TAG score COLLATE "Machine"
SET ORDER TO 0
APPEND FROM DBF("scores") FIELDS score, name
Std_Comp()
Modified()
Dense()
Ordinal()
Fractional()
COPY TO ranks.txt TYPE DELIMITED WITH TAB
lcTxt = ""
FOR i = 1 TO FCOUNT()
lcTxt = lcTxt + FIELD(i) + CTAB
ENDFOR
lcTxt = LEFT(lcTxt, LEN(lcTxt) - 1) + CRLF + FILETOSTR("ranks.txt")
STRTOFILE(lcTxt, "ranks.txt")
MODIFY FILE ranks.txt
SET SAFETY ON
FUNCTION ScoreGroup(aa)
LOCAL n As Integer
SELECT score, COUNT(*) As num FROM scores ;
GROUP BY score ORDER BY score DESC INTO ARRAY aa
n = _TALLY
RETURN n
ENDFUNC
PROCEDURE Std_Comp
LOCAL n, i, nn
LOCAL ARRAY a[1]
SELECT ranks
BLANK FIELDS sc_rank ALL
nn = ScoreGroup(@a)
n = 1
FOR i = 1 TO nn
REPLACE sc_rank WITH n FOR score = a[i,1]
n = n + a[i,2]
ENDFOR
ENDPROC
PROCEDURE Modified
LOCAL n, i, nn
LOCAL ARRAY a[1]
SELECT ranks
BLANK FIELDS mod_rank ALL
nn = ScoreGroup(@a)
n = 0
FOR i = 1 TO nn
n = n + a[i,2]
REPLACE mod_rank WITH n FOR score = a[i,1]
ENDFOR
ENDPROC
PROCEDURE Dense
LOCAL n, i, nn
LOCAL ARRAY a[1]
SELECT ranks
BLANK FIELDS dense ALL
nn = ScoreGroup(@a)
SELECT ranks
n = 0
FOR i = 1 TO nn
n = n + a[i,2]
REPLACE dense WITH i FOR score = a[i,1]
ENDFOR
ENDPROC
PROCEDURE Ordinal
SELECT ranks
BLANK FIELDS ordinal ALL
REPLACE ordinal WITH RECNO() ALL
ENDPROC
PROCEDURE Fractional
LOCAL i As Integer, nn As Integer
LOCAL ARRAY a[1]
SELECT ranks
BLANK FIELDS fractional ALL
SELECT CAST(AVG(rownum) As B(1)), score FROM scores ;
GROUP BY score ORDER BY score DESC INTO ARRAY a
nn = _TALLY
FOR i = 1 TO nn
REPLACE fractional WITH a[i,1] FOR score = a[i,2]
ENDFOR
ENDPROC
- Output:
SC_RANK MOD_RANK DENSE ORDINAL FRACTIONAL SCORE NAME 1 1 1 1 1.0 44 "Solomon" 2 3 2 2 2.5 42 "Jason" 2 3 2 3 2.5 42 "Errol" 4 6 3 4 5.0 41 "Garry" 4 6 3 5 5.0 41 "Bernard" 4 6 3 6 5.0 41 "Barry" 7 7 4 7 7.0 39 "Stephen"
Wren
import "./math" for Nums
import "./fmt" for Fmt
/* all ranking functions assume the array of Pairs is non-empty and already sorted
by decreasing order of scores and then, if the scores are equal, by reverse
alphabetic order of names
*/
var standardRanking = Fn.new { |scores|
var rankings = List.filled(scores.count, 0)
rankings[0] = 1
for (i in 1...scores.count) {
rankings[i] = (scores[i][0] == scores[i-1][0]) ? rankings[i-1] : i + 1
}
return rankings
}
var modifiedRanking = Fn.new { |scores|
var rankings = List.filled(scores.count, 0)
rankings[0] = 1
for (i in 1...scores.count) {
rankings[i] = i + 1
var currScore = scores[i][0]
for (j in i-1..0) {
if (currScore != scores[j][0]) break
rankings[j] = i + 1
}
}
return rankings
}
var denseRanking = Fn.new { |scores|
var rankings = List.filled(scores.count, 0)
rankings[0] = 1
var prevRanking = 1
for (i in 1...scores.count) {
rankings[i] = (scores[i][0] == scores[i-1][0]) ? prevRanking : (prevRanking = prevRanking+1)
}
return rankings
}
var ordinalRanking = Fn.new { |scores| (1..scores.count).toList }
var fractionalRanking = Fn.new { |scores|
var rankings = List.filled(scores.count, 0)
rankings[0] = 1
for (i in 1...scores.count) {
var k = i
var currScore = scores[i][0]
for (j in i-1..0) {
if (currScore != scores[j][0]) break
k = j
}
var avg = Nums.mean(k..i) + 1
for (m in k..i) rankings[m] = avg
}
return rankings
}
var printRankings = Fn.new { |title, rankings, scores|
System.print(title + ":")
for (i in 0...rankings.count) {
System.print("%(rankings[i]) %(scores[i][0]) %(scores[i][1])")
}
System.print()
}
var printFractionalRankings = Fn.new { |title, rankings, scores|
System.print(title + ":")
for (i in 0...rankings.count) {
Fmt.print("$3.2f $d $s", rankings[i], scores[i][0], scores[i][1])
}
System.print()
}
var scores = [[44, "Solomon"], [42, "Jason"], [42, "Errol"], [41, "Garry"],
[41, "Bernard"], [41, "Barry"], [39, "Stephen"]]
printRankings.call("Standard ranking", standardRanking.call(scores), scores)
printRankings.call("Modified ranking", modifiedRanking.call(scores), scores)
printRankings.call("Dense ranking", denseRanking.call(scores), scores)
printRankings.call("Ordinal ranking", ordinalRanking.call(scores), scores)
printFractionalRankings.call("Fractional ranking", fractionalRanking.call(scores), scores)
- Output:
Standard ranking: 1 44 Solomon 2 42 Jason 2 42 Errol 4 41 Garry 4 41 Bernard 4 41 Barry 7 39 Stephen Modified ranking: 1 44 Solomon 3 42 Jason 3 42 Errol 6 41 Garry 6 41 Bernard 6 41 Barry 7 39 Stephen Dense ranking: 1 44 Solomon 2 42 Jason 2 42 Errol 3 41 Garry 3 41 Bernard 3 41 Barry 4 39 Stephen Ordinal ranking: 1 44 Solomon 2 42 Jason 3 42 Errol 4 41 Garry 5 41 Bernard 6 41 Barry 7 39 Stephen Fractional ranking: 1.00 44 Solomon 2.50 42 Jason 2.50 42 Errol 5.00 41 Garry 5.00 41 Bernard 5.00 41 Barry 7.00 39 Stephen
Yabasic
n = 7
dim puntos(7), ptosnom(7), nombre$(7)
sub MostarTabla()
for i = 1 to n
print str$(ptosnom(i)), " ", puntos(i), " ", nombre$(i)
next i
print
end sub
print "Puntuaciones a clasificar (mejores primero):"
for i = 1 to n
read puntos(i), nombre$(i)
print " ", puntos(i), " ", nombre$(i)
next i
print
print "--- Standard ranking ---"
ptosnom(1) = 1
for i = 2 to n
if puntos(i) = puntos(i-1) then ptosnom(i) = ptosnom(i-1) else ptosnom(i) = i : fi
next i
MostarTabla()
print "--- Modified ranking ---"
ptosnom(n) = n
for i = n-1 to 1 step -1
if puntos(i) = puntos(i+1) then ptosnom(i) = ptosnom(i+1) else ptosnom(i) = i : fi
next i
MostarTabla()
print "--- Ordinal ranking ---"
for i = 1 to n
ptosnom(i) = i
next i
MostarTabla()
print "--- Fractional ranking ---"
i = 1
j = 2
repeat
if j <= n then
if (puntos(j-1) = puntos(j)) then j = j + 1 : fi
end if
for k = i to j-1
ptosnom(k) = (i+j-1) / 2
next k
i = j
j = j + 1
until i > n
MostarTabla()
data 44, "Solomon", 42, "Jason", 42, "Errol", 41, "Garry", 41, "Bernard", 41, "Barry", 39, "Stephen"
end
zkl
fcn group(scores){ // group like scores into one list --> list of lists
sink:=List();
scores.reduce('wrap(ps,sn,buf){
if(sn[0]!=ps){ sink.append(buf.copy()); buf.clear(); }
buf+sn;
sn[0];
},scores[0][0],buf:=List());
sink.append(buf);
}
fcn print(list,rank){
list.apply2('wrap(sn){ "%2s: %s (%d)".fmt(rank,sn[1],sn[0]):println(_); });
}
fcn rankViaStandard(scores){
rank:=1;
foreach group in (group(scores)){ print(group,rank); rank+=group.len(); }
}
fcn rankViaModified(scores){
rank:=0;
foreach group in (group(scores)){ rank+=group.len(); print(group,rank); }
}
fcn rankViaDense(scores){
rank:=1;
foreach group in (group(scores)){ print(group,rank); rank+=1; }
}
fcn rankViaOrdinal(scores){
scores.apply2('wrap(sn,rr){ "%2s: %s (%d)".fmt(rr.inc(),sn[1],sn[0]):println(_); },Ref(1));
}
fcn rankViaFractional(scores){
rank:=1;
foreach group in (group(scores)){
n:=group.len(); r:=rank.reduce(n,'+,0.0)/n; rank+=n;
print(group,"%5.2f".fmt(r));
}
}
// these are sorted!?!
scores:=T(T(44,"Solomon"), T(42,"Jason"), T(42,"Errol"), T(41,"Garry"),
T(41,"Bernard"),T(41,"Barry"),T(39,"Stephen"),);
"Standard:" .println(); rankViaStandard(scores);
"Modified:" .println(); rankViaModified(scores);
"Dense:" .println(); rankViaDense(scores);
"Ordinal:" .println(); rankViaOrdinal(scores);
"Fractional:".println(); rankViaFractional(scores);
- Output:
Standard: 1: Solomon (44) 2: Jason (42) 2: Errol (42) 4: Garry (41) 4: Bernard (41) 4: Barry (41) 7: Stephen (39) Modified: 1: Solomon (44) 3: Jason (42) 3: Errol (42) 6: Garry (41) 6: Bernard (41) 6: Barry (41) 7: Stephen (39) Dense: 1: Solomon (44) 2: Jason (42) 2: Errol (42) 3: Garry (41) 3: Bernard (41) 3: Barry (41) 4: Stephen (39) Ordinal: 1: Solomon (44) 2: Jason (42) 3: Errol (42) 4: Garry (41) 5: Bernard (41) 6: Barry (41) 7: Stephen (39) Fractional: 1.00: Solomon (44) 2.50: Jason (42) 2.50: Errol (42) 5.00: Garry (41) 5.00: Bernard (41) 5.00: Barry (41) 7.00: Stephen (39)
- Programming Tasks
- Sorting Algorithms
- Sorting
- 11l
- ALGOL 68
- AppleScript
- AutoHotkey
- APL
- AWK
- BASIC
- C
- C sharp
- C++
- Cowgol
- D
- Elixir
- Factor
- FreeBASIC
- Go
- Haskell
- J
- Java
- JavaScript
- Jq
- Julia
- Kotlin
- Ksh
- M2000 Interpreter
- Mathematica
- Wolfram Language
- Modula-2
- Nim
- PARI/GP
- Perl
- Phix
- PowerShell
- Python
- Racket
- Raku
- REXX
- Ruby
- Scala
- Sidef
- Tcl
- True BASIC
- Visual FoxPro
- Wren
- Wren-math
- Wren-fmt
- Yabasic
- Zkl