using System.Collections.Generic;
const short ResetValueAfterReproduction = 6;
const short NewFishReproductionDays = 8;
var response = await new HttpClient().GetStringAsync("https://tompafireadventofcode.free.beeceptor.com/day6");
var reproductionValues = response.Split(',').Select(short.Parse);
var timePeriod = TimeSpan.FromDays(80);
var laternFishes1 = new List<short>(reproductionValues);
var count1 = RunReproductionPeriod(timePeriod, laternFishes1);
Console.WriteLine($"Step 1: {count1}");
var timePeriod2 = TimeSpan.FromDays(256);
var laternFishes2 = new List<short>(reproductionValues);
var count2 = RunReproductionPeriod(timePeriod2, laternFishes2);
Console.WriteLine($"Step 2: {count2}");
long RunReproductionPeriod(TimeSpan timePeriod, List<short> reproductionValues)
var countByDaysToReproduction = reproductionValues.GroupBy(v => v)
.ToDictionary(v => v.Key, v => v.LongCount());
for (var day = 1; day <= timePeriod.Days; day++)
var changes = CalculateChanges(countByDaysToReproduction, day).ToList();
ApplyChanges(countByDaysToReproduction, changes);
var count = countByDaysToReproduction.Values.Sum(v => v);
IEnumerable<(short day, Func<long, long> change)> CalculateChanges(Dictionary<short, long> countByDaysToReproduction, int day)
foreach (var entry in countByDaysToReproduction.OrderBy(x => x.Key))
var daysUntilReproduction = entry.Key;
if (daysUntilReproduction == 0)
var moveToKey = ResetValueAfterReproduction;
yield return (0, v => v - entry.Value);
yield return (moveToKey, v => v + entry.Value);
var fishesToAdd = entry.Value;
yield return (NewFishReproductionDays, v => v + fishesToAdd);
var moveToKey = (short)(daysUntilReproduction - 1);
yield return (daysUntilReproduction, v => v - entry.Value);
yield return (moveToKey, v => v + entry.Value);
void ApplyChanges(Dictionary<short, long> countByDaysToReproduction, IEnumerable<(short day, Func<long, long> change)> changes)
foreach (var change in changes)
if (!countByDaysToReproduction.ContainsKey(change.day))
countByDaysToReproduction.Add(change.day, 0);
countByDaysToReproduction[change.day] = change.change(countByDaysToReproduction[change.day]);