Skip to content

Commit c1cd331

Browse files
authored
feat(graph): add graph coloring (alexfertel#57)
1 parent c9a3ea6 commit c1cd331

File tree

4 files changed

+183
-2
lines changed

4 files changed

+183
-2
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ cargo test
109109

110110
- [x] [Convex Hull: Graham Scan](./src/general/convex_hull.rs)
111111
- [x] [N-Queens Problem](./src/general/nqueens.rs)
112-
- [ ] Graph Coloring
112+
- [x] [Graph Coloring](./src/general/graph_coloring.rs)
113113
- [x] [Tower of Hanoi](./src/general/hanoi.rs)
114114
- [x] [Kmeans](./src/general/kmeans.rs)
115115
- [x] [Two Sum](./src/general/two_sum.rs)

src/data_structures/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub use self::avl_tree::AVLTree;
2424
pub use self::b_tree::BTree;
2525
pub use self::binary_search_tree::BinarySearchTree;
2626
pub use self::fenwick_tree::FenwickTree;
27-
pub use self::graph::{DirectedGraph, UndirectedGraph};
27+
pub use self::graph::{DirectedGraph, Graph, UndirectedGraph};
2828
pub use self::rb_tree::RBTree;
2929
pub use self::segment_tree::SegmentTree;
3030
pub use self::stack_using_singly_linked_list::Stack as SllStack;

src/general/graph_coloring.rs

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
use crate::data_structures::{Graph, UndirectedGraph};
2+
use std::collections::{HashMap, HashSet};
3+
use std::fmt::Debug;
4+
use std::hash::Hash;
5+
6+
pub fn color_graph<'a, T>(graph: &'a UndirectedGraph<T>) -> HashMap<&'a T, u32>
7+
where
8+
T: 'a + Eq + Hash + Debug,
9+
{
10+
let empty_vec = Vec::new();
11+
graph
12+
.nodes()
13+
.iter()
14+
.fold(HashMap::new(), |mut colors, node| {
15+
let used_colors = graph
16+
.neighbours(node)
17+
.unwrap_or(&empty_vec)
18+
.iter()
19+
.filter_map(|(neighbor, _)| colors.get(neighbor))
20+
.collect::<HashSet<_>>();
21+
22+
let color = (0..).find(|i| !used_colors.contains(i)).unwrap_or(0);
23+
colors.insert(node, color);
24+
25+
colors
26+
})
27+
}
28+
29+
#[cfg(test)]
30+
mod test_color_graph {
31+
use super::*;
32+
33+
#[derive(PartialEq, Eq, Hash, Debug)]
34+
struct Node {
35+
name: String,
36+
}
37+
38+
impl Node {
39+
fn new(name: String) -> Self {
40+
Node { name }
41+
}
42+
}
43+
44+
#[test]
45+
fn test_coloring() {
46+
// a->b
47+
// b->c
48+
// c->a
49+
// a->d
50+
// a->e
51+
52+
// ┌───────┐
53+
// │ a │
54+
// └△─┬─┬─┬┘
55+
// │ │ │┌▽┐
56+
// │ │ ││b│
57+
// │ │ │└┬┘
58+
// │ │┌▽┐│
59+
// │ ││d││
60+
// │ │└─┘│
61+
// │┌▽┐ │
62+
// ││e│ │
63+
// │└─┘ │
64+
// ┌┴─────▽─┐
65+
// │ c │
66+
// └────────┘
67+
68+
let mut graph: UndirectedGraph<Node> = UndirectedGraph::new();
69+
70+
let a = Node::new(String::from("a"));
71+
let b = Node::new(String::from("b"));
72+
let c = Node::new(String::from("c"));
73+
let d = Node::new(String::from("d"));
74+
let e = Node::new(String::from("e"));
75+
76+
graph.add_node(&a);
77+
graph.add_node(&b);
78+
graph.add_node(&c);
79+
graph.add_node(&d);
80+
graph.add_node(&e);
81+
82+
graph.add_edge((&a, &b, 5));
83+
graph.add_edge((&b, &c, 10));
84+
graph.add_edge((&c, &a, 7));
85+
graph.add_edge((&a, &d, 5));
86+
graph.add_edge((&a, &e, 5));
87+
88+
let colors = color_graph(&graph);
89+
90+
assert_ne!(colors[&a], colors[&b]);
91+
assert_ne!(colors[&b], colors[&c]);
92+
assert_ne!(colors[&c], colors[&a]);
93+
assert_ne!(colors[&a], colors[&d]);
94+
assert_ne!(colors[&a], colors[&e]);
95+
96+
let all_colors = vec![0, 1, 2];
97+
assert!(all_colors.contains(&colors[&a]));
98+
assert!(all_colors.contains(&colors[&b]));
99+
assert!(all_colors.contains(&colors[&c]));
100+
assert!(all_colors.contains(&colors[&d]));
101+
assert!(all_colors.contains(&colors[&e]));
102+
}
103+
104+
#[test]
105+
fn test_coloring_each_to_each() {
106+
// a->b
107+
// a->c
108+
// a->d
109+
// a->e
110+
// b->c
111+
// b->d
112+
// b->e
113+
// c->d
114+
// c->e
115+
// d->e
116+
117+
// ┌──────┐
118+
// │a │
119+
// └┬┬─┬─┬┘
120+
// ││ │┌▽────┐
121+
// ││ ││b │
122+
// ││ │└┬─┬┬─┘
123+
// ││┌▽─▽┐││
124+
// │││c │││
125+
// ││└─┬┬┘││
126+
// ││ ││ ││
127+
// ││ ││ ││
128+
// ││ ││ ││
129+
// │└─┐││ ││
130+
// │┌─│┘│ ││
131+
// ││ │┌│─│┘
132+
// ││┌▽▽▽┐│
133+
// │││d ││
134+
// ││└┬──┘│
135+
// ┌▽▽─▽───▽┐
136+
// │e │
137+
// └────────┘
138+
139+
let mut graph: UndirectedGraph<Node> = UndirectedGraph::new();
140+
141+
let a = Node::new(String::from("a"));
142+
let b = Node::new(String::from("b"));
143+
let c = Node::new(String::from("c"));
144+
let d = Node::new(String::from("d"));
145+
let e = Node::new(String::from("e"));
146+
147+
graph.add_node(&a);
148+
graph.add_node(&b);
149+
graph.add_node(&c);
150+
graph.add_node(&d);
151+
graph.add_node(&e);
152+
153+
graph.add_edge((&a, &b, 5));
154+
graph.add_edge((&a, &c, 5));
155+
graph.add_edge((&a, &d, 5));
156+
graph.add_edge((&a, &e, 5));
157+
graph.add_edge((&b, &c, 5));
158+
graph.add_edge((&b, &d, 5));
159+
graph.add_edge((&b, &e, 5));
160+
graph.add_edge((&c, &d, 5));
161+
graph.add_edge((&c, &e, 5));
162+
graph.add_edge((&d, &e, 5));
163+
164+
let colors = color_graph(&graph);
165+
166+
assert_ne!(colors[&a], colors[&b]);
167+
assert_ne!(colors[&b], colors[&c]);
168+
assert_ne!(colors[&c], colors[&d]);
169+
assert_ne!(colors[&d], colors[&e]);
170+
assert_ne!(colors[&e], colors[&a]);
171+
172+
let all_colors = vec![0, 1, 2, 3, 4, 5];
173+
assert!(all_colors.contains(&colors[&a]));
174+
assert!(all_colors.contains(&colors[&b]));
175+
assert!(all_colors.contains(&colors[&c]));
176+
assert!(all_colors.contains(&colors[&d]));
177+
assert!(all_colors.contains(&colors[&e]));
178+
}
179+
}

src/general/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
mod convex_hull;
2+
mod graph_coloring;
23
mod hanoi;
34
mod huffman_encoding;
45
mod kmeans;
56
mod nqueens;
67
mod two_sum;
78

89
pub use self::convex_hull::convex_hull_graham;
10+
pub use self::graph_coloring::color_graph;
911
pub use self::hanoi::hanoi;
1012
pub use self::huffman_encoding::HuffmanDictionary;
1113
pub use self::kmeans::{f32, f64};

0 commit comments

Comments
 (0)