Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Given a list of scores (non-negative integers) pre-sorted from greatest to least:

[ 10, 10, 6,  6,  4,  0]

Assign each score an integer rank, beginning with 1 and ascending, such that equal scores have the same rank (i.e. they are tied):

[ 1, 1, 3, 3, 5, 6 ]

In the case of ties, ranks are "skipped," e.g. since the first and second-greatest scores (10 and 10) are tied, they both have rank 1, and rank 2 is "skipped," so the third-greatest score (6) has rank 3.

Output a list of non-descending ranks corresponding to the input scores.

Examples

In:  10 10  6  6  4  0
Out:  1  1  3  3  5  6
In:  10  9  8
Out:  1  2  3
In:   0  0  0
Out:  1  1  1
In:  16 15 15 12 11 11 10  9  9  9  8  2  2  2  0
Out:  1  2  2  4  5  5  7  8  8  8 11 12 12 12 15

Input

Assume all scores will be between 0 and 1,000 inclusive, and the input will have no more than 500 scores. Input can be in whatever format is convenient for your language of choice (including but not limited to STDIN, arguments to a function, an array already stored in a variable, etc.).

Output

Return or store in a variable the resulting ordered list of ranks, or write it to STDOUT in a human-readable way (e.g. 1 2 3, [1,2,3], 1\n2\n3\n, and { 1, 2, 3 } are all fine; 123 is not, for want of a delimiter). The input scores may be stored/printed along with their corresponding output ranks, but that's not required.

Restrictions

You may use any standard library your language offers. Standard loopholes apply.

Winning conditions

This is , so the smallest program (in bytes) wins. In case of a tie, the answer with the most votes wins.

Notes

This is based on a Ruby question on SO that generated some interesting answers, including one very short one. I encourage you to come up with your own solutions before looking there.

share|improve this question
1  
I think this would be better, and illicit better answers, if it was not presorted, and the ranks needed to retain their original order. That is [10, 4, 6, 0, 6, 10] would be [1, 5, 3, 6, 3, 1] –  Cruncher Aug 1 at 19:56
    
That's a good point, @Cruncher; feel free to start a new thread. –  Jordan Aug 2 at 22:20

15 Answers 15

up vote 7 down vote accepted

J (7 6)

EDIT: Oh, wait! It doesn't need to be a function!

>:i.~y

Thank god for i.~...

>:@:i.~

Or as a named function (3 chars more, but not functionally different):

f=:>:@:i.~

Run tests:

   f=:>:@:i.~
   f 10 10  6  6  4  0
1 1 3 3 5 6
   f 10  9  8
1 2 3
   f 0  0  0
1 1 1
   f 16 15 15 12 11 11 10  9  9  9  8  2  2  2  0
1 2 2 4 5 5 7 8 8 8 11 12 12 12 15
share|improve this answer
1  
Care to comment what this does? –  corsiKa Aug 1 at 19:20
1  
1+i.~ is the kind of train that can be both assigned and used inline, so can be used as a function without its usual train parens. That's 5 chars. And for the record, @ does the same job as @: in this case, so you could've saved an easy character there. –  algorithmshark Aug 2 at 5:31

T-SQL (40)

SELECT RANK()OVER(ORDER BY B DESC)
FROM @

Assume @ is a table containing the scores as rows.

share|improve this answer

Pyth, 6

m'XYdY

List is stored in Y to begin with. This is functionally the same as the 22 character ruby solution: map over d in Y to index of d in Y plus 1, then print.

Example:

$ echo "=Y[16 15 15 12 11 11 10 9 9 9 8 2 2 2 0)m'XYdY" | python3 pyth.py

[1, 2, 2, 4, 5, 5, 7, 8, 8, 8, 11, 12, 12, 12, 15]
share|improve this answer

Python (33 characters)

lambda x:[1+x.index(i)for i in x]

Functionally the same as my J answer.

share|improve this answer
    
Because input can be in the format of your choice, you can declare the array to be stored in x to begin with, and "output" it by storing the result in a variable. –  isaacg Aug 1 at 19:16

STATA (16)

egen b=rank(c),f

Result is in b.

Assumes c is a variable in the dataset containing the input.

share|improve this answer
    
Stata in code golf? This one really opens a can of worms. –  ssdecontrol Aug 2 at 4:39

Haskell (31)

f x=succ.(`elemIndexJust`x)<$>x -- Requires the Safe module

Usage:

f [10,10,6,6,4,0] --evaluates to [1,1,3,3,5,6]
share|improve this answer
    
my solution was r l=concat$tail$scanl(\s->map$const$length s+s!!0)[0]$group l with 61 characters –  proud haskeller Aug 2 at 9:32
    
also, your first solution doesn't work because of monomorphism restriction –  proud haskeller Aug 2 at 9:32
    
That darn momoprophism restriction... I got it to work in GHCI, but since it won't compile I guess I should remove it... –  awashburn Aug 2 at 14:44
    
You could remake it so it would work –  proud haskeller Aug 2 at 15:37

So as to establish a baseline:

Ruby (38)

Assuming a is an array:

r,i=1,0;a.map{|x|i+=1;x==a[i-2]?r:r=i}

(This is based on falsetru's answer on the original SO thread and isn't my original work. I know there's a Ruby solution that's 22 characters, but I'd like to see someone come up with one shorter than that in Ruby.)

share|improve this answer

JavaScript (E6) 41

A function with an array argument, returning an array

F=s=>s.map((n,i)=>p-n?(p=n,r=i+1):r,p=-1)

Test In Firefox console

F([10,10,6,6,4,0])

Output: [1, 1, 3, 3, 5, 6]

F([16, 15, 15, 12, 11, 11, 10, 9, 9, 9, 8, 2, 2, 2, 0])

Output: [1, 2, 2, 4, 5, 5, 7, 8, 8, 8, 11, 12, 12, 12, 15]

share|improve this answer

R, 15

with input stored as vector x,

rank(-x,T,"mi")
share|improve this answer

Powershell (70)

$n=1;$c=0;$l=$a[0];$a|%{if($l-eq$_){$n}else{$n=$c+1;$n}$l=$a[$c];$c++}

It's only 51 characters if you take out the variable assignments at the beginning, which makes me feel slightly less inadequate.

Assumes $a is assigned and sorted as specified by the problem. $n tracks rank, $c is just a counter which works with $l, the last element checked in the array.

If there's anything I can do to improve this, I'd love to know.

share|improve this answer

Java (57)

Using the same 'rules' as Allbeert:

Constant i is defined as int[] array and contains the input, z contains the size of the input. Others, l,c,x and n, are defined as int.

The left over snippet of code is:

l=0;c=1;for(x=0;x<z;x++){n=i[x];i[x]=n==l?c:(c=x+1);l=n;}

The result is in the input array.

share|improve this answer

Ruby, 22

I haven't looked at the SO thread but I imagine this is what they came up with.

a.map{|i|a.index(i)+1}

Edit: Yep, it is. I doubt it's possible to get smaller in Ruby, unless you assume you're defining it as an Array method, then you can do it in 18 characters with

map{|i|index(i)+1)

But of course the full program around that snippet looks like

class Array
  def ranks
    map{|i|index(i)+1)
  end
end

p [1, 2, 2, 4, 5, 5, 7, 8, 8, 8, 11, 12, 12, 12, 15].ranks
share|improve this answer

><> (47)

Not particularly optimized, just testing the water with my first golf.

r:1:nr2&>ao$:@=?vr~&:|   
&1+&l3)?^;      >r:nr

Assumes that the input is prepopulated in the stack, such that the first element of the input is the first to be popped off.

Testing:

fish.py ranks.fish -v 1 2 3 4 5 6 7 8 9 9 10 10

outputs

1
1
3
3
5
6
7
8
9
10
11
12
share|improve this answer
1  
"testing the water" in a fish submission made me smile –  Ingo Bürk Aug 2 at 23:55

Clojure, 35

With some Java interop mixed in:

(fn[l](map #(+ 1(.indexOf l %)) l))

REPL session:

golf> ((fn[l](map #(+ 1(.indexOf l %)) l)) [10 10  6  6  4  0])
(1 1 3 3 5 6)
golf> ((fn[l](map #(+ 1(.indexOf l %)) l)) [16 15 15 12 11 11 10  9  9  9  8  2  2  2  0])
(1 2 2 4 5 5 7 8 8 8 11 12 12 12 15)
share|improve this answer

C - 62

As a code snippet, since there was no requirement for function or full program.

Assumes a, n, j, and k are already defined as int*, int, int, and int respectively, where a is an array containing the input, and n contains the length of the input.

This fails for input of length 0, in which case 3 more characters are needed.

printf("1");for(k=j=1;++j<=n;)printf(" %d",*a-*(a+++1)?k=j:k);
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.