AdventOfCode/AdventOfCode.Solutions/2023/Day 03/Day03.cs

78 lines
2.7 KiB
C#

using System.Text.RegularExpressions;
namespace AdventOfCode.Solutions._2023
{
public partial class Day03 : IChallange
{
public int Year => 2023;
public int Day => 3;
private readonly InputReader _inputReader;
public Day03(InputReader inputReader)
{
_inputReader = inputReader;
_inputReader.SetInput(this);
}
private class PartNumber
{
public int X { get; set; }
public int Y { get; set; }
public string Section { get; set; } = string.Empty;
public int Length => Section.Length;
public bool IsDigit() => Section.All(char.IsDigit);
public bool IsPartSymbol() => !IsDigit();
}
public async Task<string> GetSolutionPart1()
{
var (Numbers, Symbols) = await GetNumbersAndSymbols();
return Numbers
.Where(number => Symbols.Any(s => number.Intersect(s)))
.Select(num => int.Parse(num.Value))
.Sum()
.ToString();
}
public async Task<string> GetSolutionPart2()
{
var (Numbers, Symbols) = await GetNumbersAndSymbols();
return Symbols
.Where(s => s.Value == '*')
.Select(g => Numbers.Where(n => n.Intersect(g)))
.Where(n => n.Count() == 2)
.Select(num => int.Parse(num.First().Value) * int.Parse(num.Last().Value))
.Sum()
.ToString();
}
private async Task<(List<Rectangle> Numbers, List<Point> Symbols)> GetNumbersAndSymbols()
{
List<PartNumber> parts = [];
int row = 0;
await foreach (string line in _inputReader.ReadAsStringLine())
{
row++;
MatchCollection matchCollection = FindPartItems().Matches(line);
parts.AddRange(matchCollection.Select(match => new PartNumber { X = match.Index + 1, Y = row, Section = match.Value }));
}
List<Rectangle> numbers = parts.Where(p => p.IsDigit()).Select(number => new Rectangle(new Point(number.X - 1, number.Y - 1), new Point(number.X + number.Length, number.Y + 1), number.Section)).ToList();
List<Point> symbols = parts.Where(p => p.IsPartSymbol()).Select(symbol => new Point(symbol.X, symbol.Y, symbol.Section[0])).ToList();
return (numbers, symbols);
}
[GeneratedRegex("(\\d+)", RegexOptions.Compiled)]
private static partial Regex FindDigits();
[GeneratedRegex("(\\d+)|([^.])", RegexOptions.Compiled)]
private static partial Regex FindPartItems();
}
}