Advent of Code solutions
at main 127 lines 3.5 kB view raw
1use std::collections::{HashMap, HashSet}; 2 3use advent_core::{day_stuff, ex_for_day, Day}; 4use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; 5 6pub struct Day23; 7 8type Edges = HashMap<String, HashSet<String>>; 9 10fn 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 29fn 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 58impl Day for Day23 { 59 day_stuff!(23, "7", "co,de,ka,ta", Edges); 60 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<_>>(); 66 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 )) 111 } 112 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 }) 126 } 127}