#include <algorithm>
#include <vector>
#include <iostream>

template<typename Vector>
std::vector<double> rank(const Vector& v)
{
	std::vector<std::size_t> w(v.size());
	std::iota(begin(w), end(w), 0);
	std::sort(begin(w), end(w), 
		[&v](std::size_t i, std::size_t j) { return v[i] < v[j]; });

	std::vector<double> r(w.size());
	for (std::size_t n, i = 0; i < w.size(); i += n)
	{
		n = 1;
		while (i + n < w.size() && v[w[i]] == v[w[i+n]]) ++n;
		for (std::size_t k = 0; k < n; ++k)
		{
			r[w[i+k]] = i + (n + 1) / 2.0; // average rank of n tied values
			// r[w[i+k]] = i + 1;     // min 
			// r[w[i+k]] = i + n;     // max
			// r[w[i+k]] = i + k + 1; // random order
		}
	}
	return r;
}

int main()
{
	std::vector<int> v = { 7, 3, 1, 3, 5 }; 
	std::vector<double> ranks = rank(v);
	
	for (std::size_t i = 0; i < v.size(); ++i)
		std::cout << v[i] << " : " << ranks[i] << '\n'; 

	return 0;
}