Advertisement
eltea

Advent of Code 2020 Day 12 Parts 1 and 2

Dec 13th, 2020 (edited)
393
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.00 KB | None | 0 0
  1. //Advent of Code 2020 Day 12 Parts 1 and 2 solution by Mike LeSauvage
  2. public class FerryPathAnalyzer : MonoBehaviour
  3. {
  4.     [SerializeField] TextAsset ferryPathTextfile = null;   //Hooked up in the input text in the Unity editor.
  5.  
  6.     //The facing characters are indexed into by the ship's facing variable.
  7.     //It is important that it proceeds clockwise around the cardinal points.
  8.     static char[] FACING_CHARS = { 'N', 'E', 'S', 'W' };
  9.  
  10.     //Ship state
  11.     //facing is unsigned so (facing-x) % 4 will always result in a number from 0-3.
  12.     //This keeps it in the range of FACING_CHARS.
  13.     uint facing = 1; //Equivalent to 'E' when indexing into FACING_CHARS.
  14.  
  15.     int westEast = 0;
  16.     int northSouth = 0;
  17.  
  18.     //Waypoint state (for part 2)
  19.     int wayPointNorthSouth = 1;
  20.     int wayPointWestEast = 10;
  21.  
  22.     void Start()
  23.     {
  24.         string[] ferryPathStrings = ferryPathTextfile.text.Split('\n');
  25.  
  26.         //Solve Part one.
  27.         foreach (string instruction in ferryPathStrings)
  28.         {
  29.             ParsePartOneDirections(instruction);
  30.         }
  31.         int manhattanDistance = Mathf.Abs(northSouth) + Mathf.Abs(westEast);
  32.         Debug.Log($"Part One Manhattan Distance: {manhattanDistance}");
  33.  
  34.  
  35.         //Reset for part two and solve.
  36.         westEast = 0;
  37.         northSouth = 0;
  38.  
  39.         foreach (string instruction in ferryPathStrings)
  40.         {
  41.             ParsePartTwoDirections(instruction);
  42.         }
  43.  
  44.         manhattanDistance = Mathf.Abs(northSouth) + Mathf.Abs(westEast);
  45.         Debug.Log($"Part Two Manhattan Distance: {manhattanDistance}");
  46.  
  47.     }
  48.  
  49.     void ParsePartTwoDirections(string instruction)
  50.     {
  51.         char order = instruction[0];
  52.         int quantity = int.Parse(instruction.Substring(1));
  53.  
  54.         switch (order)
  55.         {
  56.             case 'N':
  57.                 wayPointNorthSouth += quantity;
  58.                 break;
  59.             case 'S':
  60.                 wayPointNorthSouth -= quantity;
  61.                 break;
  62.             case 'E':
  63.                 wayPointWestEast += quantity;
  64.                 break;
  65.             case 'W':
  66.                 wayPointWestEast -= quantity;
  67.                 break;
  68.             case 'L':
  69.                 (wayPointWestEast, wayPointNorthSouth) = RotateCoordsByDegress(wayPointWestEast, wayPointNorthSouth, quantity); //Clockwise is +ve in standard coordinates.
  70.                 break;
  71.             case 'R':
  72.                 (wayPointWestEast, wayPointNorthSouth) = RotateCoordsByDegress(wayPointWestEast, wayPointNorthSouth, -quantity); //Clockwise is -ve in standard coordinates.
  73.                 break;
  74.             case 'F':
  75.                 westEast += wayPointWestEast * quantity;
  76.                 northSouth += wayPointNorthSouth * quantity;
  77.                 break;
  78.             default:
  79.                 Debug.LogError($"Invalid instruction: {instruction}");
  80.                 break;
  81.         }
  82.     }
  83.  
  84.     // Rotates an (x,y) coordinate around the (0,0) position.
  85.     // See https://en.wikipedia.org/wiki/Rotation_matrix for the matrix multiplication math that gives these formulas.
  86.     (int, int) RotateCoordsByDegress(int x, int y, int degrees)
  87.     {
  88.         float rads = degrees * Mathf.Deg2Rad;
  89.         int newX = Mathf.RoundToInt((x * Mathf.Cos(rads) - y * (int)Mathf.Sin(rads)));
  90.         int newY = Mathf.RoundToInt((x * Mathf.Sin(rads) + y * (int)Mathf.Cos(rads)));
  91.  
  92.         return (newX, newY);
  93.     }
  94.  
  95.  
  96.     // Follows the ship directions for NSEW instructions.
  97.     // L and R instructions update the ship's facing.
  98.     // F instructions look at the ship's current facing and translate it to a new
  99.     //   N S E or W instruction of the same quantity, calling this parser again
  100.     //   to translate the distance.
  101.     void ParsePartOneDirections(string instruction)
  102.     {
  103.         char order = instruction[0];
  104.         int quantity = int.Parse(instruction.Substring(1));
  105.         int turns;
  106.  
  107.         switch (order)
  108.         {
  109.             case 'N':
  110.                 northSouth += quantity;
  111.                 break;
  112.             case 'S':
  113.                 northSouth -= quantity;
  114.                 break;
  115.             case 'E':
  116.                 westEast += quantity;
  117.                 break;
  118.             case 'W':
  119.                 westEast -= quantity;
  120.                 break;
  121.             case 'L':
  122.                 turns = quantity / 90;
  123.                 facing = (facing - (uint)turns) % 4;  //indexes left through FACING_CHARS, wrapping when out of bounds.
  124.                 break;
  125.             case 'R':
  126.                 turns = quantity / 90;
  127.                 facing = (facing + (uint)turns) % 4; //indexes left through FACING_CHARS, wrapping when out of bounds.
  128.                 break;
  129.             case 'F':
  130.                 string pseudoInstruction = $"{FACING_CHARS[facing]}{quantity}";
  131.                 ParsePartOneDirections(pseudoInstruction);                      
  132.                 break;
  133.             default:
  134.                 Debug.LogError($"Invalid instruction: {instruction}");
  135.                 break;
  136.         }
  137.     }
  138.  
  139.  
  140. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement