-
Notifications
You must be signed in to change notification settings - Fork 0
/
day25.rs
165 lines (142 loc) · 4.4 KB
/
day25.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
use rand::random;
use rayon::prelude::*;
use std::{
collections::{HashSet, VecDeque},
sync::atomic::{AtomicUsize, Ordering},
// f64::consts::E,
};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Edge {
vu: String,
vv: String,
}
trait Pool {
fn find_any(&self, v: &String) -> Vec<Edge>;
fn trim(&mut self, edges: Vec<Edge>);
}
impl Pool for VecDeque<Edge> {
fn find_any(&self, v: &String) -> Vec<Edge> {
let mut results = Vec::new();
for edge in self {
if edge.vu == *v || edge.vv == *v {
results.push(edge.clone());
}
}
results
}
fn trim(&mut self, edges: Vec<Edge>) {
self.retain(|edge| !edges.contains(edge));
}
}
#[derive(Debug, Clone)]
pub struct SuperVertex {
vertices: Vec<String>,
edges: Vec<Edge>,
}
impl SuperVertex {
fn new(vertices: Vec<String>, edges: Vec<Edge>) -> Self {
SuperVertex {
vertices,
edges,
}
}
fn union(self, other: SuperVertex) -> (SuperVertex, Vec<Edge>) {
let union_vertices = [
self.vertices,
other.vertices,
].concat();
let new_edges = [
self.edges,
other.edges,
].concat();
let mut duplicates = Vec::new();
let mut union_edges = Vec::new();
for edge in new_edges {
if union_edges.contains(&edge) {
duplicates.push(edge);
} else {
union_edges.push(edge);
}
}
union_edges.retain(|edge| !duplicates.contains(edge));
(SuperVertex::new(union_vertices, union_edges), duplicates)
}
}
trait Graph {
fn take(&mut self, v: &String) -> SuperVertex;
}
impl Graph for Vec<SuperVertex> {
fn take(&mut self, v: &String) -> SuperVertex {
let index = self.iter().position(|sv| sv.vertices.contains(v)).unwrap();
self.swap_remove(index)
}
}
#[aoc_generator(day25)]
pub fn input_generator(input: &str) -> (Vec<SuperVertex>, VecDeque<Edge>) {
let mut nodes = HashSet::new();
let mut edges = VecDeque::new();
input.lines().for_each(|line| {
let (start, right) = line.trim().split_once(": ").unwrap();
nodes.insert(start.to_string());
right.split(' ').for_each(|end| {
nodes.insert(end.to_string());
edges.push_back(Edge { vu: start.to_string(), vv: end.to_string() });
});
});
let svertices = nodes
.iter()
.map(|v| SuperVertex {
vertices: vec![v.clone()],
edges: edges.find_any(&v),
})
.collect();
(svertices, edges)
}
// Using Karger's algorithm
#[aoc(day25, part1)]
pub fn solve_part1((sverts, edges): &(Vec<SuperVertex>, VecDeque<Edge>)) -> usize {
// Optimal number of Monte-Carlo simulations
// let runs = (vertices.len().pow(2) as f64 * (vertices.len() as f64).log(E)) as usize;
let score = AtomicUsize::new(0);
(0..1000).into_par_iter().for_each(|_| {
let mut graph = sverts.clone().to_owned();
let mut pool = edges.clone().to_owned();
while graph.len() > 2 {
let edge = pool.get(random::<usize>() % pool.len()).unwrap();
let vu = graph.take(&edge.vu);
let vv = graph.take(&edge.vv);
let (vw, dup_edges) = vu.union(vv);
pool.trim(dup_edges);
graph.push(vw);
}
if pool.len() == 3 {
let current_score = graph[0].vertices.len() * graph[1].vertices.len();
score.fetch_max(current_score, Ordering::Relaxed);
println!("Successful run! Current score = {current_score}");
} else {
println!("Failed run.");
}
});
score.load(Ordering::Relaxed)
}
#[cfg(test)]
mod tests {
use super::*;
const TEST: &str = "jqt: rhn xhk nvd
rsh: frs pzl lsr
xhk: hfx
cmg: qnr nvd lhk bvb
rhn: xhk bvb hfx
bvb: xhk hfx
pzl: lsr hfx nvd
qnr: nvd
ntq: jqt hfx bvb xhk
nvd: lhk
lsr: lhk
rzs: qnr cmg lsr rsh
frs: qnr lhk lsr";
#[test]
fn part1_test() {
assert_eq!(solve_part1(&input_generator(TEST)), 54);
}
}