parent
2ba51b2208
commit
0b77540d9d
|
@ -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::<String>())
|
||||
.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
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue
Block a user