Day 8 Refactoring I

Parsing and variable names
This commit is contained in:
kageru 2021-12-08 14:03:12 +01:00
parent 2ba51b2208
commit 0b77540d9d

View File

@ -9,8 +9,8 @@ use std::{array, lazy::Lazy, ops};
const DAY: usize = 08; const DAY: usize = 08;
type Parsed<'a> = Vec<([&'a str; 10], [&'a str; 4])>; type Parsed<'a> = Vec<([&'a str; 10], [&'a str; 4])>;
const VALID_DISPLAYS: Lazy<[(&'static str, SSD); 10]> = const VALID_DISPLAYS: Lazy<[SSD; 10]> =
Lazy::new(|| ["abcefg", "cf", "acdeg", "acdfg", "bcdf", "abdfg", "abdefg", "acf", "abcdefg", "abcdfg"].map(|s| (s, SSD::from(s)))); Lazy::new(|| ["abcefg", "cf", "acdeg", "acdfg", "bcdf", "abdfg", "abdefg", "acf", "abcdefg", "abcdfg"].map(SSD::from));
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
struct SSD { struct SSD {
@ -82,7 +82,7 @@ fn parse_input(raw: &str) -> Parsed {
} }
fn part1<'a>(parsed: &Parsed<'a>) -> usize { fn part1<'a>(parsed: &Parsed<'a>) -> usize {
parsed.iter().flat_map(|(_, output)| output).filter(|&&input| [2, 3, 4, 7].contains(&SSD::from(input).active_digits())).count() parsed.iter().flat_map(|(_, output)| output).filter(|&&input| [2, 3, 4, 7].contains(&input.len())).count()
} }
fn part2<'a>(parsed: &Parsed<'a>) -> usize { fn part2<'a>(parsed: &Parsed<'a>) -> usize {
@ -95,49 +95,41 @@ fn part2<'a>(parsed: &Parsed<'a>) -> usize {
let seven = input.iter().find(|d| d.active_digits() == 3).unwrap(); let seven = input.iter().find(|d| d.active_digits() == 3).unwrap();
// We know the position of a for sure because it’s the only difference between 7 and 1 // We know the position of a for sure because it’s the only difference between 7 and 1
let a = (seven - one).to_array().iter().position(|&b| b).unwrap(); let a = (seven - one).to_array().iter().position(|&b| b).unwrap();
// And c and f are these two (both used in 1) // And c and f are these two (both used in 1).
let c_or_f = one.to_array().iter().positions(|&b| b).collect_vec(); // Countrary to the name, these two values are both c_or_f,
debug_assert_eq!(c_or_f.len(), 2); // so we know c and f are these two, but we don’t know which is which.
// 4 uses b, c, d, f, but we already know c and f from 1, so this leaves b and d let (c, f) = one.to_array().iter().positions(|&b| b).next_tuple().unwrap();
let b_or_d = (four - one).to_array().iter().positions(|&b| b).collect_vec(); // 4 uses b, c, d, f, but we already know c and f from 1, so this leaves b and d.
debug_assert_eq!(b_or_d.len(), 2); let (b, d) = (four - one).to_array().iter().positions(|&b| b).next_tuple().unwrap();
// Now e and g have to be in the remaining two positions // Now e and g have to be in the remaining two positions.
let e_or_g = (0..7).filter(|n| ![a, b_or_d[0], b_or_d[1], c_or_f[0], c_or_f[1]].contains(n)).collect_vec(); let (e, g) = (0..7).filter(|n| ![a, b, c, d, f].contains(n)).next_tuple().unwrap();
debug_assert_eq!(e_or_g.len(), 2); debug_assert_eq!([a, b, c, d, e, f, g].into_iter().sorted().collect_vec(), (0..7).collect_vec());
debug_assert_eq!(
[a, b_or_d[0], b_or_d[1], c_or_f[0], c_or_f[1], e_or_g[0], e_or_g[1]].into_iter().sorted().collect_vec(),
(0..7).collect_vec()
);
// Now there are 8 possible combinations from multiplying the 3 x_or_y we constructed above. // Now there are 8 possible combinations from multiplying the 3 x_or_y we constructed above.
let mapping = iproduct!( let mapping = iproduct!([[b, d], [d, b]], [[c, f], [f, c]], [[e, g], [g, e]])
[&b_or_d, &b_or_d.iter().copied().rev().collect()], .map(|([b, d], [c, f], [e, g])| {
[&c_or_f, &c_or_f.iter().copied().rev().collect()], let mut m = [' '; 7];
[&e_or_g, &e_or_g.iter().copied().rev().collect()] m[a] = 'a';
) m[b] = 'b';
.map(|(b_d, c_f, e_g)| { m[c] = 'c';
let mut m = [' '; 7]; m[d] = 'd';
m[a] = 'a'; m[e] = 'e';
m[b_d[0]] = 'b'; m[f] = 'f';
m[c_f[0]] = 'c'; m[g] = 'g';
m[b_d[1]] = 'd'; Mapping(m)
m[e_g[0]] = 'e';
m[c_f[1]] = 'f';
m[e_g[1]] = 'g';
Mapping(m)
})
.find(|m| {
raw_input.iter().all(|i| {
let translated: String = i.chars().map(|n| m.translate(n)).collect();
let ssd = SSD::from(translated.as_ref());
VALID_DISPLAYS.iter().any(|(_, d)| d == &ssd)
}) })
}) .find(|m| {
.unwrap(); raw_input.iter().all(|i| {
let translated: String = i.chars().map(|n| m.translate(n)).collect();
let ssd = SSD::from(translated.as_ref());
VALID_DISPLAYS.iter().any(|d| d == &ssd)
})
})
.unwrap();
raw_output raw_output
.iter() .iter()
.map(|i| i.chars().map(|n| mapping.translate(n)).collect::<String>()) .map(|i| i.chars().map(|n| mapping.translate(n)).collect::<String>())
.map(|t| SSD::from(t.as_ref())) .map(|t| SSD::from(t.as_ref()))
.map(|ssd| VALID_DISPLAYS.iter().position(|(_, d)| &ssd == d).unwrap()) .map(|ssd| VALID_DISPLAYS.iter().position(|d| &ssd == d).unwrap())
.fold(0, |acc, n| (acc + n) * 10) .fold(0, |acc, n| (acc + n) * 10)
/ 10 / 10
}) })