Skip to content

Commit caab831

Browse files
committed
solved day12
1 parent cd51cb7 commit caab831

File tree

7 files changed

+264
-0
lines changed

7 files changed

+264
-0
lines changed

day12/Cargo.lock

+48
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

day12/Cargo.toml

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "day12"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies]
9+
petgraph = "0.6.0"

day12/input

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
FK-gc
2+
gc-start
3+
gc-dw
4+
sp-FN
5+
dw-end
6+
FK-start
7+
dw-gn
8+
AN-gn
9+
yh-gn
10+
yh-start
11+
sp-AN
12+
ik-dw
13+
FK-dw
14+
end-sp
15+
yh-FK
16+
gc-gn
17+
AN-end
18+
dw-AN
19+
gn-sp
20+
gn-FK
21+
sp-FK
22+
yh-gc

day12/src/main.rs

+150
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
use std::collections::HashMap;
2+
use std::collections::HashSet;
3+
4+
#[derive(Debug)]
5+
struct Graph {
6+
names: HashMap<String, usize>,
7+
matrix: HashMap<usize, Vec<usize>>,
8+
big: HashSet<usize>,
9+
start: usize,
10+
end: usize,
11+
}
12+
13+
fn parse(fname: &str) -> Graph {
14+
let mut cur_num = 0;
15+
let mut g = Graph {
16+
names: HashMap::new(),
17+
matrix: HashMap::new(),
18+
big: HashSet::new(),
19+
start: 0,
20+
end: 0,
21+
};
22+
23+
let strnodes = std::fs::read_to_string(fname)
24+
.unwrap()
25+
.lines()
26+
.map(|line| line.split_once('-').unwrap())
27+
.map(|(s1, s2)| (s1.to_owned(), s2.to_owned()))
28+
.collect::<Vec<(String, String)>>();
29+
30+
for (lname, rname) in &strnodes {
31+
for name in [lname, rname] {
32+
if !g.names.contains_key(name) {
33+
g.names.insert(name.to_string(), cur_num);
34+
g.matrix.insert(cur_num, Vec::new());
35+
if name.chars().all(|c| c.is_uppercase()) {
36+
g.big.insert(cur_num);
37+
}
38+
if name == "start" {
39+
g.start = cur_num;
40+
}
41+
if name == "end" {
42+
g.end = cur_num;
43+
}
44+
cur_num += 1;
45+
}
46+
}
47+
g.matrix
48+
.get_mut(&g.names[lname])
49+
.unwrap()
50+
.push(g.names[rname]);
51+
g.matrix
52+
.get_mut(&g.names[rname])
53+
.unwrap()
54+
.push(g.names[lname]);
55+
}
56+
g
57+
}
58+
59+
fn count_paths(g: &Graph, start: usize, visits: &mut HashMap<usize, u32>) -> u128 {
60+
visits.insert(start, visits.get(&start).unwrap_or(&0) + 1);
61+
if start == g.end {
62+
return 1;
63+
} else {
64+
g.matrix
65+
.get(&start)
66+
.unwrap()
67+
.clone()
68+
.into_iter()
69+
.filter(|w| g.big.contains(w) || visits.get(w).unwrap_or(&0) < &1)
70+
.map(|w| count_paths(g, w, &mut visits.clone()))
71+
.sum()
72+
}
73+
}
74+
fn part1(g: &Graph) -> usize {
75+
count_paths(g, g.start, &mut HashMap::new()) as usize
76+
}
77+
78+
fn count_paths2(
79+
g: &Graph,
80+
start: usize,
81+
path: &mut Vec<usize>,
82+
visits: &mut HashMap<usize, u32>,
83+
) -> u128 {
84+
visits.insert(start, visits.get(&start).unwrap_or(&0) + 1);
85+
path.push(start);
86+
if start == g.end {
87+
return 1;
88+
} else {
89+
g.matrix
90+
.get(&start)
91+
.unwrap()
92+
.clone()
93+
.into_iter()
94+
.filter(|w| {
95+
let wvisits = visits.get(w).unwrap_or(&0);
96+
let mut counts: HashMap<usize, u32> = HashMap::new();
97+
for entity in path.clone() {
98+
*counts.entry(entity).or_insert(0) += 1;
99+
}
100+
*counts.entry(*w).or_insert(0) += 1;
101+
if counts
102+
.into_iter()
103+
.filter(|(node, __)| {
104+
node != &g.start && node != &g.end && !g.big.contains(node)
105+
})
106+
.filter(|(_, count)| count > &1u32)
107+
.count()
108+
> 1
109+
{
110+
return false;
111+
}
112+
g.big.contains(w)
113+
|| wvisits < &1
114+
|| ((w != &g.start) && (w != &g.end) && (wvisits < &2))
115+
})
116+
.map(|w| count_paths2(g, w, &mut path.clone(), &mut visits.clone()))
117+
.sum()
118+
}
119+
}
120+
fn part2(g: &Graph) -> usize {
121+
count_paths2(g, g.start, &mut vec![], &mut HashMap::new()) as usize
122+
}
123+
#[test]
124+
fn test0_part1() {
125+
assert_eq!(part1(&parse("test0")), 10)
126+
}
127+
#[test]
128+
fn test1_part1() {
129+
assert_eq!(part1(&parse("test1")), 19)
130+
}
131+
#[test]
132+
fn test2_part1() {
133+
assert_eq!(part1(&parse("test2")), 226)
134+
}
135+
#[test]
136+
fn test0_part2() {
137+
assert_eq!(part2(&parse("test0")), 36)
138+
}
139+
#[test]
140+
fn test1_part2() {
141+
assert_eq!(part2(&parse("test1")), 103)
142+
}
143+
#[test]
144+
fn test2_part2() {
145+
assert_eq!(part2(&parse("test2")), 3509)
146+
}
147+
fn main() {
148+
println!("{:?}", part1(&parse("input")));
149+
println!("{:?}", part2(&parse("input")));
150+
}

day12/test0

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
start-A
2+
start-b
3+
A-c
4+
A-b
5+
b-d
6+
A-end
7+
b-end

day12/test1

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
dc-end
2+
HN-start
3+
start-kj
4+
dc-start
5+
dc-HN
6+
LN-dc
7+
HN-end
8+
kj-sa
9+
kj-HN
10+
kj-dc

day12/test2

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
fs-end
2+
he-DX
3+
fs-he
4+
start-DX
5+
pj-DX
6+
end-zg
7+
zg-sl
8+
zg-pj
9+
pj-he
10+
RW-he
11+
fs-DX
12+
pj-RW
13+
zg-RW
14+
start-pj
15+
he-WI
16+
zg-he
17+
pj-fs
18+
start-RW

0 commit comments

Comments
 (0)