diff --git a/src/tasks/day24.rs b/src/tasks/day24.rs index d5b7e4e..cd6faee 100644 --- a/src/tasks/day24.rs +++ b/src/tasks/day24.rs @@ -8,8 +8,6 @@ pub fn task1() { let remaining_units = play(&input); println!("Standing units after the game: {}", remaining_units); - // 21107 too high - // 21004 too high } fn play(input: &str) -> i64 { @@ -38,10 +36,7 @@ fn play(input: &str) -> i64 { rounds_played += 1; } - println!("{:#?}", game); - println!("Played {} rounds", rounds_played); - - game.groups.values().map(|it| it.units).sum::() + game.remaining_units() } #[derive(Debug)] @@ -50,6 +45,10 @@ struct Game { } impl Game { + fn remaining_units(&self) -> i64 { + self.groups.values().map(|it| it.units).sum::() + } + fn create(input: &str) -> Self { let mut groups = HashMap::new(); let mut team = Team::ImmuneSystem; @@ -65,6 +64,8 @@ impl Game { group => { if let Some(group) = Group::from_str(group, team, id) { groups.insert(id, group); + } else { + panic!("bad group: {group}"); } } } @@ -77,22 +78,21 @@ impl Game { // lock targets ordered by effective power let mut all_by_power: Vec<&Group> = self.groups.values().collect(); all_by_power.sort_unstable_by_key(|a| Reverse((a.effective_power(), a.initiative))); - for group in all_by_power.iter() { - println!( - "{}: {} ({})", - group.id, - group.effective_power(), - group.initiative - ); - } - println!("{:?}", all_by_power); + // for group in all_by_power.iter() { + // println!( + // "{}: {} ({})", + // group.id, + // group.effective_power(), + // group.initiative + // ); + // } + // println!("{:?}", all_by_power); for group in all_by_power.iter() { if let Some(t) = self .groups .values() .filter(|it| it.team != group.team) .filter(|it| !target.values().any(|t| *t == it.id)) - // .filter(|it| group.compute_attack_damage_to(&it) >= it.hp_each) // .inspect(|it| { // println!( // "{} would deal {} damage to {}", @@ -110,10 +110,10 @@ impl Game { }) { if group.compute_attack_damage_to(t) <= 0 { - println!( - "Didn't find a target where {:?} can deal positive damage.", - group - ); + // println!( + // "Didn't find a target where {:?} can deal positive damage.", + // group + // ); continue; } else { target.insert(group.id, t.id); @@ -128,20 +128,19 @@ impl Game { for active_id in all_ids_by_initiative { if !self.groups[&active_id].alive() { // was killed in this round - println!("Group {} already dead", active_id); + // println!("Group {} already dead", active_id); continue; } if let Some(enemy_id) = target.get(&active_id) { let enemy = &self.groups[enemy_id]; let damage: i64 = self.groups[&active_id].compute_attack_damage_to(enemy); let dying_units = damage / enemy.hp_each; - if let Some(enemy) = self.groups.get_mut(enemy_id) { - enemy.units -= dying_units; - } - println!( - "{} dealt {} ({} units) damage to {}", - active_id, damage, dying_units, enemy_id - ); + self.groups.get_mut(enemy_id).unwrap().units -= dying_units; + + // println!( + // "{} dealt {} ({} units) damage to {}", + // active_id, damage, dying_units, enemy_id + // ); } } @@ -151,8 +150,7 @@ impl Game { } fn is_over(&self) -> bool { - self.groups.is_empty() - || self.groups.iter().all(|(_, it)| it.team == Team::Infection) + self.groups.iter().all(|(_, it)| it.team == Team::Infection) || self .groups .iter() @@ -182,8 +180,9 @@ struct Group { impl Group { fn from_str(input: &str, team: Team, id: usize) -> Option { // 801 units each with 4706 hit points (weak to radiation) with an attack that does 116 bludgeoning damage at initiative 1 + // 2347 units each with 3322 hit points with an attack that does 12 cold damage at initiative 2 use regex::Regex; - let regex = Regex::new(r"(\d+) units each with (\d+) hit points \((.+)\) with an attack that does (\d+) (\w+) damage at initiative (\d+)").unwrap(); + let regex = Regex::new(r"(\d+) units each with (\d+) hit points(.*)with an attack that does (\d+) (\w+) damage at initiative (\d+)").unwrap(); if let Some(m) = regex.captures(input) { let units: i64 = m[1].parse().unwrap(); let hp_each: i64 = m[2].parse().unwrap(); @@ -192,7 +191,8 @@ impl Group { let initiative: u64 = m[6].parse().unwrap(); let mut weaknesses: Vec = Vec::new(); let mut immunities: Vec = Vec::new(); - for part in m[3].split("; ") { + let attributes = m[3].trim().trim_start_matches("(").trim_end_matches(")"); + for part in attributes.split("; ") { if let Some(stripped) = part.strip_prefix("weak to ") { weaknesses = stripped.split(", ").map(|it| it.to_string()).collect(); } else if let Some(stripped) = part.strip_prefix("immune to ") {