2025-12-01 14:35:11 -06:00
|
|
|
import "dart:convert";
|
|
|
|
|
import "dart:io";
|
|
|
|
|
|
2025-11-30 11:46:59 -06:00
|
|
|
import "package:args/command_runner.dart";
|
|
|
|
|
|
2025-12-01 16:51:50 -06:00
|
|
|
enum Direction { left, right }
|
|
|
|
|
|
|
|
|
|
class Rotation {
|
|
|
|
|
Direction direction;
|
|
|
|
|
int amount;
|
|
|
|
|
Rotation(this.direction, this.amount);
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
String toString() {
|
|
|
|
|
return '{ direction: ${direction.name}, amount: $amount }';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<List<Rotation>> parseInputFile(String filePath) async {
|
|
|
|
|
var inputFile = File(filePath);
|
|
|
|
|
var openFile = inputFile.openRead();
|
|
|
|
|
|
|
|
|
|
var lines = openFile.transform(utf8.decoder).transform(LineSplitter());
|
|
|
|
|
|
|
|
|
|
List<Rotation> inputList = [];
|
|
|
|
|
await for (var line in lines) {
|
|
|
|
|
var dir = line.substring(0, 1);
|
|
|
|
|
var amount = int.parse(line.substring(1, line.length));
|
|
|
|
|
inputList.add(
|
|
|
|
|
Rotation(dir == 'L' ? Direction.left : Direction.right, amount),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return inputList;
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-30 11:46:59 -06:00
|
|
|
class Day1Command extends Command {
|
|
|
|
|
// The [name] and [description] properties must be defined by every
|
|
|
|
|
// subclass.
|
2025-11-30 12:02:28 -06:00
|
|
|
@override
|
2025-11-30 11:46:59 -06:00
|
|
|
final name = "day1";
|
2025-11-30 12:02:28 -06:00
|
|
|
|
|
|
|
|
@override
|
2025-11-30 11:46:59 -06:00
|
|
|
final description = "Run Advent of Code 2025 Day 1";
|
|
|
|
|
|
|
|
|
|
Day1Command() {
|
|
|
|
|
// we can add command specific arguments here.
|
|
|
|
|
// [argParser] is automatically created by the parent class.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// [run] may also return a Future.
|
|
|
|
|
@override
|
2025-12-01 16:51:50 -06:00
|
|
|
Future<void> run() async {
|
2025-11-30 11:46:59 -06:00
|
|
|
// [argResults] is set before [run()] is called and contains the flags/options
|
|
|
|
|
// passed to this command.
|
2025-12-01 14:35:11 -06:00
|
|
|
|
|
|
|
|
if (argResults!.rest.length != 1) {
|
|
|
|
|
print(
|
|
|
|
|
"Expected 1 positional arguments, found ${argResults!.rest.length}",
|
|
|
|
|
);
|
2025-12-08 11:30:50 -06:00
|
|
|
exit(1);
|
2025-12-01 14:35:11 -06:00
|
|
|
}
|
|
|
|
|
var fileName = argResults!.rest[0];
|
|
|
|
|
|
2025-12-01 16:51:50 -06:00
|
|
|
print("Parsing file: $fileName");
|
|
|
|
|
|
|
|
|
|
var list = await parseInputFile(fileName);
|
|
|
|
|
|
|
|
|
|
int dialValue = 50;
|
2025-12-02 12:10:27 -06:00
|
|
|
int combinationPart1 = 0;
|
|
|
|
|
int combinationPart2 = 0;
|
2025-12-01 16:51:50 -06:00
|
|
|
|
|
|
|
|
for (var instruction in list) {
|
|
|
|
|
switch (instruction.direction) {
|
|
|
|
|
case Direction.left:
|
2025-12-02 12:10:27 -06:00
|
|
|
// Count full rotations
|
|
|
|
|
combinationPart2 += (instruction.amount / 100).floor();
|
|
|
|
|
|
|
|
|
|
// Count additive rotations (remainder + previous value)
|
|
|
|
|
if (dialValue != 0 && (dialValue - (instruction.amount % 100)) <= 0) {
|
|
|
|
|
combinationPart2++;
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-01 16:51:50 -06:00
|
|
|
// Dial counter-clockwise by amount
|
|
|
|
|
dialValue -= instruction.amount;
|
|
|
|
|
case Direction.right:
|
|
|
|
|
// Dial clockwise by amount
|
|
|
|
|
dialValue += instruction.amount;
|
2025-12-02 12:10:27 -06:00
|
|
|
combinationPart2 += (dialValue / 100).floor();
|
2025-12-01 16:51:50 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dialValue = dialValue % 100;
|
|
|
|
|
if (dialValue == 0) {
|
2025-12-02 12:10:27 -06:00
|
|
|
combinationPart1++;
|
2025-12-01 16:51:50 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-02 12:10:27 -06:00
|
|
|
print("Combination - part 1: $combinationPart1");
|
|
|
|
|
print("Combination - part 2: $combinationPart2");
|
2025-11-30 11:46:59 -06:00
|
|
|
}
|
|
|
|
|
}
|