0 Comments Posted in:

So we’ve finally got to the end of the Advent of Code series of challenges. I hope you’ve enjoyed following along with my solutions. Let’s get straight down to business and see how the challenge for Christmas Day could be solved in C# with LINQ and F#:

The C# code is quite straightforward with LINQ, making use of the TakeWhile method to get a sequence of coordinates of the right length and Aggregate to perform the transformation the necessary number of times. The two parameter SelectMany expands each diagonal into all the coordinates on that diagonal.

Enumerable.Range(1, 10000)
.SelectMany(d => Enumerable.Range(1, d),
    (d,c) => new { row = d - c + 1, col = c })
.TakeWhile(d => !(d.row == 2978 && d.col == 3083))
.Aggregate(20151125L, (acc, _) => (acc * 252533L) % 33554393L)

The F# is similar. A sequence expression with nested for loops is nicer than SelectMany (or Seq.collect), and Seq.initInfinite comes in handy here. F# also has a Seq.takeWhile function, which we can use to compare each coordinate tuple with our endpoint, although I do find not equals operations a bit cumbersome to work with in F#. Finally, the Seq.fold function essentially does what LINQ’s Aggregate does.

seq { for d in Seq.initInfinite id do for c in 1..d do yield d - c + 1, c }
|> Seq.takeWhile (((=) (2978,3083)) >> not)
|> Seq.fold(fun a _-> (a * 252533L) % 33554393L) 20151125L
|> printfn "Day 25: %i" 

Anyway, I hope you’ve enjoyed following this series. I’ll probably do one final roundup post where I discuss what I’ve learned through attempting this challenge. Do subscribe to my youtube channel or this blog if you are interested in more. I hope to make a few other series on other aspects of programming.

Want to learn more about LINQ? Be sure to check out my Pluralsight course More Effective LINQ. I'm also speaking on LINQ at Techorama Netherlands 2018 on 3rd October, so I'd love to see you there if you can make it.
Vote on HN