Day 12
This commit is contained in:
parent
1b1571c323
commit
1bf6e92261
|
@ -0,0 +1,25 @@
|
||||||
|
we-NX
|
||||||
|
ys-px
|
||||||
|
ys-we
|
||||||
|
px-end
|
||||||
|
yq-NX
|
||||||
|
px-NX
|
||||||
|
yq-px
|
||||||
|
qk-yq
|
||||||
|
pr-NX
|
||||||
|
wq-EY
|
||||||
|
pr-oe
|
||||||
|
wq-pr
|
||||||
|
ys-end
|
||||||
|
start-we
|
||||||
|
ys-start
|
||||||
|
oe-DW
|
||||||
|
EY-oe
|
||||||
|
end-oe
|
||||||
|
pr-yq
|
||||||
|
pr-we
|
||||||
|
wq-start
|
||||||
|
oe-NX
|
||||||
|
yq-EY
|
||||||
|
ys-wq
|
||||||
|
ys-pr
|
|
@ -36,7 +36,7 @@ pub fn day11() {
|
||||||
|
|
||||||
println!("{:?}", grid);
|
println!("{:?}", grid);
|
||||||
|
|
||||||
for step in 0..100 {
|
for _step in 0..100 {
|
||||||
let (new, flashed) = grid.step();
|
let (new, flashed) = grid.step();
|
||||||
// println!("after step: {}, new grid: {:?}", step + 1, new);
|
// println!("after step: {}, new grid: {:?}", step + 1, new);
|
||||||
grid = new;
|
grid = new;
|
||||||
|
|
|
@ -0,0 +1,158 @@
|
||||||
|
use std::collections::{HashMap, HashSet, VecDeque};
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use std::fmt::Formatter;
|
||||||
|
|
||||||
|
pub fn day12() {
|
||||||
|
// 10 paths, 36
|
||||||
|
// let input = r#"
|
||||||
|
// start-A
|
||||||
|
// start-b
|
||||||
|
// A-c
|
||||||
|
// A-b
|
||||||
|
// b-d
|
||||||
|
// A-end
|
||||||
|
// b-end"#;
|
||||||
|
// 19 paths, 103
|
||||||
|
// let input = r#"
|
||||||
|
// dc-end
|
||||||
|
// HN-start
|
||||||
|
// start-kj
|
||||||
|
// dc-start
|
||||||
|
// dc-HN
|
||||||
|
// LN-dc
|
||||||
|
// HN-end
|
||||||
|
// kj-sa
|
||||||
|
// kj-HN
|
||||||
|
// kj-dc
|
||||||
|
// "#;
|
||||||
|
// 226 paths, 3059
|
||||||
|
// let input = r#"
|
||||||
|
// fs-end
|
||||||
|
// he-DX
|
||||||
|
// fs-he
|
||||||
|
// start-DX
|
||||||
|
// pj-DX
|
||||||
|
// end-zg
|
||||||
|
// zg-sl
|
||||||
|
// zg-pj
|
||||||
|
// pj-he
|
||||||
|
// RW-he
|
||||||
|
// fs-DX
|
||||||
|
// pj-RW
|
||||||
|
// zg-RW
|
||||||
|
// start-pj
|
||||||
|
// he-WI
|
||||||
|
// zg-he
|
||||||
|
// pj-fs
|
||||||
|
// start-RW
|
||||||
|
// "#;
|
||||||
|
let input = include_str!("../input/day12.txt");
|
||||||
|
|
||||||
|
let graph = parse_graph(&input);
|
||||||
|
println!("{:?}", graph);
|
||||||
|
|
||||||
|
println!("{:?}", count_paths(&graph, false));
|
||||||
|
println!("{:?}", count_paths(&graph, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_graph(input: &'static str) -> Graph {
|
||||||
|
let mut nodes = HashSet::new();
|
||||||
|
let mut connections: HashMap<Node, Vec<Node>> = HashMap::new();
|
||||||
|
for line in input.trim().lines() {
|
||||||
|
let (a, b) = line.trim().split_once("-").unwrap();
|
||||||
|
let first: Node = a.into();
|
||||||
|
let second: Node = b.into();
|
||||||
|
nodes.insert(first.clone());
|
||||||
|
nodes.insert(second.clone());
|
||||||
|
connections
|
||||||
|
.entry(first.clone())
|
||||||
|
.or_insert(vec![])
|
||||||
|
.push(second.clone());
|
||||||
|
connections.entry(second).or_insert(vec![]).push(first);
|
||||||
|
}
|
||||||
|
|
||||||
|
Graph { nodes, connections }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Hash, Clone)]
|
||||||
|
enum Node {
|
||||||
|
Start,
|
||||||
|
End,
|
||||||
|
Small(&'static str),
|
||||||
|
Big(&'static str),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Node {
|
||||||
|
fn big(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::Big(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for Node {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Start => write!(f, "start"),
|
||||||
|
Self::End => write!(f, "end"),
|
||||||
|
Self::Small(s) | Self::Big(s) => write!(f, "{}", s),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&'static str> for Node {
|
||||||
|
fn from(s: &'static str) -> Self {
|
||||||
|
if s == "start" {
|
||||||
|
Self::Start
|
||||||
|
} else if s == "end" {
|
||||||
|
Self::End
|
||||||
|
} else if s.chars().all(|c| c.is_uppercase()) {
|
||||||
|
Self::Big(s)
|
||||||
|
} else {
|
||||||
|
Self::Small(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Graph {
|
||||||
|
nodes: HashSet<Node>,
|
||||||
|
connections: HashMap<Node, Vec<Node>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn count_paths(g: &Graph, allow_visiting_small_twice: bool) -> usize {
|
||||||
|
let mut queue: VecDeque<(Vec<&Node>, bool)> = VecDeque::new();
|
||||||
|
queue.push_front((vec![&Node::Start], false));
|
||||||
|
let mut count = 0;
|
||||||
|
|
||||||
|
while let Some((path, mut seen_any_small_twice)) = queue.pop_front() {
|
||||||
|
let last = path.last().unwrap().clone();
|
||||||
|
|
||||||
|
if last == &Node::End {
|
||||||
|
// println!("{:?}", path);
|
||||||
|
count += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// current is small and seen current before
|
||||||
|
if !last.big() && path.iter().rev().skip(1).any(|&n| n == last) {
|
||||||
|
// if visting small twice is always prohibited (part 1), or we're revisting the start,
|
||||||
|
// or visiting a _single_ small twice is allowed but we've already done it
|
||||||
|
if !allow_visiting_small_twice || last == &Node::Start || seen_any_small_twice {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// note that we've now seen a single small cave twice, so any paths descended from this
|
||||||
|
// one can't do so themselves
|
||||||
|
seen_any_small_twice = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for connected in &g.connections[last] {
|
||||||
|
let mut new_path = path.clone();
|
||||||
|
new_path.push(connected);
|
||||||
|
queue.push_back((new_path, seen_any_small_twice));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
count
|
||||||
|
}
|
|
@ -10,7 +10,8 @@ mod day08;
|
||||||
mod day09;
|
mod day09;
|
||||||
mod day10;
|
mod day10;
|
||||||
mod day11;
|
mod day11;
|
||||||
|
mod day12;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
day11::day11();
|
day12::day12();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue