-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.rs
101 lines (92 loc) · 2.51 KB
/
main.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#[macro_use]
extern crate lazy_static;
extern crate regex;
use regex::Regex;
use std::collections::{HashMap, HashSet};
#[derive(Debug, PartialEq)]
struct Rule {
count: usize,
color: String,
}
#[derive(Debug, PartialEq)]
struct Bag {
color: String,
rules: Vec<Rule>,
}
fn parse_rules(s: &str) -> Vec<Rule> {
if s == "no other bags" {
return vec![];
}
lazy_static! {
static ref RE: Regex = Regex::new(r"(\d+) (.+?) bags?").unwrap();
}
s.split(", ")
.map(|s| {
let m = RE.captures(s).unwrap();
let color = String::from(&m[2]);
let count = (&m[1]).parse::<usize>().unwrap();
Rule {
color: color,
count: count,
}
})
.collect::<Vec<Rule>>()
}
fn parse_line(s: &str) -> Bag {
lazy_static! {
static ref RE: Regex = Regex::new(r"(.+?) bags contain (.+)\.").unwrap();
}
if let Some(m) = RE.captures(s) {
let color = String::from(&m[1]);
let rules = parse_rules(&m[2]);
Bag {
color: color,
rules: rules,
}
} else {
panic!("no match")
}
}
fn resolve_bag_count(color: String, bags: &Vec<Bag>, cache: &mut HashMap<String, usize>) -> usize {
if let Some(cached) = cache.get(&color) {
return *cached + 1;
}
let bag = bags.iter().find(|b| b.color == color).unwrap();
let contents = bag
.rules
.iter()
.map(|r| {
let resolved = resolve_bag_count(r.color.clone(), &bags, &mut cache.clone());
return r.count * resolved;
})
.sum();
cache.insert(color, contents);
return contents + 1;
}
fn main() {
let bags = include_str!("../in.txt")
.split('\n')
.map(|s| parse_line(s))
.collect::<Vec<_>>();
let mut allowed_colors = HashSet::new();
let start_color = String::from("shiny gold");
allowed_colors.insert(&start_color);
loop {
let mut more = false;
for b in bags.iter() {
if !allowed_colors.contains(&b.color)
&& b.rules.iter().any(|r| allowed_colors.contains(&r.color))
{
allowed_colors.insert(&b.color);
more = true;
}
}
if !more {
break;
}
}
let part1 =allowed_colors.len() - 1;
let mut cache: HashMap<String, usize> = HashMap::new();
let part2 = resolve_bag_count(start_color, &bags, &mut cache) - 1;
dbg!(part1, part2);
}