## DEV Community is a community of 722,735 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

dev.to staff

Posted on

# Daily Challenge #26 - Ranking Position

We're back with another week of challenges!

Today, let's get a little creative and develop a ranking system where we can sort points and calculate the position of an individual or a team competing in a game/competition.

Note:
If two or more persons have the same number of points, they should have same position number and sorted by name (name is unique).

For example, Input structure:

``````[
{
name: "John",
points: 100,
},
{
name: "Bob",
points: 130,
},
{
name: "Mary",
points: 120,
},
{
name: "Kate",
points: 120,
},
]
``````

Output should be:

``````[
{
name: "Bob",
points: 130,
position: 1,
},
{
name: "Kate",
points: 120,
position: 2,
},
{
name: "Mary",
points: 120,
position: 2,
},
{
name: "John",
points: 100,
position: 4,
},
]
``````

Good luck!

This challenge comes from user kzm. Thank you to CodeWars, who has licensed redistribution of this challenge under the 2-Clause BSD License!

Want to propose a challenge for a future post? Email yo+challenge@dev.to with your suggestions!

## Discussion (13) Alvaro Montoro

JavaScript

``````const addRanking = list => {
let prevValue = undefined;
let prevRanking = 1;
list.sort((a,b) => {
if (a.points === b.points) {
if (b.name > a.name) {
return -1;
} else {
return 1;
}
} else {
return b.points - a.points;
}
}).forEach((el, idx) => {
if (prevValue === el.points) {
el.ranking = prevRanking;
} else {
el.ranking = idx + 1;
prevValue = el.points;
prevRanking = el.ranking;
}
});
};
``````

Live demo on Codepen. nishu1343

Hi alvaro. Could u please explain what u did in this program by putting comments in ur codepen link. Im trying to understand😊 Alvaro Montoro

I updated the Codepen with comments. Let me know if more details are needed. Avalander • Edited

``````-- Data/Score.hs
module Data.Score where

data Score = Score
{ name :: String
, points :: Int
} deriving (Show)

compare_scores :: Score -> Score -> Ordering
compare_scores a b =
case compare (points a) (points b) of EQ -> compare (name b) (name a)
LT -> LT
GT -> GT
``````
``````-- Data/Rank.hs
module Data.Rank where

import Data.Score as S

data Rank = Rank
{ name :: String
, points :: Int
, position :: Int
} deriving (Show)

from_score :: S.Score -> Int -> Rank
from_score score position = Rank
{ Data.Rank.name = S.name score
, Data.Rank.points = S.points score
, Data.Rank.position = position
}
``````
``````import Data.List (sortBy)
import Data.Rank as R
import Data.Score as S

sort_scores :: [ S.Score ] -> [ S.Score ]
sort_scores = sortBy (flip S.compare_scores)

map_to_records :: [ S.Score ] -> [ R.Rank ]
map_to_records = foldl kevin []
where
kevin :: [ R.Rank ] -> S.Score -> [ R.Rank ]
kevin [] score = [ R.from_score score 1 ]
kevin xs score
| tied_score = xs ++ [ R.from_score score prev_position ]
| otherwise  = xs ++ [ R.from_score score next_position ]
where
prev = last xs
tied_score = R.points prev == S.points score
prev_position = R.position prev
next_position = (length xs) + 1

rank_scores :: [ S.Score ] -> [ R.Rank ]
rank_scores = map_to_records . sort_scores

scores :: [ S.Score ]
scores =
[ S.Score { S.name = "John"
, S.points =  100
}
, S.Score { S.name = "Bob"
, S.points = 130
}
, S.Score { S.name = "Mary"
, S.points = 120
}
, S.Score { S.name = "Kate"
, S.points = 120
}
]

rank_scores scores
{-[ Rank {name = "Bob", points = 130, position = 1}
, Rank {name = "Kate", points = 120, position = 2}
, Rank {name = "Mary", points = 120, position = 2}
, Rank {name = "John", points = 100, position = 4}
]
-}
`````` Python

``````r=[
{
'name': "John",
'points': 100,
},
{
'name': "Bob",
'points': 130,
},
{
'name': "Mary",
'points': 120,
},
{
'name': "Kate",
'points': 120,
},
]

def points(e):
return e['points']

p=1
r.sort(reverse= True , key=points)
p_max=r['points']
r['position']= p

for i in range(1,len(r)):
if r[i]['points'] == p_max:     r[i]['position']= p
else:
p+=1
p_max=r[i]['points']
r[i]['position']=p
print(r)
`````` Hao • Edited

There's probably a better way which requires only one iteration?

``````const players = [
{
name: "John",
points: 100,
}, {
name: "Bob",
points: 130,
}, {
name: "Mary",
points: 120,
}, {
name: "Kate",
points: 120,
},
];

players.sort((a, b) => {
return (a.points == b.points ? a.name > b.name : a.points < b.points) || -1;
}).forEach((e, i, arr) => {
e.rank = i && arr[i-1].points == e.points ? arr[i-1].rank : i + 1;
});

console.log(players);       // [{"name":"Bob","points":130,"rank":1},{"name":"Kate","points":120,"rank":2},{"name":"Mary","points":120,"rank":2},{"name":"John","points":100,"rank":4}]
`````` i want to contribute my idea with your code. i hope u enjoy with that. Maybe it's shoter

```players.sort((a, b) => { return (a.points == b.points ? a.name > b.name : a.points < b.points) || -1; }).map((e,i)=>({...e,position:(i+1)}))``` E. Choroba • Edited

Going functional in Perl:

``````#!/usr/bin/perl
use warnings;
use strict;

sub rank {
my (\$in) = @_;
my \$i = 1;
my \$same = 0;
my \$last = 'INF';
[ map { if (\$_->{points} == \$last) {
++\$same;
} else {
\$i += \$same;
\$last = \$_->{points};
\$same = 1;
}
+{ %\$_, position => \$i } }
sort { \$b->{points} <=> \$a->{points}
|| \$a->{name} cmp \$b->{name}
} @\$in ]
}

my \$input = [
{ name => "John", points => 100 },
{ name => "Bob",  points => 130 },
{ name => "Mary", points => 120 },
{ name => "Kate", points => 120 }];

my \$expected = [
{ name => "Bob",  points => 130, position => 1 },
{ name => "Kate", points => 120, position => 2 },
{ name => "Mary", points => 120, position => 2 },
{ name => "John", points => 100, position => 4 }];

use Test::More tests => 1;
is_deeply rank(\$input), \$expected;
`````` willsmart • Edited

Just a short one in Javascript

Edit: somehow I hadn't noticed the `position` bit 😳, so I've added that as a map call.

``````ranked = players =>
players
.slice()
.sort((a, b) => Math.sign(b.points - a.points) * 2 + a.name.localeCompare(b.name))
.map((item, index, array) =>
Object.assign(item, {
position: index && item.points == array[index - 1].points ? array[index - 1].position : index + 1,
})
);

players = [
{name: 'b', points: 1},
{name: 'b', points: 3},
{name: 'b', points: 2},
{name: 'a', points: 2},
{name: 'c', points: 2}
];

console.log(JSON.stringify(ranked(players),null,2));
/* ^ [  {
"name": "b",
"points": 3,
"position": 1
},
{
"name": "a",
"points": 2,
"position": 2
},
{
"name": "b",
"points": 2,
"position": 2
},
{
"name": "c",
"points": 2,
"position": 2
},
{
"name": "b",
"points": 1,
"position": 5
}
]
*/
`````` Here it goes!

``````const players = [
{
name: "John",
points: 100,
},
{
name: "Bob",
points: 130,
},
{
name: "Mary",
points: 120,
},
{
name: "Kate",
points: 120,
},
];

const sortPlayers = (arr) =>
arr.sort((a, b) =>
b.points - a.points
|| a.name.localeCompare(b.name)
)
.map((p, i, l) => Object.assign(p, {position: i && !(l[i-1].points-p.points) ? l[i-1].position : i+1}));
``````

And the result:

``````sortPlayers(players);
[
{
"name": "Bob",
"points": 130,
"position": 1
},
{
"name": "Kate",
"points": 120,
"position": 2
},
{
"name": "Mary",
"points": 120,
"position": 2
},
{
"name": "John",
"points": 100,
"position": 4
}
]
``````