diff --git a/src/year2016/day18.rs b/src/year2016/day18.rs index 9a655d9..955a2e7 100644 --- a/src/year2016/day18.rs +++ b/src/year2016/day18.rs @@ -41,7 +41,7 @@ fn count(input: &str, rows: u32) -> u32 { // Count the traps in each row. total += row.count_ones(); // Only consider the left and right values for the next row. - row = (row << 1) ^ (row >> 1) & mask; + row = ((row << 1) ^ (row >> 1)) & mask; } // We want the number of safe tiles so convert from the number of traps. diff --git a/src/year2020/day21.rs b/src/year2020/day21.rs index 25ce4cc..49f09f2 100644 --- a/src/year2020/day21.rs +++ b/src/year2020/day21.rs @@ -45,6 +45,7 @@ //! [`Day 16`]: crate::year2020::day16 //! [`count_ones`]: u32::count_ones use crate::util::hash::*; +use std::collections::BTreeMap; pub struct Input<'a> { ingredients: FastMap<&'a str, Ingredient>, @@ -102,34 +103,31 @@ pub fn part1(input: &Input<'_>) -> u32 { } pub fn part2(input: &Input<'_>) -> String { - let mut ingredients = input.ingredients.clone(); - ingredients.retain(|_, v| v.candidates != 0); - let inverse_allergens: FastMap<_, _> = input.allergens.iter().map(|(k, v)| (1 << v, k)).collect(); - // There must be at least one ingredient with only one allergen. - let mut todo: Vec<_> = ingredients - .iter() - .filter(|(_, v)| v.candidates.count_ones() == 1) - .map(|(k, v)| (*k, v.candidates)) - .collect(); - let mut done = Vec::new(); + let mut ingredients = input.ingredients.clone(); + ingredients.retain(|_, v| v.candidates != 0); + + let mut done = BTreeMap::new(); // Eliminate known allergens from other ingredients. - while let Some(pair @ (next, allergen)) = todo.pop() { - ingredients.remove(next); - done.push(pair); + while done.len() < ingredients.len() { + let mut mask = 0; - for (name, ingredient) in &mut ingredients { - ingredient.candidates &= !allergen; + // There must be at least one ingredient with only one allergen. + for (name, ingredient) in &ingredients { if ingredient.candidates.count_ones() == 1 { - todo.push((name, ingredient.candidates)); + let allergen = inverse_allergens[&ingredient.candidates]; + done.insert(*allergen, *name); + + mask |= ingredient.candidates; } } + + ingredients.values_mut().for_each(|ingredient| ingredient.candidates &= !mask); } // Sort by alphabetical order of the allergens. - done.sort_by_cached_key(|(_, v)| inverse_allergens[v]); - done.iter().map(|(k, _)| *k).collect::>().join(",") + done.into_values().collect::>().join(",") }