using AdventOfCode.Core.Shared.IO; using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks.Dataflow; namespace AdventOfCode.Solutions._2024 { public class Day04 : IChallange { public int Year => 2024; public int Day => 4; private readonly IInputReader _inputReader; public Day04(IInputReader inputReader) { _inputReader = inputReader; _inputReader.SetInput(this); } //18 //2514 public async Task GetSolutionPart1() { Grid grid = await _inputReader.ReadToGrid(); int total = grid.FindWithValue('X').Sum(p => GetPossibleMatches(grid, p, "XMAS")); total += grid.FindWithValue('S').Sum(p => GetPossibleMatches(grid, p, "SAMX")); return total.ToString(); } //9 //1888 public async Task GetSolutionPart2() { Grid grid = await _inputReader.ReadToGrid(); int total = grid.FindWithValue('M').Where(p => IsValid(grid, p, 'S')).Count(); total += grid.FindWithValue('S').Where(p => IsValid(grid, p, 'M')).Count(); return total.ToString(); } private static bool IsValid(Grid grid, Point p, char otherValue) { // validate the bounding box if (p.X + 3 > grid.Columns || p.Y + 3 > grid.Rows) { return false; } // check that +1,+1 from the point is A if (grid.GetNode(p.X + 1, p.Y + 1).Value != 'A') { return false; } if((grid.GetNode(p.X, p.Y).Value == 'M' && grid.GetNode(p.X + 2, p.Y + 2).Value == 'S' || grid.GetNode(p.X, p.Y).Value == 'S' && grid.GetNode(p.X + 2, p.Y + 2).Value == 'M') && (grid.GetNode(p.X, p.Y + 2).Value == 'M' && grid.GetNode(p.X + 2, p.Y).Value == 'S' || grid.GetNode(p.X, p.Y + 2).Value == 'S' && grid.GetNode(p.X + 2, p.Y).Value == 'M')) return true; return false; } private static int GetPossibleMatches(Grid grid, Point start, string word) { int matches = 0; bool canLookUp = start.Y + 1 >= word.Length, canLookForward = grid.Columns - start.X >= word.Length, canLookDown = grid.Rows - start.Y >= word.Length; // check up if possible if (canLookUp && canLookForward && IsMatch(grid, start, -1, 1, word)) { matches++; } if (canLookForward && IsMatch(grid, start, 0, 1, word)) { matches++; } if (canLookForward && canLookDown && IsMatch(grid, start, 1, 1, word)) { matches++; } if (canLookDown && IsMatch(grid, start, 1, 0, word)) { matches++; } return matches; } private static bool IsMatch(Grid grid, Point start, int rowChange, int columnChange, string word) { for (int index = 1; index < word.Length; index++) { if (grid.GetNode(start.X + (columnChange * index), start.Y + (rowChange * index)).Value != word[index]) return false; } return true; } } }