78 lines
2.7 KiB
C#
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();
|
|
}
|
|
} |