namespace day3; public class Day3 { private int _rows; private int _columns; private char[][] _grid; public Day3(string fileContents) { var lines = fileContents.Split(Environment.NewLine); _grid = lines.Select(line => line.ToCharArray()).ToArray(); _rows = _grid.Length; _columns = _grid[0].Length; } private bool _isCharacterASymbol(char c) { return !char.IsDigit(c) && c != '.'; } private bool _isSymbolInSurroundingLocation(int i, int j) { var foundSymbol = false; for (var ii = i - 1; ii <= i + 1; ii++) { for (var jj = j - 1; jj <= j + 1; jj++) { if (ii >= 0 && jj >= 0 && ii < _rows && jj < _columns) { foundSymbol |= _isCharacterASymbol(_grid[ii][jj]); } } } return foundSymbol; } private IEnumerable _getSurroundingMachineParts(int i, int j, IList machineParts) { return machineParts.Where(machinePart => machinePart.Locations.Aggregate(false, (hasBeenFound, currentPoint) => { var differenceRow = Math.Abs(i - currentPoint.Item1); var differenceCol = Math.Abs(j - currentPoint.Item2); return hasBeenFound || (!(differenceRow == 0 && differenceCol == 0) && differenceRow <= 1 && differenceCol <= 1); })); } private IList _getAllMachinePartsInGrid() { var machinePartsList = new List(); int currentlyParsedNumber = 0; var locations = new List<(int, int)>(); bool isSymbolFound = false; // We want to iterate over every cell for (int i = 0; i < _rows; i++) { for (int j = 0; j < _columns; j++) { var cellContents = _grid[i][j]; if (char.IsDigit(cellContents)) { // Check the surroundings for a symbol isSymbolFound |= _isSymbolInSurroundingLocation(i, j); locations.Add((i, j)); currentlyParsedNumber = (currentlyParsedNumber * 10) + int.Parse(cellContents.ToString()); } // Check if we are done scanning the number (i.e. at the end of a row or we find a non-integer) if (!char.IsDigit(cellContents) || j == _columns - 1) { if (isSymbolFound) { machinePartsList.Add(new MachinePart { Id = machinePartsList.Count, Value = currentlyParsedNumber, Locations = locations }); } locations = new List<(int, int)>(); currentlyParsedNumber = 0; isSymbolFound = false; } } } return machinePartsList; } public int PartOne() { var machinePartsList = _getAllMachinePartsInGrid(); return machinePartsList.Aggregate(0, (total, current) => total + current.Value); } public long PartTwo() { var machinePartsList = _getAllMachinePartsInGrid(); var runningTotal = 0L; // We are going to do a scan for all gears for (int i = 0; i < _rows; i++) { for (int j = 0; j < _columns; j++) { var cellContents = _grid[i][j]; if (cellContents == '*') { var surroundingMachineParts = _getSurroundingMachineParts(i, j, machinePartsList); var numberOfSurroundingMachingParts = surroundingMachineParts.Count(); if (numberOfSurroundingMachingParts == 2) { runningTotal += surroundingMachineParts.Aggregate(1, (currentRatio, machinePart) => currentRatio * machinePart.Value); } } } } return runningTotal; } }