AdventOfCode/AoC_2025/Day05.cs

112 lines
3.5 KiB
C#

using AdvenOfCode.Contracts;
using AdventOfCode.HelperClasses;
namespace AoC_2025;
public class Day05 : IPuzzleSolver<long>
{
private (List<string> freshIdRanges, List<string> ids) ParsePuzzleInput(string path)
{
var puzzleInput = File.ReadAllLines(path)
.Select(line => line.Trim())
.ToList();
var middle = puzzleInput.IndexOf("");
var freshIdRanges = puzzleInput[..middle];
var ids = puzzleInput[(middle + 1)..];
return (freshIdRanges, ids);
}
public long SolvePart1(string pathToPuzzleInput)
{
var database = ParsePuzzleInput(pathToPuzzleInput);
var freshIdRanges = ParseRanges(database.freshIdRanges);
var ids = ParseIds(database.ids);
var freshIds = FilterFreshIds(ids, freshIdRanges);
return freshIds.Count();
}
public long SolvePart2(string pathToPuzzleInput)
{
var database = ParsePuzzleInput(pathToPuzzleInput);
var freshIdRanges = ParseRanges(database.freshIdRanges);
var sumIds = SumIdsInRanges(freshIdRanges);
return sumIds;
}
public long SolvePart2Again(string pathToPuzzleInput)
{
var database = ParsePuzzleInput(pathToPuzzleInput);
var freshIdRanges = ParseRanges(database.freshIdRanges);
var combinedRanges = CombineOverlappingRanges(freshIdRanges);
var countIdsInRanges = CountIdsInRanges(combinedRanges);
var sumIds = countIdsInRanges.Sum();
return sumIds;
}
private IEnumerable<long> ParseIds(List<string> ids)
{
var parsedIds = ids.Select(id => long.Parse(id));
return parsedIds;
}
private IntegerRange[] ParseRanges(IEnumerable<string> ranges)
{
return ranges.Select(range =>
{
var split = range.Split('-', StringSplitOptions.RemoveEmptyEntries);
return new IntegerRange(long.Parse(split[0]), long.Parse(split[1]));
})
.OrderBy(range => range.start)
.ThenBy(range => range.end)
.ToArray();
}
private IEnumerable<long> FilterFreshIds(IEnumerable<long> ids, IntegerRange[] freshIdRanges)
{
var freshIds = ids.Where(id => IsIdInRanges(id, freshIdRanges));
return freshIds;
}
private bool IsIdInRanges(long id, IEnumerable<IntegerRange> ranges)
{
return ranges.Any(range => range.Contains(id));
}
private long SumIdsInRanges(IEnumerable<IntegerRange> ranges)
{
var sumFreshIds = 0L;
var highestSeenId = -1L;
foreach (var range in ranges)
{
var lowestNewId = Math.Max(highestSeenId + 1, range.start);
highestSeenId = Math.Max(highestSeenId, range.end);
sumFreshIds += Math.Max(0, highestSeenId - lowestNewId + 1);
}
return sumFreshIds;
}
private List<IntegerRange> CombineOverlappingRanges(IntegerRange[] ranges)
{
var optimizedRanges = new List<IntegerRange>(ranges.Length) { ranges[0] };
foreach (var range in ranges)
{
if (optimizedRanges[^1].TryCombine(range, out var combined))
{
optimizedRanges[^1] = combined;
}
else
{
optimizedRanges.Add(range);
}
}
return optimizedRanges;
}
private static IEnumerable<long> CountIdsInRanges(IEnumerable<IntegerRange> combinedRanges)
{
var countIdsInRanges = combinedRanges.Select(range => range.Count);
return countIdsInRanges;
}
}