use anyhow::Result; use std::collections::HashSet; use std::env::args; use std::fs::File; use std::io::{BufRead, BufReader}; use std::path::Path; fn read_input>(filename: T) -> Result>> { let f = File::open(filename)?; let reader = BufReader::new(f); let mut group = vec![]; let mut groups = vec![]; for line in reader.lines() { let line = line?; if line.is_empty() { groups.push(group); group = vec![]; continue; } group.push(line); } groups.push(group); Ok(groups) } fn part1(input: &[Vec]) -> Option { let mut groups = vec![]; for group in input { let mut set = HashSet::new(); for form in group.iter() { for answer in form.clone().drain(..) { set.insert(answer); } } groups.push(set); } Some(groups.iter().map(|g| g.len()).sum()) } fn part2(input: &[Vec]) -> Option { let mut groups = vec![]; for group in input { let sets: Vec<_> = group.iter().map(|form| { let mut set = HashSet::new(); for answer in form.clone().drain(..) { set.insert(answer); } set }).collect(); let combined: HashSet<_> = match sets.get(0) { Some(first) => sets.iter() .fold(first.clone(), |a, s| s.intersection(&a).cloned().collect()), None => return None, }; groups.push(combined); } Some(groups.iter().map(|g| g.len()).sum()) } fn main() { let (do_part_1, do_part_2) = aoc::do_parts(); let filename = match args().nth(1) { Some(f) => f, None => { eprintln!("Missing input filename"); std::process::exit(1); }, }; match read_input(filename) { Ok(input) => { if do_part_1 { match part1(&input) { Some(solution) => println!("Part1, sum of all groups combined yes answers: {}", solution), None => eprintln!("Part1, no soluton found"), } } if do_part_2 { match part2(&input) { Some(solution) => println!("Part2, sum of all groups common yes answers: {}", solution), None => eprintln!("Part2, no soluton found"), } } }, Err(err) => eprintln!("Could not read input: {}", err), } }