use std::{ fs::File, io::{BufRead, BufReader}, path::Path, }; pub fn solve(input: &Path) -> anyhow::Result<()> { println!("part one: {}", part_one(input)?); println!("part two: {}", part_two(input)?); Ok(()) } fn part_one(input: &Path) -> anyhow::Result { let reader = BufReader::new(File::open(input)?); let mut reading_rules = true; let mut rules = vec![]; let mut pages_to_update = vec![]; for line in reader.lines() { let line = line?; if line.is_empty() { reading_rules = false; continue; } if reading_rules { rules.push( line.split("|") .map(|s| s.parse::().unwrap()) .collect::>(), ) } else { pages_to_update.push( line.split(",") .map(|s| s.parse::().unwrap()) .collect::>(), ) } } let mut answer = 0; for pages in pages_to_update { if is_in_order(&pages, &rules) { answer += pages[pages.len() / 2]; } } Ok(answer) } fn is_in_order(pages: &[i32], rules: &[Vec]) -> bool { for (left_index, page) in pages.iter().enumerate() { for rule in rules.iter().filter(|&r| r[0] == *page) { if let Some(right_index) = pages.iter().position(|n| *n == rule[1]) { if right_index < left_index { return false; } } } } true } fn part_two(input: &Path) -> anyhow::Result { let reader = BufReader::new(File::open(input)?); let mut reading_rules = true; let mut rules = vec![]; let mut pages_to_update = vec![]; for line in reader.lines() { let line = line?; if line.is_empty() { reading_rules = false; continue; } if reading_rules { rules.push( line.split("|") .map(|s| s.parse::().unwrap()) .collect::>(), ) } else { pages_to_update.push( line.split(",") .map(|s| s.parse::().unwrap()) .collect::>(), ) } } let mut answer = 0; for pages in pages_to_update .iter() .filter(|pages| !is_in_order(pages, &rules)) { answer += ordered(pages, &rules)[pages.len() / 2]; } Ok(answer) } fn ordered(pages: &[i32], rules: &[Vec]) -> Vec { let mut pages = pages.to_owned(); 'w: while !is_in_order(&pages, rules) { for (left_index, page) in pages.iter().enumerate() { for rule in rules.iter().filter(|&r| r[0] == *page) { if let Some(right_index) = pages.iter().position(|n| *n == rule[1]) { if right_index < left_index { pages.swap(right_index, left_index); continue 'w; } } } } } pages }