|
| 1 | +package AdventOfCode2022 |
| 2 | + |
| 3 | +object Day19: |
| 4 | + case class Resources(ore: Int, clay: Int, obsidian: Int, geode: Int): |
| 5 | + def +(r: Resources): Resources = Resources(ore + r.ore, clay + r.clay, obsidian + r.obsidian, geode + r.geode) |
| 6 | + def -(r: Resources): Resources = Resources(ore - r.ore, clay - r.clay, obsidian - r.obsidian, geode - r.geode) |
| 7 | + def <=(r: Resources): Boolean = ore <= r.ore && clay <= r.clay && obsidian <= r.obsidian && geode <= r.geode |
| 8 | + |
| 9 | + def maximize(input: Seq[String], minutes: Int): Seq[Int] = input.map { line => |
| 10 | + val Seq(id, ore1, clay1, obsidian1, obsidian2, geode1, geode2) = line.split("\\D+").tail.map(_.toInt).toSeq |
| 11 | + |
| 12 | + val oreBotCost = Resources(ore1, 0, 0, 0) |
| 13 | + val clayBotCost = Resources(clay1, 0, 0, 0) |
| 14 | + val obsidianBotCost = Resources(obsidian1, obsidian2, 0, 0) |
| 15 | + val geodeBotCost = Resources(geode1, 0, geode2, 0) |
| 16 | + |
| 17 | + val zero = Resources(0, 0, 0, 0) |
| 18 | + val oreBot = Resources(1, 0, 0, 0) |
| 19 | + val clayBot = Resources(0, 1, 0, 0) |
| 20 | + val obsidianBot = Resources(0, 0, 1, 0) |
| 21 | + val geodeBot = Resources(0, 0, 0, 1) |
| 22 | + |
| 23 | + val maxOre = ore1.max(clay1).max(obsidian1).max(geode1) |
| 24 | + val maxClay = obsidian2 |
| 25 | + val maxObsidian = geode2 |
| 26 | + |
| 27 | + def helper(time: Int, bots: Resources, resources: Resources, prevCanOre: Boolean, prevCanClay: Boolean, prevCanObsidian: Boolean): Int = |
| 28 | + if time == 0 then |
| 29 | + resources.geode |
| 30 | + else if geodeBotCost <= resources then |
| 31 | + helper(time - 1, bots + geodeBot, resources + bots - geodeBotCost, false, false, false) |
| 32 | + else |
| 33 | + val canOre = oreBotCost <= resources && bots.ore < maxOre |
| 34 | + val canClay = clayBotCost <= resources && bots.clay < maxClay |
| 35 | + val canObsidian = obsidianBotCost <= resources && bots.obsidian < maxObsidian |
| 36 | + |
| 37 | + val first = helper(time - 1, bots, resources + bots, canOre, canClay, canObsidian) |
| 38 | + val second = if canOre && !prevCanOre then helper(time - 1, bots + oreBot, resources + bots - oreBotCost, false, false, false) else 0 |
| 39 | + val third = if canClay && !prevCanClay then helper(time - 1, bots + clayBot, resources + bots - clayBotCost, false, false, false) else 0 |
| 40 | + val fourth = if canObsidian && !prevCanObsidian then helper(time - 1, bots + obsidianBot, resources + bots - obsidianBotCost, false, false, false) else 0 |
| 41 | + |
| 42 | + first.max(second).max(third).max(fourth) |
| 43 | + end if |
| 44 | + end helper |
| 45 | + |
| 46 | + id * helper(minutes, oreBot, zero, false, false, false) |
| 47 | + } |
| 48 | + |
| 49 | + def part1(input: Seq[String]): Int = maximize(input, 24).sum |
| 50 | + |
| 51 | + def part2(input: Seq[String]): Int = maximize(input.take(3), 32).product / 6 |
| 52 | + |
| 53 | + def main(args: Array[String]): Unit = |
| 54 | + val data = io.Source.fromResource("AdventOfCode2022/Day19.txt").getLines().toSeq |
| 55 | + println(part1(data)) |
| 56 | + println(part2(data)) |
0 commit comments