day23
This commit is contained in:
parent
b49467a59e
commit
ac4c0f3838
|
@ -0,0 +1,249 @@
|
||||||
|
use aoc_runner_derive::{aoc, aoc_generator};
|
||||||
|
use hashbrown::{HashMap, HashSet};
|
||||||
|
|
||||||
|
type Input = (usize, [Vec<usize>; 26 * 26], HashMap<usize, String>);
|
||||||
|
|
||||||
|
#[aoc_generator(day23)]
|
||||||
|
fn parse(input: &str) -> Input {
|
||||||
|
let mut i = 0;
|
||||||
|
let mut names = HashMap::new();
|
||||||
|
let mut ids = HashMap::new();
|
||||||
|
let mut adj_list = [const { Vec::new() }; 26 * 26];
|
||||||
|
input.lines().for_each(|line| {
|
||||||
|
let mut splits = line.split('-');
|
||||||
|
let left = splits.next().unwrap().to_string();
|
||||||
|
let right = splits.next().unwrap().to_string();
|
||||||
|
|
||||||
|
let left_id = {
|
||||||
|
*ids.entry(left.clone()).or_insert_with(|| {
|
||||||
|
let id = i;
|
||||||
|
i += 1;
|
||||||
|
names.insert(id, left);
|
||||||
|
id
|
||||||
|
})
|
||||||
|
};
|
||||||
|
let right_id = {
|
||||||
|
*ids.entry(right.clone()).or_insert_with(|| {
|
||||||
|
let id = i;
|
||||||
|
i += 1;
|
||||||
|
names.insert(id, right);
|
||||||
|
id
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
adj_list[left_id].push(right_id);
|
||||||
|
adj_list[right_id].push(left_id);
|
||||||
|
});
|
||||||
|
|
||||||
|
(i, adj_list, names)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc(day23, part1)]
|
||||||
|
fn part1(input: &Input) -> usize {
|
||||||
|
let num = input.0;
|
||||||
|
let adj_list = &input.1;
|
||||||
|
let names = &input.2;
|
||||||
|
|
||||||
|
(0..num)
|
||||||
|
.filter(|id| names[id].starts_with("t"))
|
||||||
|
.flat_map(|id| {
|
||||||
|
let mut three_groups = HashSet::new();
|
||||||
|
let adj = &adj_list[id];
|
||||||
|
|
||||||
|
for left in 0..adj.len() {
|
||||||
|
for right in left + 1..adj.len() {
|
||||||
|
if adj_list[adj[left]].contains(&adj[right]) {
|
||||||
|
let mut group = [id, adj[left], adj[right]];
|
||||||
|
group.sort();
|
||||||
|
three_groups.insert((group[0], group[1], group[2]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
three_groups
|
||||||
|
})
|
||||||
|
.collect::<HashSet<(usize, usize, usize)>>()
|
||||||
|
.into_iter()
|
||||||
|
.count()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc(day23, part2)]
|
||||||
|
fn part2(input: &Input) -> String {
|
||||||
|
let num = input.0;
|
||||||
|
let adj_list = &input.1;
|
||||||
|
let names = &input.2;
|
||||||
|
|
||||||
|
let max_clique = (0..num)
|
||||||
|
.filter(|id| names[id].starts_with("t"))
|
||||||
|
.flat_map(|id| {
|
||||||
|
let mut three_groups = HashSet::new();
|
||||||
|
let adj = &adj_list[id];
|
||||||
|
|
||||||
|
for left in 0..adj.len() {
|
||||||
|
for right in left + 1..adj.len() {
|
||||||
|
if adj_list[adj[left]].contains(&adj[right]) {
|
||||||
|
let mut group = [id, adj[left], adj[right]];
|
||||||
|
group.sort();
|
||||||
|
three_groups.insert((group[0], group[1], group[2]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
three_groups
|
||||||
|
})
|
||||||
|
.collect::<HashSet<(usize, usize, usize)>>()
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|(a, b, c)| {
|
||||||
|
let clique = vec![a, b, c];
|
||||||
|
expand_cliques(clique, num, adj_list)
|
||||||
|
})
|
||||||
|
.max_by_key(|clique| clique.len())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut names = max_clique
|
||||||
|
.iter()
|
||||||
|
.map(|id| names[id].clone())
|
||||||
|
.collect::<Vec<String>>();
|
||||||
|
names.sort();
|
||||||
|
|
||||||
|
names.join(",")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expand_cliques(current: Vec<usize>, num: usize, adj: &[Vec<usize>]) -> Vec<Vec<usize>> {
|
||||||
|
let mut expansions: Vec<Vec<usize>> = vec![current.clone()];
|
||||||
|
|
||||||
|
for node in 0..num {
|
||||||
|
if current.contains(&node) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !current
|
||||||
|
.iter()
|
||||||
|
.all(|clique_node| adj[*clique_node].contains(&node))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut pushed = false;
|
||||||
|
for clique in &mut expansions {
|
||||||
|
if clique
|
||||||
|
.iter()
|
||||||
|
.all(|clique_node| adj[*clique_node].contains(&node))
|
||||||
|
{
|
||||||
|
clique.push(node);
|
||||||
|
pushed = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !pushed {
|
||||||
|
let mut new_clique = current.clone();
|
||||||
|
new_clique.push(node);
|
||||||
|
expansions.push(new_clique);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expansions
|
||||||
|
}
|
||||||
|
|
||||||
|
// fn max_clique(r: &mut HashSet<usize>, coloring: &[i32]) {
|
||||||
|
// let mut q = HashSet::new();
|
||||||
|
// let mut q_max = HashSet::new();
|
||||||
|
|
||||||
|
// while !r.is_empty() {
|
||||||
|
// let p = *r.iter().max_by_key(|node| coloring[**node]).unwrap();
|
||||||
|
// r.remove(&p);
|
||||||
|
// if q.len() + coloring[p] > q_max.len() {
|
||||||
|
// q.insert(p);
|
||||||
|
// q.remove(p);
|
||||||
|
// } else {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part1_example() {
|
||||||
|
assert_eq!(
|
||||||
|
part1(&parse(
|
||||||
|
"kh-tc
|
||||||
|
qp-kh
|
||||||
|
de-cg
|
||||||
|
ka-co
|
||||||
|
yn-aq
|
||||||
|
qp-ub
|
||||||
|
cg-tb
|
||||||
|
vc-aq
|
||||||
|
tb-ka
|
||||||
|
wh-tc
|
||||||
|
yn-cg
|
||||||
|
kh-ub
|
||||||
|
ta-co
|
||||||
|
de-co
|
||||||
|
tc-td
|
||||||
|
tb-wq
|
||||||
|
wh-td
|
||||||
|
ta-ka
|
||||||
|
td-qp
|
||||||
|
aq-cg
|
||||||
|
wq-ub
|
||||||
|
ub-vc
|
||||||
|
de-ta
|
||||||
|
wq-aq
|
||||||
|
wq-vc
|
||||||
|
wh-yn
|
||||||
|
ka-de
|
||||||
|
kh-ta
|
||||||
|
co-tc
|
||||||
|
wh-qp
|
||||||
|
tb-vc
|
||||||
|
td-yn"
|
||||||
|
)),
|
||||||
|
7
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part2_example() {
|
||||||
|
assert_eq!(
|
||||||
|
part2(&parse(
|
||||||
|
"kh-tc
|
||||||
|
qp-kh
|
||||||
|
de-cg
|
||||||
|
ka-co
|
||||||
|
yn-aq
|
||||||
|
qp-ub
|
||||||
|
cg-tb
|
||||||
|
vc-aq
|
||||||
|
tb-ka
|
||||||
|
wh-tc
|
||||||
|
yn-cg
|
||||||
|
kh-ub
|
||||||
|
ta-co
|
||||||
|
de-co
|
||||||
|
tc-td
|
||||||
|
tb-wq
|
||||||
|
wh-td
|
||||||
|
ta-ka
|
||||||
|
td-qp
|
||||||
|
aq-cg
|
||||||
|
wq-ub
|
||||||
|
ub-vc
|
||||||
|
de-ta
|
||||||
|
wq-aq
|
||||||
|
wq-vc
|
||||||
|
wh-yn
|
||||||
|
ka-de
|
||||||
|
kh-ta
|
||||||
|
co-tc
|
||||||
|
wh-qp
|
||||||
|
tb-vc
|
||||||
|
td-yn"
|
||||||
|
)),
|
||||||
|
"co,de,ka,ta"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue