Day 10’s challenge at Advent of Code was based on a fun number sequence called “Look and Say” numbers. As usual, I recorded a video explaining my solution, but inexplicably, YouTube rejected my video, citing “inappropriate content”! I’ve really got no idea what the issue with it is, and I’ve appealed the decision, so hopefully at some point I’ll be able to update my playlist with the video.

But for now, my workaround is to upload to Vimeo. So if you want to watch the content that was too shocking for YouTube to host, here it is…

Anyway, for C#, the problem is trivially solved with MoreLINQ’s `GroupAdjacent` method, and once again the `Aggregate` method comes in handy to construct each consecutive member of the sequence based on the last one.

``````Enumerable.Range(1, 40)
.Aggregate("1113122113".Select(c => c - '0').ToArray(),
(acc,_) => acc
.SelectMany(g => new int[] { g.Count(), g.First() })
.ToArray())
.Count()
``````

For my F# solution I created my own `CountAdjacent` method, to return tuples of adjacent elements and their counts. Initially I did this with some mutable state (as shown in the video), but I’ve had time to clean it up a bit since then, and might even record a new video to see if I can get it onto YouTube.

So here’s  what I ended up with in F#, making use of `Seq.fold` both in implementing `CountAdjacent`, and to repeatedly run the output of `lookAndSay` on its own output.

``````let input = "1113122113" |> Seq.map (fun f -> int f - int '0') |> Seq.toArray

Seq.fold (fun s x ->
match s with
| [|n;c|]::tail when c = x -> [|n+1;c|]::tail
| l -> [|1;x|]::l) []
>> List.rev

let lookAndSay = countAdjacent >> Seq.collect id >> Seq.toArray

let getLengthAfterRepetitions repetitions =
[1..repetitions]
|> Seq.fold (fun acc _ -> lookAndSay acc) input
|> Seq.length

getLengthAfterRepetitions 40 |> printf "a: %d"
getLengthAfterRepetitions 50 |> printf "b: %d"
``````

As always let me know in the comments how I could improve my solution.

Want to learn more about LINQ? Be sure to check out my Pluralsight course LINQ Best Practices.

``let (|Matches|) pattern =  let rgx = Regex (pattern, RegexOptions.Compiled)  fun input -> [for m in rgx.Matches input -> [for g in m.Groups -> g.Value]]let common nth =  "3113322113"  |> Seq.unfold (fun str ->    match str with    Matches "(\d)\1*" xs ->    Some (str, xs               |> Seq.map (function [repeat; digit] -> sprintf "%d%s" repeat.Length digit                                  | _ -> failwith "")               |> String.concat ""))  |> Seq.item nth  |> String.lengthlet part1 () = common 40let part2 () = common 50``