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
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]; }