Ranking methods

From Rosetta Code
Revision as of 16:29, 5 July 2014 by rosettacode>Paddy3118 (New draft task and Python solution.)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
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"""
   first, fifo = True, []
   for item in iterable:
       if first:
           first = False
           last, delta = item[0], 1
           fifo.append(item)
       else:
           if item[0] != last:
               start += delta
               while fifo:
                   yield start - 1, fifo.pop(0)
               delta = 1
           else:
               delta += 1
           last = item[0]
           fifo.append(item)
   start += delta
   while fifo:
       yield start - 1, fifo.pop(0)


def _gap_rank(iterable, start, only1):

   """Dense ranking if only1 else Standard competition ranking"""
   first = True
   for item in iterable:
       if first:
           first = False
           last, delta = item[0], 1
           yield start, item
       else:
           if item[0] != last:
               start += delta
               delta = 1
           else:
               if not only1:
                   delta += 1
           last = item[0]
           yield start, item


def sc_rank(iterable, start=1):

   """Standard competition ranking"""
   yield from _gap_rank(iterable, start, only1=False)


def d_rank(iterable, start=1):

   """Dense ranking"""
   yield from _gap_rank(iterable, start, only1=True)


def o_rank(iterable, start=1):

   """Ordinal  ranking"""
   yield from enumerate(iterable, start)


def f_rank(iterable, start=1):

   """Fractional ranking"""
   first, fifo = True, []
   for orank, item in enumerate(iterable, start):
       if first:
           first = False
           last = item[0]
           fifo.append((orank, item))
       else:
           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((orank, 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'))