My (hacky) solution to 2020 Advent of Code Challenge in Rust
#![feature(iterator_fold_self)]
use std::collections::HashSet;
use std::hash::Hash;
use std::io::{self, Read};

fn main() {
    let mut input = String::new();
    io::stdin().read_to_string(&mut input).unwrap();
    part1(&input);
    part2(&input);
}

fn part1(input: &str) {
    let mut vec_set: Vec<HashSet<char>> = Vec::new();
    for para in input.split("\n\n") {
        let mut set: HashSet<char> = HashSet::new();
        for c in para.chars() {
            if !c.is_alphabetic() {
                continue;
            }
            set.insert(c);
        }
        vec_set.push(set);
    }
    let sum: usize = vec_set.iter().map(|set| set.len()).sum();
    println!("{}", sum);
}

fn intersection<'a, T: Clone + Eq + Hash + 'a>(
    sets: impl IntoIterator<Item = &'a HashSet<T>>,
) -> Option<HashSet<T>> {
    let mut sets = sets.into_iter();
    let mut first = sets.next()?.clone();
    sets.for_each(|set| first.retain(|elem| set.contains(elem)));
    Some(first)
}

fn part2(input: &str) {
    let mut acc = 0;
    for para in input.split("\n\n") {
        let mut vec_set: Vec<HashSet<char>> = Vec::new();
        for line in para.lines() {
            let mut set: HashSet<char> = HashSet::new();
            line.chars().for_each(|c| {
                if c.is_alphabetic() {
                    set.insert(c);
                }
            });
            vec_set.push(set);
        }
        acc += intersection(&vec_set).unwrap().len();
    }
    println!("{}", acc);
}