2020: day21: part 2
This commit is contained in:
parent
33fbe9ce5a
commit
fbd7ae5be2
|
@ -10,6 +10,7 @@ pub fn run() -> Result<String> {
|
|||
let mut res = String::with_capacity(128);
|
||||
|
||||
writeln!(res, "part 1: {}", part1(INPUT)?)?;
|
||||
writeln!(res, "part 2: {}", part2(INPUT)?)?;
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
@ -39,6 +40,56 @@ fn part1(input: &str) -> Result<usize> {
|
|||
Ok(not_allergens.map(|word| all_words[word]).sum())
|
||||
}
|
||||
|
||||
fn part2(input: &str) -> Result<String> {
|
||||
let mut matchings: AllergenMatchings = input.try_into()?;
|
||||
let mut allergens_to_identify: Vec<&str> = matchings.0.keys().copied().collect();
|
||||
|
||||
for _ in 0..matchings.0.len() {
|
||||
let allergen = allergens_to_identify
|
||||
.iter()
|
||||
.min_by_key(|&name| matchings.0[name].len())
|
||||
.copied()
|
||||
.expect("should always have at least one allergen to identify");
|
||||
|
||||
// the algorithm only works if we can always find an allergen with only one possible
|
||||
// assignation
|
||||
assert_eq!(matchings.0[allergen].len(), 1);
|
||||
|
||||
let allergen_translation = matchings.0[allergen].iter().copied().next().unwrap();
|
||||
|
||||
matchings
|
||||
.0
|
||||
.iter_mut()
|
||||
.filter(|(&allerg, _)| allerg != allergen)
|
||||
.for_each(|(_, possible_matchings)| {
|
||||
possible_matchings.remove(allergen_translation);
|
||||
});
|
||||
|
||||
allergens_to_identify.swap_remove(
|
||||
allergens_to_identify
|
||||
.iter()
|
||||
.position(|al| *al == allergen)
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
// Vec of (allergen, translation)
|
||||
let mut matchings: Vec<(&str, &str)> = matchings
|
||||
.0
|
||||
.iter()
|
||||
.map(|(&key, possibilities)| (key, possibilities.iter().copied().next().unwrap()))
|
||||
.collect();
|
||||
|
||||
matchings.sort_unstable();
|
||||
|
||||
let canonical_ingredient_list: Vec<&str> = matchings
|
||||
.iter()
|
||||
.map(|(_, translation)| *translation)
|
||||
.collect();
|
||||
|
||||
Ok(canonical_ingredient_list.join(","))
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AllergenMatchings<'a>(HashMap<&'a str, HashSet<&'a str>>);
|
||||
|
||||
|
@ -84,4 +135,17 @@ mod tests {
|
|||
fn part1_real() {
|
||||
assert_eq!(part1(INPUT).unwrap(), 2315);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_provided() {
|
||||
assert_eq!(part2(PROVIDED).unwrap(), "mxmxvkd,sqjhc,fvjkl");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_real() {
|
||||
assert_eq!(
|
||||
part2(INPUT).unwrap(),
|
||||
"cfzdnz,htxsjf,ttbrlvd,bbbl,lmds,cbmjz,cmbcm,dvnbh"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue