Skip to content

Commit dfcbfb3

Browse files
committed
[2021] Day 12 part a
1 parent 392ed16 commit dfcbfb3

File tree

5 files changed

+180
-3
lines changed

5 files changed

+180
-3
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

aoc_2021/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ edition = "2021"
66
[dependencies]
77
common = { path = "../common" }
88
hashbrown = "0.13.1"
9+
indoc = "2.0.4"
910
nd_vec = "0.4.0"
11+
petgraph = "0.6.4"

aoc_2021/src/day_12.rs

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
use common::{Answer, Solution};
2+
use hashbrown::{HashMap, HashSet};
3+
use petgraph::graph::{NodeIndex, UnGraph};
4+
5+
pub struct Day12;
6+
7+
impl Solution for Day12 {
8+
fn name(&self) -> &'static str {
9+
"Passage Pathing"
10+
}
11+
12+
fn part_a(&self, input: &str) -> Answer {
13+
let graph = parse(input);
14+
paths_a(&graph, graph.start, HashSet::new()).into()
15+
}
16+
17+
fn part_b(&self, _input: &str) -> Answer {
18+
Answer::Unimplemented
19+
}
20+
}
21+
22+
fn paths_a<'a>(graph: &ParseResult<'a>, at: NodeIndex, mut visited: HashSet<NodeIndex>) -> usize {
23+
if at == graph.end {
24+
return 1;
25+
}
26+
27+
if !visited.insert(at) && graph.graph[at].cave_type != Type::Big {
28+
return 0;
29+
}
30+
31+
graph
32+
.graph
33+
.neighbors(at)
34+
.into_iter()
35+
.map(|child| paths_a(graph, child, visited.clone()))
36+
.sum()
37+
}
38+
39+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
40+
enum Type {
41+
Small,
42+
Big,
43+
Root,
44+
}
45+
46+
struct Node<'a> {
47+
name: &'a str,
48+
cave_type: Type,
49+
}
50+
51+
struct ParseResult<'a> {
52+
graph: UnGraph<Node<'a>, ()>,
53+
start: NodeIndex,
54+
end: NodeIndex,
55+
}
56+
57+
fn parse<'a>(input: &'a str) -> ParseResult<'a> {
58+
let mut graph = UnGraph::new_undirected();
59+
let mut nodes = HashMap::new();
60+
61+
fn make_node<'a>(name: &'a str) -> Node<'a> {
62+
Node {
63+
name,
64+
cave_type: if name == "start" || name == "end" {
65+
Type::Root
66+
} else if name.chars().next().unwrap().is_uppercase() {
67+
Type::Big
68+
} else {
69+
Type::Small
70+
},
71+
}
72+
}
73+
74+
fn get_node<'a>(
75+
nodes: &mut HashMap<&'a str, NodeIndex>,
76+
graph: &mut UnGraph<Node<'a>, ()>,
77+
name: &'a str,
78+
) -> NodeIndex {
79+
*nodes
80+
.entry(name)
81+
.or_insert_with(|| graph.add_node(make_node(name)))
82+
}
83+
84+
for line in input.lines() {
85+
let (from, to) = line.split_once('-').unwrap();
86+
let from = get_node(&mut nodes, &mut graph, from);
87+
let to = get_node(&mut nodes, &mut graph, to);
88+
graph.add_edge(from, to, ());
89+
}
90+
91+
fn find<'a>(graph: &'a UnGraph<Node<'a>, ()>, name: &str) -> NodeIndex {
92+
graph
93+
.node_indices()
94+
.find(|i| graph[*i].name == name)
95+
.unwrap()
96+
}
97+
98+
ParseResult {
99+
start: find(&graph, "start"),
100+
end: find(&graph, "end"),
101+
graph,
102+
}
103+
}
104+
105+
#[cfg(test)]
106+
mod test {
107+
use common::Solution;
108+
use indoc::indoc;
109+
110+
use super::Day12;
111+
112+
const CASE: &str = indoc! {"
113+
start-A
114+
start-b
115+
A-c
116+
A-b
117+
b-d
118+
A-end
119+
b-end
120+
"};
121+
122+
const CASE_2: &str = indoc! {"
123+
dc-end
124+
HN-start
125+
start-kj
126+
dc-start
127+
dc-HN
128+
LN-dc
129+
HN-end
130+
kj-sa
131+
kj-HN
132+
kj-dc
133+
"};
134+
135+
#[test]
136+
fn part_a() {
137+
assert_eq!(Day12.part_a(CASE), 10.into());
138+
assert_eq!(Day12.part_a(CASE_2), 19.into());
139+
}
140+
141+
#[test]
142+
fn part_b() {
143+
assert_eq!(Day12.part_b(CASE), 36.into());
144+
}
145+
}

aoc_2021/src/lib.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use common::DummySolution;
21
pub use common::Solution;
32

43
mod day_01;
@@ -12,11 +11,12 @@ mod day_08;
1211
mod day_09;
1312
mod day_10;
1413
mod day_11;
14+
mod day_12;
1515
mod day_13;
1616
mod day_14;
1717
// [import_marker]
1818

19-
pub const ALL: [&dyn Solution; 14] = [
19+
pub const ALL: &[&dyn Solution] = &[
2020
&day_01::Day01,
2121
&day_02::Day02,
2222
&day_03::Day03,
@@ -28,8 +28,9 @@ pub const ALL: [&dyn Solution; 14] = [
2828
&day_09::Day09,
2929
&day_10::Day10,
3030
&day_11::Day11,
31-
&DummySolution,
31+
&day_12::Day12,
3232
&day_13::Day13,
3333
&day_14::Day14,
34+
&day_12::Day12,
3435
// [list_marker]
3536
];

aoc_2021/todo.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# AOC 2021 Todo
2+
3+
- [x] Day 1
4+
- [x] Day 2
5+
- [x] Day 3
6+
- [x] Day 4
7+
- [x] Day 5
8+
- [x] Day 6
9+
- [x] Day 7
10+
- [x] Day 8
11+
- [x] Day 9
12+
- [x] Day 10
13+
- [x] Day 11
14+
- [ ] Day 12
15+
- [x] Day 13
16+
- [x] Day 14
17+
- [ ] Day 15
18+
- [ ] Day 16
19+
- [ ] Day 17
20+
- [ ] Day 18
21+
- [ ] Day 19
22+
- [ ] Day 20
23+
- [ ] Day 21
24+
- [ ] Day 22
25+
- [ ] Day 23
26+
- [ ] Day 24
27+
- [ ] Day 25

0 commit comments

Comments
 (0)