#![feature(test)] use rustc_hash::{FxHashMap, FxHashSet}; struct Line { patterns: Vec, output: Vec, } type Input = Vec; fn setup(input: &str) -> Input { input .lines() .map(|line| { let mut line = line.trim().split(" | "); let mut parse = || { line.next() .unwrap() .split(' ') .map(|x| x.to_string()) .collect() }; Line { patterns: parse(), output: parse(), } }) .collect() } fn part1(input: &Input) -> String { input .iter() .map(|line| { line.output .iter() .filter(|x| [2, 3, 4, 7].contains(&x.len())) .count() }) .sum::() .to_string() } fn parse_num(num: &str) -> u16 { num.chars() .map(|c| 1 << ((c as u16) - ('a' as u16))) .sum::() } fn is_subset(mut a: u16, mut b: u16) -> bool { while a > 0 { if 1 & a & !b == 1 { return false; } a >>= 1; b >>= 1; } true } fn part2(input: &Input) -> String { let digits = FxHashMap::from_iter([ ((7, 2), 1), ((2, 5), 2), ((3, 5), 3), ((3, 4), 4), ((4, 5), 5), ((5, 3), 7), ((1, 7), 8), ]); input .iter() .map(|line| { let patterns: Vec = line.patterns.iter().map(|s| parse_num(s)).collect(); let output: Vec = line.output.iter().map(|s| parse_num(s)).collect(); let mut mp: FxHashMap = FxHashMap::default(); let mut rp: FxHashMap = FxHashMap::default(); let mut u: FxHashSet = FxHashSet::from_iter(patterns.iter().cloned()); for x in &patterns { let sc = patterns.iter().filter(|y| is_subset(*x, **y)).count(); match digits.get(&(sc, x.count_ones())) { None => {} Some(digit) => { mp.insert(*x, *digit); rp.insert(*digit, *x); u.remove(x); } } } let x = *u .iter() .find(|x| !is_subset(*rp.get(&5).unwrap(), **x)) .unwrap(); mp.insert(x, 0); u.remove(&x); let x = *u .iter() .find(|x| is_subset(*rp.get(&4).unwrap(), **x)) .unwrap(); mp.insert(x, 9); u.remove(&x); let x = *u.iter().next().unwrap(); mp.insert(x, 6); output .iter() .map(|x| *mp.get(x).unwrap() as u32) .reduce(|a, b| a * 10 + b) .unwrap() }) .sum::() .to_string() } aoc::main!(2021, 8, ex: 1[b], 2);