mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
Implementation day 7
This commit is contained in:
@@ -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
137
2020/src/day07.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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) => {
|
||||
|
||||
Reference in New Issue
Block a user