Advent of Code solutions

Day 23

bwc9876.dev daac2043 8af887ad

verified
+117 -6
+116 -6
years/2024/src/day_23.rs
··· 1 + use std::collections::{HashMap, HashSet}; 1 2 2 - use advent_core::{Day, day_stuff, ex_for_day}; 3 + use advent_core::{day_stuff, ex_for_day, Day}; 4 + use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; 3 5 4 6 pub struct Day23; 5 7 8 + type Edges = HashMap<String, HashSet<String>>; 9 + 10 + fn find_self_in_3<'a>(node: &'a String, edges: &'a Edges) -> Vec<[&'a String; 3]> { 11 + edges 12 + .get(node) 13 + .unwrap() 14 + .iter() 15 + .flat_map(|adj| { 16 + edges.get(adj).unwrap().iter().filter_map(|sadj| { 17 + if edges.get(sadj).unwrap().contains(node) { 18 + let mut v = [node, adj, sadj]; 19 + v.sort(); 20 + Some(v) 21 + } else { 22 + None 23 + } 24 + }) 25 + }) 26 + .collect() 27 + } 28 + 29 + fn represent<'a>( 30 + node: &'a String, 31 + friends: HashSet<&'a String>, 32 + edges: &'a Edges, 33 + size: usize, 34 + seen: &mut HashSet<&'a String>, 35 + ) -> Option<HashSet<&'a String>> { 36 + if friends.len() == size { 37 + return Some(friends); 38 + } else if friends.iter().all(|f| seen.contains(f)) { 39 + return None; 40 + } 41 + 42 + seen.insert(node); 43 + 44 + edges.get(node).unwrap().iter().find_map(|dep| { 45 + if edges 46 + .get(dep) 47 + .is_some_and(|e| friends.iter().all(|f| e.contains(*f))) 48 + { 49 + let mut new_friends = friends.clone(); 50 + new_friends.insert(dep); 51 + represent(dep, new_friends, edges, size, seen) 52 + } else { 53 + None 54 + } 55 + }) 56 + } 57 + 6 58 impl Day for Day23 { 59 + day_stuff!(23, "", "", Edges); 7 60 8 - day_stuff!(23, "", ""); 61 + fn part_1(input: Self::Input) -> Option<String> { 62 + let groups = input 63 + .keys() 64 + .flat_map(|k| find_self_in_3(k, &input)) 65 + .collect::<HashSet<_>>(); 9 66 10 - fn part_1(_input: Self::Input) -> Option<String> { 11 - None 67 + let ans = groups 68 + .into_iter() 69 + .filter(|g| g.iter().any(|c| c.starts_with('t'))) 70 + .count(); 71 + 72 + Some(ans.to_string()) 73 + } 74 + 75 + fn part_2(input: Self::Input) -> Option<String> { 76 + let verts = input.keys().cloned().collect::<Vec<_>>(); 77 + let max_group_size = verts 78 + .iter() 79 + .map(|v| input.get(v).unwrap().len()) 80 + .max() 81 + .unwrap() 82 + + 1; 83 + 84 + let mut group = (0..max_group_size) 85 + .rev() 86 + .find_map(|s| { 87 + verts.par_iter().find_map_any(|node| { 88 + represent( 89 + node, 90 + HashSet::from_iter([node]), 91 + &input, 92 + s, 93 + &mut HashSet::with_capacity(s), 94 + ) 95 + }) 96 + }) 97 + .unwrap() 98 + .into_iter() 99 + .collect::<Vec<_>>(); 100 + 101 + group.sort(); 102 + let len = group.len(); 103 + let s = ",".to_string(); 104 + Some(group.into_iter().intersperse(&s).fold( 105 + String::with_capacity(len * 2 + (len - 1)), 106 + |mut acc, computer| { 107 + acc.push_str(computer.as_str()); 108 + acc 109 + }, 110 + )) 12 111 } 13 112 14 - fn part_2(_input: Self::Input) -> Option<String> { 15 - None 113 + fn parse_input(input: &str) -> Self::Input { 114 + input 115 + .lines() 116 + .fold(HashMap::with_capacity(50), |mut acc, l| { 117 + let (l, r) = l.split_once('-').unwrap(); 118 + acc.entry(l.to_string()) 119 + .or_insert(HashSet::new()) 120 + .insert(r.to_string()); 121 + acc.entry(r.to_string()) 122 + .or_insert(HashSet::new()) 123 + .insert(l.to_string()); 124 + acc 125 + }) 16 126 } 17 127 }
+1
years/2024/src/lib.rs
··· 1 1 #![feature(let_chains)] 2 + #![feature(iter_intersperse)] 2 3 3 4 use macros::year; 4 5