diff --git a/Utils/Extensions.cs b/Utils/Extensions.cs
index 3f8dfbb..7a99c1c 100644
--- a/Utils/Extensions.cs
+++ b/Utils/Extensions.cs
@@ -2,6 +2,16 @@ namespace AdventOfCode.Utils;
public static class Extensions
{
+ public static int Signal(this int x)
+ {
+ return x switch
+ {
+ < 0 => -1,
+ > 0 => 1,
+ _ => 0
+ };
+ }
+
///
/// Returns a slice of the given list
///
@@ -76,4 +86,24 @@ public static class Extensions
ret.Add(entry.Key, entry.Value.Clone());
return ret;
}
+
+ public static void Fill(this List list, int count, T element)
+ where T : ICloneable
+ {
+ for (int i = 0; i < count; i++)
+ list.Add(element);
+ }
+
+ public static void Fill(this List> list, int count, List element)
+ {
+ for (int i = 0; i < count; i++)
+ list.Add(element.Clone());
+ }
+
+ public static void Set(this List list, int index, T element)
+ {
+ List backup = list.Clone();
+ list.Clear();
+ for (int i = 0; i < list.Count; i++) list.Add(i == index ? element : list[i]);
+ }
}
\ No newline at end of file
diff --git a/Year2022/Day9.cs b/Year2022/Day9.cs
index b9794f5..dcf8849 100644
--- a/Year2022/Day9.cs
+++ b/Year2022/Day9.cs
@@ -1,87 +1,99 @@
+using AdventOfCode.Utils;
+
namespace AdventOfCode.Year2022;
public class Day9
{
- private static readonly List<(char, int)> Moves = new();
- private static readonly Dictionary> Position = new()
- {
- ['H'] = new List(),
- ['T'] = new List()
- };
-
public Day9()
{
Console.WriteLine("Day9 Solution");
+ List<(char, int)> moves = new List<(char, int)>();
File.ReadAllLines("inputs/day9.txt").ToList().ForEach(line =>
{
string[] split = line.Split(" ");
- Moves.Add((Convert.ToChar(split[0]), Convert.ToInt32(split[1])));
+ moves.Add((Convert.ToChar(split[0]), Convert.ToInt32(split[1])));
});
- Console.WriteLine($"Part1 Result: {Part1()}");
- Console.WriteLine($"Part2 Result: {Part2()}");
+ Console.WriteLine($"Part1 Result: {GetPositionCount(moves, 2)}");
+ Console.WriteLine($"Part2 Result: {GetPositionCount(moves, 10)}");
Console.WriteLine("\n=============================\n");
}
- private static int Part1()
+ private static int GetPositionCount(List<(char, int)> moves, int knots)
{
- Position['H'] = new[] {0, 0}.ToList();
- Position['T'] = new[] {0, 0}.ToList();
- HashSet<(int, int)> usedPositions = new HashSet<(int, int)>();
+ List> currentPositions = new List>();
+ currentPositions.Fill(knots, new List(new[]{0,0}));
+ HashSet<(int, int)> tailHistory = new HashSet<(int, int)>();
- foreach ((char, int) move in Moves)
- {
- List head = Position['H'];
- List tail = Position['T'];
- for (int i = 0; i < move.Item2; i++)
+ foreach ((char, int) move in moves)
+ for (int moveN = 0; moveN < move.Item2; moveN++)
{
- if (move.Item1 == 'U')
+ int[] vector = GetVector(move.Item1);
+ int[] previousTailPosition = currentPositions[0].ToArray();
+ currentPositions[0] = UpdateHead(vector, currentPositions[0]);
+ for (int tailN = 0; tailN < knots-1; tailN++)
{
- head[1]++;
- if (ValidatePosition()) continue;
- tail[1]++;
- tail[0] += head[0] - tail[0];
+ int[] nextPreviousTailPosition = currentPositions[tailN + 1].ToArray();
+ currentPositions[tailN + 1] = UpdateTail(currentPositions[tailN], currentPositions[tailN + 1], previousTailPosition);
+ previousTailPosition = nextPreviousTailPosition;
+ if (tailN == knots - 2)
+ tailHistory.Add((currentPositions[knots - 1][0], currentPositions[knots - 1][1]));
}
- else if (move.Item1 == 'D')
- {
- head[1]--;
- if (ValidatePosition()) continue;
- tail[1]--;
- tail[0] += head[0] - tail[0];
- }
- else if (move.Item1 == 'R')
- {
- head[0]++;
- if (ValidatePosition()) continue;
- tail[0]++;
- tail[1] += head[1] - tail[1];
- }
- else if (move.Item1 == 'L')
- {
- head[0]--;
- if (ValidatePosition()) continue;
- tail[0]--;
- tail[1] += head[1] - tail[1];
- }
- usedPositions.Add((tail[0], tail[1]));
}
- }
- return usedPositions.Count;
+
+ return tailHistory.Count;
}
- private static int Part2()
+ private static List UpdateHead(int[] vector, List currentPosition)
{
- Position['H'] = new[] {0, 0}.ToList();
- Position['T'] = new[] {0, 0}.ToList();
- HashSet<(int, int)> usedPositions = new HashSet<(int, int)>();
-
- foreach ((char, int) move in Moves)
- {
-
- }
-
- return usedPositions.Count;
+ currentPosition[0] += vector[0];
+ currentPosition[1] += vector[1];
+ return new List { currentPosition[0], currentPosition[1] };
}
- private static bool ValidatePosition()
- => Position['H'][0] - Position['T'][0] is > -2 and < 2 && Position['H'][1] - Position['T'][1] is > -2 and < 2;
+ private static List UpdateTail(List currentHeadPosition, List currentTailPosition, int[] previousTailPosition)
+ {
+ List head = new List
+ {
+ currentHeadPosition[0] - previousTailPosition[0],
+ currentHeadPosition[1] - previousTailPosition[1]
+ };
+
+ if (Math.Abs(currentHeadPosition[0] - currentTailPosition[0]) > 1 ||
+ Math.Abs(currentHeadPosition[1] - currentTailPosition[1]) > 1)
+ {
+ if (previousTailPosition[0] == currentTailPosition[0] ||
+ previousTailPosition[1] == currentTailPosition[1])
+ return new List
+ {
+ currentTailPosition[0] + head[0],
+ currentTailPosition[1] + head[1]
+ };
+
+ List difference = new List
+ {
+ currentHeadPosition[0] - currentTailPosition[0],
+ currentHeadPosition[1] - currentTailPosition[1]
+ };
+
+ return new List
+ {
+ currentTailPosition[0] + difference[0].Signal() * Math.Min(Math.Abs(difference[0]), 1),
+ currentTailPosition[1] + difference[1].Signal() * Math.Min(Math.Abs(difference[1]), 1)
+ };
+ }
+
+ return currentTailPosition;
+ }
+
+ private static int[] GetVector(char direction)
+ {
+ return direction switch
+ {
+ 'U' => new[] { 1, 0 },
+ 'D' => new[] { -1, 0 },
+ 'R' => new[] { 0, 1 },
+ 'L' => new[] { 0, -1 },
+ _ => new[] { 0, 0 }
+ };
+ }
}
\ No newline at end of file