use std::{ collections::{HashMap, HashSet}, env, error::Error, fs::File, io::{BufReader, prelude::*}, }; fn main() -> Result<(), Box> { // Handle command input let args: Vec = env::args().collect(); if args.len() != 2 { panic!( "{} must be run with a single argument of files name!", &args[0] ) } let input_file_string = &args[1]; let buffer = BufReader::new(File::open(input_file_string)?); let mut rules_stage = true; let mut page_rules: HashMap> = HashMap::new(); let mut valid_page_updates: Vec> = Vec::new(); for line in buffer.lines() { let line = line?; if rules_stage { // Stage 1: load rules // Load rules that look like 1|1 if line.is_empty() { // Blank line means end of rules rules_stage = false; println!("Page Rules: {:?}", page_rules); continue; } let split_line: Vec<&str> = line.split("|").collect(); if split_line.len() != 2 { Err(format!("Invalid input in rules: {}", line))?; } // parse rule line and insert into out rule sets let key = split_line[0].parse::()?; let value = split_line[1].parse::()?; match page_rules.get_mut(&key) { Some(rule) => { rule.insert(value); } None => { let mut new_rule_set = HashSet::new(); new_rule_set.insert(value); page_rules.insert(key, new_rule_set); } } } else { // Stage 2: check updates let update_page_nums: Vec = line .split(",") .map(|v| v.parse::<_>()) .collect::>()?; let mut prev_pages: HashSet = HashSet::new(); let mut is_valid = true; for page_num in update_page_nums.iter() { if let Some(rule_set) = page_rules.get(page_num) { if !prev_pages.is_disjoint(rule_set) { is_valid = false; break; } prev_pages.insert(*page_num); } } if is_valid { valid_page_updates.push(update_page_nums); } } } let mut accumulator = 0; for update in valid_page_updates { let middle_page = update[update.len() / 2]; accumulator += middle_page; } println!("Sum of middle pages from valid updates: {}", accumulator); Ok(()) }