Back to homepage | Back to blog | Back to archive
Written by Adrian Kjær Dalhaug at 2020-02-19 14:19:37 UTC.
An interesting problem landed on my desk at work today: Make a ranking list algorithm in Elixir.
Rules:
The last rule is interesting in that there will be gaps in the ranking if rule #2 gets into play.
Example:
I made my solution in Elixir because that's what the current project uses. I'd love it if someone out there would send me an email with a link to an implementation in their favourite language. I'll add any contributions below.
EDIT: Got a bunch of responses on Lobsters with great solutions to the problem :)
defmodule Ranking do
def ranking(participants) do
participants
|> Enum.sort(&(&1.points >= &2.points))
|> ranking_work()
end
defp ranking_work(
participants,
prev_points \\ 0,
prev_ranking \\ 0,
prev_count \\ 1,
ranking_list \\ []
)
defp ranking_work([], _, _, _, ranking_list) do
ranking_list
end
defp ranking_work(
[participant | other_participants],
prev_points,
prev_ranking,
prev_count,
ranking_list
) do
{new_points, new_ranking, new_count, new_ranking_list} =
if prev_points == participant.points do
new_ranking = format_rank(prev_ranking)
{prev_points, new_ranking, prev_count + 1,
ranking_list ++ [Map.merge(participant, %{ranking: new_ranking})]}
else
new_ranking = format_rank(prev_ranking + prev_count)
{participant.points, new_ranking, 1,
ranking_list ++ [Map.merge(participant, %{ranking: new_ranking})]}
end
ranking_work(other_participants, new_points, new_ranking, new_count, new_ranking_list)
end
defp format_rank(rank) do
# even if every person has 0 in rank, never use 0 as rank
if rank == 0 do
1
else
rank
end
end
def rank_mock_data() do
[
%{id: 1, points: 39},
%{id: 2, points: 26},
%{id: 3, points: 50},
%{id: 4, points: 24},
%{id: 5, points: 39},
%{id: 6, points: 67},
%{id: 7, points: 39},
%{id: 8, points: 50},
%{id: 9, points: 48},
%{id: 10, points: 24}
]
|> ranking()
end
end
Ranking.rank_mock_data()
|> inspect(pretty: true)
|> IO.puts()
$ elixir ranking.exs
[
%{id: 6, points: 67, ranking: 1},
%{id: 3, points: 50, ranking: 2},
%{id: 8, points: 50, ranking: 2},
%{id: 9, points: 48, ranking: 4},
%{id: 1, points: 39, ranking: 5},
%{id: 5, points: 39, ranking: 5},
%{id: 7, points: 39, ranking: 5},
%{id: 2, points: 26, ranking: 8},
%{id: 4, points: 24, ranking: 9},
%{id: 10, points: 24, ranking: 9}
]
Comments? Mail them to: adrian@enpo.no.
Generated at 2020-02-19 14:19:38 UTC.