diff --git a/input/day15.txt b/input/day15.txt index 63d31fe..a9fd423 100644 --- a/input/day15.txt +++ b/input/day15.txt @@ -1,7 +1,32 @@ -####### -#.G...# -#...EG# -#.#.#G# -#..G#E# -#.....# -####### \ No newline at end of file +################################ +####################.......##### +##################.G.......###.# +##################...G.........# +#############................### +############..............###### +############...##......######### +############...G.....#.######### +##..##........G##.........###### +##..##.....#.G...........E#..### +##..##.....#.....G......G..E..## +##G............................# +#....G........#####..G.........# +#......#.G...#######..E.......## +#...##..G...#########E.....##### +##...G.#....#########.....###### +######G.G...#########..#.####### +######.#...G#########.########## +#####.......#########.########## +#####.GE.....#######..########## +#####.....E...#####...########## +#######....G..........########## +#######..........G..############ +######.G............############ +#########...........#..######### +############..........########## +############E...E.##...######### +#############.....E..E.######### +##############.........######### +##############...#....########## +###############..#.############# +################################ diff --git a/src/tasks/day15.rs b/src/tasks/day15.rs index d62ada2..e7180cc 100644 --- a/src/tasks/day15.rs +++ b/src/tasks/day15.rs @@ -14,15 +14,12 @@ pub fn task1() { let mut round = 0; while game.round() { round += 1; - println!("{}", game); - println!("{:?}", game.units); } println!("Final full round was {}", round); println!( - "Remaining HP: {}", - game.units.iter().map(|it| it.health).sum::() + "Result: {}", + game.units.iter().map(|it| it.health).sum::() * round as i32 ); - println!("{:?}", game.units); } #[derive(Clone, PartialEq)] @@ -63,6 +60,20 @@ impl Position { .map(|it| Position(it.0 as usize, it.1 as usize)) .collect() } + + fn manhattan_distance(&self, other: &Self) -> usize { + let a = if self.0 > other.0 { + self.0 - other.0 + } else { + other.0 - self.0 + }; + let b = if self.1 > other.1 { + self.1 - other.1 + } else { + other.1 - self.1 + }; + a + b + } } impl PartialOrd for Position { @@ -134,7 +145,7 @@ impl Game { if let Some((_, best)) = input .iter() .filter_map(|(delta, start)| { - let map = Map::from_game(&self, *start); + let map = Map::from_game(&self, from); if let Some(path) = map.shortest_path(*start, to) { Some((delta + path.len() * 10, *path.first().unwrap_or(start))) } else { @@ -170,14 +181,14 @@ impl Game { self.units[curr].position, self.units[curr].warrior_type.enemy_type(), ) { - if let Some(next_position) = - self.next_position(self.units[curr].position, next_target_position) - { - let curr_pos = self.units[curr].position; - self.tiles[curr_pos.0][curr_pos.1] = Tile::Empty; - self.units[curr].position = next_position; - } else { - panic!("We have a reachable target but no path to it!"); + if self.units[curr].position != next_target_position { + if let Some(next_position) = + self.next_position(self.units[curr].position, next_target_position) + { + self.units[curr].position = next_position; + } else { + panic!("We have a reachable target but no path to it! {:?} wants to go to {:?}", self.units[curr], next_target_position); + } } } @@ -187,6 +198,7 @@ impl Game { .units .iter() .enumerate() + .filter(|(_, it)| it.warrior_type == self.units[curr].warrior_type.enemy_type()) .filter(|(_, it)| neighbors.contains(&it.position)) .map(|(i, _)| i) .collect(); @@ -200,6 +212,13 @@ impl Game { } }); if let Some(closest_index) = close_enemies.first() { + if self.units[*closest_index] + .position + .manhattan_distance(&self.units[curr].position) + > 1 + { + panic!("Distance WTF") + } let enemy = &mut self.units[*closest_index]; enemy.health -= ATTACK_POWER; if enemy.health <= 0 { @@ -327,11 +346,14 @@ impl Map { for y in 0..game.height { new.push(match &game.tiles[x][y] { Tile::Empty => MapTile::Empty, - _ => MapTile::Occupied, + Tile::Wall => MapTile::Occupied, }); } fields.push(new); } + for warrior in game.units.iter() { + fields[warrior.position.0][warrior.position.1] = MapTile::Occupied; + } fields[clear.0][clear.1] = MapTile::Empty; Map { fields: fields, @@ -356,6 +378,9 @@ impl Map { if curr_pos == to { break; } + if self.fields[curr_pos.0][curr_pos.1] != MapTile::Empty { + continue; + } for pos in curr_pos.neighbors(self.width, self.height) { if !predecessors.contains_key(&pos) && !open.iter().any(|it| it.1 == pos) { open.push_back((Some(curr_pos), pos)); @@ -394,6 +419,9 @@ impl Map { // all others would have a higher distance and therefore are not relevant continue; } + if self.fields[curr_pos.0][curr_pos.1] == MapTile::Occupied { + continue; + } for pos in curr_pos.neighbors(self.width, self.height) { if !visited.contains(&pos) && !open.iter().any(|it| it.1 == pos) { open.push_back((curr_dist + 1, pos));