Ranking methods: Difference between revisions
(Improve description) |
(J) |
||
Line 185: | Line 185: | ||
C:\Users\RC\Code></pre> |
C:\Users\RC\Code></pre> |
||
=={{header|J}}== |
|||
Implementation: |
|||
<lang J>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,.]'</lang> |
|||
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: |
|||
<lang J> 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│ |
|||
└───┴──┴───────┘</lang> |
|||
=={{header|Python}}== |
=={{header|Python}}== |
Revision as of 03:39, 18 August 2014
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
Create functions/methods/procedures/subroutines... that apply one, each, of the following ranking methods 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.
AWK
This uses separate files for each method of ranking: <lang awk>##
- 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()} </lang>
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>
J
Implementation:
<lang J>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,.]'</lang>
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:
<lang J> 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│ └───┴──┴───────┘</lang>
Python
<lang 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))</lang>
- 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')