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