Created
December 9, 2021 22:37
-
-
Save rabuf/835d3963143cb5bd89e501e2a2de31b4 to your computer and use it in GitHub Desktop.
Present version of AoC2021 Day 08, not at all optimal
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use itertools::Itertools; | |
use lazy_static::lazy_static; | |
use std::fs::File; | |
use std::io::{BufRead, BufReader}; | |
fn get_input(filename: &str) -> (Vec<Vec<String>>, Vec<Vec<String>>) { | |
let file = File::open(filename).unwrap(); | |
let lines = BufReader::new(file).lines(); | |
let mut displays = vec![]; | |
let mut codes = vec![]; | |
for line in lines { | |
let line = line.unwrap(); | |
let mut parts = line.split(" | "); | |
let cs = parts | |
.next() | |
.unwrap() | |
.split(' ') | |
.map(|s| s.chars().sorted().collect()) | |
.collect(); | |
codes.push(cs); | |
let ds = parts | |
.next() | |
.unwrap() | |
.split(' ') | |
.map(|s| s.chars().sorted().collect()) | |
.collect(); | |
displays.push(ds); | |
} | |
(codes, displays) | |
} | |
/** | |
Part 1 is straightforward: going through the display portions, count how many 2, 3, 4, and 7 | |
length strings appear. | |
*/ | |
pub fn part1() -> usize { | |
let (_displays, codes) = get_input("../input/08.txt"); | |
codes | |
.iter() | |
.map(|s| { | |
s.iter() | |
.filter(|s| s.len() == 2 || s.len() == 3 || s.len() == 4 || s.len() == 7) | |
.count() | |
}) | |
.sum() | |
} | |
fn translate(perm: &[char], codes: &[String]) -> Vec<String> { | |
let mut translated = vec![]; | |
// for each code, use the index of the code in the permutation | |
// as the basis for mapping. That is, if 'g' is in the first index | |
// it becomes 'a' when translated | |
for code in codes.iter() { | |
let mut t: Vec<char> = vec![]; | |
for c in code.chars() { | |
let indexes = perm.iter().positions(|p| *p == c).collect::<Vec<usize>>(); | |
let i = indexes.get(0).unwrap(); | |
let c = char::from_u32((*i as u32) + ('a' as u32)).unwrap(); | |
t.push(c); | |
} | |
translated.push(t.iter().sorted().collect()); | |
} | |
translated | |
} | |
fn decode_line(codes: &[String], display: &[String]) -> usize { | |
lazy_static! { | |
static ref CANONICAL_STRINGS: Vec<String> = vec![ | |
"abcefg", "cf", "acdeg", "acdfg", "bcdf", "abdfg", "abdefg", "acf", "abcdefg", "abcdfg" | |
] | |
.iter() | |
.map(|s| s.to_string()) | |
.collect(); | |
} | |
for perm in "abcdefg".chars().permutations(7) { | |
let codes = translate(&perm, &codes); | |
if 10 | |
== CANONICAL_STRINGS | |
.iter() | |
.map(|s| codes.contains(s)) | |
.filter(|b| *b) | |
.count() | |
{ | |
let displays = translate(&perm, &display); | |
let result = displays | |
.iter() | |
.map(|d| { | |
for (index, pattern) in CANONICAL_STRINGS.iter().enumerate() { | |
if pattern == d { | |
return index; | |
} | |
} | |
0 | |
}) | |
.fold(0, |acc, val| acc * 10 + val); | |
return result; | |
} | |
} | |
0 // should never happen, but if it can't be decoded just returns 0 | |
} | |
pub fn part2() -> usize { | |
let (codes, displays) = get_input("../input/08.txt"); | |
codes | |
.iter() | |
.zip(displays) | |
.map(|(c, d)| decode_line(c, &d)) | |
.sum() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment