day21
This commit is contained in:
75
src/day21.rs
Normal file
75
src/day21.rs
Normal file
@@ -0,0 +1,75 @@
|
||||
use crate::split_once;
|
||||
use aoc_runner_derive::aoc;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Food<'a> {
|
||||
ingredients: HashSet<&'a str>,
|
||||
allergens: HashSet<&'a str>,
|
||||
}
|
||||
impl<'a> Food<'a> {
|
||||
fn parse(input: &'a str) -> Option<Self> {
|
||||
let (ingredients, allergens) = split_once(input, " (contains ")?;
|
||||
let allergens = allergens.strip_suffix(")")?;
|
||||
Some(Food {
|
||||
ingredients: ingredients.split(" ").collect(),
|
||||
allergens: allergens.split(", ").collect(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[aoc(day21, part1)]
|
||||
fn solve_d2_p1(input: &str) -> usize {
|
||||
//let input = EXAMPLE;
|
||||
let foods: Vec<_> = input.split('\n').map(|l| Food::parse(l).unwrap()).collect();
|
||||
|
||||
let mut allergen_causes = HashMap::new();
|
||||
for food in &foods {
|
||||
for &allergen in &food.allergens {
|
||||
let ingredients = allergen_causes
|
||||
.entry(allergen)
|
||||
.or_insert_with(|| food.ingredients.clone());
|
||||
ingredients.retain(|ingredient| food.ingredients.contains(ingredient));
|
||||
}
|
||||
}
|
||||
let possible_allergens: HashSet<_> = allergen_causes.values().flatten().collect();
|
||||
foods
|
||||
.iter()
|
||||
.flat_map(|food| &food.ingredients)
|
||||
.filter(|ingredient| !possible_allergens.contains(ingredient))
|
||||
.count()
|
||||
}
|
||||
|
||||
#[aoc(day21, part2)]
|
||||
fn solve_d2_p2(input: &str) -> String {
|
||||
let foods: Vec<_> = input.split('\n').map(|l| Food::parse(l).unwrap()).collect();
|
||||
|
||||
let mut allergen_causes = HashMap::new();
|
||||
for food in &foods {
|
||||
for &allergen in &food.allergens {
|
||||
let ingredients = allergen_causes
|
||||
.entry(allergen)
|
||||
.or_insert_with(|| food.ingredients.clone());
|
||||
ingredients.retain(|ingredient| food.ingredients.contains(ingredient));
|
||||
}
|
||||
}
|
||||
let mut dangerous_ingredients = Vec::new();
|
||||
while let Some(&allergen) = allergen_causes
|
||||
.iter()
|
||||
.find(|(_k, v)| v.len() == 1)
|
||||
.map(|(k, _v)| k)
|
||||
{
|
||||
let (allergen, mut ingredient) = allergen_causes.remove_entry(allergen).unwrap();
|
||||
let ingredient = ingredient.drain().next().unwrap();
|
||||
dangerous_ingredients.push((allergen, ingredient));
|
||||
for ingredient_set in allergen_causes.values_mut() {
|
||||
ingredient_set.remove(&ingredient);
|
||||
}
|
||||
}
|
||||
dangerous_ingredients.sort_by(|(a, _), (b, _)| a.cmp(b));
|
||||
dangerous_ingredients
|
||||
.into_iter()
|
||||
.map(|(_allergen, ingredient)| ingredient)
|
||||
.collect::<Vec<_>>()
|
||||
.join(",")
|
||||
}
|
||||
@@ -11,6 +11,7 @@ pub mod day18;
|
||||
pub mod day19;
|
||||
pub mod day2;
|
||||
pub mod day20;
|
||||
pub mod day21;
|
||||
pub mod day3;
|
||||
pub mod day4;
|
||||
pub mod day5;
|
||||
|
||||
Reference in New Issue
Block a user