Day 5: Print Queue
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
Rust
I don’t love this code, but I didn’t initially use a hashmap and it runs so fast it wasn’t worth the time to refactor.
use std::{cmp::Ordering, fs, str::FromStr}; use color_eyre::eyre::{Report, Result}; use itertools::Itertools; struct Updates(Vec<Vec<isize>>); impl FromStr for Updates { type Err = Report; fn from_str(s: &str) -> Result<Self, Self::Err> { let pages = s .lines() .map(|l| l.split(",").map(|n| n.parse::<isize>()).collect()) .collect::<Result<_, _>>()?; Ok(Self(pages)) } } impl Updates { fn get_valid(&self, rules: &OrderingRules) -> Self { let pages = self .0 .clone() .into_iter() .filter(|p| rules.validate(p)) .collect(); Self(pages) } fn get_invalid(&self, rules: &OrderingRules) -> Self { let pages = self .0 .clone() .into_iter() .filter(|p| !rules.validate(p)) .collect(); Self(pages) } } struct OrderingRules(Vec<(isize, isize)>); impl OrderingRules { fn validate(&self, pnums: &Vec<isize>) -> bool { self.0.iter().all(|(a, b)| { let Some(a_pos) = pnums.iter().position(|&x| x == *a) else { return true; }; let Some(b_pos) = pnums.iter().position(|&x| x == *b) else { return true; }; a_pos < b_pos }) } fn fix(&self, pnums: &Vec<isize>) -> Vec<isize> { let mut v = pnums.clone(); v.sort_by(|a, b| { let mut fr = self .0 .iter() .filter(|(ra, rb)| (ra == a || ra == b) && (rb == a || rb == b)); if let Some((ra, _rb)) = fr.next() { if ra == a { Ordering::Less } else { Ordering::Greater } } else { Ordering::Equal } }); v } } impl FromStr for OrderingRules { type Err = Report; fn from_str(s: &str) -> Result<Self, Self::Err> { let v = s .lines() .map(|l| { l.splitn(2, "|") .map(|n| n.parse::<isize>().unwrap()) .collect_tuple() .ok_or_else(|| Report::msg("Rules need two items")) }) .collect::<Result<_, _>>()?; Ok(Self(v)) } } fn parse(s: &str) -> Result<(OrderingRules, Updates)> { let parts: Vec<_> = s.splitn(2, "\n\n").collect(); let rules = OrderingRules::from_str(parts[0])?; let updates = Updates::from_str(parts[1])?; Ok((rules, updates)) } fn part1(filepath: &str) -> Result<isize> { let input = fs::read_to_string(filepath)?; let (rules, updates) = parse(&input)?; let res = updates .get_valid(&rules) .0 .iter() .map(|v| v[v.len() / 2]) .sum(); Ok(res) } fn part2(filepath: &str) -> Result<isize> { let input = fs::read_to_string(filepath)?; let (rules, updates) = parse(&input)?; let res = updates .get_invalid(&rules) .0 .iter() .map(|v| rules.fix(&v)) .map(|v| v[v.len() / 2]) .sum(); Ok(res) } fn main() -> Result<()> { color_eyre::install()?; println!("Part 1: {}", part1("d05/input.txt")?); println!("Part 2: {}", part2("d05/input.txt")?); Ok(()) }