summaryrefslogtreecommitdiff
path: root/2023/day19.rs
diff options
context:
space:
mode:
Diffstat (limited to '2023/day19.rs')
-rw-r--r--2023/day19.rs140
1 files changed, 140 insertions, 0 deletions
diff --git a/2023/day19.rs b/2023/day19.rs
new file mode 100644
index 0000000..f8ad1d8
--- /dev/null
+++ b/2023/day19.rs
@@ -0,0 +1,140 @@
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(unused_mut)]
+use std::cmp::Ordering;
+use std::collections::HashMap;
+use std::env;
+use std::fs::File;
+use std::io::Read;
+
+#[derive(Debug, Clone)]
+struct Comp {
+ i: usize,
+ comp: Ordering,
+ val: i32,
+ next: String,
+}
+
+type Comps = Vec<Comp>;
+
+fn name_to_num(c: char) -> usize {
+ match c {
+ 'x' => return 0,
+ 'm' => return 1,
+ 'a' => return 2,
+ 's' => return 3,
+ _ => panic!(),
+ }
+}
+
+fn parse_comp(s: &str) -> Comp {
+ let mut c: Comp = Comp {
+ i: 0,
+ comp: Ordering::Equal,
+ val: 0,
+ next: "".to_string(),
+ };
+
+ if !s.contains(":") {
+ c.i = 0;
+ c.comp = Ordering::Greater;
+ c.val = -1;
+ c.next = s.to_string();
+ return c;
+ }
+
+ let (a, b) = s.split_once(":").unwrap();
+
+ if a.contains("<") {
+ let (i, val) = a.split_once("<").unwrap();
+ c.comp = Ordering::Less;
+ c.i = name_to_num(i.chars().next().unwrap());
+ c.val = val.parse().unwrap();
+ } else if a.contains(">") {
+ let (i, val) = a.split_once(">").unwrap();
+ c.comp = Ordering::Greater;
+ c.i = name_to_num(i.chars().next().unwrap());
+ c.val = val.parse().unwrap();
+ } else {
+ panic!();
+ }
+ c.next = b.to_string();
+
+ return c;
+}
+
+fn parse_wf(s: &str) -> (&str, Comps) {
+ let (a, b) = s.split_once('{').unwrap();
+ let b = b.trim_end_matches('}');
+
+ let mut comps: Comps = Vec::new();
+ for comp in b.split(',') {
+ comps.push(parse_comp(comp));
+ }
+
+ (a, comps)
+}
+
+fn parse_vals(mut s: &str) -> Vec<i32> {
+ let mut vec: Vec<i32> = Vec::new();
+ s = &s[1..s.len() - 1];
+ for mut v in s.split(',') {
+ v = &v[2..];
+ let v: u32 = v.parse().unwrap();
+ vec.push(v as i32);
+ }
+ vec
+}
+
+fn rec(wf: &str, part: &Vec<i32>, wfs: &HashMap<&str, Comps>) -> bool {
+ if wf == "R" {
+ return false;
+ } else if wf == "A" {
+ return true;
+ }
+
+ let comps = wfs.get(wf).unwrap();
+ for comp in comps {
+ if part[comp.i].cmp(&comp.val) == comp.comp {
+ return rec(&comp.next, part, wfs);
+ }
+ }
+ panic!();
+}
+
+fn main() {
+ let args: Vec<String> = env::args().collect();
+ let filename = if args.len() == 1 {
+ "in/".to_owned() + args[0].split('/').last().unwrap() + ".pzl"
+ } else {
+ args[1].clone()
+ };
+ let mut f = File::open(filename).expect("cannot open file");
+ let mut content = String::new();
+ f.read_to_string(&mut content).expect("cannot read file");
+ let mut paragraph = content.trim_end().split("\n\n");
+
+ let mut workflows: HashMap<&str, Comps> = HashMap::new();
+ for line in paragraph.next().unwrap().split('\n') {
+ let (key, val) = parse_wf(line);
+ workflows.insert(key, val);
+ }
+
+ let mut parts: Vec<Vec<i32>> = Vec::new();
+ for line in paragraph.next().unwrap().split('\n') {
+ parts.push(parse_vals(line));
+ }
+
+ let mut res1 = 0;
+
+ for part in parts {
+ if rec("in", &part, &workflows) {
+ res1 += part.iter().fold(0, |x, y| x + y);
+ }
+ }
+
+ let mut res2 = 0;
+
+ println!("res1: {}", res1);
+ println!("res2: {}", res2);
+}