Last active
December 12, 2020 23:56
-
-
Save deanbot/ab210cbaecabd8232fd9d64b24aab6fe to your computer and use it in GitHub Desktop.
Advent Of Code 2020 Day 12 in dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void main() { | |
final List<Object> solutions = [ | |
SolutionA(), | |
SolutionB() | |
]; | |
solutions.forEach((s) => print(s.toString())); | |
} | |
// Full inputs at https://adventofcode.com/2020/day/12/input | |
const inputsDay12 = """F10 | |
N3 | |
F7 | |
R90 | |
F11"""; | |
enum Action { N, S, E, W, L, R, F } | |
var charAction = { | |
'N': Action.N, | |
'S': Action.S, | |
'E': Action.E, | |
'W': Action.W, | |
'L': Action.L, | |
'R': Action.R, | |
'F': Action.F | |
}; | |
List<Instruction> _parseInputs(String inputs) => inputs | |
.split('\n') | |
.where((element) => element.isNotEmpty) | |
.map((e) => Instruction.fromString(e)) | |
.toList(); | |
var _inputs = _parseInputs(inputsDay12); | |
class Instruction { | |
final Action action; | |
final int distance; | |
Instruction.fromString(String input) | |
: action = charAction[input.split('')[0]], | |
distance = int.parse(input.split('').skip(1).join('')); | |
@override | |
String toString() => "$action$distance"; | |
} | |
enum Direction { | |
N, | |
S, | |
E, | |
W, | |
} | |
var directions = [Direction.N, Direction.E, Direction.S, Direction.W]; | |
var actionDirection = { | |
Action.N: Direction.N, | |
Action.E: Direction.E, | |
Action.S: Direction.S, | |
Action.W: Direction.W | |
}; | |
enum ShipVersion { One, Two } | |
class Ship { | |
final shipVersion; | |
int _x = 0; | |
int _y = 0; | |
Direction direction; | |
int _rX = 10; | |
int _rY = 1; | |
Ship({this.shipVersion = ShipVersion.Two}) : direction = Direction.E; | |
instruct(Instruction instruction) { | |
Direction moveDirection; | |
Action action = instruction.action; | |
int distanceOrDegree = instruction.distance; | |
if (shipVersion == ShipVersion.One) { | |
if (action == Action.R || action == Action.L) { | |
turn(distanceOrDegree, isLeft: action == Action.L); | |
} else { | |
if (action != Action.F) { | |
moveDirection = actionDirection[action]; | |
} | |
move(distanceOrDegree, moveDirection); | |
} | |
} else if (shipVersion == ShipVersion.Two) { | |
if (action == Action.R || action == Action.L) { | |
rotate(distanceOrDegree, isLeft: action == Action.L); | |
} else { | |
if (action == Action.F) { | |
move(distanceOrDegree * _rX, _rX >= 0 ? Direction.E : Direction.W); | |
move(distanceOrDegree * _rY, _rY >= 0 ? Direction.N : Direction.S); | |
} else { | |
moveDirection = actionDirection[action]; | |
moveWaypoint(distanceOrDegree, moveDirection); | |
} | |
} | |
} | |
// print(this.toString()); | |
} | |
rotate(int degree, {isLeft = false}) { | |
var deg = (360 + (isLeft ? -degree : degree)) % 360; | |
var prevRX = _rX; | |
var prevRY = _rY; | |
if (deg == 90 || deg == 270) { | |
_rX = prevRY; | |
_rY = prevRX; | |
} | |
if (deg == 90) { | |
_rY = -_rY; | |
} else if (deg == 180) { | |
_rX = -_rX; | |
_rY = -_rY; | |
} else if (deg == 270) { | |
_rX = -_rX; | |
} | |
} | |
turn(int degree, {isLeft = false}) { | |
var index = directions.indexOf(direction), inc = degree ~/ 90; | |
index += inc * (isLeft ? -1 : 1); | |
index = index % directions.length; | |
direction = directions[index]; | |
} | |
moveWaypoint(int instructionDistance, Direction instructionDirection) { | |
var dir = instructionDirection != null ? instructionDirection : direction; | |
switch (dir) { | |
case Direction.N: | |
_rY += instructionDistance; | |
break; | |
case Direction.S: | |
_rY -= instructionDistance; | |
break; | |
case Direction.E: | |
_rX += instructionDistance; | |
break; | |
case Direction.W: | |
_rX -= instructionDistance; | |
break; | |
} | |
} | |
move(int instructionDistance, Direction instructionDirection) { | |
var dir = instructionDirection != null ? instructionDirection : direction; | |
switch (dir) { | |
case Direction.N: | |
case Direction.S: | |
_y += instructionDistance; | |
break; | |
case Direction.E: | |
case Direction.W: | |
_x += instructionDistance; | |
break; | |
} | |
} | |
get absX => _x < 0 ? -_x : _x; | |
get absY => _y < 0 ? -_y : _y; | |
get absRX => _rX < 0 ? -_rX : _rX; | |
get absRY => _rY < 0 ? -_rY : _rY; | |
@override | |
String toString() => "${_x >= 0 ? 'east' : 'west'} $absX," | |
" ${_y >= 0 ? 'north' : 'south'} $absY" | |
" -> $direction" | |
" (WP: ${_rX >= 0 ? 'east' : 'west'} $absRX, ${_rY >= 0 ? 'north' : 'south'} $absRY)"; | |
} | |
abstract class AdventSolution { | |
final int day; | |
final String name; | |
AdventSolution(this.day, this.name); | |
// implement in subclass | |
String getSolution(); | |
@override | |
String toString() { | |
return "Advent Of Code, " | |
"Day $day " | |
"${name.isNotEmpty ? name : ''} " | |
"solution: ${getSolution()}"; | |
} | |
} | |
abstract class _Day12Solution extends AdventSolution { | |
_Day12Solution(name) : super(12, name); | |
} | |
class SolutionA extends _Day12Solution { | |
SolutionA() : super('A'); | |
String getSolution() { | |
var ship = Ship(shipVersion: ShipVersion.One); | |
_inputs.forEach(ship.instruct); | |
return (ship.absX + ship.absY).toString(); | |
} | |
} | |
class SolutionB extends _Day12Solution { | |
SolutionB() : super('B'); | |
String getSolution() { | |
var ship = Ship(); | |
_inputs.forEach(ship.instruct); | |
return (ship.absX + ship.absY).toString(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment