Ranking methods

From Rosetta Code
Revision as of 17:29, 5 July 2014 by rosettacode>Paddy3118 (→‎{{header|Python}}: f_rank without use of name: first.)
Ranking methods is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

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:

  1. Standard.
  2. Modified.
  3. Dense.
  4. Ordinal.
  5. Fractional.

Show here, on this page, the ranking of the test scores under each of the numbered ranking methods.

Python

<lang python>def mc_rank(iterable, start=1):

   """Modified competition ranking"""
   lastresult, lastrank, fifo = None, None, []
   for n, item in enumerate(iterable, start-1):
       if item[0] == lastresult:
           fifo += [item]
       else:
           while fifo:
               yield n, fifo.pop(0)
           lastresult, lastrank, fifo = item[0], n, 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)
       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)


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, (1, (44, 'Solomon'))
  2.5, (2, (42, 'Jason'))
  2.5, (3, (42, 'Errol'))
    5, (4, (41, 'Garry'))
    5, (5, (41, 'Bernard'))
    5, (6, (41, 'Barry'))
    7, (7, (39, 'Stephen'))