Advent of Code Day 25–Mission Accomplished
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.