Skip to content

Commit 50353cc

Browse files
committed
refactor(23/2024): extract graph struct
1 parent 1c1bad1 commit 50353cc

File tree

3 files changed

+90
-17
lines changed

3 files changed

+90
-17
lines changed

src/solutions/year2024/day23.rs

+21-17
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,19 @@
11
use crate::solutions::Solution;
2+
use crate::utils::graphs::graph::Graph;
23
use itertools::Itertools;
3-
use std::collections::HashMap;
44

55
pub struct Day23;
66

77
impl Solution for Day23 {
88
fn part_one(&self, input: &str) -> String {
9-
let mut neighbours: HashMap<&str, Vec<&str>> = HashMap::new();
9+
let graph = self.parse(input);
1010

11-
let connections: Vec<(&str, &str)> = input
12-
.lines()
13-
.map(|line| {
14-
let (a, b) = line.split_once('-').unwrap();
15-
16-
neighbours.entry(a).or_default().push(b);
17-
neighbours.entry(b).or_default().push(a);
18-
19-
(a, b)
20-
})
21-
.collect();
22-
23-
connections
11+
graph
12+
.edges()
2413
.iter()
2514
.flat_map(|(a, b)| {
26-
let a_neighbours = neighbours.get(a).unwrap();
27-
let b_neighbours = neighbours.get(b).unwrap();
15+
let a_neighbours = graph.neighbours(a);
16+
let b_neighbours = graph.neighbours(b);
2817

2918
a_neighbours
3019
.iter()
@@ -34,6 +23,7 @@ impl Solution for Day23 {
3423
set.sort();
3524
set
3625
})
26+
.collect::<Vec<[&str; 3]>>()
3727
})
3828
.unique()
3929
.filter(|set| set.iter().any(|c| c.starts_with("t")))
@@ -46,6 +36,20 @@ impl Solution for Day23 {
4636
}
4737
}
4838

39+
impl Day23 {
40+
fn parse<'a>(&self, input: &'a str) -> Graph<&'a str> {
41+
let mut graph: Graph<&str> = Graph::undirected();
42+
43+
input.lines().for_each(|line| {
44+
let (a, b) = line.split_once('-').unwrap();
45+
46+
graph.add_edge(a, b);
47+
});
48+
49+
graph
50+
}
51+
}
52+
4953
#[cfg(test)]
5054
mod tests {
5155
use crate::solutions::year2024::day23::Day23;

src/utils/graphs/graph.rs

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
use std::collections::{HashMap, HashSet};
2+
use std::hash::Hash;
3+
4+
enum GraphType {
5+
#[allow(dead_code)]
6+
Directed,
7+
Undirected,
8+
}
9+
10+
pub struct Graph<T> {
11+
nodes: HashSet<T>,
12+
edges: HashSet<(T, T)>,
13+
neighbours: HashMap<T, Vec<T>>,
14+
graph_type: GraphType,
15+
}
16+
17+
impl<T> Graph<T> {
18+
pub fn undirected() -> Self {
19+
Self {
20+
nodes: HashSet::new(),
21+
edges: HashSet::new(),
22+
neighbours: HashMap::new(),
23+
graph_type: GraphType::Undirected,
24+
}
25+
}
26+
27+
pub fn add_edge(&mut self, a: T, b: T)
28+
where
29+
T: Eq + Hash + Copy,
30+
{
31+
match self.graph_type {
32+
GraphType::Directed => self.add_directed_edge(a, b),
33+
GraphType::Undirected => self.add_undirected_edge(a, b),
34+
}
35+
}
36+
37+
fn add_directed_edge(&mut self, a: T, b: T)
38+
where
39+
T: Eq + Hash + Copy,
40+
{
41+
self.nodes.insert(a);
42+
self.nodes.insert(b);
43+
self.edges.insert((a, b));
44+
self.neighbours.entry(a).or_default().push(b);
45+
}
46+
47+
fn add_undirected_edge(&mut self, a: T, b: T)
48+
where
49+
T: Eq + Hash + Copy,
50+
{
51+
self.nodes.insert(a);
52+
self.nodes.insert(b);
53+
self.edges.insert((a, b));
54+
self.neighbours.entry(a).or_default().push(b);
55+
self.neighbours.entry(b).or_default().push(a);
56+
}
57+
58+
pub fn edges(&self) -> &HashSet<(T, T)> {
59+
&self.edges
60+
}
61+
62+
pub fn neighbours(&self, node: &T) -> Vec<T>
63+
where
64+
T: Eq + Hash + Clone,
65+
{
66+
self.neighbours.get(node).unwrap_or(&Vec::new()).to_vec()
67+
}
68+
}

src/utils/graphs/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
pub mod a_star;
22
pub mod all_paths;
33
pub mod dijkstra;
4+
pub mod graph;
45
pub mod longest_path;
56
mod state_utils;

0 commit comments

Comments
 (0)