Linux 6.17 To Finish Clearing Out Old Code For OpenMoko Devices
madmo @ madmo @programming.dev Posts 0Comments 4Joined 2 yr. ago
madmo @ madmo @programming.dev
Posts
0
Comments
4
Joined
2 yr. ago
Rust
Used a sorted/unsorted comparison to solve the first part, the second part was just filling out the else branch.
use std::{ cmp::Ordering, collections::HashMap, io::{BufRead, BufReader}, }; fn main() { let mut lines = BufReader::new(std::fs::File::open("input.txt").unwrap()).lines(); let mut rules: HashMap<u64, Vec<u64>> = HashMap::default(); for line in lines.by_ref() { let line = line.unwrap(); if line.is_empty() { break; } let lr = line .split('|') .map(|el| el.parse::<u64>()) .collect::<Result<Vec<u64>, _>>() .unwrap(); let left = lr[0]; let right = lr[1]; if let Some(values) = rules.get_mut(&left) { values.push(right); values.sort(); } else { rules.insert(left, vec![right]); } } let mut updates: Vec<Vec<u64>> = Vec::default(); for line in lines { let line = line.unwrap(); let update = line .split(',') .map(|el| el.parse::<u64>()) .collect::<Result<Vec<u64>, _>>() .unwrap(); updates.push(update); } let mut middle_sum = 0; let mut fixed_middle_sum = 0; for update in updates { let mut update_sorted = update.clone(); update_sorted.sort_by(|a, b| { if let Some(rules) = rules.get(a) { if rules.contains(b) { Ordering::Less } else { Ordering::Equal } } else { Ordering::Equal } }); if update.eq(&update_sorted) { let middle = update[(update.len() - 1) / 2]; middle_sum += middle; } else { let middle = update_sorted[(update_sorted.len() - 1) / 2]; fixed_middle_sum += middle; } } println!("part1: {} part2: {}", middle_sum, fixed_middle_sum); }
Rust with nom parser
Decided to give it a go with the nom parser (first time using this crate). Turned out quite nicely. Had some issues with the alt combinator: All alternatives have to return the same type, using a enum to wrap all options did the trick.
use memmap2::Mmap; use nom::{ branch::alt, bytes::complete::*, character::complete::*, combinator::map, multi::many_till, sequence::tuple, AsBytes, IResult, }; #[derive(Debug)] enum Token { Do, Dont, Mul(u64, u64), } fn main() -> anyhow::Result<()> { let file = std::fs::File::open("input.txt")?; let mmap = unsafe { Mmap::map(&file)? }; let mut sum_part1 = 0; let mut sum_part2 = 0; let mut enabled = true; let mut cursor = mmap.as_bytes(); while let Ok(token) = parse(cursor) { match token.1 .1 { Token::Do => enabled = true, Token::Dont => enabled = false, Token::Mul(left, right) => { let prod = left * right; sum_part1 += prod; if enabled { sum_part2 += prod; } } } cursor = token.0; } println!("part1: {} part2: {}", sum_part1, sum_part2); Ok(()) } type ParseResult<'a> = Result<(&'a [u8], (Vec<char>, Token)), nom::Err<nom::error::Error<&'a [u8]>>>; fn parse(input: &[u8]) -> ParseResult { many_till( anychar, alt(( map(doit, |_| Token::Do), map(dont, |_| Token::Dont), map(mul, |el| Token::Mul(el.2, el.4)), )), )(input) } fn doit(input: &[u8]) -> IResult<&[u8], &[u8]> { tag("do()")(input) } fn dont(input: &[u8]) -> IResult<&[u8], &[u8]> { tag("don't()")(input) } type ParsedMulResult<'a> = (&'a [u8], &'a [u8], u64, &'a [u8], u64, &'a [u8]); fn mul(input: &[u8]) -> IResult<&[u8], ParsedMulResult> { tuple((tag("mul"), tag("("), u64, tag(","), u64, tag(")")))(input) }
Thanks for creating and sharing this tool! Will definitely add it to my toolbelt!
Well, I really tried to daily drive the Freerunner, but it was just not there: unstable software paired with unfinished buggy hardware. Im still grateful for the project. It was my gateway to a professional career in embedded linux development.