Skip to content

Commit b5e64d9

Browse files
committed
day19: done
1 parent 40b22ae commit b5e64d9

File tree

4 files changed

+148
-0
lines changed

4 files changed

+148
-0
lines changed

Cargo.lock

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ members = [
3636
"day17pt2",
3737
"day18",
3838
"day18pt2",
39+
"day19",
3940
]
4041

4142
[profile.dev]

day19/Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[package]
2+
name = "day19"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies]

day19/src/main.rs

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
use std::collections::HashMap;
2+
3+
#[derive(Debug)]
4+
struct Test {
5+
prop: char,
6+
op: char,
7+
value: usize,
8+
}
9+
10+
#[derive(Debug)]
11+
struct Rule {
12+
test: Option<Test>,
13+
dest: String,
14+
}
15+
16+
fn main() {
17+
let mut lines = std::io::stdin().lines().map(Result::unwrap);
18+
19+
// Read in workflows.
20+
let mut workflows: HashMap<String, Vec<Rule>> = HashMap::new();
21+
loop {
22+
let line = lines.next().unwrap_or_else(|| "".to_string());
23+
if line == "" {
24+
break;
25+
}
26+
let (workflow_name, rules_str) = line
27+
.split_once('{')
28+
.map(|(wn, rs)| (wn, rs.strip_suffix('}').expect("workflow '}'")))
29+
.expect("workflow '{'");
30+
let rules: Vec<Rule> = rules_str
31+
.split(',')
32+
.map(|rule_str| {
33+
if let Some((test_str, dest)) = rule_str.split_once(':') {
34+
if let Some((prop_str, value_str)) = test_str.split_once('<') {
35+
Rule {
36+
test: Some(Test {
37+
prop: prop_str.chars().next().expect("prop char"),
38+
op: '<',
39+
value: value_str.parse::<usize>().expect("value usize"),
40+
}),
41+
dest: dest.to_string(),
42+
}
43+
} else if let Some((prop_str, value_str)) = test_str.split_once('>') {
44+
Rule {
45+
test: Some(Test {
46+
prop: prop_str.chars().next().expect("prop char"),
47+
op: '>',
48+
value: value_str.parse::<usize>().expect("value usize"),
49+
}),
50+
dest: dest.to_string(),
51+
}
52+
} else {
53+
panic!("unknown op");
54+
}
55+
} else {
56+
Rule {
57+
test: None,
58+
dest: rule_str.to_string(),
59+
}
60+
}
61+
})
62+
.collect::<Vec<Rule>>();
63+
workflows.insert(workflow_name.to_string(), rules);
64+
}
65+
66+
// Read in parts.
67+
let parts: Vec<[usize; 4]> = lines
68+
.map(|line| {
69+
let mut props = line.split(',').map(|p| {
70+
p.trim_matches(|c: char| !c.is_ascii_digit())
71+
.parse::<usize>()
72+
.expect("prop usize")
73+
});
74+
[
75+
props.next().expect("prop x"),
76+
props.next().expect("prop m"),
77+
props.next().expect("prop a"),
78+
props.next().expect("prop s"),
79+
]
80+
})
81+
.collect::<Vec<[usize; 4]>>();
82+
83+
let rating = parts
84+
.iter()
85+
.map(|part| {
86+
let mut workflow_name = &"in".to_string();
87+
while let Some(workflow) = workflows.get(workflow_name) {
88+
for rule in workflow {
89+
let test_result = match rule.test {
90+
Some(Test {
91+
prop,
92+
op: '<',
93+
value,
94+
}) => {
95+
let pi = match prop {
96+
'x' => 0,
97+
'm' => 1,
98+
'a' => 2,
99+
's' => 3,
100+
_ => panic!("unknown prop"),
101+
};
102+
part[pi] < value
103+
}
104+
Some(Test {
105+
prop,
106+
op: '>',
107+
value,
108+
}) => {
109+
let pi = match prop {
110+
'x' => 0,
111+
'm' => 1,
112+
'a' => 2,
113+
's' => 3,
114+
_ => panic!("unknown prop"),
115+
};
116+
part[pi] > value
117+
}
118+
_ => true,
119+
};
120+
if test_result {
121+
workflow_name = &rule.dest;
122+
break;
123+
}
124+
}
125+
}
126+
if workflow_name == "A" {
127+
part.iter().sum::<usize>()
128+
} else {
129+
assert!(workflow_name == "R");
130+
0
131+
}
132+
})
133+
.sum::<usize>();
134+
println!("{rating}");
135+
}

0 commit comments

Comments
 (0)