DISCLOSURE: If you buy through affiliate links, I may earn a small commission. (disclosures)
In this post we'll walk through my solution to Advent of Code 2025 Day 5 in C#.
Notes:
Part 1:
* Fresh food ranges, blank line, then inventory food
Goal:
* Get the count of fresh foods
Subproblems:
* A: How to parse the data
* Find first empty line - split on that
* Grab the fresh data and put into set
* Go over other food and see if fresh
* B: How to do the fresh inventory parsing - O(n)
* 1: Simple fresh to set then go thorugh inventory and check
-> Hashset not working, it's OOM
* To do less memory:
* A: Do intervals
* Sort by low ranges, merge ranges
* See if fresh food id in the inventories
I originally tried doing a simple range to set lookup but OOMed as the number values are huge. So had to switch to a merge range and binary search.
public static long Day5Part1(string[] lines)
{
var indexOfInventory = lines.ToList().IndexOf("");
var foodInventory = lines.Skip(indexOfInventory + 1).ToList();
var freshFoodRanges = BuildFreshFoodDataRanges(lines.Take(indexOfInventory).ToArray());
return foodInventory
.Select(long.Parse)
.Select(foodId => IsFoodIdInFreshData(freshFoodRanges, foodId))
.Count(isInRange => isInRange);
}
public static List<FoodRangeInclusive> BuildFreshFoodDataRanges(string[] lines)
{
return lines
.Select(l => l.Split("-"))
.Select(rawStrings => new FoodRangeInclusive(long.Parse(rawStrings[0]), long.Parse(rawStrings[1])))
.OrderBy(r => r.Low)
.Aggregate(new List<FoodRangeInclusive>(), (acc, next) =>
{
if (acc.Count == 0 || next.Low > acc[^1].High + 1)
acc.Add(next);
else
acc[^1] = new FoodRangeInclusive(acc[^1].Low, Math.Max(acc[^1].High, next.High));
return acc;
});
}
public static bool IsFoodIdInFreshData(List<FoodRangeInclusive> freshFoodRanges, long foodId)
{
int lo = 0, hi = freshFoodRanges.Count - 1;
while (lo <= hi)
{
int mid = lo + (hi - lo) / 2;
var range = freshFoodRanges[mid];
if (foodId < range.Low)
hi = mid - 1;
else if (foodId > range.High)
lo = mid + 1;
else
return true; // foodId is within [Low, High]
}
return false;
}
// Doesn't work - OOM, numbers too big
// public static HashSet<long> BuildFreshDataSet(string[] lines)
// {
// return lines
// .Select(l => l.Split("-"))
// .Select(rawStrings => (Lower: long.Parse(rawStrings[0]), Upper: long.Parse(rawStrings[1])))
// .SelectMany(t => EnumerableExtensions.RangeInclusive(t.Lower, t.Upper).ToList())
// .ToHashSet();
// }
Part 2 was pretty easy cause I already had the functionality coded - just had to sum up the merged ranges.
public static long Day5Part2(string[] lines)
{
var indexOfInventory = lines.ToList().IndexOf("");
var foodInventory = lines.Skip(indexOfInventory + 1).ToList();
var freshFoodRanges = BuildFreshFoodDataRanges(lines.Take(indexOfInventory).ToArray());
return freshFoodRanges
.Sum(range => range.High - range.Low + 1);
}
HAMINIONs Members get access to the full source code (Github Repo) and that of dozens of other example projects.
If you liked this post you might also like: