Files
2020/Q12.cs

228 lines
5.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
namespace _2020
{
class Q12
{
[DebuggerDisplay("({x}, {y})")]
struct Vec2
{
public int x;
public int y;
}
static Vec2 shipPosition;
static Vec2 waypointPosition = new Vec2() { x = 10, y = 1 };
static int facingDir = 90;
static readonly List<Tuple<char, int>> instructions = new List<Tuple<char, int>>();
public static void Go()
{
var start = DateTime.Now;
MakeList();
Util.Log($"Q12 MakeList took {(DateTime.Now - start).TotalMilliseconds}ms");
var p1start = DateTime.Now;
Part1();
Util.Log($"Q12 part1 took {(DateTime.Now - p1start).TotalMilliseconds}ms");
var p2start = DateTime.Now;
Part2();
Util.Log($"Q12 part2 took {(DateTime.Now - p2start).TotalMilliseconds}ms");
Util.Log($"Q12 took {(DateTime.Now - start).TotalMilliseconds}ms");
}
static void MakeList()
{
foreach (var line in File.ReadAllLines("12input.txt"))
{
instructions.Add(new Tuple<char, int>(line[0], Convert.ToInt32(line[1..]) % 360));
}
}
static void MoveDir(ref Vec2 vec, char dir, int amount)
{
switch (dir)
{
case 'N':
vec.y += amount;
break;
case 'S':
vec.y -= amount;
break;
case 'E':
vec.x += amount;
break;
case 'W':
vec.x -= amount;
break;
default:
throw new Exception("Invalid MoveDir direction");
}
}
static void MoveShipDir(char dir, int amount)
{
MoveDir(ref shipPosition, dir, amount);
}
static void MoveShipToWaypoint(int amount)
{
shipPosition.x += waypointPosition.x * amount;
shipPosition.y += waypointPosition.y * amount;
}
static void MoveWaypointDir(char dir, int amount)
{
MoveDir(ref waypointPosition, dir, amount);
}
static char GetFacingDir()
{
if (facingDir == 0)
{
return 'N';
}
else if (facingDir == 90)
{
return 'E';
}
else if (facingDir == 180)
{
return 'S';
}
else if (facingDir == 270)
{
return 'W';
}
throw new Exception("Invalid facing dir");
}
static void RotateShipDir(char dir, int amount)
{
if (amount % 90 != 0)
{
throw new Exception("Turned toward a non-cardinal direction");
}
if (dir == 'R')
{
facingDir = (facingDir + amount) % 360;
}
else if (dir == 'L')
{
facingDir -= amount;
while (facingDir < 0)
{
facingDir = 360 + facingDir;
}
}
else
{
throw new Exception("Invalid rotation dir");
}
}
static void RotateWaypointDir(char dir, int amount)
{
if (amount % 90 != 0)
{
throw new Exception("Turned toward a non-cardinal direction");
}
switch (amount % 360)
{
case 180:
waypointPosition.y = -waypointPosition.y;
waypointPosition.x = -waypointPosition.x;
break;
case 90:
if (dir == 'R')
{
var tmp = waypointPosition.x;
waypointPosition.x = waypointPosition.y;
waypointPosition.y = -tmp;
}
else if (dir == 'L')
{
var tmp = waypointPosition.y;
waypointPosition.y = waypointPosition.x;
waypointPosition.x = -tmp;
}
break;
case 270:
RotateWaypointDir(dir == 'R' ? 'L' : 'R', 90);
break;
default:
throw new Exception("Unexpected waypoint rotation direction");
}
}
static void Part1()
{
foreach (var inst in instructions)
{
switch (inst.Item1)
{
case 'N':
case 'S':
case 'E':
case 'W':
MoveShipDir(inst.Item1, inst.Item2);
break;
case 'F':
MoveShipDir(GetFacingDir(), inst.Item2);
break;
case 'R':
case 'L':
RotateShipDir(inst.Item1, inst.Item2);
break;
}
}
Util.Log($"Q12Part1: finished facing {facingDir}, x={shipPosition.x}, y={shipPosition.y}, manhattan dist={Math.Abs(shipPosition.x) + Math.Abs(shipPosition.y)}");
}
static void Part2()
{
shipPosition = new Vec2();
foreach (var inst in instructions)
{
switch (inst.Item1)
{
case 'N':
case 'S':
case 'E':
case 'W':
MoveWaypointDir(inst.Item1, inst.Item2);
break;
case 'F':
MoveShipToWaypoint(inst.Item2);
break;
case 'R':
case 'L':
RotateWaypointDir(inst.Item1, inst.Item2);
break;
}
}
Util.Log($"Q12Part2: finished facing {facingDir}, x={shipPosition.x}, y={shipPosition.y}, manhattan dist={Math.Abs(shipPosition.x) + Math.Abs(shipPosition.y)}");
}
}
}