Compare commits
2 Commits
6e850188a7
...
a451ba2ade
| Author | SHA1 | Date | |
|---|---|---|---|
| a451ba2ade | |||
| 07b03f31e1 |
148
src/day23.rs
Normal file
148
src/day23.rs
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
use std::{
|
||||||
|
collections::{HashMap, HashSet},
|
||||||
|
fs::read_to_string,
|
||||||
|
};
|
||||||
|
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
pub fn day_main() {
|
||||||
|
let input = read_to_string("input/day23.txt").unwrap();
|
||||||
|
let input = input.trim();
|
||||||
|
println!(" part1: {}", part1(input));
|
||||||
|
println!(" part2: {}", part2(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
type RiddleResult = usize;
|
||||||
|
|
||||||
|
fn part1(input: &str) -> RiddleResult {
|
||||||
|
let neighbours = make_graph(input);
|
||||||
|
let mut sets = vec![];
|
||||||
|
for a in neighbours.keys() {
|
||||||
|
for b in &neighbours[a] {
|
||||||
|
let common = neighbours[a].intersection(&neighbours[b]);
|
||||||
|
for c in common {
|
||||||
|
let mut v = vec![a, b, c];
|
||||||
|
v.sort_unstable();
|
||||||
|
sets.push(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let sets = sets.iter().unique().collect_vec();
|
||||||
|
dbg!(sets.len());
|
||||||
|
sets.iter()
|
||||||
|
.filter(|set| set.iter().any(|t| t.starts_with("t")))
|
||||||
|
.count()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_graph(input: &str) -> HashMap<&str, HashSet<&str>> {
|
||||||
|
let mut neighbours: HashMap<&str, HashSet<&str>> = HashMap::new();
|
||||||
|
input.lines().for_each(|line| {
|
||||||
|
let (a, b) = line.split_once("-").unwrap();
|
||||||
|
neighbours
|
||||||
|
.entry(a)
|
||||||
|
.and_modify(|list| {
|
||||||
|
list.insert(b);
|
||||||
|
})
|
||||||
|
.or_insert_with(|| HashSet::from([b]));
|
||||||
|
neighbours
|
||||||
|
.entry(b)
|
||||||
|
.and_modify(|list| {
|
||||||
|
list.insert(a);
|
||||||
|
})
|
||||||
|
.or_insert_with(|| HashSet::from([a]));
|
||||||
|
});
|
||||||
|
neighbours
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part2(input: &str) -> String {
|
||||||
|
let graph = make_graph(input);
|
||||||
|
|
||||||
|
let mut best = "".to_string();
|
||||||
|
for a in graph.keys() {
|
||||||
|
let mut edge_counts = HashMap::<&str, u32>::new();
|
||||||
|
for b in &graph[a] {
|
||||||
|
edge_counts.entry(b).and_modify(|v| *v += 1).or_insert(1);
|
||||||
|
for c in &graph[b] {
|
||||||
|
edge_counts.entry(c).and_modify(|v| *v += 1).or_insert(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// now we have all counts for shared edges
|
||||||
|
// next, we find the highest number k for which there are k nodes which are connected to at least k other nodes
|
||||||
|
let mut k = *edge_counts.values().max().unwrap();
|
||||||
|
while k > 0 {
|
||||||
|
let nodes = edge_counts
|
||||||
|
.iter()
|
||||||
|
.filter(|(_, v)| **v >= k)
|
||||||
|
.map(|(k, _)| k)
|
||||||
|
.collect_vec();
|
||||||
|
|
||||||
|
if nodes.len() < k as usize {
|
||||||
|
k -= 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// now we find all nodes in the neighborhood of a (including a) that have an edge to every node in `nodes`, excluding themselves ofc
|
||||||
|
let found = graph[a]
|
||||||
|
.iter()
|
||||||
|
.chain([*a].iter())
|
||||||
|
.filter(|x| nodes.iter().all(|y| y == x || graph[*x].contains(*y)))
|
||||||
|
.sorted_unstable()
|
||||||
|
.join(",");
|
||||||
|
|
||||||
|
if found.len() > best.len() {
|
||||||
|
best = found;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
best
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::{part1, part2};
|
||||||
|
|
||||||
|
const TEST_INPUT: &str = r"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";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test1() {
|
||||||
|
assert_eq!(part1(TEST_INPUT), 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test2() {
|
||||||
|
assert_eq!(part2(TEST_INPUT), "co,de,ka,ta");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,5 +17,6 @@ pub mod day16;
|
|||||||
pub mod day17;
|
pub mod day17;
|
||||||
pub mod day19;
|
pub mod day19;
|
||||||
pub mod day22;
|
pub mod day22;
|
||||||
|
pub mod day23;
|
||||||
// PLACEHOLDER
|
// PLACEHOLDER
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ fn main() {
|
|||||||
(17, day17::day_main),
|
(17, day17::day_main),
|
||||||
(19, day19::day_main),
|
(19, day19::day_main),
|
||||||
(22, day22::day_main),
|
(22, day22::day_main),
|
||||||
|
(23, day23::day_main),
|
||||||
|
(23, day23::day_main),
|
||||||
// PLACEHOLDER
|
// PLACEHOLDER
|
||||||
]);
|
]);
|
||||||
let day: Option<u8> = args().nth(1).and_then(|a| a.parse().ok());
|
let day: Option<u8> = args().nth(1).and_then(|a| a.parse().ok());
|
||||||
|
|||||||
Reference in New Issue
Block a user