namespace AdventOfCodeLibrary._2022.Day_09 { internal class VirtualPoint { internal int X { get; set; } = 0; internal int Y { get; set; } = 0; internal void Translate(int x, int y) { X += x; Y += y; } } internal class RopeWalker { private readonly VirtualPoint HeadLocation = new(); private VirtualPoint LastHeadLocation = new(); private VirtualPoint TailLocation = new(); private List TailVistedLocations = new(); internal int ProcessMovement(string[] movements) { // add the start position TailVistedLocations.Add($"0,0"); for (int movementIndex = 0; movementIndex < movements.Length; movementIndex++) { char direction = movements[movementIndex][0]; int amountToMove = Convert.ToInt32(movements[movementIndex].Substring(2)); for (int movement = 0; movement < amountToMove; movement++) { // set the last pos before moving LastHeadLocation.X = HeadLocation.X; LastHeadLocation.Y = HeadLocation.Y; // do the actual move switch (direction) { case 'U': HeadLocation.Translate(0, 1); break; case 'D': HeadLocation.Translate(0, -1); break; case 'R': HeadLocation.Translate(1, 0); break; case 'L': HeadLocation.Translate(-1, 0); break; } // check if the tail is touching if (!IsTailTouchingHead(HeadLocation, TailLocation)) { TailLocation.Translate(Math.Sign(HeadLocation.X - TailLocation.X), Math.Sign(HeadLocation.Y - TailLocation.Y)); // add the new position to the list of visited positions TailVistedLocations.Add($"{TailLocation.X},{TailLocation.Y}"); } } } return TailVistedLocations.Distinct().Count(); } private bool IsTailTouchingHead(VirtualPoint point1, VirtualPoint point2) { return !(Math.Abs(point1.X - point2.X) > 1) && !(Math.Abs(point1.Y - point2.Y) > 1); } } }