224 lines
8.7 KiB
Rust
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'));
|
|
}
|
|
}
|