The theme for today is:
Sometimes looking up is better than searching
Think of clustering the lanternfish swarm into buckets of their current day of the creation cycle.
GroupBy() 1 followed by
ToDictionary() 2 to compute the initial clustering:
IDictionary<int, long> swarm = input.GroupBy(d => d).ToDictionary(i => i.Key, i => (long)i.Count());
Then you can computer the new clustering after an iteration by iterating over the buckets of your clustering and computing the new count of lanternfish and the new bucket(s).
Puzzle two is only about performance. If your the implementation of puzzle one is efficient, it’s just a change of parameters.
Full Source is available on GitHub. 3