diff --git a/lib/day12.dart b/lib/day12.dart index 3783c73..9db58d3 100644 --- a/lib/day12.dart +++ b/lib/day12.dart @@ -1,6 +1,125 @@ // --- Day 12: Garden Groups --- // https://adventofcode.com/2024/day/12 -int solveA(Iterable input) { - return 0; +import 'dart:collection'; +import 'dart:typed_data'; + +int solveA(List input) { + final grid = Grid(input); + + Queue todo = Queue()..add(Point(0, 0)); + Set pointsAlreadyPartOfGroup = HashSet(); + List> groups = []; + + while (todo.isNotEmpty) { + final currentPoint = todo.removeFirst(); + + if (pointsAlreadyPartOfGroup.contains(currentPoint)) { + continue; + } + + final result = + scan(currentPoint, grid.getByPoint(currentPoint), grid, todo, {}) + .toList(); + groups.add(result); + + pointsAlreadyPartOfGroup.addAll(result); + } + + var sum = 0; + for (final group in groups) { + var fences = 0; + + for (final point in group) { + final currentChar = grid.getByPoint(point); + + for (final scan in scanningList) { + if (grid.getByPoint(point + scan) != currentChar) { + fences++; + } + } + } + + sum += (fences * group.length); + } + + return sum; +} + +List scanningList = const [ + Point(0, -1), // up + Point(1, 0), // right + Point(0, 1), // down + Point(-1, 0), // left +]; + +Iterable scan( + Point currentPoint, + int lookFor, + Grid grid, + Queue todo, + Set history, +) sync* { + if (!history.add(currentPoint)) { + return; + } + + final currentValue = grid.getByPoint(currentPoint); + + if (currentValue == 0) { + return; + } + + if (currentValue != lookFor) { + todo.add(currentPoint); + return; + } + + yield currentPoint; + + for (final scanning in scanningList) { + yield* scan(currentPoint + scanning, lookFor, grid, todo, history); + } +} + +extension type const Point._(({int x, int y}) _point) { + const Point(int x, int y) : this._((x: x, y: y)); + + int get x => _point.x; + int get y => _point.y; + + Point operator +(Point other) => Point( + x + other.x, + y + other.y, + ); + + Point operator -(Point other) => Point( + x - other.x, + y - other.y, + ); +} + +class Grid { + final int length, height; + final Uint8List _list; + + Grid(List input) + : length = input.first.length, + height = input.length, + _list = Uint8List((input.length * input.first.length)) { + for (final (y, line) in input.indexed) { + for (var x = 0; x < line.length; x++) { + set(x, y, line.codeUnitAt(x)); + } + } + } + + int getByPoint(Point p) => get(p.x, p.y); + int get(int x, int y) => + (x < 0 || y < 0 || x >= length || y >= height) ? 0 : _list[_getPos(x, y)]; + + void setByPoint(Point p, int value) => set(p.x, p.y, value); + void set(int x, int y, int value) => _list[_getPos(x, y)] = value; + + int _getPos(int x, int y) => x + (y * length); } diff --git a/test/day12_test.dart b/test/day12_test.dart index 740051f..558080a 100644 --- a/test/day12_test.dart +++ b/test/day12_test.dart @@ -18,7 +18,7 @@ BBCD BBCC EEEC ''' - .asLines), + .toLinesList()), equals(140)); }); test('Example 2', () { @@ -30,7 +30,7 @@ OOOOO OXOXO OOOOO ''' - .asLines), + .toLinesList()), equals(772)); }); test('Example 3', () { @@ -47,11 +47,11 @@ MIIIIIJJEE MIIISIJEEE MMMISSJEEE ''' - .asLines), + .toLinesList()), equals(1930)); }); test('Solution', () { - expect(solveA(input), equals(-1)); + expect(solveA(input), equals(1387004)); }); - }, skip: true); + }); }