1use crate::util::iter::*;
6use crate::util::parse::*;
7use std::ops::Add;
8
9#[derive(Clone, Copy)]
10struct Item {
11 cost: u32,
12 damage: u32,
13 armor: u32,
14}
15
16impl Add for Item {
17 type Output = Self;
18
19 fn add(self, rhs: Self) -> Self {
20 Item {
21 cost: self.cost + rhs.cost,
22 damage: self.damage + rhs.damage,
23 armor: self.armor + rhs.armor,
24 }
25 }
26}
27
28type Input = (u32, u32);
29
30pub fn parse(input: &str) -> Input {
31 let [boss_health, boss_damage, boss_armor]: [u32; 3] =
32 input.iter_unsigned().chunk::<3>().next().unwrap();
33
34 let weapon = [
35 Item { cost: 8, damage: 4, armor: 0 },
36 Item { cost: 10, damage: 5, armor: 0 },
37 Item { cost: 25, damage: 6, armor: 0 },
38 Item { cost: 40, damage: 7, armor: 0 },
39 Item { cost: 74, damage: 8, armor: 0 },
40 ];
41
42 let armor = [
43 Item { cost: 0, damage: 0, armor: 0 },
44 Item { cost: 13, damage: 0, armor: 1 },
45 Item { cost: 31, damage: 0, armor: 2 },
46 Item { cost: 53, damage: 0, armor: 3 },
47 Item { cost: 75, damage: 0, armor: 4 },
48 Item { cost: 102, damage: 0, armor: 5 },
49 ];
50
51 let ring = [
52 Item { cost: 25, damage: 1, armor: 0 },
53 Item { cost: 50, damage: 2, armor: 0 },
54 Item { cost: 100, damage: 3, armor: 0 },
55 Item { cost: 20, damage: 0, armor: 1 },
56 Item { cost: 40, damage: 0, armor: 2 },
57 Item { cost: 80, damage: 0, armor: 3 },
58 ];
59
60 let mut combinations = Vec::with_capacity(22);
61 combinations.push(Item { cost: 0, damage: 0, armor: 0 });
62
63 for i in 0..6 {
64 combinations.push(ring[i]);
65 for j in (i + 1)..6 {
66 combinations.push(ring[i] + ring[j]);
67 }
68 }
69
70 let mut part_one = u32::MAX;
71 let mut part_two = u32::MIN;
72
73 for first in weapon {
74 for second in armor {
75 for &third in &combinations {
76 let Item { cost, damage, armor } = first + second + third;
77
78 let hero_hit = damage.saturating_sub(boss_armor).max(1);
79 let hero_turns = boss_health.div_ceil(hero_hit);
80 let boss_hit = boss_damage.saturating_sub(armor).max(1);
81 let boss_turns = 100_u32.div_ceil(boss_hit);
82 let win = hero_turns <= boss_turns;
83
84 if win {
85 part_one = part_one.min(cost);
86 } else {
87 part_two = part_two.max(cost);
88 }
89 }
90 }
91 }
92
93 (part_one, part_two)
94}
95
96pub fn part1(input: &Input) -> u32 {
97 input.0
98}
99
100pub fn part2(input: &Input) -> u32 {
101 input.1
102}