Day 7 Part1
Day 8
This commit is contained in:
@@ -204,7 +204,6 @@ internal class GuardGallivant : Problem<int, int>
|
|||||||
found.Add(obstaclePos);
|
found.Add(obstaclePos);
|
||||||
|
|
||||||
}
|
}
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -253,13 +252,13 @@ file class GuardMap
|
|||||||
var curNode = nodes[0];
|
var curNode = nodes[0];
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (curNode.Next is int nextId)
|
if (curNode.Next is int nextId && nextId >= 0)
|
||||||
{
|
{
|
||||||
var next = nodes[nextId];
|
var next = nodes[nextId];
|
||||||
path.AddRange(GetPointsBetween(curNode.Pos, next.Pos, curNode.Direction).Select(p => (p, curNode)));
|
path.AddRange(GetPointsBetween(curNode.Pos, next.Pos, curNode.Direction).Select(p => (p, curNode)));
|
||||||
curNode = next;
|
curNode = next;
|
||||||
}
|
}
|
||||||
else
|
else if(curNode.Next == -1)
|
||||||
{
|
{
|
||||||
var end = curNode.Direction switch
|
var end = curNode.Direction switch
|
||||||
{
|
{
|
||||||
@@ -271,7 +270,8 @@ file class GuardMap
|
|||||||
};
|
};
|
||||||
path.AddRange(GetPointsBetween(curNode.Pos, end, curNode.Direction).Select(p => (p, curNode)));
|
path.AddRange(GetPointsBetween(curNode.Pos, end, curNode.Direction).Select(p => (p, curNode)));
|
||||||
break;
|
break;
|
||||||
}
|
}else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
@@ -312,7 +312,11 @@ file class GuardMap
|
|||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (!GetNextObstacle(curNode.Pos, curNode.Direction, out var next))
|
if (!GetNextObstacle(curNode.Pos, curNode.Direction, out var next))
|
||||||
|
{
|
||||||
|
curNode.Next = -1;
|
||||||
|
Nodes[curNode.Id] = curNode;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
var newNode = new GuardNode(next - GuardGallivant.DIRS[curNode.Direction], (curNode.Direction + 1) % 4, Nodes.Count);
|
var newNode = new GuardNode(next - GuardGallivant.DIRS[curNode.Direction], (curNode.Direction + 1) % 4, Nodes.Count);
|
||||||
curNode.Next = newNode.Id;
|
curNode.Next = newNode.Id;
|
||||||
Nodes[curNode.Id] = curNode;
|
Nodes[curNode.Id] = curNode;
|
||||||
|
|||||||
@@ -5,6 +5,70 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2024.Day7;
|
namespace AdventOfCode.Problems.AOC2024.Day7;
|
||||||
internal class BridgeRepair
|
|
||||||
|
[ProblemInfo(2024, 7, "Bridge Repair")]
|
||||||
|
internal class BridgeRepair : Problem<ulong, ulong>
|
||||||
{
|
{
|
||||||
}
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
139
AdventOfCode/Problems/AOC2024/Day8/ResonantCollinearity.cs
Normal file
139
AdventOfCode/Problems/AOC2024/Day8/ResonantCollinearity.cs
Normal file
@@ -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<int, int>
|
||||||
|
{
|
||||||
|
private string[] _map = [];
|
||||||
|
private int _width;
|
||||||
|
private int _height;
|
||||||
|
private FrozenDictionary<char, List<Vec2<int>>> _nodes = FrozenDictionary<char, List<Vec2<int>>>.Empty;
|
||||||
|
|
||||||
|
public override void CalculatePart1()
|
||||||
|
{
|
||||||
|
var antiNodes = new List<Vec2<int>>();
|
||||||
|
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<Vec2<int>> antinodes)
|
||||||
|
{
|
||||||
|
Console.WriteLine();
|
||||||
|
for (int y = 0; y < _height; y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < _width; x++)
|
||||||
|
{
|
||||||
|
Console.ResetColor();
|
||||||
|
var p = new Vec2<int>(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<int> pos)
|
||||||
|
{
|
||||||
|
if (pos.X < 0 || pos.Y < 0)
|
||||||
|
return false;
|
||||||
|
if (pos.X >= _width || pos.Y >= _height)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vec2<int>[] GetAntiNodes(Vec2<int> a, Vec2<int> b)
|
||||||
|
{
|
||||||
|
var dir = a - b;
|
||||||
|
|
||||||
|
var aNode1 = dir + a;
|
||||||
|
var aNode2 = -dir + b;
|
||||||
|
|
||||||
|
return [aNode1, aNode2];
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vec2<int>[] GetHarmonicAntiNodes(Vec2<int> a, Vec2<int> b)
|
||||||
|
{
|
||||||
|
var dir = a - b;
|
||||||
|
|
||||||
|
List<Vec2<int>> GetNodes(Vec2<int> start, Vec2<int> dir)
|
||||||
|
{
|
||||||
|
var results = new List<Vec2<int>>();
|
||||||
|
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<Vec2<int>>();
|
||||||
|
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<char, List<Vec2<int>>>();
|
||||||
|
_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<int>(x, y);
|
||||||
|
if (!nodes.TryAdd(row[x], [p]))
|
||||||
|
nodes[row[x]].Add(p);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_nodes = nodes.ToFrozenDictionary();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,19 +2,37 @@
|
|||||||
|
|
||||||
namespace AdventOfCode.Utils.Models;
|
namespace AdventOfCode.Utils.Models;
|
||||||
|
|
||||||
|
|
||||||
public record struct Vec2<T>(T X, T Y) where T : INumber<T>
|
public record struct Vec2<T>(T X, T Y) where T : INumber<T>
|
||||||
{
|
{
|
||||||
public static Vec2<T> operator +(Vec2<T> left, Vec2<T> right) => new Vec2<T>(left.X + right.X, left.Y + right.Y);
|
public static Vec2<T> operator +(Vec2<T> left, Vec2<T> right) => new Vec2<T>(left.X + right.X, left.Y + right.Y);
|
||||||
public static Vec2<T> operator -(Vec2<T> left, Vec2<T> right) => new Vec2<T>(left.X - right.X, left.Y - right.Y);
|
public static Vec2<T> operator -(Vec2<T> left, Vec2<T> right) => new Vec2<T>(left.X - right.X, left.Y - right.Y);
|
||||||
|
public static Vec2<T> operator -(Vec2<T> vec) => new Vec2<T>(-vec.X, -vec.Y);
|
||||||
public static Vec2<T> operator *(Vec2<T> left, T right) => new Vec2<T>(left.X * right, left.Y * right);
|
public static Vec2<T> operator *(Vec2<T> left, T right) => new Vec2<T>(left.X * right, left.Y * right);
|
||||||
|
public static Vec2<T> operator *(T left, Vec2<T> right) => new Vec2<T>(right.X * left, right.Y * left);
|
||||||
public static Vec2<T> operator /(Vec2<T> left, T right) => new Vec2<T>(left.X / right, left.Y / right);
|
public static Vec2<T> operator /(Vec2<T> left, T right) => new Vec2<T>(left.X / right, left.Y / right);
|
||||||
|
|
||||||
|
public T DistanceSq(Vec2<T> other)
|
||||||
|
{
|
||||||
|
var a = other.X - this.X;
|
||||||
|
var b = other.Y - this.Y;
|
||||||
|
return (a * a) + (b * b);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record struct Vec3<T>(T X, T Y, T Z) where T : INumber<T>
|
public record struct Vec3<T>(T X, T Y, T Z) where T : INumber<T>
|
||||||
{
|
{
|
||||||
public static Vec3<T> operator +(Vec3<T> left, Vec3<T> right) => new Vec3<T>(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
|
public static Vec3<T> operator +(Vec3<T> left, Vec3<T> right) => new Vec3<T>(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
|
||||||
public static Vec3<T> operator -(Vec3<T> left, Vec3<T> right) => new Vec3<T>(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
|
public static Vec3<T> operator -(Vec3<T> left, Vec3<T> right) => new Vec3<T>(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
|
||||||
|
public static Vec3<T> operator -(Vec3<T> vec) => new Vec3<T>(-vec.X, -vec.Y, -vec.Z);
|
||||||
public static Vec3<T> operator *(Vec3<T> left, T right) => new Vec3<T>(left.X * right, left.Y * right, left.Z * right);
|
public static Vec3<T> operator *(Vec3<T> left, T right) => new Vec3<T>(left.X * right, left.Y * right, left.Z * right);
|
||||||
|
public static Vec3<T> operator *(T left, Vec3<T> right) => new Vec3<T>(right.X * left, right.Y * left, right.Z * left);
|
||||||
public static Vec3<T> operator /(Vec3<T> left, T right) => new Vec3<T>(left.X / right, left.Y / right, left.Z / right);
|
public static Vec3<T> operator /(Vec3<T> left, T right) => new Vec3<T>(left.X / right, left.Y / right, left.Z / right);
|
||||||
|
|
||||||
|
public T DistanceSq(Vec3<T> 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user