-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday21.dart
67 lines (52 loc) · 1.9 KB
/
day21.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import 'package:dart/grid.dart';
extension GridBoolExtensions on Grid<bool> {
Grid<bool> mapAccordingToRules(List<Rule> rules) =>
rules.firstWhere((rule) => rule.matches(this)).to;
Grid<bool> nextState(List<Rule> rules) {
print("Size: $width ✕ $height");
Grid<Grid<bool>> determineChoppedUp(List<int> options, Grid<bool> g) {
final n = options.firstWhere((n) => g.canBeChoppedUpBy(n),
orElse: () =>
throw StateError("Failed to figure out how to chop up grid $g"));
return chopUpBy(n);
}
final Grid<Grid<bool>> choppedUp = determineChoppedUp([2, 3], this);
final Grid<Grid<bool>> mapped =
choppedUp.map((grid) => grid.mapAccordingToRules(rules));
return mapped.merge();
}
}
bool parseChar(String ch) {
return switch (ch) {
'.' => false,
'#' => true,
_ => throw ArgumentError("Unknown character $ch")
};
}
Grid<bool> parseGrid(String input) => Grid<bool>.parse(input, "/", parseChar);
class Rule {
final Grid<bool> from;
final Grid<bool> to;
Rule(this.from, this.to);
factory Rule.parse(String line) {
final elements = line.split(" => ");
return (elements.length == 2)
? Rule(parseGrid(elements[0]), parseGrid(elements[1]))
: throw ArgumentError("Invalid rule format: $line");
}
List<Grid<bool>> variations() =>
from.rotations() + from.mirrored().rotations();
bool matches(Grid<bool> grid) =>
variations().any((variation) => variation == grid);
}
const String startingPattern = ".#./..#/###";
int solution(String data, int iterations) {
final rules = data.split("\n").map(Rule.parse).toList(growable: false);
final Grid<bool> start = parseGrid(startingPattern);
final Grid<bool> state =
Iterable<int>.generate(iterations).fold(start, (currentState, idx) {
print("Step $idx...");
return currentState.nextState(rules);
});
return state.count((elem) => elem);
}