From 7739cb08a520023ff6746ed85bea749c03aae2e7 Mon Sep 17 00:00:00 2001 From: Amatsugu Date: Wed, 11 Dec 2024 21:37:58 -0500 Subject: [PATCH] Day 7 Part1 Day 8 --- .../Problems/AOC2024/Day6/GuardGallivant.cs | 12 +- .../Problems/AOC2024/Day7/BridgeRepair.cs | 68 ++++++++- .../AOC2024/Day8/ResonantCollinearity.cs | 139 ++++++++++++++++++ AdventOfCode/Utils/Models/Common.cs | 20 ++- 4 files changed, 232 insertions(+), 7 deletions(-) create mode 100644 AdventOfCode/Problems/AOC2024/Day8/ResonantCollinearity.cs diff --git a/AdventOfCode/Problems/AOC2024/Day6/GuardGallivant.cs b/AdventOfCode/Problems/AOC2024/Day6/GuardGallivant.cs index 1c04bcb..b804ecf 100644 --- a/AdventOfCode/Problems/AOC2024/Day6/GuardGallivant.cs +++ b/AdventOfCode/Problems/AOC2024/Day6/GuardGallivant.cs @@ -204,7 +204,6 @@ internal class GuardGallivant : Problem found.Add(obstaclePos); } - //} } } } @@ -253,13 +252,13 @@ file class GuardMap var curNode = nodes[0]; while (true) { - if (curNode.Next is int nextId) + if (curNode.Next is int nextId && nextId >= 0) { var next = nodes[nextId]; path.AddRange(GetPointsBetween(curNode.Pos, next.Pos, curNode.Direction).Select(p => (p, curNode))); curNode = next; } - else + else if(curNode.Next == -1) { var end = curNode.Direction switch { @@ -271,7 +270,8 @@ file class GuardMap }; path.AddRange(GetPointsBetween(curNode.Pos, end, curNode.Direction).Select(p => (p, curNode))); break; - } + }else + break; } return path; @@ -312,7 +312,11 @@ file class GuardMap while (true) { if (!GetNextObstacle(curNode.Pos, curNode.Direction, out var next)) + { + curNode.Next = -1; + Nodes[curNode.Id] = curNode; break; + } var newNode = new GuardNode(next - GuardGallivant.DIRS[curNode.Direction], (curNode.Direction + 1) % 4, Nodes.Count); curNode.Next = newNode.Id; Nodes[curNode.Id] = curNode; diff --git a/AdventOfCode/Problems/AOC2024/Day7/BridgeRepair.cs b/AdventOfCode/Problems/AOC2024/Day7/BridgeRepair.cs index afc82ad..5ec1513 100644 --- a/AdventOfCode/Problems/AOC2024/Day7/BridgeRepair.cs +++ b/AdventOfCode/Problems/AOC2024/Day7/BridgeRepair.cs @@ -5,6 +5,70 @@ using System.Text; using System.Threading.Tasks; namespace AdventOfCode.Problems.AOC2024.Day7; -internal class BridgeRepair + +[ProblemInfo(2024, 7, "Bridge Repair")] +internal class BridgeRepair : Problem { -} + private List<(ulong total, ulong[] nums)> _data = []; + + private enum Operator + { + Mul, + Add, + Concat + } + + public override void CalculatePart1() + { + foreach (var (target, nums) in _data) + { + if (IsSolvable(target, nums, [Operator.Mul, Operator.Add])) + Part1 += target; + } + } + + private bool IsSolvable(ulong target, ulong[] nums, Operator[] ops) + { + return ops.Any(o => IsSolvable(target, nums, o, nums[0], ops)); + } + + private bool IsSolvable(ulong target, ulong[] nums, Operator curOperator, ulong curTotal, Operator[] ops, int idx = 1) + { + if (target == curTotal) + return true; + if (idx >= nums.Length) + return false; + + curTotal = curOperator switch + { + Operator.Mul => curTotal * nums[idx++], + Operator.Add => curTotal + nums[idx++], + Operator.Concat => ulong.Parse($"{curTotal}{nums[idx++]}"), + _ => curTotal, + }; + + return ops.Any(o => IsSolvable(target, nums, o, curTotal, ops, idx)); + } + + public override void CalculatePart2() + { + foreach (var (target, nums) in _data) + { + if (IsSolvable(target, nums, [Operator.Mul, Operator.Add, Operator.Concat])) + Part2 += target; + } + } + + public override void LoadInput() + { + var lines = ReadInputLines("input.txt"); + _data = new List<(ulong total, ulong[] nums)>(lines.Length); + foreach (var line in lines) + { + var s = line.Split(':'); + var sum = ulong.Parse(s[0].Trim()); + var nums = s[1].Trim().Split(' ').Select(ulong.Parse).ToArray(); + _data.Add((sum, nums)); + } + } +} \ No newline at end of file diff --git a/AdventOfCode/Problems/AOC2024/Day8/ResonantCollinearity.cs b/AdventOfCode/Problems/AOC2024/Day8/ResonantCollinearity.cs new file mode 100644 index 0000000..3e2b9e4 --- /dev/null +++ b/AdventOfCode/Problems/AOC2024/Day8/ResonantCollinearity.cs @@ -0,0 +1,139 @@ +using AdventOfCode.Utils.Models; + +using System.Collections.Frozen; + +namespace AdventOfCode.Problems.AOC2024.Day8; + +[ProblemInfo(2024, 8, "Resonant Collinearity")] +internal class ResonantCollinearity : Problem +{ + private string[] _map = []; + private int _width; + private int _height; + private FrozenDictionary>> _nodes = FrozenDictionary>>.Empty; + + public override void CalculatePart1() + { + var antiNodes = new List>(); + foreach (var (nodeType, nodes) in _nodes) + { + foreach (var a in nodes) + { + foreach (var b in nodes) + { + if (a == b) + continue; + antiNodes.AddRange(GetAntiNodes(a, b)); + } + } + } + //PrintBoard(antiNodes); + Part1 = antiNodes.Where(IsInBounds).Distinct().Count(); + } + + public void PrintBoard(List> antinodes) + { + Console.WriteLine(); + for (int y = 0; y < _height; y++) + { + for (int x = 0; x < _width; x++) + { + Console.ResetColor(); + var p = new Vec2(x, y); + if (antinodes.Contains(p)) + Console.BackgroundColor = ConsoleColor.DarkGreen; + Console.Write(_map[y][x]); + } + Console.ResetColor(); + Console.WriteLine(); + } + Console.ResetColor(); + } + + public bool IsInBounds(Vec2 pos) + { + if (pos.X < 0 || pos.Y < 0) + return false; + if (pos.X >= _width || pos.Y >= _height) + return false; + return true; + } + + private Vec2[] GetAntiNodes(Vec2 a, Vec2 b) + { + var dir = a - b; + + var aNode1 = dir + a; + var aNode2 = -dir + b; + + return [aNode1, aNode2]; + } + + private Vec2[] GetHarmonicAntiNodes(Vec2 a, Vec2 b) + { + var dir = a - b; + + List> GetNodes(Vec2 start, Vec2 dir) + { + var results = new List>(); + while (true) + { + var p = dir + start; + if(!IsInBounds(p)) + break; + results.Add(p); + start = p; + + } + return results; + } + + return [.. GetNodes(a, dir), .. GetNodes(b, -dir)]; + } + + public override void CalculatePart2() + { + var antiNodes = new List>(); + foreach (var (nodeType, nodes) in _nodes) + { + foreach (var a in nodes) + { + foreach (var b in nodes) + { + if (a == b) + continue; + antiNodes.AddRange(GetHarmonicAntiNodes(a, b)); + } + } + } + //PrintBoard(antiNodes); + antiNodes.AddRange(_nodes.Values.Where(v => v.Count > 1).SelectMany(v => v)); + Part2 = antiNodes.Distinct().Count(); + } + + public override void LoadInput() + { + _map = ReadInputLines("input.txt"); + var nodes = new Dictionary>>(); + _width = _map[0].Length; + _height = _map.Length; + for (int y = 0; y < _map.Length; y++) + { + var row = _map[y]; + for (int x = 0; x < row.Length; x++) + { + switch (row[x]) + { + case '.': + continue; + default: + var p = new Vec2(x, y); + if (!nodes.TryAdd(row[x], [p])) + nodes[row[x]].Add(p); + continue; + } + } + } + _nodes = nodes.ToFrozenDictionary(); + } +} \ No newline at end of file diff --git a/AdventOfCode/Utils/Models/Common.cs b/AdventOfCode/Utils/Models/Common.cs index 76738a0..53490e3 100644 --- a/AdventOfCode/Utils/Models/Common.cs +++ b/AdventOfCode/Utils/Models/Common.cs @@ -2,19 +2,37 @@ namespace AdventOfCode.Utils.Models; - public record struct Vec2(T X, T Y) where T : INumber { public static Vec2 operator +(Vec2 left, Vec2 right) => new Vec2(left.X + right.X, left.Y + right.Y); public static Vec2 operator -(Vec2 left, Vec2 right) => new Vec2(left.X - right.X, left.Y - right.Y); + public static Vec2 operator -(Vec2 vec) => new Vec2(-vec.X, -vec.Y); public static Vec2 operator *(Vec2 left, T right) => new Vec2(left.X * right, left.Y * right); + public static Vec2 operator *(T left, Vec2 right) => new Vec2(right.X * left, right.Y * left); public static Vec2 operator /(Vec2 left, T right) => new Vec2(left.X / right, left.Y / right); + + public T DistanceSq(Vec2 other) + { + var a = other.X - this.X; + var b = other.Y - this.Y; + return (a * a) + (b * b); + } } public record struct Vec3(T X, T Y, T Z) where T : INumber { public static Vec3 operator +(Vec3 left, Vec3 right) => new Vec3(left.X + right.X, left.Y + right.Y, left.Z + right.Z); public static Vec3 operator -(Vec3 left, Vec3 right) => new Vec3(left.X - right.X, left.Y - right.Y, left.Z - right.Z); + public static Vec3 operator -(Vec3 vec) => new Vec3(-vec.X, -vec.Y, -vec.Z); public static Vec3 operator *(Vec3 left, T right) => new Vec3(left.X * right, left.Y * right, left.Z * right); + public static Vec3 operator *(T left, Vec3 right) => new Vec3(right.X * left, right.Y * left, right.Z * left); public static Vec3 operator /(Vec3 left, T right) => new Vec3(left.X / right, left.Y / right, left.Z / right); + + public T DistanceSq(Vec3 other) + { + var a = other.X - this.X; + var b = other.Y - this.Y; + var c = other.Z - this.Z; + return (a * a) + (b * b) + (c * c); + } } \ No newline at end of file