Skip to content

Commit

Permalink
2023 Day03 Refactored
Browse files Browse the repository at this point in the history
  • Loading branch information
smabuk committed Dec 3, 2023
1 parent 9a50d64 commit 3cbb949
Showing 1 changed file with 56 additions and 50 deletions.
106 changes: 56 additions & 50 deletions Solutions/2023/Day03.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Linq;
using PartNoAndAPosition = (int PartNo, Smab.Helpers.Point Position);

namespace AdventOfCode.Solutions._2023;

Expand All @@ -12,64 +12,18 @@ public sealed partial class Day03 {
public static string Part1(string[] input, params object[]? _) => Solution1(input).ToString();
public static string Part2(string[] input, params object[]? _) => Solution2(input).ToString();

private static int Solution1(string[] input) {
List<int> partNos = [];

char[,] engine = string.Join("", input).To2dArray<char>(input[0].Length);
int maxX = input[0].Length - 1;
int maxY = input.Length - 1;
for (int row = 0; row < input.Length; row++) {
string engineLine = input[row].Replace('.', ' ');
MatchCollection possibleParts = Regex.Matches(engineLine, @"(?<number>\d+)");
foreach (Match number in possibleParts) {
bool foundPart = false;
for (int y = Math.Max(row - 1, 0); y <= Math.Min(row + 1, maxY); y++) {
for (int x = Math.Max(number.Index - 1, 0); x < Math.Min(number.Index + number.Length + 1, maxX); x++) {
char cell = engine[x, y];
if (!char.IsDigit(cell) && cell is not '.') {
partNos.Add(number.Value.AsInt());
foundPart = true;
break;
}
}
if (foundPart) {
break;
}
}
}
}

return partNos.Sum();
}
private static int Solution1(string[] input) => FindPartNosAndGears(input, 1).Select(p => p.PartNo).Sum();

private static int Solution2(string[] input) {
List<(int PartNo, Point Position)> possibleGears = [];

char[,] engine = string.Join("", input).To2dArray<char>(input[0].Length);
int maxX = input[0].Length - 1;
int maxY = input.Length - 1;
for (int row = 0; row < input.Length; row++) {
string engineLine = input[row].Replace('.', ' ');
MatchCollection possibleParts = Regex.Matches(engineLine, @"(?<number>\d+)");
foreach (Match number in possibleParts) {
for (int y = Math.Max(row - 1, 0); y <= Math.Min(row + 1, maxY); y++) {
for (int x = Math.Max(number.Index - 1, 0); x < Math.Min(number.Index + number.Length + 1, maxX); x++) {
char cell = engine[x, y];
if (cell is '*') {
possibleGears.Add((number.Value.AsInt(), new(x, y)));
}
}
}
}
}
List<PartNoAndAPosition> possibleGears = FindPartNosAndGears(input, 2);

IEnumerable<Point> gearPositions = possibleGears
.GroupBy(p => p.Position)
.Where(p => p.Count() == 2)
.Select(g => g.Key);

int sumOfGearRatios = 0;
foreach (var position in gearPositions) {
foreach (Point position in gearPositions) {
sumOfGearRatios += possibleGears
.Where(g => g.Position == position)
.Select(g => g.PartNo)
Expand All @@ -78,4 +32,56 @@ private static int Solution2(string[] input) {

return sumOfGearRatios;
}

private static List<PartNoAndAPosition> FindPartNosAndGears(string[] input, int solutionPartNo)
{
const char GEAR = '*';
const char SPACE = '.';

char[,] engineSchematic = string.Join("", input).To2dArray(input[0].Length);
int maxX = input[0].Length - 1;
int maxY = input.Length - 1;

List<PartNoAndAPosition> list = [];

for (int row = 0; row < input.Length; row++) {
foreach (Match number in NumberRegex().Matches(input[row])) {
SearchAdjacent(row, number);
}
}

return list;

void SearchAdjacent(int row, Match number)
{
int lowerY = Math.Max(row - 1, 0);
int upperY = Math.Min(row + 1, maxY);
int lowerX = Math.Max(number.Index - 1, 0);
int upperX = Math.Min(number.Index + number.Length + 1, maxX);
int skip = Math.Max(number.Length - 2, 1); // Can skip self
bool foundPart = false;
for (int y = lowerY; y <= upperY; y++) {
for (int x = lowerX; x < upperX; x += (y == row ? skip : 1)) {
char cellValue = engineSchematic[x, y];
if (solutionPartNo == 1) {
if (IsSymbol(cellValue)) {
list.Add((number.Value.AsInt(), new(number.Index, row)));
foundPart = true;
break;
}
} else if (cellValue is GEAR) { // Part2
list.Add((number.Value.AsInt(), new(x, y)));
}
}
if (foundPart) {
break;
}
}
}

bool IsSymbol(char cell) => !(char.IsDigit(cell) || cell is SPACE);
}

[GeneratedRegex(@"\d+")]
private static partial Regex NumberRegex();
}

0 comments on commit 3cbb949

Please sign in to comment.