Compare commits

..

2 Commits

Author SHA1 Message Date
e93f6d01ca Day 12 clippy lint. 2021-12-11 22:21:27 -08:00
b542304187 Day 12 part 2 2021-12-11 22:19:43 -08:00

View File

@ -1,24 +1,7 @@
use std::{ use std::collections::HashMap;
collections::HashMap,
fmt::{Debug, Error, Formatter},
num::ParseIntError,
ops::{Index, IndexMut},
str::FromStr,
};
use anyhow::Result; use anyhow::Result;
use aoc_runner_derive::{aoc, aoc_generator}; use aoc_runner_derive::aoc;
use thiserror::Error;
struct Node {
name: String,
small: bool,
neighbors: Vec<usize>,
}
struct Graph {
nodes: Vec<String>,
}
fn search(node: &str, nodes: &HashMap<&str, Vec<&str>>, path: String, paths: &mut Vec<String>) { fn search(node: &str, nodes: &HashMap<&str, Vec<&str>>, path: String, paths: &mut Vec<String>) {
if node == "end" { if node == "end" {
@ -27,11 +10,9 @@ fn search(node: &str, nodes: &HashMap<&str, Vec<&str>>, path: String, paths: &mu
} }
for neighbor in &nodes[node] { for neighbor in &nodes[node] {
// If lowercase. // If lowercase.
if neighbor.as_bytes()[0] & 0x20 != 0 { if neighbor.as_bytes()[0] & 0x20 != 0 && path.contains(neighbor) {
if path.contains(neighbor) {
continue; continue;
} }
}
search(neighbor, nodes, format!("{},{}", path, neighbor), paths); search(neighbor, nodes, format!("{},{}", path, neighbor), paths);
} }
} }
@ -39,7 +20,6 @@ fn search(node: &str, nodes: &HashMap<&str, Vec<&str>>, path: String, paths: &mu
fn paths(nodes: &HashMap<&str, Vec<&str>>) -> usize { fn paths(nodes: &HashMap<&str, Vec<&str>>) -> usize {
let mut paths = Vec::new(); let mut paths = Vec::new();
search("start", nodes, "start".to_string(), &mut paths); search("start", nodes, "start".to_string(), &mut paths);
//dbg!(&paths);
paths.len() paths.len()
} }
@ -48,19 +28,78 @@ fn part1(input: &str) -> Result<usize> {
let mut nodes = HashMap::new(); let mut nodes = HashMap::new();
input.lines().for_each(|p| { input.lines().for_each(|p| {
let (n1, n2) = p.split_once('-').expect("missing dash"); let (n1, n2) = p.split_once('-').expect("missing dash");
nodes.entry(n1).or_insert(Vec::new()).push(n2); nodes.entry(n1).or_insert_with(Vec::new).push(n2);
nodes.entry(n2).or_insert(Vec::new()).push(n1); nodes.entry(n2).or_insert_with(Vec::new).push(n1);
}); });
Ok(paths(&nodes)) Ok(paths(&nodes))
} }
/* fn search2<'a>(
#[aoc(day12, part2)] node: &str,
fn part2(input: &[u64]) -> Result<u64> { nodes: &HashMap<&'a str, Vec<&'a str>>,
todo!("part2"); path: &[&'a str],
Ok(0) paths: &mut Vec<Vec<&'a str>>,
double: &'a str,
smalls: &[&'a str],
) {
if node == "end" {
paths.push(path.to_vec());
return;
}
for neighbor in &nodes[node] {
// If lowercase.
if neighbor.as_bytes()[0] & 0x20 != 0 {
if neighbor == &double {
// Allow two passes for this small node.
if path.iter().filter(|p| p == &neighbor).count() >= 2 {
continue;
}
} else {
// Only allow one pass for this small node.
if path.contains(neighbor) {
continue;
}
}
}
let mut child_path = path.to_vec();
child_path.push(neighbor);
search2(neighbor, nodes, &child_path, paths, double, smalls);
}
}
fn paths2(nodes: &HashMap<&str, Vec<&str>>) -> usize {
let mut paths = Vec::new();
let smalls: Vec<_> = nodes
.keys()
.filter(|n| n.as_bytes()[0] & 0x20 != 0)
.filter(|&n| n != &"start" && n != &"end")
.cloned()
.collect();
for double in &smalls {
search2(
"start",
nodes,
&["start"],
&mut paths,
double,
smalls.as_slice(),
);
}
paths.sort();
paths.dedup();
paths.len()
}
#[aoc(day12, part2)]
fn part2(input: &str) -> Result<usize> {
let mut nodes = HashMap::new();
input.lines().for_each(|p| {
let (n1, n2) = p.split_once('-').expect("missing dash");
nodes.entry(n1).or_insert_with(Vec::new).push(n2);
nodes.entry(n2).or_insert_with(Vec::new).push(n1);
});
Ok(paths2(&nodes))
} }
*/
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
@ -83,14 +122,19 @@ b-end
Ok(()) Ok(())
} }
/*
#[test] #[test]
fn test_part2()->Result<()> { fn test_part2() -> Result<()> {
let input = r#" let input = r#"
start-A
start-b
A-c
A-b
b-d
A-end
b-end
"# "#
.trim(); .trim();
assert_eq!(part2(&parse(input)?)?, u64::MAX); assert_eq!(part2(input)?, 36);
Ok(()) Ok(())
} }
*/
} }