~janbaudisch/aoc-2020

02d7ae1cc0e7852f989f92018708c2b3eea7f6ef — Jan Baudisch 7 months ago dbbcb47
add day 6
5 files changed, 137 insertions(+), 1 deletions(-)

M Cargo.lock
M Cargo.toml
A day_06/Cargo.toml
A day_06/src/group.rs
A day_06/src/main.rs
M Cargo.lock => Cargo.lock +7 -0
@@ 38,3 38,10 @@ version = "1.0.0"
dependencies = [
 "common",
]

[[package]]
name = "day_06"
version = "1.0.0"
dependencies = [
 "common",
]

M Cargo.toml => Cargo.toml +2 -1
@@ 5,7 5,8 @@ members = [
    "day_02",
    "day_03",
    "day_04",
    "day_05"
    "day_05",
    "day_06"
]

[profile.release]

A day_06/Cargo.toml => day_06/Cargo.toml +12 -0
@@ 0,0 1,12 @@
[package]
name = "day_06"
version = "1.0.0"
description = "Day 6 - Advent of Code 2020"
authors = ["Jan Baudisch <jan@baudisch.xyz>"]
license = "GPL-3.0-or-later"
readme = "../README.md"
edition = "2018"
workspace = ".."

[dependencies]
common = { path = "../common" }

A day_06/src/group.rs => day_06/src/group.rs +50 -0
@@ 0,0 1,50 @@
pub struct Group(Vec<Vec<char>>);

impl From<&Vec<String>> for Group {
    fn from(input: &Vec<String>) -> Self {
        let mut persons = Vec::with_capacity(input.len());

        for person in input {
            persons.push(person.chars().collect());
        }

        Self(persons)
    }
}

impl From<Vec<String>> for Group {
    fn from(input: Vec<String>) -> Self {
        Group::from(&input)
    }
}

impl Group {
    pub fn count_anyone_yes(&self) -> usize {
        let mut combined = self.0.concat();
        combined.sort_unstable();
        combined.dedup();
        combined.len()
    }

    pub fn count_everyone_yes(&self) -> usize {
        let first = &self.0[0];

        if self.0.len() == 1 {
            return first.len();
        }

        let mut count = 0;

        'answers: for answer in first {
            for other in self.0.iter() {
                if !other.contains(answer) {
                    continue 'answers;
                }
            }

            count += 1;
        }

        count
    }
}

A day_06/src/main.rs => day_06/src/main.rs +66 -0
@@ 0,0 1,66 @@
mod group;

use common::input;
use group::Group;

fn main() {
    let groups: Vec<Group> = input::read_blocks().iter().map(|x| x.into()).collect();

    let count: u32 = groups.iter().map(|x| x.count_anyone_yes() as u32).sum();

    println!("[PART ONE] sum of \"yes\" answeres from anyone: {}", count);

    let count: u32 = groups.iter().map(|x| x.count_everyone_yes() as u32).sum();

    println!(
        "[PART TWO] sum of \"yes\" answeres from everyone: {}",
        count
    );
}

#[cfg(test)]
mod tests {
    use super::Group;

    fn generate_groups() -> Vec<Group> {
        let input = vec![
            vec!["abc"],
            vec!["a", "b", "c"],
            vec!["ab", "ac"],
            vec!["a", "a", "a", "a"],
            vec!["b"],
        ];

        input
            .into_iter()
            .map(|x| {
                x.into_iter()
                    .map(|x| x.to_string())
                    .collect::<Vec<String>>()
            })
            .map(|x| x.into())
            .collect()
    }

    #[test]
    fn part_one() {
        assert_eq!(
            generate_groups()
                .iter()
                .map(|x| x.count_anyone_yes() as u32)
                .sum::<u32>(),
            11
        );
    }

    #[test]
    fn part_two() {
        assert_eq!(
            generate_groups()
                .iter()
                .map(|x| x.count_everyone_yes() as u32)
                .sum::<u32>(),
            6
        );
    }
}