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:
@@ -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);
|
// 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 {
|
||||||
None
|
// None
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.min_by_key(|(d, _)| *d)
|
// .min_by_key(|(d, _)| *d)
|
||||||
{
|
// {
|
||||||
Some(best)
|
// Some(best)
|
||||||
|
// } else {
|
||||||
|
// None
|
||||||
|
// }
|
||||||
|
let map = Map::from_game(&self, from);
|
||||||
|
if let Some(path) = map.shortest_path(from, to) {
|
||||||
|
// println!("{:?}", path);
|
||||||
|
Some(*path.get(1).unwrap_or(&from))
|
||||||
} 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(¤t) {
|
while let Some(Some(predecessor)) = predecessors.get(¤t) {
|
||||||
result.push(*predecessor);
|
result.push(*predecessor);
|
||||||
current = *predecessor;
|
current = *predecessor;
|
||||||
|
|||||||
Reference in New Issue
Block a user