2024 day-1 done

This commit is contained in:
Dylan Thies
2024-12-01 09:41:59 -05:00
parent 26262dcdb7
commit 5d8cba4189
6 changed files with 199 additions and 0 deletions

4
2024/day-1/src/lib.rs Normal file
View File

@@ -0,0 +1,4 @@
pub(crate) mod part1;
pub use crate::part1::*;
pub(crate) mod part2;
pub use crate::part2::*;

31
2024/day-1/src/main.rs Normal file
View File

@@ -0,0 +1,31 @@
#![warn(clippy::all, clippy::pedantic)]
use day_1::part1;
use day_1::part2;
use error_stack::{Result, ResultExt};
use thiserror::Error;
#[cfg(feature = "dhat-heap")]
#[global_allocator]
static ALLOC: dhat::Alloc = dhat::Alloc;
#[derive(Debug, Error)]
enum Day1Error {
#[error("Part 1 failed")]
Part1Error,
#[error("Part 2 failed")]
Part2Error,
}
fn main() -> Result<(), Day1Error> {
#[cfg(feature = "dhat-heap")]
let _profiler = dhat::Profiler::new_heap();
let input = include_str!("./input.txt");
let part1_result = part1(input).change_context(Day1Error::Part1Error)?;
println!("part 1: {part1_result}");
let part2_result = part2(input).change_context(Day1Error::Part2Error)?;
println!("part 2: {part2_result}");
Ok(())
}

54
2024/day-1/src/part1.rs Normal file
View File

@@ -0,0 +1,54 @@
#![warn(clippy::all, clippy::pedantic)]
use error_stack::Result;
use nom::{character::complete, multi::separated_list1, sequence::separated_pair, IResult};
use thiserror::Error;
// day-1
#[derive(Debug, Error)]
pub enum Day1Part1Error {
#[error("Problem parsing Day 1")]
ParseError,
}
pub fn part1(input: &str) -> Result<u64, Day1Part1Error> {
let (_, (mut col1, mut col2)) =
parse_input(input).expect("there should always be valid input from aoc");
col1.sort();
col2.sort();
Ok(col1
.into_iter()
.zip(col2.iter())
.map(|(a, b)| u64::max(a, *b) - u64::min(a, *b))
.sum())
}
fn parse_input(input: &str) -> IResult<&str, (Vec<u64>, Vec<u64>)> {
let (input, combo) = separated_list1(
complete::line_ending,
separated_pair(complete::u64, complete::space1, complete::u64),
)(input)?;
Ok((input, combo.into_iter().unzip()))
}
#[cfg(test)]
mod test {
use super::*;
const INPUT: &str = "3 4
4 3
2 5
1 3
3 9
3 3 ";
#[test_log::test]
#[test_log(default_log_filter = "trace")]
fn part1_works() {
let result = part1(INPUT).unwrap();
assert_eq!(result, 11);
}
}

54
2024/day-1/src/part2.rs Normal file
View File

@@ -0,0 +1,54 @@
#![warn(clippy::all, clippy::pedantic)]
use std::collections::HashMap;
use error_stack::{Report, Result, ResultExt};
use nom::{character::complete, multi::separated_list1, sequence::separated_pair, IResult};
use thiserror::Error;
// day-1
#[derive(Debug, Error)]
pub enum Day1Part2Error {
#[error("Problem parsing Day 1")]
ParseError,
}
pub fn part2(input: &str) -> Result<u64, Day1Part2Error> {
let (_, (col1, col2)) = parse_input(input)
.map_err(|x| Report::from(x.to_owned()))
.change_context(Day1Part2Error::ParseError)?;
let col2_bucket: HashMap<u64, u64> = col2.into_iter().fold(HashMap::new(), |mut acc, x| {
let val = acc.entry(x).or_insert(0);
*val += 1;
acc
});
Ok(col1.iter().map(|x| *x * col2_bucket.get(x).or(Some(&0)).unwrap()).sum())
}
fn parse_input(input: &str) -> IResult<&str, (Vec<u64>, Vec<u64>)> {
let (input, combo) = separated_list1(
complete::line_ending,
separated_pair(complete::u64, complete::space1, complete::u64),
)(input)?;
Ok((input, combo.into_iter().unzip()))
}
#[cfg(test)]
mod test {
use super::*;
const INPUT: &str = "3 4
4 3
2 5
1 3
3 9
3 3 ";
#[test_log::test]
#[test_log(default_log_filter = "trace")]
fn part2_works() {
let result = part2(INPUT).unwrap();
assert_eq!(result, 31);
}
}