This commit is contained in:
Andrew Glaze 2023-12-28 13:35:25 -05:00
parent 59a21265c6
commit 2c499e9efe
4 changed files with 176 additions and 0 deletions

52
Cargo.lock generated
View File

@ -9,10 +9,21 @@ dependencies = [
"aoc-runner", "aoc-runner",
"aoc-runner-derive", "aoc-runner-derive",
"itertools", "itertools",
"lazy_static",
"regex",
"strum", "strum",
"strum_macros", "strum_macros",
] ]
[[package]]
name = "aho-corasick"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "aoc-runner" name = "aoc-runner"
version = "0.3.0" version = "0.3.0"
@ -69,6 +80,18 @@ version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "memchr"
version = "2.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.71" version = "1.0.71"
@ -87,6 +110,35 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "regex"
version = "1.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]] [[package]]
name = "rustversion" name = "rustversion"
version = "1.0.14" version = "1.0.14"

View File

@ -14,3 +14,5 @@ aoc-runner-derive = "0.3.0"
itertools = "0.12.0" itertools = "0.12.0"
strum = "0.25.0" strum = "0.25.0"
strum_macros = "0.25" strum_macros = "0.25"
lazy_static = "1.4.0"
regex = "1.10.2"

119
src/day7.rs Normal file
View File

@ -0,0 +1,119 @@
use std::collections::{HashMap, VecDeque};
use aoc_runner_derive::{aoc, aoc_generator};
use regex::Regex;
const GOAL: &str = "shiny gold";
lazy_static! {
static ref LINE_RE: Regex = Regex::new(r"(\w+ \w+) bags contain (.*)").unwrap();
static ref ITEM_RE: Regex = Regex::new(r"(\d+) (\w+ \w+) bags?").unwrap();
}
#[aoc_generator(day7)]
fn parse(input: &str) -> HashMap<String, Vec<(usize, String)>> {
let mut bags = HashMap::<String, Vec<(usize, String)>>::new();
for line in input.lines() {
if let Some((item, items)) = LINE_RE
.captures(line.as_ref())
.and_then(|captures| {
Some((captures.get(1)?.as_str(), captures.get(2)?.as_str()))
}) {
bags.insert(
item.to_string(),
ITEM_RE
.captures_iter(items)
.filter_map(|captures| {
Some((
captures.get(1)?.as_str().parse().ok()?,
captures.get(2)?.as_str().to_string(),
))
}).collect()
);
}
}
bags
}
struct Expand<'a> {
bags: &'a HashMap<String, Vec<(usize, String)>>,
queue: VecDeque<(usize, &'a str)>
}
fn expand<'a>(bags: &'a HashMap<String, Vec<(usize, String)>>, bag: &str) -> Expand<'a> {
Expand {
bags,
queue: bags.get(bag).map_or_else(VecDeque::new, |items| {
items.iter()
.map(|(count, item)| (*count, item.as_str()))
.collect()
}),
}
}
impl<'a> Iterator for Expand<'a> {
type Item = (usize, &'a str);
fn next(&mut self) -> Option<Self::Item> {
self.queue.pop_front().map(|(count, item)| {
if let Some(items) = self.bags.get(item) {
for (subcount, subitem) in items {
self.queue.push_back((count * subcount, subitem));
}
}
(count, item)
})
}
}
#[aoc(day7, part1)]
fn part1(bags: &HashMap<String, Vec<(usize, String)>>) -> usize {
bags.keys()
.filter(|key| expand(&bags, key).any(|(_, item)| item == GOAL))
.count()
}
#[aoc(day7, part2)]
fn part2(bags: &HashMap<String, Vec<(usize, String)>>) -> usize {
expand(bags, GOAL).map(|(count, _)| count).sum()
}
#[cfg(test)]
mod tests {
use super::*;
const EX: &str = r"light red bags contain 1 bright white bag, 2 muted yellow bags.
dark orange bags contain 3 bright white bags, 4 muted yellow bags.
bright white bags contain 1 shiny gold bag.
muted yellow bags contain 2 shiny gold bags, 9 faded blue bags.
shiny gold bags contain 1 dark olive bag, 2 vibrant plum bags.
dark olive bags contain 3 faded blue bags, 4 dotted black bags.
vibrant plum bags contain 5 faded blue bags, 6 dotted black bags.
faded blue bags contain no other bags.
dotted black bags contain no other bags.";
const EX_2: &str = r"shiny gold bags contain 2 dark red bags.
dark red bags contain 2 dark orange bags.
dark orange bags contain 2 dark yellow bags.
dark yellow bags contain 2 dark green bags.
dark green bags contain 2 dark blue bags.
dark blue bags contain 2 dark violet bags.
dark violet bags contain no other bags.";
#[test]
fn part1_example() {
assert_eq!(part1(&parse(EX)), 4);
}
#[test]
fn part2_example() {
assert_eq!(part2(&parse(EX)), 32);
}
#[test]
fn part2_example2() {
assert_eq!(part2(&parse(EX_2)), 126);
}
}

View File

@ -1,3 +1,4 @@
mod day7;
mod day6; mod day6;
mod day5; mod day5;
mod day1; mod day1;
@ -8,5 +9,7 @@ extern crate aoc_runner;
#[macro_use] #[macro_use]
extern crate aoc_runner_derive; extern crate aoc_runner_derive;
#[macro_use]
extern crate lazy_static;
aoc_lib!{ year = 2020 } aoc_lib!{ year = 2020 }