Skip to content

Commit

Permalink
Day 16 solves sample
Browse files Browse the repository at this point in the history
  • Loading branch information
rtsuk committed Dec 19, 2022
1 parent 84e1fba commit 7bb4a83
Showing 1 changed file with 120 additions and 25 deletions.
145 changes: 120 additions & 25 deletions src/bin/day16.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ type FlowGraph = UnGraphMap<RoomId, String>;

#[derive(Debug, PartialEq)]
enum Action {
Move(String),
Move(RoomId),
Open,
Idle,
}
Expand Down Expand Up @@ -94,14 +94,18 @@ impl Volcano {
FlowGraph::from_edges(&edges)
}

fn path_between(&self, start: &str, end: &str) -> Vec<RoomId> {
let start = RoomId::new(start.to_string());
let end = RoomId::new(end.to_string());
fn path_between(&self, start: &RoomId, end: &RoomId) -> Vec<RoomId> {
let graph = self.graph.clone();
let path = bfs(&start, |p| successors(p, &graph), |p| p == &end).unwrap();
let path = bfs(start, |p| successors(p, &graph), |p| p == end).unwrap();
path[1..].to_vec()
}

fn path_between_str(&self, start: &str, end: &str) -> Vec<RoomId> {
let start = RoomId::new(start.to_string());
let end = RoomId::new(end.to_string());
self.path_between(&start, &end)
}

fn rooms_with_valves(&self) -> Vec<RoomId> {
self.rooms
.values()
Expand All @@ -110,8 +114,77 @@ impl Volcano {
}

fn current_flow(&self, open_valves: &OpenValves) -> usize {
open_valves.iter().map(|room_id| self.rooms.get(room_id).expect("room").flow).sum()
open_valves
.iter()
.map(|room_id| self.rooms.get(room_id).expect("room").flow)
.sum()
}

fn actions(&self, path: &[RoomId]) -> Vec<Action> {
let mut actions = vec![];
for room_id in path.iter() {
actions.push(Action::Move(*room_id));
}
actions.push(Action::Open);
actions
}
}

fn to_string(path: &[&RoomId]) -> String {
path.iter()
.map(|r| r.as_ref().to_string())
.collect::<Vec<String>>()
.join(",")
}

fn to_path(path: &[&str]) -> Vec<RoomId> {
path.iter()
.map(|r| Intern::new(r.to_string()))
.collect::<Vec<RoomId>>()
}

fn to_ref_path<'a>(path: &'a [RoomId]) -> Vec<&'a RoomId> {
path.iter().map(|r| r).collect::<Vec<&'a RoomId>>()
}

fn solve(volcano: &Volcano, start: &RoomId, path: &[&RoomId], limit: usize) -> usize {
let mut total_pressure = 0;
let mut open_valves = OpenValves::default();
let mut player_location = *start;
let mut time = 1;
for next_destination in path {
let path_to_next_destination = volcano.path_between(&player_location, next_destination);
let actions = volcano.actions(path_to_next_destination.as_slice());
for action in actions {
let current_flow = volcano.current_flow(&open_valves);
total_pressure += current_flow;
match &action {
Action::Move(t) => {
player_location = *t;
}

Action::Open => {
open_valves.insert(player_location);
}

Action::Idle => (),
}
time += 1;

if time > limit {
// println!("#### solving {:?}", to_string(path));
// println!("### ran out of time");
return total_pressure;
}
}
}
while time <= limit {
let current_flow = volcano.current_flow(&open_valves);
total_pressure += current_flow;
time += 1;
}

total_pressure
}

fn parse(s: &str) -> Volcano {
Expand Down Expand Up @@ -172,7 +245,7 @@ impl From<&str> for ExampleStep {
let re = Regex::new(r"You ([a-z]+).*valve ([A-Z][A-Z]).").expect("re");
let captures = re.captures(parts[2]).expect("captures");
action = match &captures[1] {
"move" => Action::Move(captures[2].to_string()),
"move" => Action::Move(RoomId::new(captures[2].to_string())),
"open" => Action::Open,
_ => Action::Idle,
};
Expand Down Expand Up @@ -218,15 +291,19 @@ fn main() -> Result<(), Error> {
let rooms = volcano.rooms_with_valves();
println!("{} rooms, {:?}", rooms.len(), rooms);

for one_permutation in rooms.iter().permutations(rooms.len()) {
println!(
"one_permutation, {:?}",
one_permutation
.iter()
.map(|r_id| r_id.as_ref())
.collect::<Vec<_>>()
);
}
let start_room = RoomId::new("AA".to_string());

let mut solutions: Vec<_> = rooms
.iter()
.permutations(rooms.len().min(6))
.map(|path| (solve(&volcano, &start_room, path.as_slice(), 30), path.clone()))
.collect();

solutions.sort_by_key(|s| s.0);

solutions.reverse();

println!("total pressure = {}", solutions[0].0);
}

Ok(())
Expand All @@ -251,12 +328,18 @@ mod test {
.collect();

assert_eq!(example_steps.len(), 30);
assert_eq!(example_steps[0].action, Action::Move("DD".to_string()));
assert_eq!(
example_steps[0].action,
Action::Move(RoomId::new("DD".to_string()))
);
assert_eq!(example_steps[0].pressure, 0);
assert_eq!(example_steps[0].open_valves.len(), 0);

let middle_step = &example_steps[17];
assert_eq!(middle_step.action, Action::Move("GG".to_string()));
assert_eq!(
middle_step.action,
Action::Move(RoomId::new("GG".to_string()))
);
assert_eq!(middle_step.pressure, 76);
assert_eq!(middle_step.open_valves.len(), 4);

Expand Down Expand Up @@ -299,23 +382,35 @@ mod test {
fn test_volcano() {
let mut v = parse(SAMPLE);

let path = v.path_between("AA", "HH");
let path = v.path_between_str("AA", "HH");
assert_eq!(path.len(), 5);

dbg!(&path);
}

#[test]
#[ignore]
fn test_permute() {
let mut v = parse(SAMPLE);
fn test_permute_solve() {
let v = parse(SAMPLE);
let start_room = RoomId::new("AA".to_string());

let rooms = v.rooms_with_valves();

let b: Vec<_> = rooms.iter().permutations(rooms.len()).collect();
let one_path = to_path(&["DD", "BB", "JJ", "HH", "EE", "CC"]);
let one_solution = solve(&v, &start_room, &to_ref_path(one_path.as_slice()), 30);
assert_eq!(one_solution, 1651);

let mut solutions: Vec<_> = rooms
.iter()
.permutations(rooms.len())
.map(|path| (solve(&v, &start_room, path.as_slice(), 30), path.clone()))
.collect();

solutions.sort_by_key(|s| s.0);

solutions.reverse();

println!("{} permutations, {:?}", b.len(), b);
dbg!(&solutions[0..10]);

todo!();
assert_eq!(solutions[0].1, to_ref_path(one_path.as_slice()));
}
}

0 comments on commit 7bb4a83

Please sign in to comment.