2025-12-06 15:48:26 -06:00
|
|
|
import "dart:convert";
|
2025-12-04 14:57:15 -06:00
|
|
|
import "dart:io";
|
|
|
|
|
|
|
|
|
|
import "package:args/command_runner.dart";
|
|
|
|
|
|
|
|
|
|
class Day3Command extends Command {
|
|
|
|
|
// The [name] and [description] properties must be defined by every
|
|
|
|
|
// subclass.
|
|
|
|
|
@override
|
|
|
|
|
final name = "day3";
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
final description = "Run Advent of Code 2025 Day 3";
|
|
|
|
|
|
|
|
|
|
Day3Command() {
|
|
|
|
|
// we can add command specific arguments here.
|
|
|
|
|
// [argParser] is automatically created by the parent class.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// [run] may also return a Future.
|
|
|
|
|
@override
|
|
|
|
|
Future<void> run() async {
|
|
|
|
|
// [argResults] is set before [run()] is called and contains the flags/options
|
|
|
|
|
// passed to this command.
|
|
|
|
|
|
|
|
|
|
if (argResults!.rest.length != 1) {
|
|
|
|
|
print(
|
|
|
|
|
"Expected 1 positional arguments, found ${argResults!.rest.length}",
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
var filePath = argResults!.rest[0];
|
|
|
|
|
|
|
|
|
|
print("Parsing file: $filePath");
|
|
|
|
|
|
|
|
|
|
var inputFile = File(filePath);
|
2025-12-06 15:48:26 -06:00
|
|
|
var part1Result = await inputFile
|
|
|
|
|
.openRead()
|
|
|
|
|
.transform(utf8.decoder)
|
|
|
|
|
.transform(LineSplitter())
|
|
|
|
|
.map((line) {
|
|
|
|
|
int tens = -1;
|
|
|
|
|
int ones = -1;
|
|
|
|
|
final chars = line.split("");
|
|
|
|
|
|
|
|
|
|
for (final (idx, char) in chars.indexed) {
|
2025-12-06 15:49:12 -06:00
|
|
|
final charAsInt = int.parse(char);
|
|
|
|
|
if (charAsInt > tens && idx < chars.length - 1) {
|
|
|
|
|
tens = charAsInt;
|
2025-12-06 15:48:26 -06:00
|
|
|
ones = -1;
|
2025-12-06 15:49:12 -06:00
|
|
|
} else if (charAsInt > ones) {
|
|
|
|
|
ones = charAsInt;
|
2025-12-06 15:48:26 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return tens * 10 + ones;
|
|
|
|
|
})
|
|
|
|
|
.reduce((left, right) => left + right);
|
|
|
|
|
|
|
|
|
|
print("Part 1 Answer: $part1Result");
|
2025-12-06 17:07:53 -06:00
|
|
|
|
|
|
|
|
var part2Result = await inputFile
|
|
|
|
|
.openRead()
|
|
|
|
|
.transform(utf8.decoder)
|
|
|
|
|
.transform(LineSplitter())
|
|
|
|
|
.map((line) {
|
|
|
|
|
int resultLength = 12;
|
|
|
|
|
var resultList = List.generate(
|
|
|
|
|
resultLength,
|
|
|
|
|
(i) => 0,
|
|
|
|
|
growable: false,
|
|
|
|
|
);
|
|
|
|
|
final chars = line.split("");
|
|
|
|
|
|
|
|
|
|
for (final (charIdx, char) in chars.indexed) {
|
|
|
|
|
final charAsInt = int.parse(char);
|
|
|
|
|
var charsLeftInStream = chars.length - charIdx - 1;
|
|
|
|
|
for (final (placeIdx, placeValue) in resultList.indexed) {
|
|
|
|
|
var placesLeft = resultList.length - placeIdx - 1;
|
|
|
|
|
if (placesLeft > charsLeftInStream) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (charAsInt > placeValue) {
|
|
|
|
|
resultList[placeIdx] = charAsInt;
|
|
|
|
|
resultList.fillRange(placeIdx + 1, resultList.length, 0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int result = 0;
|
|
|
|
|
for (final placeValue in resultList) {
|
|
|
|
|
result *= 10;
|
|
|
|
|
result += placeValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
})
|
|
|
|
|
.reduce((left, right) => left + right);
|
|
|
|
|
|
|
|
|
|
print("Part 2 Answer: $part2Result");
|
2025-12-04 14:57:15 -06:00
|
|
|
}
|
|
|
|
|
}
|