Day 15: Warehouse Woes
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
You are viewing a single thread.
View all comments 2 points
*
Dart
canMove
does a recursive search and returns all locations that need moving, or none if there’s an obstacle anywhere downstream. For part2, that involves checking if there’s half of a box in front of us, and if so ensuring that we also check the other half of that box. I don’t bother tracking whether we’re double-checking as it runs fast enough as is.
import 'dart:math';
import 'package:collection/collection.dart';
import 'package:more/more.dart';
var d4 = <Point<num>>[Point(1, 0), Point(-1, 0), Point(0, 1), Point(0, -1)];
var m4 = '><v^';
solve(List<String> lines, {wide = false}) {
if (wide) {
lines = lines
.map((e) => e
.replaceAll('#', '##')
.replaceAll('.', '..')
.replaceAll('O', '[]')
.replaceAll('@', '@.'))
.toList();
}
var room = {
for (var r in lines.takeWhile((e) => e.isNotEmpty).indexed())
for (var c in r.value.split('').indexed().where((c) => (c.value != '.')))
Point<num>(c.index, r.index): c.value
};
var bot = room.entries.firstWhere((e) => e.value == '@').key;
var moves = lines.skipTo('').join('').split('');
for (var d in moves.map((m) => d4[m4.indexOf(m)])) {
if (didMove(d, bot, room)) bot += d;
}
return room.entries
.where((e) => e.value == '[' || e.value == 'O')
.map((e) => e.key.x + 100 * e.key.y)
.sum;
}
bool didMove(Point m, Point here, Map<Point, String> room) {
var moves = canMove(m, here, room).toSet();
if (moves.isNotEmpty) {
var vals = moves.map((e) => room.remove(e)!).toList();
for (var ms in moves.indexed()) {
room[ms.value + m] = vals[ms.index];
}
return true;
}
return false;
}
List<Point> canMove(Point m, Point here, Map<Point, String> room) {
if (room[here + m] == '#') return [];
if (!room.containsKey(here + m)) return [here];
var cm1 = canMove(m, here + m, room);
if (m.x != 0) return (cm1.isEmpty) ? [] : cm1 + [here];
List<Point> cm2 = [here];
if (room[here + m] == '[') cm2 = canMove(m, here + m + Point(1, 0), room);
if (room[here + m] == ']') cm2 = canMove(m, here + m - Point(1, 0), room);
return cm1.isEmpty || cm2.isEmpty ? [] : cm1 + cm2 + [here];
}