From 0b77540d9da2825a99a17ea67a06937417e2d04f Mon Sep 17 00:00:00 2001 From: kageru Date: Wed, 8 Dec 2021 14:03:12 +0100 Subject: [PATCH] Day 8 Refactoring I Parsing and variable names --- 2021/src/bin/day08.rs | 72 +++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 40 deletions(-) diff --git a/2021/src/bin/day08.rs b/2021/src/bin/day08.rs index 2fdf459..11f8c41 100644 --- a/2021/src/bin/day08.rs +++ b/2021/src/bin/day08.rs @@ -9,8 +9,8 @@ use std::{array, lazy::Lazy, ops}; const DAY: usize = 08; type Parsed<'a> = Vec<([&'a str; 10], [&'a str; 4])>; -const VALID_DISPLAYS: Lazy<[(&'static str, SSD); 10]> = - Lazy::new(|| ["abcefg", "cf", "acdeg", "acdfg", "bcdf", "abdfg", "abdefg", "acf", "abcdefg", "abcdfg"].map(|s| (s, SSD::from(s)))); +const VALID_DISPLAYS: Lazy<[SSD; 10]> = + Lazy::new(|| ["abcefg", "cf", "acdeg", "acdfg", "bcdf", "abdfg", "abdefg", "acf", "abcdefg", "abcdfg"].map(SSD::from)); #[derive(Debug, PartialEq)] struct SSD { @@ -82,7 +82,7 @@ fn parse_input(raw: &str) -> Parsed { } 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 { @@ -95,49 +95,41 @@ fn part2<'a>(parsed: &Parsed<'a>) -> usize { 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 let a = (seven - one).to_array().iter().position(|&b| b).unwrap(); - // And c and f are these two (both used in 1) - let c_or_f = one.to_array().iter().positions(|&b| b).collect_vec(); - debug_assert_eq!(c_or_f.len(), 2); - // 4 uses b, c, d, f, but we already know c and f from 1, so this leaves b and d - let b_or_d = (four - one).to_array().iter().positions(|&b| b).collect_vec(); - debug_assert_eq!(b_or_d.len(), 2); - // 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(); - debug_assert_eq!(e_or_g.len(), 2); - 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() - ); + // And c and f are these two (both used in 1). + // Countrary to the name, these two values are both c_or_f, + // so we know c and f are these two, but we don’t know which is which. + let (c, f) = one.to_array().iter().positions(|&b| b).next_tuple().unwrap(); + // 4 uses b, c, d, f, but we already know c and f from 1, so this leaves b and d. + 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. + let (e, g) = (0..7).filter(|n| ![a, b, c, d, f].contains(n)).next_tuple().unwrap(); + debug_assert_eq!([a, b, c, d, e, f, g].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. - let mapping = iproduct!( - [&b_or_d, &b_or_d.iter().copied().rev().collect()], - [&c_or_f, &c_or_f.iter().copied().rev().collect()], - [&e_or_g, &e_or_g.iter().copied().rev().collect()] - ) - .map(|(b_d, c_f, e_g)| { - let mut m = [' '; 7]; - m[a] = 'a'; - m[b_d[0]] = 'b'; - m[c_f[0]] = 'c'; - m[b_d[1]] = 'd'; - 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) + let mapping = iproduct!([[b, d], [d, b]], [[c, f], [f, c]], [[e, g], [g, e]]) + .map(|([b, d], [c, f], [e, g])| { + let mut m = [' '; 7]; + m[a] = 'a'; + m[b] = 'b'; + m[c] = 'c'; + m[d] = 'd'; + m[e] = 'e'; + m[f] = 'f'; + m[g] = 'g'; + Mapping(m) }) - }) - .unwrap(); + .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) + }) + }) + .unwrap(); raw_output .iter() .map(|i| i.chars().map(|n| mapping.translate(n)).collect::()) .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) / 10 })