diff options
| author | nekineki <nekineki@nekineki.net> | 2023-12-19 08:05:32 +0100 |
|---|---|---|
| committer | nekineki <nekineki@nekineki.net> | 2023-12-19 08:05:32 +0100 |
| commit | 544d51e8207e5e2c3193b8865dc30378f34be441 (patch) | |
| tree | 43c3def227715ddfcf749b524b9d47ab97030d9d /2023/day19.rs | |
| parent | a893cfc486c3f0a18de4d5cd9e48e5beba4c6073 (diff) | |
day19 part1
Diffstat (limited to '2023/day19.rs')
| -rw-r--r-- | 2023/day19.rs | 140 |
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); +} |
