day 7 part 2 solution

Signed-off-by: Stephen Waits <swaits@amazon.com>
This commit is contained in:
Stephen Waits committed 2020-12-09 19:52:55 -08:00
1 parent be6253e53f
commit fd309fe709
2 files changed
+22 -14

No files matched your search

+1 -1
View File
@@ -1,2 +1,2 @@
229 229
0 6683
+21 -13
View File
@@ -2,10 +2,7 @@
use crate::utils; use crate::utils;
use anyhow::Result; use anyhow::Result;
use std::{ use std::collections::HashMap;
collections::{HashMap, HashSet},
iter::{self, FromIterator},
};
// light red bags contain 1 bright white bag, 2 muted yellow bags. // light red bags contain 1 bright white bag, 2 muted yellow bags.
// dark orange bags contain 3 bright white bags, 4 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. // faded blue bags contain no other bags.
// dotted black 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>> // parse data into a HashMap<&str, Vec<&str>>
// //
// for example: "light red bags contain 1 bright white bag, 2 muted yellow bags." // for example: "light red bags contain 1 bright white bag, 2 muted yellow bags."
// becomes: { "light red": ["bright white", "muted yellow", "muted yellow"]} // becomes: { "light red": ["bright white", "muted yellow", "muted yellow"]}
// //
fn parse(s: &str) -> HashMap<&str, Vec<&str>> { fn parse(s: &str) -> HashMap<&str, Vec<PurseQuantity>> {
s.lines() s.lines()
.map(|l| { .map(|l| {
let parsed: Vec<&str> = l.splitn(2, " bags contain ").collect(); let parsed: Vec<&str> = l.splitn(2, " bags contain ").collect();
let container = parsed[0]; let container = parsed[0];
let contents: Vec<&str> = match parsed[1].trim() { let contents: Vec<PurseQuantity> = match parsed[1].trim() {
"no other bags." => Vec::new(), "no other bags." => Vec::new(),
_ => parsed[1] _ => parsed[1]
.trim_end_matches('.') .trim_end_matches('.')
.split(',') .split(',')
.flat_map(|c| { .map(|c| {
let trimmed = c.trim_end_matches("bags").trim_end_matches("bag").trim(); let trimmed = c.trim_end_matches("bags").trim_end_matches("bag").trim();
let count: usize = trimmed[0..1].parse().unwrap(); let count: usize = trimmed[0..1].parse().unwrap();
let purse = &trimmed[2..]; let purse = &trimmed[2..];
let seq: Vec<&str> = iter::repeat(purse).take(count).collect(); PurseQuantity(count, purse)
seq
}) })
.collect(), .collect(),
}; };
@@ -46,15 +44,22 @@ fn parse(s: &str) -> HashMap<&str, Vec<&str>> {
.collect() .collect()
} }
fn has_contents(data: &HashMap<&str, Vec<&str>>, container: &str, contents: &str) -> bool { fn has_contents(data: &HashMap<&str, Vec<PurseQuantity>>, container: &str, contents: &str) -> bool {
let these_contents: HashSet<&str> = let these_contents: &Vec<&str> = &data.get(&container).unwrap().iter().map(|c| c.1).collect();
HashSet::from_iter(data.get(&container).unwrap().iter().cloned());
these_contents.contains(&contents) these_contents.contains(&contents)
|| these_contents || these_contents
.iter() .iter()
.any(|m| has_contents(data, m, contents)) .any(|m| has_contents(data, m, contents))
} }
fn count_contents(data: &HashMap<&str, Vec<PurseQuantity>>, container: &str) -> usize {
let these_contents: &Vec<PurseQuantity> = &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)> { pub fn run() -> Result<(usize, usize)> {
let data = utils::read_file("data/input-07.txt")?; let data = utils::read_file("data/input-07.txt")?;
let answers = utils::read_i64s("data/output-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")) .filter(|k| has_contents(&parsed, k, "shiny gold"))
.count(); .count();
let p2 = count_contents(&parsed, "shiny gold");
assert_eq!(p1, answers[0] as usize); assert_eq!(p1, answers[0] as usize);
Ok((p1, 0)) assert_eq!(p2, answers[1] as usize);
Ok((p1, p2))
} }