Rank a list of integers

You're given a non-empty list of positive integers, e.g.

[6 2 9 7 2 6 5 3 3 4]

You should rank these numbers by their value, but as is usual in leaderboards, if there is a tie then all the tied numbers get the same rank, and an appropriate number of ranks is skipped. The expected output for the above list would therefore be

[3 9 1 2 9 3 5 7 7 6]

For example, the highest value in the input was 9, so this becomes a 1 (first rank). The third highest value is 6, so both 6s become 3, and the rank 4 is skipped entirely.

Rules

You can use any convenient, unambiguous, flat list format for input and output. The first/smallest rank in the output should always be 1.

You may write a program or a function and use any of the our standard methods of receiving input and providing output.

You may use any programming language, but note that these loopholes are forbidden by default.

This is , so the shortest valid answer – measured in bytes – wins.

Test Cases

 -> 
[1 15] -> [2 1]
[18 14 11] -> [1 2 3]
[11 16 14 8] -> [3 1 2 4]
[15 15 15 15 15] -> [1 1 1 1 1]
[10 2 5 4 15 5] -> [2 6 3 5 1 3]
[5 5 10 10 5 11 18] -> [5 5 3 3 5 2 1]
[2 4 9 4 17 9 17 16] -> [8 6 4 6 1 4 1 3]
[11 17 19 17 10 10 15 3 18] -> [6 3 1 3 7 7 5 9 2]
[2 11 4 8 3 3 12 20 4 18] -> [10 4 6 5 8 8 3 1 6 2]
[12 6 10 2 19 19 6 19 8 6 18] -> [5 8 6 11 1 1 8 1 7 8 4]
[5 6 14 19 13 5 19 9 19 9 9 19] -> [11 10 5 1 6 11 1 7 1 7 7 1]
[9 2 12 3 7 11 15 11 6 8 11 17 11] -> [8 13 3 12 10 4 2 4 11 9 4 1 4]
[3 5 15 7 18 5 3 9 11 2 18 1 10 19] -> [11 9 4 8 2 9 11 7 5 13 2 14 6 1]
[6 11 4 19 14 7 13 16 10 12 7 9 7 10 10] -> [14 6 15 1 3 11 4 2 7 5 11 10 11 7 7]
[11 20 11 1 20 16 11 11 4 8 9 7 11 14 10 14] -> [6 1 6 16 1 3 6 6 15 13 12 14 6 4 11 4]
[4 7 15 2 3 2 3 1 14 2 10 4 7 6 11 2 18] -> [9 6 2 13 11 13 11 17 3 13 5 9 6 8 4 13 1]
[5 1 17 7 1 9 3 6 9 7 6 3 2 18 14 4 18 16] -> [12 17 3 8 17 6 14 10 6 8 10 14 16 1 5 13 1 4]
[5 6 8 10 18 13 20 10 7 1 8 19 20 10 10 18 7 2 1] -> [16 15 11 7 4 6 1 7 13 18 11 3 1 7 7 4 13 17 18]
[12 17 8 2 9 7 15 6 19 5 13 16 14 20 10 11 18 4 3 1] -> [9 4 13 19 12 14 6 15 2 16 8 5 7 1 11 10 3 17 18 20]
• Closely related. The difference is that that challenge guarantees that the input is sorted, which means that most answers rely on a form of indexOf function. I believe for unsorted input there are shorter alternatives in many languages. – Martin Ender Dec 8 '16 at 19:13
• Also related – Lynn Dec 8 '16 at 21:55
• Im sorry, but I believe that this is too close to Lynn's link. The differences are minimal: The values are truncated, you can't assume an already-sorted input and half of the output has its order swapped. The accepted answer on the linked question nearly works. With minimal effort, someone could make it work. As such, I stand that this is a duplicated. – Ismael Miguel Dec 9 '16 at 18:25
• I disagree, this is clearly not a duplicate. – Timtech Dec 9 '16 at 21:24
• I agree with timtech, this challenge is simpler, but not a duplicate. – tuskiomi Dec 9 '16 at 21:53

Workaround in Excel for silly Rules Regarding Mouse Inputs on Code Golf Stack Exchange: (WESRRMICGSE) 28 bytes

rank(RC,r1c1:r1024:c1024)

Input list as csv (10,23,34,2,) into the compiler after entering the source. no quotes, no brackets, trailing comma.

WESRRMICGSE is exactly like programming in excel, except you can omit the initial '=' sign to save a byte. The difference in functionality comes from the fact that WESRRMICGSE will either drag the formula down to copy the code automatically and provide different outputs provided with a single integer input. provided a list as input, that list goes into the B column (input column), and the formula is drug down automatically to match the number of inputs. (eg: the input 34,21,45, would 'drag' the formula down 2 cells, for a total of 3 cells with the formula).

Edit: I never expected this answer to be popular. Wow!

• The language name is a bit obnoxious... – Conor O'Brien Dec 8 '16 at 19:22
• What rules do you refer and how exactly are they silly? – Luis Mendo Dec 8 '16 at 21:21
• @LuisMendo the rules declared here: meta.codegolf.stackexchange.com/questions/10199/… I think the rule is silly because I took 5 minutes to write an 'interpreter' that circumvents exactly what they are talking about. The more that this language can be used in challenges, the sillier the rule becomes. I'll be sure to include this in the link. – tuskiomi Dec 8 '16 at 21:27

MATL, 4 bytes

&<sQ

Explanation

&<   % Input array implicitly. Matrix of all pairwise "less than" comparisons
s    % Sum of each column
Q    % Add 1. Display implicitly

Python 2, 41 bytes

lambda l:map(sorted(l+[l])[::-1].index,l)

For each value, find its index in the list sorted by decreasing order. To make the largest value give 1 instead of 0, we use an extra "infinity" element of the list itself, since Python 2 treats lists as bigger than numbers.

A more direct solution is 42 bytes and also works in Python 3.

lambda l:[1+sum(y<x for x in l)for y in l]

For each element, counts the number of smaller elements, adding 1 to shift to 1-indexed.

Jelly, 5 bytes

ṢṚiÐ€

Try it online!

How it works

ṢṚiÐ€  Main link. Argument: A (array)

ṢṚ     Sort and reverse A.
iÐ€  Find the index of each n in A in the previous result.

R, 24 2520 bytes

Uses the standard rank function with the "min" ties method over the negated vector. cat added to output it to STDOUT. Saved one thanks to @Guiseppe

cat(rank(-scan(),,"mi"))

Example

> cat(rank(-scan(),,"mi"))
1: 9 2 12 3 7 11 15 11 6 8 11 17 11
14:
8 13 3 12 10 4 2 4 11 9 4 1 4
>
• I think you need to wrap it in cat for it to be a full program. – Alex A. Dec 10 '16 at 19:56
• @AlexA. I was wondering about that. Would it be fair to say that this is a function in it's own right and in that case would rank(-a,,'min') be ok where a is the list input in vector form? – MickyT Dec 11 '16 at 21:29
• In that case we would consider it a snippet, because it assumes that a variable already exists in the namespace. To make it a proper function submission you'd need function(a)rank(-a,,'min'). – Alex A. Dec 13 '16 at 3:39
• can be shortened to just "mi" rather than "min". – Giuseppe Oct 22 '17 at 13:41
• @AlexA. why does it need to be wrapped in cat? If the submission had been function(a)rank(-a,,'mi') that would be considered sufficient and the program output is identical to rank(-scan(),,'mi') – Mark Nov 13 '17 at 4:10

PowerShell v2+, 43 41 bytes

($a=$args)|%{@($a|sort -d).indexof($_)+1}

Developed independently, but I see that this is the same algorithm as @xnor's Python solution, so /shrug.

Takes input as individual command-line arguments (i.e., a space separated list). Output (default formatting) is a newline between elements.

For each element in the input list, it sorts the input list in -descending order, takes the .indexOf() the current element, and adds 1. Note the explicit array cast @(...) in order to account for a single-digit input. The resulting numbers are left on the pipeline and output is implicit.

Saved 2 bytes thanks to @Matt!

Example

PS C:\Tools\Scripts\golfing> .\rank-the-integers.ps1 6 2 9 7 2 6 5 3 3 4
3
9
1
2
9
3
5
7
7
6
• Is there a reason sort -d didn't work for you? That is unambiguous for me. – Matt Dec 10 '16 at 5:33
• @Matt Odd. On my Win8.1 ISE, it states that -Descending and -Debug are ambiguous. But in the straight shell on Win8.1 and the shell and ISE on Win10 it works fine. This wouldn't be the first time that my particular Win8.1 install is goofy... :-/ Thanks for the golf! – AdmBorkBork Dec 10 '16 at 5:49
• Also did this not work for all test cases? $args|%{@($args|sort -d).indexof($_)+1} it is shorter but I have not had a good look to know if it works – Matt Dec 10 '16 at 5:53 • @Matt That doesn't work because the second$args functions as input for the script block of the loop {...}, just like if you were using a filter or function. – AdmBorkBork Dec 10 '16 at 6:14

Octave, 15 bytes

@(x)sum(x<x')+1

Port of my MATL answer to Octave. It also works in Matlab R2016b.

The code defines an anonymous function. To call it, assign it to a variable. Try it at Ideone.

JavaScript (ES6), 38 36 bytes

a=>a.map(e=>a.map(d=>r+=e<d,r=1)&&r)

Edit: Saved 2 bytes thanks to @ETHproductions.

• .map FTW ;-) a=>a.map(e=>a.map(d=>r+=e<d,r=1)&&r) – ETHproductions Dec 8 '16 at 23:09
• @ETHproductions Why do you always have to spoil my fun? – Neil Dec 9 '16 at 0:22

Jelly, 5 bytes

<S‘ð€

TryItOnline!

How?

<S‘ð€ - Main link: listOfValues
ð  - dyadic chain separation
€ - for each
<     - less than (vectorises) - yields a list of 1s and 0s
S    - sum - yields number of values the current value is less than (those that beat it)
‘   - increment - the place of a value is the number that beat it plus 1.
• How similar is this to the J code I was about to submit? 1+(+/@:<)"0 1~ – Dane Dec 8 '16 at 21:28
• Looks similar (uses a reduce to sum?), but that should by no means stop you posting your code! – Jonathan Allan Dec 8 '16 at 21:34
• I guess I was more wondering what "dyadic chain separation" and "for each" do in a J-inspired language. – Dane Dec 8 '16 at 21:44
• Ah, well from your explanation I think your code is more like >€µS‘, or really like <@€µS‘ (@ reverses arguments to the < operator). The J ~ is implicit in the chain to the left of the µ, which is monadic (rather than dyadic) separation and < vectorises if the argument(s) is(are) list(s). – Jonathan Allan Dec 8 '16 at 22:10

Perl 6,  42  26 bytes

Find the first index :k in a reversed [R,] sorted list

{map {[R,](.sort).first(*==$^a,:k)+1},@$_}

Count the values that are larger, and add one

{map {1+.grep(*>$^a)},@$_}

JavaScript, 87 49 bytes

f=a=>a.slice().map(function(v){return a.sort(function(a,b){return b-a}).indexOf(v)+1 })

a=>[...a].map(v=>a.sort((a,b)=>b-a).indexOf(v)+1)

Thanks Conor O'Brien and ETHproductions!

• You can use an anonymous function in the map, i.e. v=>a.sort((a,b)=>b-a).indexOf(v)+1. – Conor O'Brien Dec 8 '16 at 19:55
• You don't need .slice() at all, because .map operates on a copy of the array. – ETHproductions Dec 8 '16 at 20:12
• And our site policy is that the function does not need to be named, so you can remove the leading f=, too. – Conor O'Brien Dec 8 '16 at 20:14
• @ETHproductions If I remove slice, passing in [18,13,18] returns [1,1,2] instead of [1, 3, 1] – Oliver Dec 8 '16 at 20:16
• Oh, that's weird... I guess it's because a.sort() stores the sorted array in a. But you can change a.slice() to [...a] to save a few bytes. – ETHproductions Dec 8 '16 at 20:20

Mathematica, 44 bytes42 bytes 40 bytes

xPosition[SortBy[x,-#&],#][[1,1]]&/@x

is the 3 byte private use character U+F4A1 (Wolfram docs page)

Edit: Thanks to JHM for the byte savings.

• Fails for test case {10,2,5,4,15,5} (the output should be {2,6,3,5,1,3} not {2,5,3,4,1,3}. Note that 4 has to be skipped because there are two 5s in the input). – JungHwan Min Dec 8 '16 at 23:22
• Duly corrected. – ngenisis Dec 8 '16 at 23:58
• -2 bytes by switching x and # (effectively getting rid of the parentheses): xPosition[SortBy[x,-#&],#][[1,1]]&/@x. – JungHwan Min Dec 9 '16 at 0:00

Pyke, 6 bytes

FQS_@h

Try it here!

F      - for i in input():
QS    -     sorted(input())
_   -    reversed(^)
@  -   i.find(^)
h -  ^+1 (not required if allowed to start from 0)

J, 14 8 bytes

1+1#.</~

How?

1+1#.</~ - Consumes and returns a list of integers
~ - Use the same list for both inputs
</  - Create a table of less-than comparisons
1#.    - Treat each row like digits of a base-one number, returning a list of integers
1+       - Increment the results

Previous solution

1+(+/@:<)"0 1~
• Hello, I've found a shorter version for 8 bytes 1+1#.</~. Row-wise summation is performed using base 1 conversion. Another alternative is 1+\:~i.] which is also 8 bytes. – miles Dec 8 '16 at 22:07
• Nice! Do you want to post your own answer? I'll otherwise include the base-one improvement. – Dane Dec 8 '16 at 22:36
• Nah, I'm fine with just suggesting byte-savings. Feel free to use them – miles Dec 8 '16 at 23:58

f l=[1+sum[1|y<-l,y>x]|x<-l]

Just some list comprehensions.

• 20sec too late. I was about to post the very same answer. – nimi Dec 8 '16 at 19:36
• @nimi You can post it too! – xnor Dec 8 '16 at 19:36

Wonder, 28 bytes

@(->@+1:0iO#0rev sort#I#1)#0

Usage:

(@(->@+1:0iO#0rev sort#I#1)#0)[6 2 9 7 2 6 5 3 3 4]

Map over input array with a function that adds 1 to the first index of the item in a descending-sorted version of the input.

Dyalog APL, 7 bytes

⊢⍳⍨⍒⊃¨⊂

arguments'

⍳⍨ indices in

the indices which would sort the argument descending

⊃¨ each picked from

the entire argument

TryAPL online!

Mathematica, 37 bytes

Min@Position[-Sort@-#,i]~Table~{i,#}&

A pure function which will rank it's input, as per the rules of the problem. Ex:

Min@Position[-Sort@-#, i]~Table~{i, #} &[{6, 2, 9, 7, 2, 6, 5, 3, 3, 4}]
(*{3, 9, 1, 2, 9, 3, 5, 7, 7, 6}*)

Jellyfish, 15 bytes

p&& ~i
>/+<

Try it online!

Explanation

There doesn't seem to be a good way to find the index of a value in a list in Jellyfish yet, so this uses the approach of counting how many values are bigger than current one and incrementing the result. This is largely done by constructing a unary function which computes this value for a given element.

<

This creates a threaded version of the comparison operator, so if you give this an integer and a list, it will return a list of comparison results between that integer and each element in the list.

~i
<

This curries the right-hand argument of the previous function with the input list. So the result is a unary function which takes an integer and gives you the list of comparison results with the input of the program.

& ~i
/+<

Here, /+ is reduction by addition, which means it's simply a "sum this list" function. & composes this onto the previous function, so we now have a unary function which counts how many values in the input are bigger than that integer.

&& ~i
>/+<

We also compose the increment function onto this.

&& ~i
>/+<

Finally, we thread this function as well, so that it's automatically applied to each integer of a list passed to it. Due to the layout of the code, i happens to be taken as the input of this function as well, so that this computes the desired output.

p&& ~i
>/+<

Finally, this prints the result.

brainfuck, 124 bytes

->,[>>>+>,]<[-<+]+[-->[<[<<<<]>>>+>[>[>>]<[[<<+<<]>+>[->>>>]]<+>>>]+[-<<+]->]<[<
<<<]>+.,>>[>[>->+>>]<<[-<<<<]>-]+[->+]+>>>>]

Formatted:

->
,[>>>+>,]
<[-<+]
+
[
-->
[
<[<<<<]
>>>+>
[
>[>>]
<
[
[<<+<<]
>+>[->>>>]
]
<+> >>
]
+[-<<+]
->
]
<[<<<<]
>+.,>>
[
>[>->+>>]
<<[-<<<<]
>-
]
+[->+]
+>>>>
]

This is designed for 8-bit brainfuck implementations. Input and output are via byte values.

Try it online.

For each element, this counts the number of elements greater than it, then prints the result plus one. This is accomplished by incrementing all elements until the current element equals zero, updating the result whenever another element becomes zero before the current element.

The tape is broken into 4-cell nodes,

b c 0 0

where c is the element and b is a navigation flag that is negative one for the current element, otherwise one.

The result and a copy of the current element are kept to the left of the array.

Java, 215 bytes

public class G{public static void L(int[]A){int[]r=new int[A.length];for(int i=0;i<A.length;i++){int c=1;for(int j=0;j<A.length;j++){if(A[j]>A[i])c++;}r[i]=c;}for(int i=0;i<r.length;i++)System.out.print(r[i]+",");}}

Explanation:

Very self explanatory.

Basically for each integer in the array it checks how many are larger than it, then prints the new array with the rankings.

I'm sorry this isn't very concise but it's my first try at one of these and I didn't see an entry for java. I'm sure it can be golfed down more.

It can be run just by making reference to the static method and passing an array. I didn't think it was necessary to write the main function but if it is I'll do that in the future.

• Can you remove some of this whitespace? As it is this isn't golfed really at all. (i.e. the spaces in r = new) – Rɪᴋᴇʀ Dec 28 '16 at 23:06
• @EasterlyIrk Yes, sorry i'm not used to doing this. I think I got rid of all unnecesary whitespace. – Henry Dec 28 '16 at 23:46
• Can you name the "rankNumbersGolf" something shorter like "G" or something? – Rɪᴋᴇʀ Dec 28 '16 at 23:47
• @EasterlyIrk Yes, thanks. – Henry Dec 28 '16 at 23:56
• I don't java well, but can you remove some spaces in the three for (? – Rɪᴋᴇʀ Dec 28 '16 at 23:58

PHP, 101 bytes

There must be some shorter way.

function f(&$a){for($r=1;$v++<max($a);$r+=$n,$n=0)foreach($a as$k=>$w)if($w===$v){$a[$k]="$r";$n++;}}

function takes input as array of integers, overwrites input variable with ranks as numeric strings.

Try it online!

PHP, 84 bytes

function r($l){$s=$l;rsort($s);foreach($l as$n)$r[]=array_search($n,$s)+1;return$r;}

Usage: Pass the function r your array of integers and it will return the corresponding array of ranked integers.

Passing tests here.

Perl 5, 23 +2 (-ap)

s/\d+/1+grep$&<$_,@F/ge

Try it online

K (oK), 11 bytes

Solution:

1+(x@>x)?x:

Try it online!

Examples:

1+(x@>x)?x:6 2 9 7 2 6 5 3 3 4
3 9 1 2 9 3 5 7 7 6
1+(x@>x)?x:5 6 14 19 13 5 19 9 19 9 9 19
11 10 5 1 6 11 1 7 1 7 7 1

Explanation:

Lookup position of original list in sorted list, then add one.

1+(x@>x)?x: / the solution
x: / save input as x
(  >x)    / return indices of x sorted in descending order
x@       / apply these indices to x (thus sort x)
?   / lookup right in left
1+          / add one