diff --git a/data/output-07.txt b/data/output-07.txt index a121e13..bebaa29 100644 --- a/data/output-07.txt +++ b/data/output-07.txt @@ -1,2 +1,2 @@ 229 -0 \ No newline at end of file +6683 \ No newline at end of file diff --git a/src/day07.rs b/src/day07.rs index 3c88380..740f82f 100644 --- a/src/day07.rs +++ b/src/day07.rs @@ -2,10 +2,7 @@ use crate::utils; use anyhow::Result; -use std::{ - collections::{HashMap, HashSet}, - iter::{self, FromIterator}, -}; +use std::collections::HashMap; // light red bags contain 1 bright white bag, 2 muted yellow bags. // dark orange bags contain 3 bright white bags, 4 muted yellow bags. @@ -17,27 +14,28 @@ use std::{ // faded blue bags contain no other bags. // dotted black bags contain no other bags. +struct PurseQuantity<'a>(usize, &'a str); + // parse data into a HashMap<&str, Vec<&str>> // // for example: "light red bags contain 1 bright white bag, 2 muted yellow bags." // becomes: { "light red": ["bright white", "muted yellow", "muted yellow"]} // -fn parse(s: &str) -> HashMap<&str, Vec<&str>> { +fn parse(s: &str) -> HashMap<&str, Vec> { s.lines() .map(|l| { let parsed: Vec<&str> = l.splitn(2, " bags contain ").collect(); let container = parsed[0]; - let contents: Vec<&str> = match parsed[1].trim() { + let contents: Vec = match parsed[1].trim() { "no other bags." => Vec::new(), _ => parsed[1] .trim_end_matches('.') .split(',') - .flat_map(|c| { + .map(|c| { let trimmed = c.trim_end_matches("bags").trim_end_matches("bag").trim(); let count: usize = trimmed[0..1].parse().unwrap(); let purse = &trimmed[2..]; - let seq: Vec<&str> = iter::repeat(purse).take(count).collect(); - seq + PurseQuantity(count, purse) }) .collect(), }; @@ -46,15 +44,22 @@ fn parse(s: &str) -> HashMap<&str, Vec<&str>> { .collect() } -fn has_contents(data: &HashMap<&str, Vec<&str>>, container: &str, contents: &str) -> bool { - let these_contents: HashSet<&str> = - HashSet::from_iter(data.get(&container).unwrap().iter().cloned()); +fn has_contents(data: &HashMap<&str, Vec>, container: &str, contents: &str) -> bool { + let these_contents: &Vec<&str> = &data.get(&container).unwrap().iter().map(|c| c.1).collect(); these_contents.contains(&contents) || these_contents .iter() .any(|m| has_contents(data, m, contents)) } +fn count_contents(data: &HashMap<&str, Vec>, container: &str) -> usize { + let these_contents: &Vec = &data.get(&container).unwrap(); + these_contents + .iter() + .map(|c| c.0 + c.0 * count_contents(data, c.1)) + .sum() +} + pub fn run() -> Result<(usize, usize)> { let data = utils::read_file("data/input-07.txt")?; let answers = utils::read_i64s("data/output-07.txt")?; @@ -66,6 +71,9 @@ pub fn run() -> Result<(usize, usize)> { .filter(|k| has_contents(&parsed, k, "shiny gold")) .count(); + let p2 = count_contents(&parsed, "shiny gold"); + assert_eq!(p1, answers[0] as usize); - Ok((p1, 0)) + assert_eq!(p2, answers[1] as usize); + Ok((p1, p2)) }