Question: Starting from a sorted sequence of values, my goal is to assign a rank to each value, using identical ranks for equal values (aka ties):

Input: `Vector(1, 1, 3, 3, 3, 5, 6)`

Output: `Vector((0,1), (0,1), (1,3), (1,3), (1,3), (2,5), (3,6))`

A few type aliases for readability:

```
type Rank = Int
type Value = Int
type RankValuePair = (Rank, Value)

```

An imperative implementation using a mutable `rank` variable could look like this:

```
var rank = 0
val ranked1: Vector[RankValuePair] = for ((value, index) <- values.zipWithIndex) yield {
  if ((index > 0) && (values(index - 1) != value)) rank += 1
  (rank, value)
}

// ranked1: Vector((0,1), (0,1), (1,3), (1,3), (1,3), (2,5), (3,6))

```

To hone my FP skills, I was trying to come up with a functional implementation:

```
val ranked2: Vector[RankValuePair] = values.sliding(2).foldLeft((0 , Vector.empty[RankValuePair])) {
  case ((rank: Rank, rankedValues: Vector[RankValuePair]), Vector(currentValue, nextValue)) =>
    val newRank = if (nextValue > currentValue) rank + 1 else rank
    val newRankedValues =  rankedValues :+ (rank, currentValue)
    (newRank, newRankedValues)
}._2

// ranked2: Vector((0,1), (0,1), (1,3), (1,3), (1,3), (2,5))

```

It is less readable, and – more importantly – is missing the last value (due to using `sliding(2)` on an odd number of values).

How could this be fixed and improved?

Answer: 
This is a modification of the solution by @jwvh, that doesn't make any assumptions about the values:

```
val vs = Vector(1, 1, 3, 3, 3, 5, 6)
vs.sliding(2).scanLeft(0, vs.head) {
  case ((rank, _), Seq(a, b)) => (if (a != b) rank + 1 else rank, b)
}.toVector

```

Note, that it would throw if `vs` is empty, so you'd have to use `vs.headOption getOrElse 0`, or check if the input is empty beforehand: `if (vs.isEmpty) Vector.empty else ...`
```
val list = List(1, 1, 3, 3, 5, 6)
val result = list
    .groupBy(identity)
    .mapValues(_.size)
    .toArray
    .sortBy(_._1)
    .zipWithIndex
    .flatMap(tuple => List.fill(tuple._1._2)((tuple._2, tuple._1._1)))
result: Array[(Int, Int)] = Array((0,1), (0,1), (1,3), (1,3), (2,5), (3,6))

```

The idea is using groupBy to find identical elements and find their occurrences and then sort and then flatMap. Time complexity I would say is O(nlogn), groupBy is O(n), sort is O(nlogn), fl