#![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; 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 { let mut vec: Vec = 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, 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 = 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::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); }