Implementation day 7

This commit is contained in:
2020-12-07 09:35:41 +01:00
parent 4cb74e742b
commit 10f123bf04
6 changed files with 751 additions and 1 deletions

View File

@@ -19,7 +19,7 @@ fn compute_answers(group: &str) -> Answers {
fn count_answers_all(group: &str) -> u32 {
let combined = group
.split('\n')
.lines()
.map(compute_answers)
.fold(0xffff_ffff, |a, b| a & b);

137
2020/src/day07.rs Normal file
View File

@@ -0,0 +1,137 @@
use std::collections::{HashMap, HashSet};
use std::io::Read;
use regex::Regex;
use crate::common::Lines;
use crate::Solution;
fn read_graph(input: &mut dyn Read) -> HashMap<String, Vec<String>> {
let regex = Regex::new(r"(\w+ \w+) bag").unwrap();
let mut graph: HashMap<String, Vec<String>> = HashMap::new();
for line in Lines::new(input) {
let mut captures = regex.captures_iter(&line);
let container = &captures.next().unwrap()[1];
for cap in captures {
let contained = cap[1].to_owned();
graph
.entry(contained)
.or_default()
.push(container.to_owned());
}
}
graph
}
fn read_graph2(input: &mut dyn Read) -> HashMap<String, Vec<(usize, String)>> {
let regex = Regex::new(r"(\d+) (\w+ \w+) bag").unwrap();
let mut graph: HashMap<String, Vec<(usize, String)>> = HashMap::new();
for line in Lines::new(input) {
let second_space = line
.chars()
.enumerate()
.filter(|&(_, c)| ' ' == c)
.nth(1)
.unwrap()
.0;
let container = line[..second_space].to_owned();
let contained = regex
.captures_iter(&line)
.map(|cap| (cap[1].parse().unwrap(), cap[2].to_owned()))
.collect();
graph.insert(container, contained);
}
graph
}
fn compute_contained(
color: &str,
graph: &HashMap<String, Vec<(usize, String)>>,
memo: &mut HashMap<String, usize>,
) -> usize {
if let Some(amount) = memo.get(color) {
return *amount;
}
let total = if let Some(contained) = graph.get(color) {
contained
.iter()
.map(|(count, color)| count * compute_contained(color, graph, memo))
.sum::<usize>()
+ 1
} else {
1
};
memo.insert(color.to_owned(), total);
total
}
#[derive(Default)]
pub struct Day07;
impl Solution for Day07 {
fn part1(&mut self, input: &mut dyn Read) -> String {
let graph = read_graph(input);
let mut todo = vec!["shiny gold"];
let mut routes = 0;
let mut done = HashSet::new();
done.insert("shiny gold");
while let Some(color) = todo.pop() {
if let Some(neighbours) = graph.get(color) {
for neighbour in neighbours {
if !done.contains(neighbour.as_str()) {
routes += 1;
done.insert(neighbour);
todo.push(neighbour);
}
}
}
}
routes.to_string()
}
fn part2(&mut self, input: &mut dyn Read) -> String {
let graph = read_graph2(input);
let mut count_memo = HashMap::with_capacity(graph.len());
(compute_contained("shiny gold", &graph, &mut count_memo) - 1).to_string()
}
}
#[cfg(test)]
mod tests {
use crate::test_implementation;
use super::*;
const SAMPLE: &[u8] = include_bytes!("../samples/07.txt");
const SAMPLE2: &[u8] = include_bytes!("../samples/07.2.txt");
#[test]
fn sample_part1() {
test_implementation!(Day07, 1, SAMPLE, 4);
}
#[test]
fn sample_part2() {
test_implementation!(Day07, 2, SAMPLE, 32);
test_implementation!(Day07, 2, SAMPLE2, 126);
}
}

View File

@@ -7,6 +7,7 @@ mod day03;
mod day04;
mod day05;
mod day06;
mod day07;
pub trait Solution {
fn part1(&mut self, input: &mut dyn Read) -> String;
@@ -24,10 +25,12 @@ pub fn get_implementation(day: usize) -> Box<dyn Solution> {
4 => Box::new(day04::Day04::default()),
5 => Box::new(day05::Day05::default()),
6 => Box::new(day06::Day06::default()),
7 => Box::new(day07::Day07::default()),
_ => panic!("Unsupported day {}", day),
}
}
#[cfg(test)]
#[macro_export]
macro_rules! test_implementation {
($impl:ident, 1, $source:ident, $output:expr) => {