Skip to content

Commit

Permalink
Day 7 Part 2 solution
Browse files Browse the repository at this point in the history
  • Loading branch information
dancarroll committed Dec 7, 2024
1 parent 91c113c commit 9ba140c
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 29 deletions.
3 changes: 2 additions & 1 deletion bin/day7.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import 'package:aoc_2024/lib.dart';
import 'package:aoc_2024/day7/part_1.dart' as part1;
import 'package:aoc_2024/day7/part_2.dart' as part2;

Future<void> main(List<String> arguments) async {
await runDay(
day: 7,
part1: part1.calculate,
part2: (r) => Future.value(0),
part2: part2.calculate,
);
}
5 changes: 4 additions & 1 deletion lib/day7/part_1.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,7 @@ Future<int> calculate(Resources resources) async {
}

bool _canEquationBeTrue(final AmbiguousEquation equation) =>
equation.potentialEquations.any((e) => e.isValid());
equation.potentialEquations([
Add(),
Multiply(),
]).any((e) => e.isValid());
19 changes: 19 additions & 0 deletions lib/day7/part_2.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import 'package:aoc_2024/lib.dart';

import 'shared.dart';

Future<int> calculate(Resources resources) async {
final equations = await loadData(resources);

final result = equations
.where((e) => _canEquationBeTrue(e))
.fold(0, (v, e) => v + e.result);
return result;
}

bool _canEquationBeTrue(final AmbiguousEquation equation) =>
equation.potentialEquations([
Add(),
Multiply(),
Concatenation(),
]).any((e) => e.isValid());
61 changes: 34 additions & 27 deletions lib/day7/shared.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,36 @@ import 'dart:math';

import 'package:aoc_2024/lib.dart';

enum Operators {
add,
multiply;
}

class Component {}
/// Represents an arbitrary equation component.
abstract class Component {}

/// Represents an operator within an equation.
abstract class Operator extends Component {}

/// Addition operator.
class Add extends Operator {
@override
String toString() => '+';
}

/// Multiplication operator.
class Multiply extends Operator {
@override
String toString() => '*';
}

/// Concatenation operator (concatenates the numbers on
/// the left and right side to make a new number).
class Concatenation extends Operator {
@override
String toString() => '||';
}

/// Identity operator, which just copies the next number in
/// the equation.
class Identity extends Operator {}

/// Represents a numerical value operand.
class Value extends Component {
final int num;

Expand All @@ -32,12 +41,15 @@ class Value extends Component {
String toString() => num.toString();
}

/// Represents an equation, which may or may not be valid.
final class Equation {
final int result;
final List<Component> components;

Equation({required this.result, required this.components});

/// Computes the result of the equation, and returns true if the value
/// matches the equations stated result.
bool isValid() {
var computedResult = 0;
Operator operator = Identity();
Expand All @@ -53,6 +65,8 @@ final class Equation {
computedResult += component.num;
case == Multiply:
computedResult *= component.num;
case == Concatenation:
computedResult = int.parse('$computedResult${component.num}');
}
}
}
Expand All @@ -65,32 +79,24 @@ final class Equation {
'$result: ${components.map((c) => c.toString()).join(' ')}';
}

/// Represents an ambiguous equation, which has a list of operands
/// but no operators.
final class AmbiguousEquation {
final int result;
final List<int> operands;

AmbiguousEquation({required this.result, required this.operands});

List<Equation> get potentialEquations {
// 1 2 3 4
// 3 operators
// + + +
// + + *
// + * *
// * * *
// * + +
// * * +
// * + *
// + * +
List<List<Operator>> operatorOptions = [];
/// Generates a list of all potential equations from the operands
/// in this equation, based on the given list of operators.
Iterable<Equation> potentialEquations(List<Operator> operators) {
List<List<Operator>> operatorCombinatorial = [];
_generateOperators(
operands.length - 1, [Add(), Multiply()], operatorOptions, 0, []);
assert(operatorOptions.length == pow(2, operands.length - 1));
operands.length - 1, operators, operatorCombinatorial, 0, []);
assert(operatorCombinatorial.length ==
pow(operators.length, operands.length - 1));

//for (final operatorList in operatorOptions) {
// print(operatorList);
//}
return operatorOptions.map((operators) {
return operatorCombinatorial.map((operators) {
var components = <Component>[];
for (int i = 0; i < operands.length; i++) {
components.add(Value(operands[i]));
Expand All @@ -99,9 +105,10 @@ final class AmbiguousEquation {
}
}
return Equation(result: result, components: components);
}).toList();
});
}

/// Recursively generates a list of operator combinations.
void _generateOperators(int length, List<Operator> operators,
List<List<Operator>> result, int depth, List<Operator> current) {
if (depth == length) {
Expand All @@ -118,7 +125,7 @@ final class AmbiguousEquation {

/// Loads data from file, with each line represents as
/// an equation.
Future<List<AmbiguousEquation>> loadData(Resources resources) async {
Future<Iterable<AmbiguousEquation>> loadData(Resources resources) async {
final file = resources.file(Day.day7);
final lines = await file.readAsLines();

Expand All @@ -131,5 +138,5 @@ Future<List<AmbiguousEquation>> loadData(Resources resources) async {
components[1].trim().split(' ').map((s) => int.parse(s)).toList();

return AmbiguousEquation(result: result, operands: operands);
}).toList();
});
}
9 changes: 9 additions & 0 deletions test/day7_test.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:aoc_2024/lib.dart';
import 'package:aoc_2024/day7/part_1.dart' as part1;
import 'package:aoc_2024/day7/part_2.dart' as part2;
import 'package:test/test.dart';

void main() {
Expand All @@ -9,6 +10,10 @@ void main() {
test('part1', () async {
expect(await part1.calculate(resources), 3749);
});

test('part2', () async {
expect(await part2.calculate(resources), 11387);
});
});

group('real data', tags: 'real-data', () {
Expand All @@ -17,5 +22,9 @@ void main() {
test('part1', () async {
expect(await part1.calculate(resources), 4998764814652);
});

test('part2', () async {
expect(await part2.calculate(resources), 37598910447546);
});
});
}

0 comments on commit 9ba140c

Please sign in to comment.