233 lines
7.3 KiB
Rust
233 lines
7.3 KiB
Rust
use std::collections::HashMap;
|
|
use std::collections::HashSet;
|
|
use std::io::stdin;
|
|
use std::io::BufRead;
|
|
|
|
const SEGMENTS: [char; 7] = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
|
|
|
|
fn main() {
|
|
println!("Hello, world!");
|
|
|
|
let arg = std::env::args().nth(1).unwrap_or("part2".to_string());
|
|
match arg.as_str() {
|
|
"part1" => part1(),
|
|
_ => part2(),
|
|
};
|
|
}
|
|
|
|
fn part1() {
|
|
println!("Part1");
|
|
|
|
let mut lines = Vec::new();
|
|
|
|
let mut cur_line = String::new();
|
|
for line in stdin().lock().lines() {
|
|
let line = line.unwrap().replace("_", "");
|
|
cur_line += &line;
|
|
let last_char = line.chars().rev().nth(0).unwrap();
|
|
let is_wrapping = last_char == '|';
|
|
if !is_wrapping {
|
|
lines.push(cur_line);
|
|
cur_line = String::new()
|
|
} else {
|
|
cur_line.push(' ');
|
|
}
|
|
}
|
|
|
|
dbg!(&lines);
|
|
|
|
let mut count = 0;
|
|
let interesting_lengths = HashSet::from([2, 3, 4, 7]);
|
|
for line in lines {
|
|
let second_part = line.split('|').nth(1).unwrap();
|
|
let count_interesting = second_part
|
|
.split_whitespace()
|
|
.filter(|s| interesting_lengths.contains(&s.len()))
|
|
.count();
|
|
count += count_interesting;
|
|
dbg!(second_part);
|
|
dbg!(count_interesting);
|
|
}
|
|
|
|
dbg!(count);
|
|
}
|
|
|
|
fn part2() {
|
|
println!("Part2");
|
|
let mut lines = Vec::new();
|
|
|
|
let mut cur_line = String::new();
|
|
for line in stdin().lock().lines() {
|
|
let line = line.unwrap().replace("_", "");
|
|
cur_line += &line;
|
|
let last_char = line.chars().rev().nth(0).unwrap();
|
|
let is_wrapping = last_char == '|';
|
|
if !is_wrapping {
|
|
lines.push(cur_line);
|
|
cur_line = String::new()
|
|
} else {
|
|
cur_line.push(' ');
|
|
}
|
|
}
|
|
|
|
dbg!(&lines);
|
|
|
|
let sum: i32 = lines.iter().map(|l| identify_numbers(l)).sum();
|
|
dbg!(sum);
|
|
}
|
|
|
|
fn identify_numbers(line: &str) -> i32 {
|
|
let mut number_map = HashMap::new();
|
|
number_map.insert("abcefg".to_string(), 0);
|
|
number_map.insert("cf".to_string(), 1);
|
|
number_map.insert("acdeg".to_string(), 2);
|
|
number_map.insert("acdfg".to_string(), 3);
|
|
number_map.insert("bcdf".to_string(), 4);
|
|
number_map.insert("abdfg".to_string(), 5);
|
|
number_map.insert("abdefg".to_string(), 6);
|
|
number_map.insert("acf".to_string(), 7);
|
|
number_map.insert("abcdefg".to_string(), 8);
|
|
number_map.insert("abcdfg".to_string(), 9);
|
|
|
|
let mut possibilities = HashMap::new();
|
|
|
|
for segment in SEGMENTS {
|
|
possibilities.insert(segment, HashSet::from(SEGMENTS));
|
|
}
|
|
|
|
let words: Vec<String> = line
|
|
.split(&[' ', '|'][..])
|
|
.filter(|s| !s.is_empty())
|
|
.map(|s| s.to_string())
|
|
.collect();
|
|
|
|
let mut word_cycle = words.iter().cycle();
|
|
|
|
let mut last_hint = 0;
|
|
let mut unclear: usize = possibilities.values().map(|set| set.len()).sum();
|
|
while unclear > SEGMENTS.len() {
|
|
let word = &word_cycle.next().unwrap();
|
|
dbg!(word);
|
|
if word.len() == 2 {
|
|
let should_be = HashSet::from(['c', 'f']);
|
|
let should_not_be = &HashSet::from(SEGMENTS) - &should_be;
|
|
let word_chars: HashSet<char> = word.chars().collect();
|
|
let word_inverse = &HashSet::from(SEGMENTS) - &word_chars;
|
|
for a in word_chars {
|
|
for b in &should_not_be {
|
|
possibilities.get_mut(&a).unwrap().remove(&b);
|
|
}
|
|
}
|
|
for a in word_inverse {
|
|
for b in &should_be {
|
|
possibilities.get_mut(&a).unwrap().remove(&b);
|
|
}
|
|
}
|
|
}
|
|
if word.len() == 3 {
|
|
let should_be = HashSet::from(['a', 'c', 'f']);
|
|
let should_not_be = &HashSet::from(SEGMENTS) - &should_be;
|
|
let word_chars: HashSet<char> = word.chars().collect();
|
|
let word_inverse = &HashSet::from(SEGMENTS) - &word_chars;
|
|
for a in word_chars {
|
|
for b in &should_not_be {
|
|
possibilities.get_mut(&a).unwrap().remove(&b);
|
|
}
|
|
}
|
|
for a in word_inverse {
|
|
for b in &should_be {
|
|
possibilities.get_mut(&a).unwrap().remove(&b);
|
|
}
|
|
}
|
|
}
|
|
if word.len() == 4 {
|
|
let should_be = HashSet::from(['b', 'c', 'd', 'f']);
|
|
let should_not_be = &HashSet::from(SEGMENTS) - &should_be;
|
|
let word_chars: HashSet<char> = word.chars().collect();
|
|
let word_inverse = &HashSet::from(SEGMENTS) - &word_chars;
|
|
for a in word_chars {
|
|
for b in &should_not_be {
|
|
possibilities.get_mut(&a).unwrap().remove(&b);
|
|
}
|
|
}
|
|
for a in word_inverse {
|
|
for b in &should_be {
|
|
possibilities.get_mut(&a).unwrap().remove(&b);
|
|
}
|
|
}
|
|
}
|
|
if word.len() == 5 {
|
|
let should_be = HashSet::from(['b', 'c', 'e', 'f']);
|
|
let should_not_be = &HashSet::from(SEGMENTS) - &should_be;
|
|
let word_chars: HashSet<char> = word.chars().collect();
|
|
let word_inverse = &HashSet::from(SEGMENTS) - &word_chars;
|
|
for a in word_inverse {
|
|
for b in &should_not_be {
|
|
possibilities.get_mut(&a).unwrap().remove(&b);
|
|
}
|
|
}
|
|
}
|
|
if word.len() == 6 {
|
|
let should_be = HashSet::from(['c', 'd', 'e']);
|
|
let should_not_be = &HashSet::from(SEGMENTS) - &should_be;
|
|
let word_chars: HashSet<char> = word.chars().collect();
|
|
let word_inverse = &HashSet::from(SEGMENTS) - &word_chars;
|
|
for a in word_inverse {
|
|
for b in &should_not_be {
|
|
possibilities.get_mut(&a).unwrap().remove(&b);
|
|
}
|
|
}
|
|
}
|
|
|
|
last_hint += 1;
|
|
let new_unclear = possibilities.values().map(|set| set.len()).sum();
|
|
if new_unclear < unclear {
|
|
last_hint = 0
|
|
}
|
|
|
|
let clear: HashSet<char> = possibilities
|
|
.values()
|
|
.filter(|set| set.len() == 1)
|
|
.fold(HashSet::<char>::new(), |acc, ele| {
|
|
acc.union(ele).copied().collect()
|
|
});
|
|
for val in possibilities.values_mut() {
|
|
if val.len() > 1 {
|
|
for c in &clear {
|
|
val.remove(&c);
|
|
}
|
|
}
|
|
}
|
|
|
|
unclear = new_unclear;
|
|
|
|
println!("{:?}", possibilities);
|
|
if last_hint > words.len() {
|
|
panic!("Loop detected. Cannot deduce segments");
|
|
}
|
|
}
|
|
println!("{:?}", possibilities);
|
|
|
|
let signal_map: HashMap<char, char> = possibilities
|
|
.iter()
|
|
.map(|(key, set)| (*key, *set.iter().next().unwrap()))
|
|
.collect();
|
|
|
|
println!("signal map: {:?}", signal_map);
|
|
|
|
let mut num = 0;
|
|
let mut multiplier = 1;
|
|
for word in words.iter().rev().take(4) {
|
|
let mut signal: Vec<char> = word.chars().map(|c| *signal_map.get(&c).unwrap()).collect();
|
|
signal.sort();
|
|
let signal: String = signal.iter().collect();
|
|
dbg!(&signal);
|
|
let digit = number_map.get(&signal).unwrap();
|
|
num += digit * multiplier;
|
|
multiplier *= 10;
|
|
dbg!(digit);
|
|
}
|
|
dbg!(num);
|
|
return num;
|
|
}
|