Skip to content

Instantly share code, notes, and snippets.

@uroybd
Created December 9, 2021 03:34
Show Gist options
  • Save uroybd/744ff6493f2c4c2622e818e0edc7b9b5 to your computer and use it in GitHub Desktop.
Save uroybd/744ff6493f2c4c2622e818e0edc7b9b5 to your computer and use it in GitHub Desktop.
A not so elegant solution of Advent of Code 2021: Day 8, Part 2
use std::collections::HashMap;
pub fn read_lines(filename: String) -> Vec<String> {
let content: Vec<String> = fs::read_to_string(filename)
.expect("Invalid File")
.split('\n')
.map(|s| s.to_string())
.collect();
return content;
}
fn sort_chars(val: String) -> String {
let s_slice: &str = &val[..];
let mut chars: Vec<char> = s_slice.chars().collect();
chars.sort_by(|a, b| a.cmp(b));
return chars.into_iter().collect::<String>();
}
fn diffs(val1: String, val2: String) -> Vec<char> {
let mut diff: HashMap<char, bool> = HashMap::new();
let val1_chars: Vec<char> = val1.chars().collect();
let val2_chars: Vec<char> = val2.chars().collect();
for v in val1_chars.iter() {
if !val2_chars.contains(v) {
diff.insert(*v, true);
}
}
for v in val2_chars.iter() {
if !val1_chars.contains(v) {
diff.insert(*v, true);
}
}
return diff.iter().map(|(&k, _)| k).collect();
}
fn parse(data: String) -> (Vec<String>, Vec<String>) {
let mut splitted = data.split(" | ");
let entries: Vec<String> = splitted
.next()
.unwrap()
.to_string()
.split(" ")
.map(|x| x.to_string())
.collect();
let to_decode: Vec<String> = splitted
.next()
.unwrap()
.to_string()
.split(" ")
.map(|x| x.to_string())
.collect();
return (entries, to_decode);
}
fn decodePattern(data: (Vec<String>, Vec<String>)) -> usize {
let (clues, to_decode) = data;
let (mut zero, mut one, mut two, mut four, mut five, mut six, mut seven, mut eight, mut nine) = (
"".to_string(),
"".to_string(),
"".to_string(),
"".to_string(),
"".to_string(),
"".to_string(),
"".to_string(),
"".to_string(),
"".to_string(),
);
for clue in clues.clone() {
match clue.len() {
2 => one = clue.clone(),
4 => four = clue.clone(),
3 => seven = clue.clone(),
7 => eight = clue.clone(),
_ => (),
}
}
let one_chars: Vec<char> = one.chars().collect();
// Get 'a'
let a = seven
.chars()
.into_iter()
.find(|c| !one_chars.contains(c))
.unwrap();
let five_longs: Vec<String> = clues.clone().into_iter().filter(|x| x.len() == 5).collect();
// Get 3
let mut three = five_longs
.clone()
.into_iter()
.find(|x| {
let chars: Vec<char> = x.chars().collect();
return chars.contains(&one_chars[0]) && chars.contains(&one_chars[1]);
})
.unwrap();
// Get b and e
let b_and_e = diffs(three.clone(), eight.clone());
// Get d
let mut sides = vec![];
sides.extend(one_chars.clone());
sides.extend(b_and_e.clone());
let four_chars: Vec<char> = four.chars().collect();
let d = four_chars
.iter()
.find(|&x| !sides.contains(x))
.unwrap()
.to_string();
// Get g
let mut sides_and_a_d = vec![];
sides_and_a_d.push(d.chars().nth(0).unwrap());
sides_and_a_d.push(a);
// Get Zero, Six, Nine
let (mut c, mut f) = ("".to_string(), "".to_string());
let six_longs: Vec<String> = clues.into_iter().filter(|x| x.len() == 6).collect();
let (sixty_nine, zeros): (Vec<String>, Vec<String>) = six_longs.into_iter().partition(|x| {
let chars: Vec<char> = x.chars().collect();
return chars.contains(&d.chars().nth(0).unwrap());
});
zero = zeros[0].clone();
for number in sixty_nine.into_iter() {
let chars: Vec<char> = number.chars().collect();
let one_chars: Vec<char> = one.chars().collect();
if chars.contains(&one.chars().nth(0).unwrap())
&& chars.contains(&one.chars().nth(1).unwrap())
{
nine = number;
} else {
six = number;
if chars.contains(&one.chars().nth(0).unwrap()) {
f = one_chars[0].to_string();
c = one_chars[1].to_string();
} else {
f = one_chars[1].to_string();
c = one_chars[0].to_string();
}
}
}
// Get e
let e_diff = diffs(eight.clone(), nine.clone());
let e_char = e_diff[0];
let e = e_char.to_string();
// Get b
let b_char = b_and_e.clone().into_iter().find(|&x| x != e_char).unwrap();
let b = b_char.to_string();
// Get 2 and 5
let two_and_five: Vec<String> = five_longs
.clone()
.into_iter()
.filter(|x| x != &three)
.collect();
for number in two_and_five.into_iter() {
let chars: Vec<char> = number.chars().collect();
if chars.contains(&e_char) {
two = number;
} else if chars.contains(&b_char) {
five = number;
}
}
// Sort all
let mut num_map = HashMap::new();
num_map.insert(sort_chars(zero), '0');
num_map.insert(sort_chars(one), '1');
num_map.insert(sort_chars(two), '2');
num_map.insert(sort_chars(three), '3');
num_map.insert(sort_chars(four), '4');
num_map.insert(sort_chars(five), '5');
num_map.insert(sort_chars(six), '6');
num_map.insert(sort_chars(seven), '7');
num_map.insert(sort_chars(eight), '8');
num_map.insert(sort_chars(nine), '9');
let mut result = to_decode
.into_iter()
.map(|digit| {
let sorted = sort_chars(digit);
let val = num_map.get(&sorted).unwrap();
return *val;
})
.collect::<String>()
.parse::<usize>()
.unwrap();
return result;
}
fn solution(filename: String) -> usize {
let mut data: Vec<String> = read_lines(filename);
return data.iter().fold(0, |acc, x| {
return acc + decodePattern(parse(x.to_string()));
});
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_day_8_2() {
let filename: String = String::from("src/inputs/day8e.txt");
let result = solution(filename);
assert_eq!(result, 61229);
}
#[test]
#[ignore]
fn output_day_8_2() {
let filename: String = String::from("src/inputs/day8.txt");
let result = solution(filename);
println!("{:?}", result);
assert_eq!(1, 1);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment