namespace AdventOfCodeLibrary._2022.Day_09 { internal class VirtualPoint { internal int X { get; private set; } = 0; internal int Y { get; private set; } = 0; internal void MoveUp() { Y++; } internal void MoveDown() { Y--; } internal void MoveRight() { X++; } internal void MoveLeft() { X--; } } internal class RopeWalker { private 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 = HeadLocation; // do the actual move switch (direction) { case 'U': HeadLocation.MoveUp(); break; case 'D': HeadLocation.MoveDown(); break; case 'R': HeadLocation.MoveRight(); break; case 'L': HeadLocation.MoveLeft(); break; } // check if the tail is touching if (!IsTailTouchingHead(direction)) { // if not, move tail to last head position TailLocation = LastHeadLocation; // add the new position to the list of visited positions TailVistedLocations.Add($"{TailLocation.X},{TailLocation.Y}"); } } } return TailVistedLocations.Distinct().Count(); } private bool IsTailTouchingHead(char direction) { return direction switch { // up; Y + 1 'U' => TailLocation.Y + 1 >= HeadLocation.Y, // down; Y - 1 'D' => TailLocation.Y - 1 <= HeadLocation.Y, // right; X + 1 'R' => TailLocation.X + 1 >= HeadLocation.X, // left; X - 1 'L' => TailLocation.X - 1 <= HeadLocation.X, _ => throw new AccessViolationException(), }; } } }