1
0
Fork 0

Added Day 8 Part 2

This commit is contained in:
Ishan Jain 2021-12-08 23:20:11 +05:30
parent ea098fbff3
commit 3a8ea28480
2 changed files with 202 additions and 70 deletions

View File

@ -1,11 +1 @@
be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe acedgfb cdfbe gcdfa fbcad dab cefabd cdfgeb eafb cagedb ab | cdfeb fcadb cdfeb cdbaf
edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec | fcgedb cgb dgebacf gc
fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef | cg cg fdcagb cbg
fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega | efabcd cedba gadfec cb
aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga | gecf egdcabf bgf bfgea
fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf | gebdcfa ecba ca fadegcb
dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf | cefg dcbef fcge gbcadfe
bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd | ed bcgafe cdgba cbgef
egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg | gbdfcae bgc cg cgb
gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce

View File

@ -1,4 +1,6 @@
#![feature(test)] #![feature(test)]
use std::collections::HashMap;
extern crate test; extern crate test;
const INPUTS: [&'static str; 2] = [ const INPUTS: [&'static str; 2] = [
@ -6,79 +8,219 @@ const INPUTS: [&'static str; 2] = [
include_str!("../inputs/input.txt"), include_str!("../inputs/input.txt"),
]; ];
#[derive(Copy, Clone, Debug, Eq, PartialEq)] const fn map_to_segment(c: char) -> u8 {
enum Segment { 1 << (c as u8 - b'a')
Top = 0b0000001,
TopLeft = 0b0000010,
TopRight = 0b0000100,
Middle = 0b0001000,
BottomLeft = 0b0010000,
BottomRight = 0b0100000,
Bottom = 0b1000000,
None = 0,
} }
#[derive(Debug, Copy, Clone)] fn parse_digits(ip: &str) -> Vec<u8> {
struct Display { let mut out = Vec::with_capacity(ip.len());
layout: [Segment; 7],
for c in ip.chars() {
out.push(map_to_segment(c));
}
out.sort_unstable();
out
} }
impl From<&str> for Display { fn parse_input(input: &'static str) -> Vec<(Vec<Vec<u8>>, Vec<Vec<u8>>)> {
fn from(s: &str) -> Self { input
let mut layout = [Segment::None; 7]; .lines()
for (i, c) in s.chars().enumerate() { .filter(|&x| !x.is_empty())
let to_push = match c { .map(|line| {
'a' => Segment::Top, let (hints, displays) = line.split_once(" | ").unwrap();
'b' => Segment::TopLeft,
'c' => Segment::TopRight,
'd' => Segment::Middle,
'e' => Segment::BottomLeft,
'f' => Segment::BottomRight,
'g' => Segment::Bottom,
_ => unreachable!(), let hints = hints
}; .split(' ')
.filter(|x| !x.is_empty())
.map(parse_digits)
.collect();
let digits = displays
.split(' ')
.filter(|x| !x.is_empty())
.map(parse_digits)
.collect();
layout[i] = to_push; (hints, digits)
})
.collect()
}
pub fn permute(mut nums: [u8; 7]) -> Vec<[u8; 7]> {
let mut ans = vec![];
let k = nums.len();
permute_helper(&mut nums, &mut ans, k);
ans
}
fn permute_helper(nums: &mut [u8; 7], permutations: &mut Vec<[u8; 7]>, k: usize) {
if k == 1 {
permutations.push(*nums);
} else {
for i in 0..k {
permute_helper(nums, permutations, k - 1);
if i < k - 1 {
if k % 2 == 0 {
nums.swap(i, k - 1);
} else {
nums.swap(0, k - 1);
}
}
} }
Self { layout }
} }
} }
fn parse_input(input: &'static str) -> impl Iterator<Item = (Vec<Display>, Vec<Display>)> { fn generate_charset(permutation: &[u8]) -> Vec<Vec<u8>> {
input.lines().filter(|&x| !x.is_empty()).map(|x| { let mut answer = vec![vec![]; 10];
let mut x = x.split("|");
let hints = x
.next()
.unwrap()
.split(' ')
.filter(|x| !x.is_empty())
.map(|x| x.into())
.collect();
let digits = x
.next()
.unwrap()
.split(' ')
.filter(|x| !x.is_empty())
.map(|x| x.into())
.collect();
(hints, digits) for digit in 0..=9 {
}) let mut out = vec![];
match digit {
0 => {
out.push(permutation[0]);
out.push(permutation[1]);
out.push(permutation[2]);
out.push(permutation[4]);
out.push(permutation[5]);
out.push(permutation[6]);
}
1 => {
out.push(permutation[2]);
out.push(permutation[5]);
}
2 => {
out.push(permutation[0]);
out.push(permutation[2]);
out.push(permutation[3]);
out.push(permutation[4]);
out.push(permutation[6]);
}
3 => {
out.push(permutation[0]);
out.push(permutation[2]);
out.push(permutation[3]);
out.push(permutation[5]);
out.push(permutation[6]);
}
4 => {
out.push(permutation[1]);
out.push(permutation[2]);
out.push(permutation[3]);
out.push(permutation[5]);
}
5 => {
out.push(permutation[0]);
out.push(permutation[1]);
out.push(permutation[3]);
out.push(permutation[5]);
out.push(permutation[6]);
}
6 => {
out.push(permutation[0]);
out.push(permutation[1]);
out.push(permutation[3]);
out.push(permutation[4]);
out.push(permutation[5]);
out.push(permutation[6]);
}
7 => {
out.push(permutation[0]);
out.push(permutation[2]);
out.push(permutation[5]);
}
8 => {
out.push(permutation[0]);
out.push(permutation[1]);
out.push(permutation[2]);
out.push(permutation[3]);
out.push(permutation[4]);
out.push(permutation[5]);
out.push(permutation[6]);
}
9 => {
out.push(permutation[0]);
out.push(permutation[1]);
out.push(permutation[2]);
out.push(permutation[3]);
out.push(permutation[5]);
out.push(permutation[6]);
}
_ => (),
}
answer[digit] = out;
}
answer
.into_iter()
.map(|mut set| {
set.sort_unstable();
set
})
.collect()
} }
fn solution(input: impl Iterator<Item = (Vec<Display>, Vec<Display>)>) -> u64 { #[inline]
let mut answer = 0; fn verify_perfect_overlap(d1: &[u8], d2: &[u8]) -> bool {
for (_, digits) in input { if d1.len() != d2.len() {
for digit in digits { return false;
let set_bits_count = digit.layout.iter().filter(|&&s| s == Segment::None).count(); }
match 7 - set_bits_count { d1 == d2
2 | 7 | 4 | 3 => answer += 1, }
_ => (),
fn find_best_fit(permutations: &[[u8; 7]], mut hints: Vec<Vec<u8>>) -> Option<Vec<Vec<u8>>> {
hints.sort_unstable_by(|a, b| a.len().cmp(&b.len()));
for permutation in permutations {
let charset = generate_charset(permutation);
let mut map = HashMap::new();
for (i, cset) in charset.iter().enumerate() {
for hint in hints.iter() {
if verify_perfect_overlap(&cset, &hint) {
if map.contains_key(&hint) {
continue;
} else {
map.insert(hint, i);
}
}
} }
} }
if map.len() == hints.len() {
return Some(charset);
}
}
None
}
fn solution(input: Vec<(Vec<Vec<u8>>, Vec<Vec<u8>>)>) -> u64 {
// Generate all possible permutations of abcdefg
let permutations = permute([
0b0000001, 0b0000010, 0b0000100, 0b0001000, 0b0010000, 0b0100000, 0b1000000,
]);
let mut answer = 0;
for (hints, digits) in input {
let best_fit = find_best_fit(&permutations, hints).unwrap();
let mut out_digit = String::new();
for digit in digits {
for (i, fit) in best_fit.iter().enumerate() {
if fit == &digit {
out_digit.push_str(&i.to_string());
}
}
}
let parsed = u64::from_str_radix(&out_digit, 10).unwrap();
answer += parsed;
} }
answer answer
@ -94,9 +236,9 @@ fn main() {
#[bench] #[bench]
fn solution_bench(b: &mut test::Bencher) { fn solution_bench(b: &mut test::Bencher) {
let input = parse_input(INPUTS[1]);
b.iter(|| { b.iter(|| {
let input = parse_input(INPUTS[1]); let result = solution(input.clone());
let result = solution(input);
test::black_box(result); test::black_box(result);
}) })
} }