Advertisement
mykdavies

AOC 2022 Day 19

Dec 19th, 2022 (edited)
1,118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Dart 4.96 KB | None | 0 0
  1. /// Produce some machines that produce resources in a horrible network :-)
  2. /// 1) Find best results for a long list.
  3. /// 2) Now for a short list over a longer time.
  4. ///
  5. /// Part 1, typical solution for second line
  6. /// [0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 3, 2, 3, 2, 3, 3, 3] -> 12
  7.  
  8. import 'package:collection/collection.dart';
  9. import 'package:more/more.dart';
  10.  
  11. var ore = 0, clay = 1, obsidian = 2, geode = 3;
  12.  
  13. class Blueprint {
  14.   int number;
  15.   List<List<int>> costs = [[], [], [], []];
  16.   Blueprint(this.number, this.costs);
  17. }
  18.  
  19. class State {
  20.   int time;
  21.   List<int> robots = [1, 0, 0, 0];
  22.   List<int> stocks = [0, 0, 0, 0];
  23.   List<bool> wasIdleInstead = [false, false, false, false];
  24.   State(this.time);
  25.   State.copyFrom(State other)
  26.       : time = other.time,
  27.         robots = other.robots.toList(),
  28.         stocks = other.stocks.toList();
  29.  
  30.   canBuildRobot(int r, Blueprint bp) {
  31.     if (wasIdleInstead[r]) return false;
  32.     for (var i in 0.to(4)) {
  33.       if (stocks[i] < bp.costs[r][i]) return false;
  34.     }
  35.     return true;
  36.   }
  37.  
  38.   buildRobot(int r, Blueprint bp) {
  39.     robots[r] += 1;
  40.     for (var i in 0.to(4)) {
  41.       stocks[i] -= bp.costs[r][i];
  42.     }
  43.   }
  44.  
  45.   @override
  46.   int get hashCode => time.hashCode ^ robots.hashCode ^ stocks.hashCode;
  47.   // int get hashCode => Object.hash(time, robots, stocks);
  48.  
  49.   @override
  50.   bool operator ==(Object other) =>
  51.       (other is State) &&
  52.       time == other.time &&
  53.       0.to(robots.length).every((e) => robots[e] == other.robots[e]) &&
  54.       0.to(robots.length).every((e) => stocks[e] == other.stocks[e]);
  55. }
  56.  
  57. var debug = false;
  58. Blueprint read(String line) {
  59.   var reD = RegExp(r'\d+');
  60.   var ms = reD.allMatches(line).map((m) => int.parse(m[0]!)).toList();
  61.   return Blueprint(ms[0], [
  62.     [ms[1], 0, 0, 0],
  63.     [ms[2], 0, 0, 0],
  64.     [ms[3], ms[4], 0, 0],
  65.     [ms[5], 0, ms[6], 0]
  66.   ]);
  67. }
  68.  
  69. List<int> sums(List<int> a, List<int> b) =>
  70.     [0, 1, 2, 3].map((e) => a[e] + b[e]).toList();
  71. int getMaxGeodes(Blueprint bp, int timeLimit) {
  72.   var best = 0;
  73.   var q = QueueList.from([State(timeLimit)]);
  74.   var seen = <int>{};
  75.   while (q.isNotEmpty) {
  76.     var curr = q.removeFirst();
  77.     if (seen.contains(curr.hashCode)) {
  78.       continue;
  79.     }
  80.     seen.add(curr.hashCode);
  81.     if (curr.time == 0) {
  82.       if (curr.stocks[geode] > best) {
  83.         best = curr.stocks[geode];
  84.       }
  85.       continue;
  86.     }
  87.     // can we prune?
  88.     //if we magically made geode bots every round, could we catch up with best?
  89.     // if (curr.stocks[geode] +
  90.     //         curr.time * curr.robots[geode] +
  91.     //         (curr.time - 1 * (curr.time) ~/ 2) <
  92.     //     best) {
  93.     //   continue;
  94.     // }
  95.  
  96.     var nextState = State.copyFrom(curr)
  97.       ..time -= 1
  98.       ..stocks = sums(curr.stocks, curr.robots);
  99.  
  100.     // What should we build next?
  101.  
  102.     //Always build geode
  103.     var buildGeode = curr.canBuildRobot(geode, bp);
  104.     if (buildGeode) {
  105.       q.add(State.copyFrom(nextState)..buildRobot(geode, bp));
  106.     }
  107.  
  108.     // Geode >>> Obs, plus don't need too many
  109.     var buildObs = !buildGeode &&
  110.         curr.robots[obsidian] < bp.costs[geode][obsidian] &&
  111.         curr.canBuildRobot(obsidian, bp);
  112.     if (buildObs) {
  113.       q.add(State.copyFrom(nextState)..buildRobot(obsidian, bp));
  114.     }
  115.  
  116.     // Only build clay if we need it to feed obsidians
  117.     var buildClay = !buildGeode &&
  118.         !buildObs &&
  119.         curr.robots[clay] < bp.costs[obsidian][clay] &&
  120.         curr.canBuildRobot(clay, bp);
  121.     if (buildClay) {
  122.       q.add(State.copyFrom(nextState)..buildRobot(clay, bp));
  123.     }
  124.  
  125.     // Only build clay if we need it to feed any of the others
  126.     var buildOre = !buildGeode &&
  127.         !buildObs &&
  128.         // Next line based on
  129.         // https://old.reddit.com/r/adventofcode/comments/zpihwi/2022_day_19_solutions/j0w8ujl/
  130.         curr.robots[clay] < 2 &&
  131.         (curr.robots[ore] < bp.costs[geode][ore] ||
  132.             curr.robots[ore] < bp.costs[obsidian][ore] ||
  133.             curr.robots[ore] < bp.costs[clay][ore]) &&
  134.         curr.canBuildRobot(ore, bp);
  135.     if (buildOre) {
  136.       q.add(State.copyFrom(nextState)..buildRobot(ore, bp));
  137.     }
  138.  
  139.     // Dunno about these numbers... May be data-dependent
  140.     var canIdle = !buildGeode &&
  141.         (curr.stocks[ore] < 1 * bp.costs[geode][ore] ||
  142.             curr.stocks[ore] < 1 * bp.costs[obsidian][ore] ||
  143.             curr.stocks[ore] < 2 * bp.costs[clay][ore]) &&
  144.         curr.stocks[clay] < 3 * bp.costs[obsidian][clay];
  145.     if (canIdle) {
  146.       // https://old.reddit.com/r/adventofcode/comments/zpihwi/2022_day_19_solutions/j0vvtdt/
  147.       nextState.wasIdleInstead = [buildOre, buildClay, buildObs, buildGeode];
  148.       q.add(nextState);
  149.     }
  150.   }
  151.   print('best for ${bp.number} = $best');
  152.   return best;
  153. }
  154.  
  155. part1(List<String> lines) =>
  156.     lines.map(read).map((e) => getMaxGeodes(e, 24) * e.number).sum;
  157.  
  158. part2(List<String> lines) => lines
  159.     .take(3)
  160.     .map(read)
  161.     .map((e) => getMaxGeodes(e, 32))
  162.     .reduce((s, t) => s * t);
  163.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement