Day 23
This commit is contained in:
parent
1aa90ba9db
commit
12fde697d3
|
@ -0,0 +1,93 @@
|
|||
use itertools::Itertools;
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
fmt::{Display, Write},
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Ord, PartialOrd)]
|
||||
struct Computer(char, char);
|
||||
|
||||
pub fn day23() {
|
||||
let input_connections: Vec<(Computer, Computer)> = parse_input(&crate::input(23));
|
||||
let connections = {
|
||||
let mut connections: HashMap<Computer, Vec<Computer>> = HashMap::new();
|
||||
for &(a, b) in input_connections.iter() {
|
||||
connections.entry(a).or_insert(vec![]).push(b);
|
||||
connections.entry(b).or_insert(vec![]).push(a);
|
||||
}
|
||||
connections
|
||||
};
|
||||
|
||||
fn collect_cliques(
|
||||
connections: &HashMap<Computer, Vec<Computer>>,
|
||||
clique: &Vec<Computer>,
|
||||
visited: &mut HashSet<Vec<Computer>>,
|
||||
) -> Vec<Vec<Computer>> {
|
||||
let mut bigger_cliques: Vec<Vec<Computer>> = vec![];
|
||||
bigger_cliques.push(clique.clone());
|
||||
for (computer, friends) in connections.iter() {
|
||||
if clique.contains(computer) {
|
||||
continue;
|
||||
}
|
||||
if clique.iter().all(|groupie| friends.contains(groupie)) {
|
||||
let mut new_clique = clique.clone();
|
||||
new_clique.push(*computer);
|
||||
new_clique.sort();
|
||||
if visited.contains(&new_clique) {
|
||||
continue;
|
||||
} else {
|
||||
visited.insert(new_clique.clone());
|
||||
}
|
||||
let mut new_bigger_cliques = collect_cliques(connections, &new_clique, visited);
|
||||
bigger_cliques.append(&mut new_bigger_cliques);
|
||||
}
|
||||
}
|
||||
bigger_cliques
|
||||
}
|
||||
let mut visited = HashSet::new();
|
||||
let mut all_cliques: Vec<Vec<Computer>> = connections
|
||||
.keys()
|
||||
.map(|&c| vec![c])
|
||||
.flat_map(|seed| collect_cliques(&connections, &seed, &mut visited))
|
||||
.collect();
|
||||
all_cliques.sort_by_key(|group| group.len());
|
||||
let mut maximum_clique = all_cliques.last().unwrap().clone();
|
||||
println!("The biggest clique's size is {}.", maximum_clique.len());
|
||||
maximum_clique.sort();
|
||||
println!(
|
||||
"The biggest clique's password is {}",
|
||||
maximum_clique.iter().map(|c| format!("{c}")).join(",")
|
||||
);
|
||||
|
||||
let t_trios = all_cliques
|
||||
.iter()
|
||||
.filter(|clique| clique.len() == 3)
|
||||
.filter(|trio| trio.iter().any(|c| c.0 == 't'))
|
||||
.count();
|
||||
println!("{t_trios} trios contain a friend who starts with t.");
|
||||
}
|
||||
|
||||
impl Computer {
|
||||
fn from_string(s: &str) -> Self {
|
||||
Self(s.chars().nth(0).unwrap(), s.chars().nth(1).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Computer {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_char(self.0)?;
|
||||
f.write_char(self.1)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_input(input: &str) -> Vec<(Computer, Computer)> {
|
||||
input
|
||||
.lines()
|
||||
.map(|line| {
|
||||
line.split("-")
|
||||
.map(Computer::from_string)
|
||||
.collect_tuple()
|
||||
.unwrap()
|
||||
})
|
||||
.collect()
|
||||
}
|
|
@ -28,7 +28,9 @@ mod day2;
|
|||
mod day20;
|
||||
#[allow(dead_code)]
|
||||
mod day21;
|
||||
#[allow(dead_code)]
|
||||
mod day22;
|
||||
mod day23;
|
||||
#[allow(dead_code)]
|
||||
mod day3;
|
||||
#[allow(dead_code)]
|
||||
|
@ -45,7 +47,7 @@ mod day8;
|
|||
mod day9;
|
||||
|
||||
fn main() {
|
||||
day22::day22();
|
||||
day23::day23();
|
||||
}
|
||||
|
||||
pub fn input(day: u8) -> String {
|
||||
|
|
Loading…
Reference in New Issue