The way you implemented to_run_length is correct, readable, and efficient. This is a good decision. (nitpick only: indent after in is wrong)
If you want to avoid an intermediate function, you should instead use the information present in the return from the recursive call. This can be described in a slightly more abstract way:
- the length of the empty list is the empty list
- the path length in the list
x::xs is equal to- if the encoding of length
xs starts with x , then ... - if not, then
(x,1) :: enter the length xs
(I intentionally do not provide source code so that you can work with the details, but unfortunately there is not much to hide with such relatively simple functions.)
Food for thought. You usually come across such methods when considering recursive and non-tail recursive functions (what I did is like turning the tail-rec function in the form of non-tail-rec). In this particular case, your original function was not recursive. A function is tail recursive when the argument / result flows only βdropβ the recursive calls (you return them, rather than reusing them to create a larger result). In my function, the stream of arguments / results only "raises" recursive calls (calls have the least information, and all the logic in the code is done by checking the results). In your implementation, threads go both down (integer counter) and up (encoded result).
Edit: as requested by the source poster, here is my solution:
let rec run_length = function | [] -> [] | x::xs -> match run_length xs with | (n,y)::ys when x = y -> (n+1,x)::ys | res -> (1,x)::res
source share