2021: day08: only store "hard" digits in mapping

This commit is contained in:
Antoine Martin 2021-12-08 20:04:45 +01:00
parent b5c79e9b1c
commit b5c4b72864

View file

@ -65,21 +65,20 @@ impl<'a> Entry<'a> {
let mut mapping = Vec::new(); let mut mapping = Vec::new();
// first, let's get the easy digits // first, let's get the easy digits
self.unique_signals let easy_digits: Vec<(&str, u64)> = self
.unique_signals
.iter() .iter()
.filter_map(|signal| Self::translate_easy_digit(signal).zip(Some(signal))) .filter_map(|signal| Some(*signal).zip(Self::translate_easy_digit(signal)))
.for_each(|(translation, &signal)| { .collect();
mapping.push((signal, translation));
});
// now we can get `9` for free: it's the signal that uses 6 segments and has 4 in common // now we can get `9` for free: it's the signal that uses 6 segments and has 4 in common
// with the digit `4` (`6` and `0` also use 6 segments, but only have 3 segments in common // with the digit `4` (`6` and `0` also use 6 segments, but only have 3 segments in common
// with `4`). // with `4`).
let (four, _) = *mapping let (four, _) = *easy_digits
.iter() .iter()
.find(|(_, translation)| *translation == 4) .find(|(_, translation)| *translation == 4)
.context("no signal found for the digit 4!")?; .context("no signal found for the digit 4!")?;
let nine = self let nine = *self
.unique_signals .unique_signals
.iter() .iter()
.filter(|signal| signal.len() == 6) .filter(|signal| signal.len() == 6)
@ -88,32 +87,32 @@ impl<'a> Entry<'a> {
mapping.push((nine, 9)); mapping.push((nine, 9));
// `0` has 2 segments in common with `1`, while `6` only has 1. // `0` has 2 segments in common with `1`, while `6` only has 1.
let (one, _) = *mapping let (one, _) = *easy_digits
.iter() .iter()
.find(|(_, translation)| *translation == 1) .find(|(_, translation)| *translation == 1)
.context("no signal found for the digit 1!")?; .context("no signal found for the digit 1!")?;
let zero = self let zero = *self
.unique_signals .unique_signals
.iter() .iter()
.filter(|signal| signal.len() == 6) .filter(|&signal| signal.len() == 6)
.filter(|signal| *signal != nine) .filter(|&signal| *signal != nine)
.find(|signal| one.chars().all(|c| signal.contains(c))) .find(|signal| one.chars().all(|c| signal.contains(c)))
.context("couldn't identify any signal corresponding to the digit 0!")?; .context("couldn't identify any signal corresponding to the digit 0!")?;
mapping.push((zero, 0)); mapping.push((zero, 0));
// `6` is an easy one now, the only other signal with 6 segments, that isn't nine or zero. // `6` is an easy one now, the only other signal with 6 segments, that isn't nine or zero.
let six = self let six = *self
.unique_signals .unique_signals
.iter() .iter()
.filter(|signal| signal.len() == 6) .filter(|signal| signal.len() == 6)
.find(|signal| *signal != nine && *signal != zero) .find(|&signal| *signal != nine && *signal != zero)
.context("couldn't identify any signal corresponding to the digit 6!")?; .context("couldn't identify any signal corresponding to the digit 6!")?;
mapping.push((six, 6)); mapping.push((six, 6));
// `2`, `3` and `5` have 5 segments each. // `2`, `3` and `5` have 5 segments each.
// //
// `3` has 2 segments in common with `1`. // `3` has 2 segments in common with `1`.
let three = self let three = *self
.unique_signals .unique_signals
.iter() .iter()
.filter(|signal| signal.len() == 5) .filter(|signal| signal.len() == 5)
@ -122,7 +121,7 @@ impl<'a> Entry<'a> {
mapping.push((three, 3)); mapping.push((three, 3));
// `5` has all its segments used in `6`, `2` doesn't. // `5` has all its segments used in `6`, `2` doesn't.
let five = self let five = *self
.unique_signals .unique_signals
.iter() .iter()
.filter(|signal| signal.len() == 5) .filter(|signal| signal.len() == 5)
@ -135,11 +134,11 @@ impl<'a> Entry<'a> {
.unique_signals .unique_signals
.iter() .iter()
.filter(|signal| signal.len() == 5) .filter(|signal| signal.len() == 5)
.find(|signal| *signal != five && *signal != three) .find(|&signal| *signal != five && *signal != three)
.context("couldn't identify any signal corresponding to the digit 2!")?; .context("couldn't identify any signal corresponding to the digit 2!")?;
mapping.push((two, 2)); mapping.push((two, 2));
debug_assert_eq!(mapping.len(), 10); debug_assert_eq!(mapping.len(), 6);
Ok(mapping) Ok(mapping)
} }
@ -149,16 +148,21 @@ impl<'a> Entry<'a> {
for digit in &self.four_digits_output { for digit in &self.four_digits_output {
// search is kind of ugly, but having to sort everything is probably time consuming as // search is kind of ugly, but having to sort everything is probably time consuming as
// well. // well.
let digit = digit_mapping let digit = if let Some(translation) = Self::translate_easy_digit(digit) {
.iter() translation
.find_map(|(signal, translation)| { } else {
if digit.len() == signal.len() && digit.chars().all(|c| signal.contains(c)) { *digit_mapping
Some(translation) .iter()
} else { .find_map(|(signal, translation)| {
None if digit.len() == signal.len() && digit.chars().all(|c| signal.contains(c))
} {
}) Some(translation)
.with_context(|| format!("couldn't translate digit `{}`", digit))?; } else {
None
}
})
.with_context(|| format!("couldn't translate digit `{}`", digit))?
};
res = (res * 10) + digit; res = (res * 10) + digit;
} }