aoc-rs-2021/src/day_08/model.rs
Jan Christian Grünhage e20149a5c4 implement day 8
2021-12-09 08:11:59 +01:00

224 lines
8.7 KiB
Rust

use std::collections::HashSet;
pub struct Input {
pub unique_combinations: Vec<String>,
pub output_values: Vec<String>,
}
#[derive(Debug, PartialEq, Clone)]
pub struct Ssd {
pub a: HashSet<char>,
pub b: HashSet<char>,
pub c: HashSet<char>,
pub d: HashSet<char>,
pub e: HashSet<char>,
pub f: HashSet<char>,
pub g: HashSet<char>,
}
impl Default for Ssd {
fn default() -> Self {
let possible_pins: HashSet<char> = "abcdefg".chars().collect();
Self {
a: possible_pins.clone(),
b: possible_pins.clone(),
c: possible_pins.clone(),
d: possible_pins.clone(),
e: possible_pins.clone(),
f: possible_pins.clone(),
g: possible_pins,
}
}
}
impl Ssd {
pub fn try_decode(&mut self, number: &str) -> Option<char> {
let number: HashSet<char> = number.chars().collect();
match number.len() {
2 => {
self.a.retain(|c| !number.contains(c));
self.b.retain(|c| !number.contains(c));
self.c.retain(|c| number.contains(c));
self.d.retain(|c| !number.contains(c));
self.e.retain(|c| !number.contains(c));
self.f.retain(|c| number.contains(c));
self.g.retain(|c| !number.contains(c));
Some('1')
}
3 => {
self.a.retain(|c| number.contains(c));
self.b.retain(|c| !number.contains(c));
self.c.retain(|c| number.contains(c));
self.d.retain(|c| !number.contains(c));
self.e.retain(|c| !number.contains(c));
self.f.retain(|c| number.contains(c));
self.g.retain(|c| !number.contains(c));
Some('7')
}
4 => {
self.a.retain(|c| !number.contains(c));
self.b.retain(|c| number.contains(c));
self.c.retain(|c| number.contains(c));
self.d.retain(|c| number.contains(c));
self.e.retain(|c| !number.contains(c));
self.f.retain(|c| number.contains(c));
self.g.retain(|c| !number.contains(c));
Some('4')
}
5 => {
let full: HashSet<char> = "abcdefg".chars().collect();
let missing = full.difference(&number).copied().collect::<HashSet<char>>();
let four = self.get_number_set(4);
let one = self.get_number_set(1);
let missing_six = full
.difference(&self.get_number_set(6))
.copied()
.collect::<HashSet<char>>();
let missing_nince = full
.difference(&self.get_number_set(9))
.copied()
.collect::<HashSet<char>>();
let missing_five = missing_six
.union(&missing_nince)
.copied()
.collect::<HashSet<char>>();
if missing.is_disjoint(&one) {
self.a.retain(|c| number.contains(c));
self.b.retain(|c| !number.contains(c));
self.c.retain(|c| number.contains(c));
self.d.retain(|c| number.contains(c));
self.e.retain(|c| !number.contains(c));
self.f.retain(|c| number.contains(c));
self.g.retain(|c| number.contains(c));
Some('3')
} else if missing.is_subset(&four) {
self.a.retain(|c| number.contains(c));
self.b.retain(|c| !number.contains(c));
self.c.retain(|c| number.contains(c));
self.d.retain(|c| number.contains(c));
self.e.retain(|c| number.contains(c));
self.f.retain(|c| !number.contains(c));
self.g.retain(|c| number.contains(c));
Some('2')
} else if missing == missing_five {
self.a.retain(|c| number.contains(c));
self.b.retain(|c| number.contains(c));
self.c.retain(|c| !number.contains(c));
self.d.retain(|c| number.contains(c));
self.e.retain(|c| !number.contains(c));
self.f.retain(|c| number.contains(c));
self.g.retain(|c| number.contains(c));
Some('5')
} else {
None
}
}
6 => {
let full: HashSet<char> = "abcdefg".chars().collect();
let missing = full.difference(&number).copied().collect::<HashSet<char>>();
let four = self.get_number_set(4);
let one = self.get_number_set(1);
if missing.is_disjoint(&four) {
self.a.retain(|c| number.contains(c));
self.b.retain(|c| number.contains(c));
self.c.retain(|c| number.contains(c));
self.d.retain(|c| number.contains(c));
self.e.retain(|c| !number.contains(c));
self.f.retain(|c| number.contains(c));
self.g.retain(|c| number.contains(c));
Some('9')
} else if missing.is_disjoint(&one) {
self.a.retain(|c| number.contains(c));
self.b.retain(|c| number.contains(c));
self.c.retain(|c| number.contains(c));
self.d.retain(|c| !number.contains(c));
self.e.retain(|c| number.contains(c));
self.f.retain(|c| number.contains(c));
self.g.retain(|c| number.contains(c));
Some('0')
} else {
self.a.retain(|c| number.contains(c));
self.b.retain(|c| number.contains(c));
self.c.retain(|c| !number.contains(c));
self.d.retain(|c| number.contains(c));
self.e.retain(|c| number.contains(c));
self.f.retain(|c| number.contains(c));
self.g.retain(|c| number.contains(c));
Some('6')
}
}
7 => Some('8'),
_ => None,
}
}
fn get_number_set(&self, num: usize) -> HashSet<char> {
Self::merge_sets(self.get_number_sets(num))
}
fn get_number_sets(&self, num: usize) -> Vec<HashSet<char>> {
match num {
1 => vec![&self.c, &self.f],
2 => vec![&self.a, &self.c, &self.d, &self.e, &self.g],
3 => vec![&self.a, &self.c, &self.d, &self.f, &self.g],
4 => vec![&self.b, &self.c, &self.d, &self.f],
5 => vec![&self.a, &self.b, &self.d, &self.f, &self.g],
6 => vec![&self.a, &self.b, &self.d, &self.e, &self.f, &self.g],
7 => vec![&self.a, &self.c, &self.f],
8 => vec![
&self.a, &self.b, &self.c, &self.d, &self.e, &self.f, &self.g,
],
9 => vec![&self.a, &self.b, &self.c, &self.d, &self.f, &self.g],
0 => vec![&self.a, &self.b, &self.c, &self.e, &self.f, &self.g],
_ => panic!(),
}
.iter()
.map(|set| set.iter().copied().collect())
.collect()
}
fn merge_sets(sets: Vec<HashSet<char>>) -> HashSet<char> {
sets.iter().flat_map(HashSet::iter).copied().collect()
}
}
#[cfg(test)]
mod test {
use super::Ssd;
#[test]
fn try_decode_trivials() {
let mut ssd = Ssd::default();
dbg!(&ssd);
assert_eq!(ssd.try_decode("cf"), Some('1'));
dbg!(&ssd);
assert_eq!(ssd.try_decode("acf"), Some('7'));
dbg!(&ssd);
assert_eq!(ssd.try_decode("bcdf"), Some('4'));
dbg!(&ssd);
assert_eq!(ssd.try_decode("abcdefg"), Some('8'));
}
#[test]
fn try_decode() {
let mut ssd = Ssd::default();
dbg!(&ssd);
assert_eq!(ssd.try_decode("gf"), Some('1'));
dbg!(&ssd);
assert_eq!(ssd.try_decode("fgd"), Some('7'));
dbg!(&ssd);
assert_eq!(ssd.try_decode("fgec"), Some('4'));
dbg!(&ssd);
assert_eq!(ssd.try_decode("bdegcaf"), Some('8'));
dbg!(&ssd);
assert_eq!(ssd.try_decode("aegbdf"), Some('0'));
dbg!(&ssd);
assert_eq!(ssd.try_decode("ecdfab"), Some('6'));
dbg!(&ssd);
assert_eq!(ssd.try_decode("gdcebf"), Some('9'));
dbg!(&ssd);
assert_eq!(ssd.try_decode("dbcfg"), Some('3'));
dbg!(&ssd);
assert_eq!(ssd.try_decode("dacgb"), Some('2'));
dbg!(&ssd);
assert_eq!(ssd.try_decode("fbedc"), Some('5'));
}
}