[TASK] Solved day 16 but it's extremely slow
This commit is contained in:
19
.run/run-day-16.run.xml
Normal file
19
.run/run-day-16.run.xml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="run-day-16" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
|
||||||
|
<option name="command" value="run --package advent-of-code-2022-rust --bin advent-of-code-2022-rust --release -- -d 16" />
|
||||||
|
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
|
||||||
|
<option name="channel" value="DEFAULT" />
|
||||||
|
<option name="requiredFeatures" value="true" />
|
||||||
|
<option name="allFeatures" value="false" />
|
||||||
|
<option name="emulateTerminal" value="false" />
|
||||||
|
<option name="withSudo" value="false" />
|
||||||
|
<option name="buildTarget" value="REMOTE" />
|
||||||
|
<option name="backtrace" value="SHORT" />
|
||||||
|
<envs />
|
||||||
|
<option name="isRedirectInput" value="false" />
|
||||||
|
<option name="redirectInputPath" value="" />
|
||||||
|
<method v="2">
|
||||||
|
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
150
src/day16.rs
150
src/day16.rs
@@ -1,4 +1,5 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use crate::day16::ValveStep::{MoveTo, OpenValve};
|
||||||
use crate::day_solver::DaySolver;
|
use crate::day_solver::DaySolver;
|
||||||
|
|
||||||
use super::util;
|
use super::util;
|
||||||
@@ -59,6 +60,104 @@ impl Day16 {
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn should_valve_be_opened(&self, valve_idx: &usize, open_valves_mask: &u64) -> bool {
|
||||||
|
if Self::is_open(valve_idx, open_valves_mask) { false }
|
||||||
|
else if let Some(valve) = self.valves.get(*valve_idx) {
|
||||||
|
valve.flow_rate > 0
|
||||||
|
} else { false }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_best_option_pt2(&self, valve_state: ValveStatePt2, cur_flow_rate: u32, cache: &mut HashMap<ValveStatePt2, BestOptionPt2>) -> BestOptionPt2 {
|
||||||
|
|
||||||
|
if valve_state.minutes_left == 0 {
|
||||||
|
return BestOptionPt2 {
|
||||||
|
// my_step: ValveStep::None,
|
||||||
|
// elephant_step: ValveStep::None,
|
||||||
|
total_flow: 0,
|
||||||
|
// cur_flow: cur_flow_rate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(res) = cache.get(&valve_state) {
|
||||||
|
return res.to_owned();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut my_options = Vec::new();
|
||||||
|
let mut elephant_options = Vec::new();
|
||||||
|
|
||||||
|
if self.should_valve_be_opened(&valve_state.my_position, &valve_state.open_valves_mask) {
|
||||||
|
// One option is to open the valve at the current position
|
||||||
|
my_options.push(OpenValve(valve_state.my_position));
|
||||||
|
}
|
||||||
|
|
||||||
|
if valve_state.my_position != valve_state.elephant_position && self.should_valve_be_opened(&valve_state.elephant_position, &valve_state.open_valves_mask) {
|
||||||
|
elephant_options.push(OpenValve(valve_state.elephant_position));
|
||||||
|
}
|
||||||
|
|
||||||
|
// We try and move to an adjacent valve, see if we can be more useful there
|
||||||
|
let my_valve = &self.valves[valve_state.my_position];
|
||||||
|
for connection in my_valve.connections.iter() {
|
||||||
|
my_options.push(MoveTo(connection.to_owned()))
|
||||||
|
}
|
||||||
|
|
||||||
|
let elephant_valve = &self.valves[valve_state.elephant_position];
|
||||||
|
for connection in elephant_valve.connections.iter() {
|
||||||
|
elephant_options.push(MoveTo(connection.to_owned()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we try all combinations of my and elephants options:
|
||||||
|
let mut best: u32 = 0;
|
||||||
|
let mut my_best_step = None;
|
||||||
|
let mut elephant_best_step = None;
|
||||||
|
let next_minutes_left = valve_state.minutes_left - 1;
|
||||||
|
for my_option in my_options {
|
||||||
|
|
||||||
|
let mut my_next_position = valve_state.my_position;
|
||||||
|
let mut next_valve_mask_for_me = valve_state.open_valves_mask;
|
||||||
|
let mut next_flow_rate_for_me = cur_flow_rate;
|
||||||
|
|
||||||
|
match my_option {
|
||||||
|
MoveTo(idx) => my_next_position = idx,
|
||||||
|
OpenValve(idx) => {
|
||||||
|
next_valve_mask_for_me = Self::set_open(&idx, &next_valve_mask_for_me);
|
||||||
|
next_flow_rate_for_me += self.valves[idx].flow_rate
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
for elephant_option in &elephant_options {
|
||||||
|
|
||||||
|
let mut next_valve_mask = next_valve_mask_for_me;
|
||||||
|
let mut next_flow_rate = next_flow_rate_for_me;
|
||||||
|
let mut elephant_next_position = valve_state.elephant_position;
|
||||||
|
|
||||||
|
match elephant_option {
|
||||||
|
MoveTo(idx) => elephant_next_position = *idx,
|
||||||
|
OpenValve(idx) => {
|
||||||
|
next_valve_mask = Self::set_open(&idx, &next_valve_mask);
|
||||||
|
next_flow_rate += self.valves[*idx].flow_rate
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let res = self.find_best_option_pt2(ValveStatePt2::new(my_next_position, elephant_next_position, next_valve_mask, next_minutes_left), next_flow_rate, cache);
|
||||||
|
if best == 0 || res.total_flow > best {
|
||||||
|
best = res.total_flow;
|
||||||
|
my_best_step = Some(my_option);
|
||||||
|
elephant_best_step = Some(elephant_option.to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let res = BestOptionPt2 {
|
||||||
|
// my_step: my_best_step.unwrap(),
|
||||||
|
// elephant_step: elephant_best_step.unwrap(),
|
||||||
|
// cur_flow: cur_flow_rate,
|
||||||
|
total_flow: best + cur_flow_rate
|
||||||
|
};
|
||||||
|
cache.insert(valve_state, res.to_owned());
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
fn find_best_option(&self, valve_state: ValveState, cur_flow_rate: u32, cache: &mut HashMap<ValveState, BestOptionResult>) -> Option<BestOptionResult> {
|
fn find_best_option(&self, valve_state: ValveState, cur_flow_rate: u32, cache: &mut HashMap<ValveState, BestOptionResult>) -> Option<BestOptionResult> {
|
||||||
|
|
||||||
if valve_state.minutes_left == 0 { return None }
|
if valve_state.minutes_left == 0 { return None }
|
||||||
@@ -70,7 +169,7 @@ impl Day16 {
|
|||||||
let cur_valve = &self.valves.get(valve_state.my_position).unwrap();
|
let cur_valve = &self.valves.get(valve_state.my_position).unwrap();
|
||||||
let mut best_step_option: Option<ValveStep> = None;
|
let mut best_step_option: Option<ValveStep> = None;
|
||||||
let mut best_step_result_option: Option<BestOptionResult> = None;
|
let mut best_step_result_option: Option<BestOptionResult> = None;
|
||||||
if Self::is_closed(&valve_state.my_position, &valve_state.open_valves_mask) && cur_valve.flow_rate > 0 {
|
if self.should_valve_be_opened(&valve_state.my_position, &valve_state.open_valves_mask) {
|
||||||
// One option is to open the valve at the current position
|
// One option is to open the valve at the current position
|
||||||
let new_open_valves_mask = Self::set_open(&valve_state.my_position, &valve_state.open_valves_mask);
|
let new_open_valves_mask = Self::set_open(&valve_state.my_position, &valve_state.open_valves_mask);
|
||||||
best_step_result_option = self.find_best_option(ValveState::new(valve_state.my_position, new_open_valves_mask, valve_state.minutes_left - 1), cur_flow_rate + cur_valve.flow_rate, cache);
|
best_step_result_option = self.find_best_option(ValveState::new(valve_state.my_position, new_open_valves_mask, valve_state.minutes_left - 1), cur_flow_rate + cur_valve.flow_rate, cache);
|
||||||
@@ -127,19 +226,23 @@ impl DaySolver for Day16 {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
let best = self.find_best_option(ValveState::new(self.initial_valve_idx, 0, 30), 0, &mut cache).unwrap();
|
let best = self.find_best_option(ValveState::new(self.initial_valve_idx, 0, 30), 0, &mut cache).unwrap();
|
||||||
for i in 0..best.steps.len() {
|
// for i in 0..best.steps.len() {
|
||||||
println!("Step {}", i + 1);
|
// println!("Step {}", i + 1);
|
||||||
match best.steps[i] {
|
// match best.steps[i] {
|
||||||
ValveStep::OpenValve(v) => println!("Opening valve {}", self.valve_names[v]),
|
// ValveStep::OpenValve(v) => println!("Opening valve {}", self.valve_names[v]),
|
||||||
ValveStep::MoveTo(v ) => println!("Moving to valve {}", self.valve_names[v])
|
// ValveStep::MoveTo(v ) => println!("Moving to valve {}", self.valve_names[v])
|
||||||
}
|
// }
|
||||||
println!("The flow is now {}\n", best.flow_per_step[i]);
|
// println!("The flow is now {}\n", best.flow_per_step[i]);
|
||||||
}
|
// }
|
||||||
best.total_flow.to_string()
|
best.total_flow.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn solve_part2(&mut self) -> String {
|
fn solve_part2(&mut self) -> String {
|
||||||
return 0.to_string();
|
|
||||||
|
let mut cache= HashMap::new();
|
||||||
|
let best = self.find_best_option_pt2(ValveStatePt2::new(self.initial_valve_idx, self.initial_valve_idx, 0, 26), 0, &mut cache);
|
||||||
|
|
||||||
|
return best.total_flow.to_string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,6 +266,28 @@ impl ValveState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
||||||
|
struct ValveStatePt2 {
|
||||||
|
my_position: usize,
|
||||||
|
elephant_position: usize,
|
||||||
|
open_valves_mask: u64,
|
||||||
|
minutes_left: u32
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
struct BestOptionPt2 {
|
||||||
|
// my_step: ValveStep,
|
||||||
|
// elephant_step: ValveStep,
|
||||||
|
total_flow: u32,
|
||||||
|
// cur_flow: u32
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ValveStatePt2 {
|
||||||
|
fn new(my_position: usize, elephant_position: usize, open_valves_mask: u64, minutes_left: u32) -> Self{
|
||||||
|
ValveStatePt2 { my_position, elephant_position, open_valves_mask, minutes_left }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct BestOptionResult {
|
struct BestOptionResult {
|
||||||
steps: Vec<ValveStep>,
|
steps: Vec<ValveStep>,
|
||||||
@@ -170,8 +295,9 @@ struct BestOptionResult {
|
|||||||
total_flow: u32
|
total_flow: u32
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
enum ValveStep {
|
enum ValveStep {
|
||||||
OpenValve(usize),
|
OpenValve(usize),
|
||||||
MoveTo(usize)
|
MoveTo(usize),
|
||||||
|
None
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user