Files
AdventOfCode/Days/Day5.cs
2025-12-06 23:15:01 +01:00

133 lines
3.7 KiB
C#

using Spectre.Console;
namespace AdventOfCode.Days;
public class Day5 : Day
{
public override int Number => 5;
public override string Name => "Cafeteria";
public override void RunPart1(bool display = true)
{
var freshIngredients = 0;
var idRanges = new List<IdRange>();
var readingRanges = true;
foreach (var line in Input.EnumerateLines())
{
// Read ranges
if (readingRanges)
{
// End of ranges
if (line.IsWhiteSpace())
{
readingRanges = false;
continue;
}
var rangeSeparatorIndex = line.IndexOf('-');
var lower = long.Parse(line[..rangeSeparatorIndex]);
var upper = long.Parse(line[(rangeSeparatorIndex + 1)..]);
idRanges.Add(new IdRange(lower, upper));
}
else
{
// Read ingredients
var ingredientId = long.Parse(line);
if (idRanges.Any(range => ingredientId >= range.Lower && ingredientId <= range.Upper))
{
freshIngredients++;
}
}
}
if (display)
{
AnsiConsole.MarkupLine($"[green]Fresh ingredients count: [yellow]{freshIngredients}[/][/]");
}
}
public override void RunPart2(bool display = true)
{
var idRanges = new List<IdRange>();
var rangesToDelete = new List<IdRange>();
// Read ranges
foreach (var line in Input.EnumerateLines())
{
// End of ranges
if (line.IsWhiteSpace())
{
break;
}
var rangeSeparatorIndex = line.IndexOf('-');
var lower = long.Parse(line[..rangeSeparatorIndex]);
var upper = long.Parse(line[(rangeSeparatorIndex + 1)..]);
// Simplify ranges if there is overlap
rangesToDelete.Clear();
var skipRange = false;
foreach (var idRange in idRanges)
{
// Distinct
if (lower > idRange.Upper || upper < idRange.Lower)
{
continue;
}
// Outer overlap
if (lower >= idRange.Lower && upper <= idRange.Upper)
{
skipRange = true;
break;
}
// Inner overlap
if (lower <= idRange.Lower && upper >= idRange.Upper)
{
rangesToDelete.Add(idRange);
}
// Left overlap
if (lower >= idRange.Lower && lower <= idRange.Upper)
{
lower = idRange.Lower;
rangesToDelete.Add(idRange);
}
// Right overlap
if (upper >= idRange.Lower && upper <= idRange.Upper)
{
upper = idRange.Upper;
rangesToDelete.Add(idRange);
}
}
if (!skipRange)
{
foreach (var idRange in rangesToDelete)
{
idRanges.Remove(idRange);
}
idRanges.Add(new IdRange(lower, upper));
}
}
var freshIngredients = idRanges.Sum(range => (range.Upper - range.Lower) + 1);
if (display)
{
AnsiConsole.MarkupLine($"[green]Fresh ingredients count: [yellow]{freshIngredients}[/][/]");
}
}
private record struct IdRange(long Lower, long Upper);
}