08.rs
1 #![feature(test)] 2 3 use rustc_hash::{FxHashMap, FxHashSet}; 4 5 struct Line { 6 patterns: Vec<String>, 7 output: Vec<String>, 8 } 9 10 type Input = Vec<Line>; 11 12 fn setup(input: &str) -> Input { 13 input 14 .lines() 15 .map(|line| { 16 let mut line = line.trim().split(" | "); 17 let mut parse = || { 18 line.next() 19 .unwrap() 20 .split(' ') 21 .map(|x| x.to_string()) 22 .collect() 23 }; 24 Line { 25 patterns: parse(), 26 output: parse(), 27 } 28 }) 29 .collect() 30 } 31 32 fn part1(input: &Input) -> String { 33 input 34 .iter() 35 .map(|line| { 36 line.output 37 .iter() 38 .filter(|x| [2, 3, 4, 7].contains(&x.len())) 39 .count() 40 }) 41 .sum::<usize>() 42 .to_string() 43 } 44 45 fn parse_num(num: &str) -> u16 { 46 num.chars() 47 .map(|c| 1 << ((c as u16) - ('a' as u16))) 48 .sum::<u16>() 49 } 50 51 fn is_subset(mut a: u16, mut b: u16) -> bool { 52 while a > 0 { 53 if 1 & a & !b == 1 { 54 return false; 55 } 56 a >>= 1; 57 b >>= 1; 58 } 59 true 60 } 61 62 fn part2(input: &Input) -> String { 63 let digits = FxHashMap::from_iter([ 64 ((7, 2), 1), 65 ((2, 5), 2), 66 ((3, 5), 3), 67 ((3, 4), 4), 68 ((4, 5), 5), 69 ((5, 3), 7), 70 ((1, 7), 8), 71 ]); 72 73 input 74 .iter() 75 .map(|line| { 76 let patterns: Vec<u16> = line.patterns.iter().map(|s| parse_num(s)).collect(); 77 let output: Vec<u16> = line.output.iter().map(|s| parse_num(s)).collect(); 78 let mut mp: FxHashMap<u16, u8> = FxHashMap::default(); 79 let mut rp: FxHashMap<u8, u16> = FxHashMap::default(); 80 let mut u: FxHashSet<u16> = FxHashSet::from_iter(patterns.iter().cloned()); 81 for x in &patterns { 82 let sc = patterns.iter().filter(|y| is_subset(*x, **y)).count(); 83 match digits.get(&(sc, x.count_ones())) { 84 None => {} 85 Some(digit) => { 86 mp.insert(*x, *digit); 87 rp.insert(*digit, *x); 88 u.remove(x); 89 } 90 } 91 } 92 93 let x = *u 94 .iter() 95 .find(|x| !is_subset(*rp.get(&5).unwrap(), **x)) 96 .unwrap(); 97 mp.insert(x, 0); 98 u.remove(&x); 99 100 let x = *u 101 .iter() 102 .find(|x| is_subset(*rp.get(&4).unwrap(), **x)) 103 .unwrap(); 104 mp.insert(x, 9); 105 u.remove(&x); 106 107 let x = *u.iter().next().unwrap(); 108 mp.insert(x, 6); 109 110 output 111 .iter() 112 .map(|x| *mp.get(x).unwrap() as u32) 113 .reduce(|a, b| a * 10 + b) 114 .unwrap() 115 }) 116 .sum::<u32>() 117 .to_string() 118 } 119 120 aoc::main!(2021, 8, ex: 1[b], 2);