day15 part 2 optimized

instead of senselessly trying to find the best starting point, just rely
on the order of neighbor point generation. Since we use a queue
to manage open points and he neighbors are added in the correct
order, they neighbor that has precedence due to reading order will
automatically be the one to be predecessor on a final path, if he is on
a shortest path.
This commit is contained in:
Johannes
2018-12-18 22:43:10 +01:00
parent cef96d55be
commit ba622fd408

View File

@@ -8,13 +8,14 @@ const HEALTH: i32 = 200;
pub fn task1() { pub fn task1() {
let input = utils::read_file("input/day15.txt"); let input = utils::read_file("input/day15.txt");
let mut game = Game::from_input(input.lines().collect(), 3, 8); let mut game = Game::from_input(&input.lines().collect(), 3, 3);
println!("{}", game); println!("{}", game);
let mut round = 0; let mut round = 0;
while game.round() { while game.round() {
round += 1; round += 1;
// println!("{}", game);
// println!("round was {}", round);
} }
println!("{:?}", game.units);
println!("Final full round was {}", round); println!("Final full round was {}", round);
println!( println!(
"Result: {}", "Result: {}",
@@ -24,6 +25,7 @@ pub fn task1() {
pub fn task2() { pub fn task2() {
let input = utils::read_file("input/day15.txt"); let input = utils::read_file("input/day15.txt");
let input = input.lines().collect();
let mut highest_fail = 3; let mut highest_fail = 3;
let mut lowest_win = None::<i32>; let mut lowest_win = None::<i32>;
while lowest_win.is_none() || lowest_win.unwrap() - 1 > highest_fail { while lowest_win.is_none() || lowest_win.unwrap() - 1 > highest_fail {
@@ -31,7 +33,7 @@ pub fn task2() {
Some(upper) => highest_fail + (upper - highest_fail) / 2, Some(upper) => highest_fail + (upper - highest_fail) / 2,
None => 2 * highest_fail, None => 2 * highest_fail,
}; };
let mut game = Game::from_input(input.lines().collect(), 3, attack); let mut game = Game::from_input(&input, 3, attack);
let initial_elve_count = game let initial_elve_count = game
.units .units
.iter() .iter()
@@ -175,25 +177,32 @@ impl Game {
if from == to { if from == to {
return Some(from); return Some(from);
} }
let input = vec![ // let input = vec![
(1, Position(from.0, from.1 - 1)), // (1, Position(from.0, from.1 - 1)),
(2, Position(from.0 - 1, from.1)), // (2, Position(from.0 - 1, from.1)),
(3, Position(from.0 + 1, from.1)), // (3, Position(from.0 + 1, from.1)),
(4, Position(from.0, from.1 + 1)), // (4, Position(from.0, from.1 + 1)),
]; // ];
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, from);
// if let Some(path) = map.shortest_path(*start, to) {
// Some((delta + path.len() * 10, *path.first().unwrap_or(start)))
// } else {
// None
// }
// })
// .min_by_key(|(d, _)| *d)
// {
// Some(best)
// } else {
// None
// }
let map = Map::from_game(&self, from); let map = Map::from_game(&self, from);
if let Some(path) = map.shortest_path(*start, to) { if let Some(path) = map.shortest_path(from, to) {
Some((delta + path.len() * 10, *path.first().unwrap_or(start))) // println!("{:?}", path);
} else { Some(*path.get(1).unwrap_or(&from))
None
}
})
.min_by_key(|(d, _)| *d)
{
Some(best)
} else { } else {
None None
} }
@@ -224,6 +233,10 @@ impl Game {
if let Some(next_position) = if let Some(next_position) =
self.next_position(self.units[curr].position, next_target_position) self.next_position(self.units[curr].position, next_target_position)
{ {
// println!(
// "{:?} moves to {:?} via {:?}",
// self.units[curr].position, next_target_position, next_position
// );
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! {:?} wants to go to {:?}", self.units[curr], next_target_position);
@@ -274,7 +287,7 @@ impl Game {
return true; return true;
} }
fn from_input(input: Vec<&str>, goblin_attack: i32, elve_attack: i32) -> Self { fn from_input(input: &Vec<&str>, goblin_attack: i32, elve_attack: i32) -> Self {
use self::Tile::*; use self::Tile::*;
use self::WarriorType::*; use self::WarriorType::*;
let width = input[0].len(); let width = input[0].len();
@@ -433,6 +446,7 @@ impl Map {
if let Some(Some(_)) = predecessors.get(&to) { if let Some(Some(_)) = predecessors.get(&to) {
let mut result: Vec<Position> = Vec::new(); let mut result: Vec<Position> = Vec::new();
let mut current = to; let mut current = to;
result.push(current);
while let Some(Some(predecessor)) = predecessors.get(&current) { while let Some(Some(predecessor)) = predecessors.get(&current) {
result.push(*predecessor); result.push(*predecessor);
current = *predecessor; current = *predecessor;