The problem

P11 (*) Modified run-length encoding. Modify the result of problem P10 in such a way that if an element has no duplicates it is simply copied into the result list. Only elements with duplicates are transferred as (N, E) terms.

Example:

scala> encodeModified(List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e))
res0: List[Any] = List((4,'a), 'b, (2,'c), (2,'a), 'd, (4,'e))

Initial thoughts

The solution shall be a modification of that of problem 10, and the only difference is that this time we do not produce the same type of result for each element.

Choices

If the source element is a list with more than an element, we produce a tuple (Int, A), where A is the actual type of elements in the list. If the source element is a list with a single element, we just produce that element, so the type is A.

In Scala this situation may be represented by means of Either, Left and Right. Good explanations of this matter may be found here and here.

Given that, the solution is straightforward

def encode[A](l: List[A]):List[Either[A, (Int, A)]] = {
    utils.packer.pack(l) map {
        e => e match {
            case e if e.length == 1 => Left(e.head)
            case e => Right((e.length, e.head))
        }
    }
}

I prefer to express conditions through pattern matching, but the same code may be expressed with an if/else statement.

Final considerations

This time I learned how to use the three types Either, Left and Right. Reading the suggested posts I also dug into Option, Some and None, and the three similar types introduced with Scala 2.10 Try, Success and Failure.

Feedback

The GitHub issues page is the best place to submit corrections.