Skip to content

Instantly share code, notes, and snippets.

@rabuf
Created December 9, 2021 22:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rabuf/835d3963143cb5bd89e501e2a2de31b4 to your computer and use it in GitHub Desktop.
Save rabuf/835d3963143cb5bd89e501e2a2de31b4 to your computer and use it in GitHub Desktop.
Present version of AoC2021 Day 08, not at all optimal
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