diff options
author | Irene Knapp <ireneista@gmail.com> | 2020-12-06 22:06:27 -0800 |
---|---|---|
committer | Irene Knapp <ireneista@gmail.com> | 2020-12-06 22:06:27 -0800 |
commit | e3e71ffb705208cc188ff19a4936880f709aaf12 (patch) | |
tree | 86a2f6a1a4d3894f465acb7dfbdb07562dbb4746 /07/src | |
parent | 9293a2fd8ca2d4c1307f966568745f94327a0bba (diff) |
07
Diffstat (limited to '07/src')
-rw-r--r-- | 07/src/main.rs | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/07/src/main.rs b/07/src/main.rs new file mode 100644 index 0000000..e8e12b5 --- /dev/null +++ b/07/src/main.rs @@ -0,0 +1,99 @@ +use advent_lib::prelude::*; + +use std::collections::BTreeMap; +use std::collections::BTreeSet; + + +fn main() -> Result<()> { + let mut args = std::env::args(); + if args.len() != 2 { + eprintln!("Usage: advent input"); + } + let _ = args.next(); + let filename = args.next().unwrap(); + + let input = advent_lib::read_lines_file(&filename)?; + + let mut rules: BTreeMap<String, BTreeSet<(i64, String)>> = + BTreeMap::new(); + + for line in &input { + let mut words = Vec::new(); + for word in line.split(' ') { + words.push(word); + } + + let key = two_words(words[0], words[1]); + let mut value = BTreeSet::new(); + + if words[4] != "no" { + let mut i = 4; + while i + 2 < words.len() { + let quantity = words[i].parse::<i64>()?; + let color = two_words(words[i+1], words[i+2]); + value.insert((quantity, color)); + i += 4; + } + } + + rules.insert(key, value); + } + + let mut closure: BTreeSet<String> = BTreeSet::new(); + + for (container, rhs) in rules.iter() { + for (_, containee) in rhs.iter() { + if containee == "shiny gold" { + closure.insert(container.to_string()); + } + } + } + + loop { + let mut added_any = false; + for (container, rhs) in rules.iter() { + if closure.contains(container) { + continue; + } + + for (_, containee) in rhs.iter() { + if closure.contains(containee) { + closure.insert(container.to_string()); + added_any = true; + } + } + } + + if !added_any { + break; + } + } + + println!("{}", closure.len()); + + println!("{}", recursive_count(&rules, "shiny gold".to_string()) - 1); + + Ok(()) +} + + +fn two_words(a: &str, b: &str) -> String { + let mut result = String::new(); + result.push_str(a); + result.push_str(" "); + result.push_str(b); + result +} + + +fn recursive_count(rules: &BTreeMap<String, BTreeSet<(i64, String)>>, container: String) -> i64 { + let mut sum = 1; + + let rhs: &BTreeSet<(i64, String)> = rules.get(&container).unwrap(); + for (quantity, containee) in rhs.iter() { + let count_below = recursive_count(rules, containee.to_string()); + sum += quantity * count_below; + } + + sum +} |