day15 part1 done

This commit is contained in:
Johannes
2018-12-18 19:11:55 +01:00
parent ac3a741f0d
commit 3f2ff6e5a2
2 changed files with 75 additions and 22 deletions

View File

@@ -1,7 +1,32 @@
####### ################################
#.G...# ####################.......#####
#...EG# ##################.G.......###.#
#.#.#G# ##################...G.........#
#..G#E# #############................###
#.....# ############..............######
####### ############...##......#########
############...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.#########
##############.........#########
##############...#....##########
###############..#.#############
################################

View File

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