Day 21: Keypad Conundrum
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
The secret ingredient is a big cache.
import 'dart:math';
import 'package:collection/collection.dart';
import 'package:more/more.dart';
Map<String, Point<num>> mapper(List<String> list) => {
for (var r in list.indexed())
for (var c in r.value.split('').indexed())
c.value: Point<num>(c.index, r.index)
};
var dirMap = mapper(['_^A', '<v>']);
var numMap = mapper(['789', '456', '123', '_0A']);
var lenCache = <(String, int), int>{};
int len(String code, int level, isNum) =>
lenCache.putIfAbsent((code, level), () => _len(code, level, isNum));
int n(p, isNum, level) => len(getMoves(p[0], p[1], isNum), level - 1, false);
int _len(String code, int level, isNum) => (level == 0)
? code.length
: 'A$code'.split('').window(2).map((p) => n(p, isNum, level)).sum;
String getMoves(String f, String t, bool isNum) {
var map = isNum ? numMap : dirMap;
var (from, to) = (map[f]!, map[t]!);
var mv = to - from;
var s = <String>{};
var x = ''.padRight(mv.x.abs() as int, mv.x.sign == 1 ? '>' : '<');
var y = ''.padRight(mv.y.abs() as int, mv.y.sign == 1 ? 'v' : '^');
// avoid '_', dislike '<'
if (Point(from.x, to.y) != map['_']!) s.add('$y${x}A');
if (Point(to.x, from.y) != map['_']!) s.add('$x${y}A');
return (s.length < 2 || mv.x > 0) ? s.first : s.last;
}
int solve(String code, int level) =>
len(code, level + 1, true) * int.parse(code.skipLast(1));
part1(List<String> lines) => lines.map((e) => solve(e, 2)).sum;
part2(List<String> lines) => lines.map((e) => solve(e, 25)).sum;