🖨️ - 2024 DAY 5 SOLUTIONS - 🖨️ 1 0
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);
}
Reply
🍷 - 2024 DAY 3 SOLUTIONS -🍷 1 0
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)
}
Reply
I created rcp, an OSC52 copy tool for your remote server 2 0
Thanks for creating and sharing this tool! Will definitely add it to my toolbelt!
Reply
Next
madmo @programming.dev
Posts 0
Comments 3