|
1 | 1 | advent_of_code::solution!(23);
|
2 | 2 |
|
3 |
| -use advent_of_code::maneatingape::hash::*; |
| 3 | +use std::iter::once; |
4 | 4 |
|
5 |
| -use std::collections::BTreeSet; |
| 5 | +use advent_of_code::maneatingape::hash::*; |
6 | 6 |
|
7 | 7 | struct Computer {}
|
8 | 8 |
|
@@ -78,53 +78,46 @@ pub fn part_one(input: &str) -> Option<u32> {
|
78 | 78 | Some(result)
|
79 | 79 | }
|
80 | 80 |
|
81 |
| -pub fn part_two(input: &str) -> Option<String> { |
82 |
| - let nodes = parse_data(input); |
83 |
| - |
84 |
| - let mut cache = FastSet::new(); |
85 |
| - |
86 |
| - let mut keys = nodes.keys().copied().collect::<Vec<_>>(); |
87 |
| - keys.sort_by(|a, b| nodes[b].len().cmp(&nodes[a].len())); |
88 |
| - |
89 |
| - let to_check = keys; |
90 |
| - let group = BTreeSet::new(); |
91 |
| - let mut queue = vec![(to_check, group)]; |
92 |
| - while let Some((c, g)) = queue.pop() { |
93 |
| - for i in 0..c.len() { |
94 |
| - let mut is_ok = true; |
95 |
| - for el in g.iter() { |
96 |
| - if !nodes[el].contains(&c[i]) { |
97 |
| - is_ok = false; |
98 |
| - break; |
99 |
| - } |
100 |
| - } |
101 |
| - |
102 |
| - if is_ok { |
103 |
| - let mut new_g = g.clone(); |
104 |
| - new_g.insert(c[i]); |
| 81 | +fn bors_kerbosch( |
| 82 | + r: Vec<usize>, |
| 83 | + p: FastSet<usize>, |
| 84 | + x: FastSet<usize>, |
| 85 | + g: &FastMap<usize, FastSet<usize>>, |
| 86 | +) -> Vec<usize> { |
| 87 | + if p.is_empty() && x.is_empty() { |
| 88 | + return r; |
| 89 | + } |
105 | 90 |
|
106 |
| - if cache.contains(&new_g) { |
107 |
| - continue; |
108 |
| - } |
| 91 | + let mut max_result = vec![]; |
| 92 | + let mut p = p; |
| 93 | + let mut x = x; |
109 | 94 |
|
110 |
| - cache.insert(new_g.clone()); |
| 95 | + let pivot = p.union(&x).max_by_key(|v| g[v].len()).unwrap(); |
111 | 96 |
|
112 |
| - let mut new_c = c.clone(); |
113 |
| - new_c.remove(i); |
| 97 | + for v in p.difference(&g[pivot]).copied().collect::<Vec<_>>() { |
| 98 | + let next_r = r.iter().chain(once(&v)).copied().collect::<Vec<_>>(); |
| 99 | + let next_p = p.intersection(&g[&v]).copied().collect::<FastSet<_>>(); |
| 100 | + let next_x = x.intersection(&g[&v]).copied().collect::<FastSet<_>>(); |
114 | 101 |
|
115 |
| - queue.push((new_c, new_g)); |
116 |
| - } |
| 102 | + let result = bors_kerbosch(next_r, next_p, next_x, g); |
| 103 | + if result.len() > max_result.len() { |
| 104 | + max_result = result; |
117 | 105 | }
|
| 106 | + |
| 107 | + p.remove(&v); |
| 108 | + x.insert(v); |
118 | 109 | }
|
119 | 110 |
|
120 |
| - let mut result = cache |
121 |
| - .iter() |
122 |
| - .max_by(|x, y| x.len().cmp(&y.len())) |
123 |
| - .unwrap() |
124 |
| - .iter() |
125 |
| - .map(|&x| Computer::decode(x)) |
126 |
| - .collect::<Vec<_>>(); |
| 111 | + max_result |
| 112 | +} |
| 113 | + |
| 114 | +pub fn part_two(input: &str) -> Option<String> { |
| 115 | + let nodes = parse_data(input); |
| 116 | + |
| 117 | + let keys = nodes.keys().copied().collect::<FastSet<_>>(); |
| 118 | + let result = bors_kerbosch(vec![], keys, FastSet::new(), &nodes); |
127 | 119 |
|
| 120 | + let mut result = result.into_iter().map(Computer::decode).collect::<Vec<_>>(); |
128 | 121 | result.sort_unstable();
|
129 | 122 |
|
130 | 123 | let result = result.join(",");
|
|
0 commit comments