This commit is contained in:
parent
148f240696
commit
b3434735e6
122
src/day12.rs
122
src/day12.rs
|
@ -26,98 +26,15 @@ impl Day for Day12 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part1(&self) -> anyhow::Result<String> {
|
fn part1(&self) -> anyhow::Result<String> {
|
||||||
fn get_all_paths(caves: &HashMap<String, Cave>, complete_paths: &mut Vec<Vec<String>>, current_path: &Vec<String>, current_cave_idx: &str) {
|
let m = HashMap::new();
|
||||||
if current_cave_idx == "end" {
|
Ok(format!("{}", self.search("start", &m, true)))
|
||||||
complete_paths.push(current_path.clone());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let current_cave = caves.get(current_cave_idx).expect("This cave does not exist!").clone();
|
|
||||||
|
|
||||||
for connected_cave in current_cave.connections {
|
|
||||||
let current = caves.get(&connected_cave).unwrap();
|
|
||||||
match current.cave_type {
|
|
||||||
CaveType::Small => {
|
|
||||||
if current_path.iter().find(|&cave_pair| cave_pair == &connected_cave) != None {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut new_path = current_path.clone();
|
|
||||||
new_path.push(connected_cave.clone());
|
|
||||||
get_all_paths(&caves, complete_paths, &new_path, &connected_cave);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut complete_paths = Vec::new();
|
|
||||||
let current_path = vec!["start".into()];
|
|
||||||
|
|
||||||
get_all_paths(&self.0, &mut complete_paths, ¤t_path, "start".into());
|
|
||||||
|
|
||||||
Ok(format!("{}", complete_paths.len()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part2(&self) -> anyhow::Result<String> {
|
fn part2(&self) -> anyhow::Result<String> {
|
||||||
let mut small_caves_thing: HashMap<Vec<String>, Vec<String>> = HashMap::<Vec<String>, Vec<String>>::new();
|
let m = HashMap::new();
|
||||||
fn get_all_paths(caves: &HashMap<String, Cave>, complete_paths: &mut Vec<Vec<String>>, current_path: &Vec<String>, current_cave_idx: &str, small_caves_thing: &mut HashMap<Vec<String>, Vec<String>>) {
|
Ok(format!("{}", self.search("start", &m, false)))
|
||||||
if current_cave_idx == "end" {
|
|
||||||
complete_paths.push(current_path.clone());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let current_cave = caves.get(current_cave_idx).expect("This cave does not exist!").clone();
|
|
||||||
|
|
||||||
let small_caves = {
|
|
||||||
let e = small_caves_thing.entry(current_path.clone()).or_insert(small_caves_visited_at_least_twice(caves, current_path));
|
|
||||||
e.clone()
|
|
||||||
};
|
|
||||||
|
|
||||||
for connected_cave in current_cave.connections {
|
|
||||||
if connected_cave == "start" {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if !small_caves.is_empty() {
|
|
||||||
let current = caves.get(&connected_cave).unwrap();
|
|
||||||
match current.cave_type {
|
|
||||||
CaveType::Small => {
|
|
||||||
if !(small_caves.len() == 1 && small_caves[0] != connected_cave) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut new_path = current_path.clone();
|
|
||||||
new_path.push(connected_cave.clone());
|
|
||||||
get_all_paths(&caves, complete_paths, &new_path, &connected_cave, small_caves_thing);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut complete_paths = Vec::new();
|
|
||||||
let current_path = vec!["start".into()];
|
|
||||||
|
|
||||||
get_all_paths(&self.0, &mut complete_paths, ¤t_path, "start", &mut small_caves_thing);
|
|
||||||
|
|
||||||
Ok(format!("{}", complete_paths.len()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn small_caves_visited_at_least_twice(caves: &HashMap<String, Cave>, current_path: &Vec<String>) -> Vec<String> {
|
|
||||||
let mut small_cave_indices = HashMap::new();
|
|
||||||
for cave_name in current_path {
|
|
||||||
let c = caves.get(cave_name).expect("how?");
|
|
||||||
if c.cave_type == CaveType::Small {
|
|
||||||
let e = small_cave_indices.entry(cave_name).or_insert(0);
|
|
||||||
*e += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return small_cave_indices.iter().filter(|(_, &b)| b > 1).map(|(&a, _)| a.clone()).collect();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Ord, PartialOrd, Eq, PartialEq, Copy, Clone)]
|
#[derive(Ord, PartialOrd, Eq, PartialEq, Copy, Clone)]
|
||||||
enum CaveType {
|
enum CaveType {
|
||||||
Large,
|
Large,
|
||||||
|
@ -153,23 +70,22 @@ impl Cave {
|
||||||
impl Day12 {
|
impl Day12 {
|
||||||
fn search(&self, cur: &str, had: &HashMap<String, i32>, part1: bool) -> i32 {
|
fn search(&self, cur: &str, had: &HashMap<String, i32>, part1: bool) -> i32 {
|
||||||
let mut had = had.clone();
|
let mut had = had.clone();
|
||||||
if had.values().any(|&i| i > 0) || part1 {
|
if had.values().any(|&i| i > 1) || part1 {
|
||||||
if had.contains_key(cur) {
|
if had.contains_key(cur) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if cur == "start" && had.contains_key("start") {
|
if cur == "start" && had.contains_key("start") {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if cur == "end" {
|
if cur == "end" {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if cur.chars().all(|x| x.is_lowercase()) {
|
let n = self.0.get(cur).unwrap();
|
||||||
|
if n.cave_type == CaveType::Small {
|
||||||
let e = had.entry(cur.into()).or_insert(0);
|
let e = had.entry(cur.into()).or_insert(0);
|
||||||
*e += 1;
|
*e += 1;
|
||||||
}
|
}
|
||||||
let n = self.0.get(cur).unwrap();
|
|
||||||
return n.connections.iter().map(|c| self.search(c, &mut had, part1)).sum::<i32>();
|
return n.connections.iter().map(|c| self.search(c, &mut had, part1)).sum::<i32>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -237,12 +153,12 @@ start-RW";
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[test]
|
#[test]
|
||||||
// fn part1_real() -> anyhow::Result<()> {
|
fn part1_real() -> anyhow::Result<()> {
|
||||||
// let d = Day12::init(crate::load_input("12")?)?;
|
let d = Day12::init(crate::load_input("12")?)?;
|
||||||
// assert_eq!("4885", d.part1()?);
|
assert_eq!("4885", d.part1()?);
|
||||||
// Ok(())
|
Ok(())
|
||||||
// }
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn part2_test_1() -> anyhow::Result<()> {
|
fn part2_test_1() -> anyhow::Result<()> {
|
||||||
|
@ -259,12 +175,12 @@ start-RW";
|
||||||
}
|
}
|
||||||
|
|
||||||
// These are very slow, so they are commented out.
|
// These are very slow, so they are commented out.
|
||||||
// #[test]
|
#[test]
|
||||||
// fn part2_test_3() -> anyhow::Result<()> {
|
fn part2_test_3() -> anyhow::Result<()> {
|
||||||
// let d = Day12::init(INPUT_3.to_string())?;
|
let d = Day12::init(INPUT_3.to_string())?;
|
||||||
// assert_eq!("3509", d.part2()?);
|
assert_eq!("3509", d.part2()?);
|
||||||
// Ok(())
|
Ok(())
|
||||||
// }
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn part2_real() -> anyhow::Result<()> {
|
fn part2_real() -> anyhow::Result<()> {
|
||||||
|
|
Loading…
Reference in a new issue